diff --git a/app/src/main/java/nep/timeline/cirno/hooks/android/binder/HansKernelUnfreezeHook.java b/app/src/main/java/nep/timeline/cirno/hooks/android/binder/HansKernelUnfreezeHook.java index bfd3c0d..9bd69da 100644 --- a/app/src/main/java/nep/timeline/cirno/hooks/android/binder/HansKernelUnfreezeHook.java +++ b/app/src/main/java/nep/timeline/cirno/hooks/android/binder/HansKernelUnfreezeHook.java @@ -3,6 +3,7 @@ import de.robv.android.xposed.XC_MethodHook; import nep.timeline.cirno.framework.AbstractMethodHook; import nep.timeline.cirno.framework.MethodHook; +import nep.timeline.cirno.services.FreezerService; import nep.timeline.cirno.utils.SystemChecker; public class HansKernelUnfreezeHook extends MethodHook { @@ -34,6 +35,8 @@ protected void beforeMethod(MethodHookParam param) { if (type != 1) // Sync binder return; int target = (int) param.args[4]; + + FreezerService.temporaryUnfreezeIfNeed(target, "Binder", 3000); } }; } diff --git a/app/src/main/java/nep/timeline/cirno/hooks/android/binder/MilletBinderTransHook.java b/app/src/main/java/nep/timeline/cirno/hooks/android/binder/MilletBinderTransHook.java index 774878b..39ee31c 100644 --- a/app/src/main/java/nep/timeline/cirno/hooks/android/binder/MilletBinderTransHook.java +++ b/app/src/main/java/nep/timeline/cirno/hooks/android/binder/MilletBinderTransHook.java @@ -3,6 +3,7 @@ import de.robv.android.xposed.XC_MethodHook; import nep.timeline.cirno.framework.AbstractMethodHook; import nep.timeline.cirno.framework.MethodHook; +import nep.timeline.cirno.services.FreezerService; import nep.timeline.cirno.utils.SystemChecker; public class MilletBinderTransHook extends MethodHook { @@ -35,6 +36,8 @@ protected void beforeMethod(MethodHookParam param) { return; int dstUid = (int) param.args[0]; + + FreezerService.temporaryUnfreezeIfNeed(dstUid, "Binder", 3000); } }; } diff --git a/app/src/main/java/nep/timeline/cirno/hooks/android/binder/SamsungBinderTransHook.java b/app/src/main/java/nep/timeline/cirno/hooks/android/binder/SamsungBinderTransHook.java index 3d82f94..6e6e47f 100644 --- a/app/src/main/java/nep/timeline/cirno/hooks/android/binder/SamsungBinderTransHook.java +++ b/app/src/main/java/nep/timeline/cirno/hooks/android/binder/SamsungBinderTransHook.java @@ -5,6 +5,7 @@ import de.robv.android.xposed.XC_MethodHook; import nep.timeline.cirno.framework.AbstractMethodHook; import nep.timeline.cirno.framework.MethodHook; +import nep.timeline.cirno.services.FreezerService; import nep.timeline.cirno.utils.SystemChecker; public class SamsungBinderTransHook extends MethodHook { @@ -38,6 +39,8 @@ protected void beforeMethod(MethodHookParam param) { if (flags == 1) // Async binder return; int uid = (int) param.args[1]; + + FreezerService.temporaryUnfreezeIfNeed(uid, "Binder", 3000); } }; } diff --git a/app/src/main/java/nep/timeline/cirno/services/ActivityManagerService.java b/app/src/main/java/nep/timeline/cirno/services/ActivityManagerService.java index 30c7405..33ab7b7 100644 --- a/app/src/main/java/nep/timeline/cirno/services/ActivityManagerService.java +++ b/app/src/main/java/nep/timeline/cirno/services/ActivityManagerService.java @@ -29,4 +29,14 @@ public static ApplicationInfo getApplicationInfo(String packageName, int userId) } return null; } + + public static String[] getPackagesForUid(int uid) { + Context context = getContext(); + + if (context == null) + return null; + + PackageManager packageManager = context.getPackageManager(); + return packageManager.getPackagesForUid(uid); + } } diff --git a/app/src/main/java/nep/timeline/cirno/services/AppService.java b/app/src/main/java/nep/timeline/cirno/services/AppService.java index a17b87e..1378bae 100644 --- a/app/src/main/java/nep/timeline/cirno/services/AppService.java +++ b/app/src/main/java/nep/timeline/cirno/services/AppService.java @@ -1,14 +1,19 @@ package nep.timeline.cirno.services; import android.content.pm.ApplicationInfo; +import android.os.Process; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import nep.timeline.cirno.entity.AppRecord; +import nep.timeline.cirno.utils.PKGUtils; public class AppService { private static final Map> APP_RECORD_MAP = new ConcurrentHashMap<>(); + private static final Map> UID_RECORD_MAP = new ConcurrentHashMap<>(); public static AppRecord get(String packageName, int userId) { if (packageName == null || packageName.equals("android")) @@ -25,4 +30,40 @@ public static AppRecord get(String packageName, int userId) { return appRecords.put(packageName, new AppRecord(applicationInfo)); } + + public static List getByUid(int uid) { + try { + if (!UID_RECORD_MAP.containsKey(uid)) + putAppToCacheByUid(uid); + List records = UID_RECORD_MAP.get(uid); + if (records == null) + return new ArrayList<>(); + return records; + } catch (Throwable ignored) { + + } + return null; + } + + private static synchronized void putAppToCacheByUid(int uid) { + if (uid <= Process.SYSTEM_UID) { + UID_RECORD_MAP.put(uid, null); + return; + } + + String[] keys = ActivityManagerService.getPackagesForUid(uid); + if (keys == null || keys.length == 0) { + UID_RECORD_MAP.put(uid, null); + return; + } + + List appRecords = new ArrayList<>(); + for (String key : keys) { + String[] split = key.split(":"); + int userId = split.length == 1 ? PKGUtils.getUserId(uid) : Integer.parseInt(split[1].trim()); + appRecords.add(get(split[0], userId)); + } + + UID_RECORD_MAP.put(uid, appRecords); + } } diff --git a/app/src/main/java/nep/timeline/cirno/services/FreezerService.java b/app/src/main/java/nep/timeline/cirno/services/FreezerService.java index 3c2addc..55dc0d5 100644 --- a/app/src/main/java/nep/timeline/cirno/services/FreezerService.java +++ b/app/src/main/java/nep/timeline/cirno/services/FreezerService.java @@ -1,7 +1,10 @@ package nep.timeline.cirno.services; +import java.util.List; + import nep.timeline.cirno.entity.AppRecord; import nep.timeline.cirno.entity.ProcessRecord; +import nep.timeline.cirno.log.Log; import nep.timeline.cirno.threads.FreezerHandler; import nep.timeline.cirno.utils.FrozenRW; @@ -34,4 +37,33 @@ public static void thaw(AppRecord appRecord) { processRecord.setFrozen(false); } } + + public static void temporaryUnfreezeIfNeed(int uid, String reason, long interval) { + List appRecords = AppService.getByUid(uid); + + if (appRecords == null || appRecords.isEmpty()) + return; + + for (AppRecord appRecord : appRecords) { + if (appRecord == null) + continue; + + temporaryUnfreezeIfNeed(appRecord, reason, interval); + } + } + + public static void temporaryUnfreezeIfNeed(String packageName, int userId, String reason, long interval) { + temporaryUnfreezeIfNeed(AppService.get(packageName, userId), reason, interval); + } + + public static void temporaryUnfreezeIfNeed(AppRecord appRecord, String reason, long interval) { + if (appRecord == null || appRecord.isSystem()) + return; + + if (appRecord.isFrozen()) + Log.i(appRecord.getPackageNameWithUser() + " " + reason); + + thaw(appRecord); + FreezerHandler.sendFreezeMessageIgnoreMessages(appRecord, interval); + } }