Skip to content

Commit

Permalink
Finally
Browse files Browse the repository at this point in the history
  • Loading branch information
Nep-Timeline committed Sep 9, 2024
1 parent 0ee4d48 commit 09dba49
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 6 deletions.
6 changes: 6 additions & 0 deletions app/src/main/java/nep/timeline/cirno/entity/AppRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public boolean isSystem() {
return packageName == null || packageName.equals("android") || PKGUtils.isSystemApp(applicationInfo);
}

public String getPackageNameWithUser() {
if (userId == 0)
return packageName;
return packageName + ":" + userId;
}

public void reset() {
this.frozen = false;
this.appState = new AppState(this);
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/nep/timeline/cirno/entity/AppState.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
package nep.timeline.cirno.entity;

import android.os.IBinder;

import java.util.HashSet;
import java.util.Set;

import lombok.Getter;

@Getter
public class AppState {
private final AppRecord parent;
private boolean visible = false;
private final Set<IBinder> activities = new HashSet<>();

public AppState(AppRecord appRecord) {
this.parent = appRecord;
}

public synchronized boolean setVisible(boolean value) {
if (visible == value)
return false;
visible = value;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import android.content.pm.ApplicationInfo;

import de.robv.android.xposed.XposedHelpers;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import nep.timeline.cirno.services.AppService;

@Getter
Expand All @@ -15,7 +17,10 @@ public class ProcessRecord {
private final int uid;
private final String packageName;
private final String processName;
@Getter(AccessLevel.NONE)
private AppRecord appRecord;
@Setter
private boolean frozen;

public ProcessRecord(Object instance) {
this.instance = instance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import nep.timeline.cirno.entity.AppRecord;
import nep.timeline.cirno.framework.AbstractMethodHook;
import nep.timeline.cirno.framework.MethodHook;
import nep.timeline.cirno.log.Log;
import nep.timeline.cirno.services.FreezerService;
import nep.timeline.cirno.threads.FreezerHandler;

public class ActivityStatsHook extends MethodHook {
private final Map<IBinder, ActivityRecord> activityRecords = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -62,6 +65,20 @@ protected void beforeMethod(MethodHookParam param) {
if (appRecord == null)
return;

if (event == UsageEvents.Event.ACTIVITY_RESUMED)
appRecord.getAppState().getActivities().add(activityRecord.getToken());
else
appRecord.getAppState().getActivities().remove(activityRecord.getToken());

if (appRecord.getAppState().getActivities().isEmpty()) {
if (appRecord.getAppState().setVisible(false)) {
Log.d(appRecord.getPackageNameWithUser() + " 进入后台");
FreezerHandler.sendFreezeMessage(appRecord, 3000);
}
} else if (appRecord.getAppState().setVisible(true)) {
Log.d(appRecord.getPackageNameWithUser() + " 进入前台");
FreezerService.thaw(appRecord);
}
}
};
}
Expand Down
31 changes: 25 additions & 6 deletions app/src/main/java/nep/timeline/cirno/services/FreezerService.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
package nep.timeline.cirno.services;

import nep.timeline.cirno.utils.RWUtils;
import nep.timeline.cirno.entity.AppRecord;
import nep.timeline.cirno.entity.ProcessRecord;
import nep.timeline.cirno.utils.FrozenRW;

public class FreezerService {
public static final String cgroupV2 = "/sys/fs/cgroup/";
public static void freezer(AppRecord appRecord) {
if (appRecord.isFrozen() || appRecord.isSystem() || appRecord.getAppState().isVisible())
return;

public static void frozen(int uid, int pid) {
RWUtils.writeFrozen(cgroupV2 + "/uid_" + uid + "/pid_" + pid + "/cgroup.freeze", 1);
for (ProcessRecord processRecord : appRecord.getProcessRecords()) {
if (processRecord.isDeathProcess() || processRecord.isFrozen())
continue;

FrozenRW.frozen(processRecord.getRunningUid(), processRecord.getPid());
processRecord.setFrozen(true);
}
}

public static void thaw(int uid, int pid) {
RWUtils.writeFrozen(cgroupV2 + "/uid_" + uid + "/pid_" + pid + "/cgroup.freeze", 0);

public static void thaw(AppRecord appRecord) {
if (!appRecord.isFrozen() || appRecord.isSystem())
return;

for (ProcessRecord processRecord : appRecord.getProcessRecords()) {
if (processRecord.isDeathProcess() || !processRecord.isFrozen())
continue;

FrozenRW.thaw(processRecord.getRunningUid(), processRecord.getPid());
processRecord.setFrozen(false);
}
}
}
32 changes: 32 additions & 0 deletions app/src/main/java/nep/timeline/cirno/threads/FreezerHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package nep.timeline.cirno.threads;

import android.os.Handler;
import android.os.Message;

import nep.timeline.cirno.entity.AppRecord;

public class FreezerHandler {
public static final Handler handler = new FreezerMessageHandler(Handlers.makeLooper("Freezer"));

public static void removeAppMessage(AppRecord appRecord) {
if (handler.hasMessages(0, appRecord))
handler.removeMessages(0, appRecord);
}

public static void sendFreezeMessage(AppRecord appRecord, long delay) {
if (handler.hasMessages(0, appRecord))
return;

sendFreezeMessageIgnoreMessages(appRecord, delay);
}

public static void sendFreezeMessageIgnoreMessages(AppRecord appRecord, long delay) {
removeAppMessage(appRecord);

Message obtain = handler.obtainMessage(0, appRecord);
if (delay < 1)
handler.sendMessage(obtain);
else
handler.sendMessageDelayed(obtain, delay);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package nep.timeline.cirno.threads;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;

import nep.timeline.cirno.entity.AppRecord;
import nep.timeline.cirno.log.Log;
import nep.timeline.cirno.services.FreezerService;

public class FreezerMessageHandler extends Handler {
public FreezerMessageHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(@NonNull Message message) {
super.handleMessage(message);
try {
FreezerService.freezer((AppRecord) message.obj);
} catch (Throwable th) {
Log.e("Freezer", th);
}
}
}
13 changes: 13 additions & 0 deletions app/src/main/java/nep/timeline/cirno/utils/FrozenRW.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nep.timeline.cirno.utils;

public class FrozenRW {
public static final String cgroupV2 = "/sys/fs/cgroup/";

public static void frozen(int uid, int pid) {
RWUtils.writeFrozen(cgroupV2 + "/uid_" + uid + "/pid_" + pid + "/cgroup.freeze", 1);
}

public static void thaw(int uid, int pid) {
RWUtils.writeFrozen(cgroupV2 + "/uid_" + uid + "/pid_" + pid + "/cgroup.freeze", 0);
}
}

0 comments on commit 09dba49

Please sign in to comment.