Loading apex/jobscheduler/framework/java/com/android/server/AppStateTracker.java +18 −8 Original line number Diff line number Diff line Loading @@ -25,19 +25,29 @@ public interface AppStateTracker { String TAG = "AppStateTracker"; /** * Register a {@link ServiceStateListener} to listen for forced-app-standby changes that should * affect services. * Register a {@link ForcedAppStandbyListener} to listen for forced-app-standby changes that * should affect services etc. */ void addServiceStateListener(@NonNull ServiceStateListener listener); void addForcedAppStandbyListener(@NonNull ForcedAppStandbyListener listener); /** * A listener to listen to forced-app-standby changes that should affect services. * @return {code true} if the given UID/package has been in forced app standby mode. */ interface ServiceStateListener { boolean isAppInForcedAppStandby(int uid, @NonNull String packageName); /** * A listener to listen to forced-app-standby changes that should affect services etc. */ interface ForcedAppStandbyListener { /** * Called when an app goes in/out of forced app standby. */ void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby); /** * Called when an app goes into forced app standby and its foreground * services need to be removed from that state. * Called when all apps' forced-app-standby states need to be re-evaluated, due to * enable/disable certain feature flags. */ void stopForegroundServicesForUidPackage(int uid, String packageName); void updateForcedAppStandbyForAllApps(); } } apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +85 −10 Original line number Diff line number Diff line Loading @@ -60,8 +60,10 @@ import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; /** * Class to keep track of the information related to "force app standby", which includes: Loading Loading @@ -160,16 +162,46 @@ public class AppStateTrackerImpl implements AppStateTracker { @GuardedBy("mLock") boolean mForcedAppStandbyEnabled; /** * A lock-free set of (uid, packageName) pairs in forced app standby mode. * * <p> * It's bascially shadowing the {@link #mRunAnyRestrictedPackages} together with * the {@link #mForcedAppStandbyEnabled} and the {@link #mForceAllAppsStandby} - mutations on * them would result in copy-on-write. * * Note: when {@link #mForcedAppStandbyEnabled} is {@code false}, it'll be set to an empty set. * when {@link #mForceAllAppsStandby} is {@code true}, it'll be set to null; * </p> */ volatile Set<Pair<Integer, String>> mForcedAppStandbyUidPackages = Collections.emptySet(); @Override public void addServiceStateListener(@NonNull ServiceStateListener listener) { public void addForcedAppStandbyListener(@NonNull ForcedAppStandbyListener listener) { addListener(new Listener() { @Override public void stopForegroundServicesForUidPackage(int uid, String packageName) { listener.stopForegroundServicesForUidPackage(uid, packageName); public void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby) { listener.updateForceAppStandbyForUidPackage(uid, packageName, standby); } @Override public void updateForcedAppStandbyForAllApps() { listener.updateForcedAppStandbyForAllApps(); } }); } @Override public boolean isAppInForcedAppStandby(int uid, @NonNull String packageName) { final Set<Pair<Integer, String>> fasUidPkgs = mForcedAppStandbyUidPackages; if (fasUidPkgs == null) { // Meaning the mForceAllAppsStandby is true. return true; } return fasUidPkgs.contains(Pair.create(uid, packageName)); } interface Stats { int UID_FG_STATE_CHANGED = 0; int UID_ACTIVE_STATE_CHANGED = 1; Loading Loading @@ -233,6 +265,7 @@ public class AppStateTrackerImpl implements AppStateTracker { return; } mForcedAppStandbyEnabled = enabled; updateForcedAppStandbyUidPackagesLocked(); if (DEBUG) { Slog.d(TAG, "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled); Loading Loading @@ -277,7 +310,11 @@ public class AppStateTrackerImpl implements AppStateTracker { if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) { Slog.v(TAG, "Package " + packageName + "/" + uid + " toggled into fg service restriction"); stopForegroundServicesForUidPackage(uid, packageName); updateForceAppStandbyForUidPackage(uid, packageName, true); } else { Slog.v(TAG, "Package " + packageName + "/" + uid + " toggled out of fg service restriction"); updateForceAppStandbyForUidPackage(uid, packageName, false); } } Loading Loading @@ -342,6 +379,7 @@ public class AppStateTrackerImpl implements AppStateTracker { private void onForceAllAppsStandbyChanged(AppStateTrackerImpl sender) { updateAllJobs(); updateAllAlarms(); updateForcedAppStandbyForAllApps(); } /** Loading @@ -366,10 +404,17 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** * Called when an app goes into forced app standby and its foreground * services need to be removed from that state. * Called when an app goes in/out of forced app standby. */ public void stopForegroundServicesForUidPackage(int uid, String packageName) { public void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby) { } /** * Called when all apps' forced-app-standby states need to be re-evaluated due to changes of * feature flags such as {@link #mForcedAppStandbyEnabled} or {@link #mForceAllAppsStandby}. */ public void updateForcedAppStandbyForAllApps() { } /** Loading Loading @@ -438,10 +483,13 @@ public class AppStateTrackerImpl implements AppStateTracker { final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); // No need to notify for state change as all the alarms and jobs should be // removed too. synchronized (mLock) { mExemptedBucketPackages.remove(userId, pkgName); mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName)); updateForcedAppStandbyUidPackagesLocked(); mActiveUids.delete(uid); } } break; } } Loading Loading @@ -580,6 +628,29 @@ public class AppStateTrackerImpl implements AppStateTracker { } } } updateForcedAppStandbyUidPackagesLocked(); } /** * Update the {@link #mForcedAppStandbyUidPackages} upon mutations on * {@link #mRunAnyRestrictedPackages}, {@link #mForcedAppStandbyEnabled} or * {@link #mForceAllAppsStandby}. */ @GuardedBy("mLock") private void updateForcedAppStandbyUidPackagesLocked() { if (!mForcedAppStandbyEnabled) { mForcedAppStandbyUidPackages = Collections.emptySet(); return; } if (mForceAllAppsStandby) { mForcedAppStandbyUidPackages = null; return; } Set<Pair<Integer, String>> fasUidPkgs = new ArraySet<>(); for (int i = 0, size = mRunAnyRestrictedPackages.size(); i < size; i++) { fasUidPkgs.add(mRunAnyRestrictedPackages.valueAt(i)); } mForcedAppStandbyUidPackages = Collections.unmodifiableSet(fasUidPkgs); } private void updateForceAllAppStandbyState() { Loading @@ -601,6 +672,7 @@ public class AppStateTrackerImpl implements AppStateTracker { return; } mForceAllAppsStandby = enable; updateForcedAppStandbyUidPackagesLocked(); mHandler.notifyForceAllAppsStandbyChanged(); } Loading Loading @@ -645,6 +717,7 @@ public class AppStateTrackerImpl implements AppStateTracker { } else { mRunAnyRestrictedPackages.removeAt(index); } updateForcedAppStandbyUidPackagesLocked(); return true; } Loading Loading @@ -896,6 +969,7 @@ public class AppStateTrackerImpl implements AppStateTracker { if (unblockAlarms) { l.unblockAllUnrestrictedAlarms(); } l.updateForcedAppStandbyForAllApps(); } mStatLogger.logDurationStat( Stats.FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED, start); Loading Loading @@ -966,6 +1040,7 @@ public class AppStateTrackerImpl implements AppStateTracker { mRunAnyRestrictedPackages.removeAt(i); } } updateForcedAppStandbyUidPackagesLocked(); cleanUpArrayForUser(mActiveUids, removedUserId); mExemptedBucketPackages.remove(removedUserId); } Loading core/java/android/app/ApplicationExitInfo.java +9 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,15 @@ public final class ApplicationExitInfo implements Parcelable { */ public static final int SUBREASON_ISOLATED_NOT_NEEDED = 17; /** * The process was killed because it's in forced-app-standby state, and it's cached and * its uid state is idle; this would be set only when the reason is {@link #REASON_OTHER}. * * For internal use only. * @hide */ public static final int SUBREASON_CACHED_IDLE_FORCED_APP_STANDBY = 18; // If there is any OEM code which involves additional app kill reasons, it should // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000. Loading core/proto/android/app/appexit_enums.proto +7 −2 Original line number Diff line number Diff line Loading @@ -213,10 +213,15 @@ enum AppExitSubReasonCode { * The process was killed because it's isolated and was in a cached state. */ SUBREASON_ISOLATED_NOT_NEEDED = 17; } /** * The relative importance level that the system places on a process. * The process was killed because it's in forced-app-standby state, and it's cached and * its uid state is idle; this would be set only when the reason is {@link #REASON_OTHER}. */ SUBREASON_CACHED_IDLE_FORCED_APP_STANDBY = 18; } /** * The relative importance level that the system places on a process. * Keep sync with the definitions in * {@link android.app.ActivityManager.RunningAppProcessInfo} */ Loading services/core/java/com/android/server/am/ActiveServices.java +16 −4 Original line number Diff line number Diff line Loading @@ -309,12 +309,24 @@ public final class ActiveServices { * Watch for apps being put into forced app standby, so we can step their fg * services down. */ class ForcedStandbyListener implements AppStateTracker.ServiceStateListener { class ForcedStandbyListener implements AppStateTracker.ForcedAppStandbyListener { @Override public void stopForegroundServicesForUidPackage(final int uid, final String packageName) { public void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby) { synchronized (mAm) { if (standby) { stopAllForegroundServicesLocked(uid, packageName); } mAm.mProcessList.updateForceAppStandbyForUidPackageLocked( uid, packageName, standby); } } @Override public void updateForcedAppStandbyForAllApps() { synchronized (mAm) { mAm.mProcessList.updateForcedAppStandbyForAllAppsLocked(); } } } Loading Loading @@ -499,7 +511,7 @@ public final class ActiveServices { void systemServicesReady() { AppStateTracker ast = LocalServices.getService(AppStateTracker.class); ast.addServiceStateListener(new ForcedStandbyListener()); ast.addForcedAppStandbyListener(new ForcedStandbyListener()); mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class); setAllowListWhileInUsePermissionInFgs(); } Loading Loading
apex/jobscheduler/framework/java/com/android/server/AppStateTracker.java +18 −8 Original line number Diff line number Diff line Loading @@ -25,19 +25,29 @@ public interface AppStateTracker { String TAG = "AppStateTracker"; /** * Register a {@link ServiceStateListener} to listen for forced-app-standby changes that should * affect services. * Register a {@link ForcedAppStandbyListener} to listen for forced-app-standby changes that * should affect services etc. */ void addServiceStateListener(@NonNull ServiceStateListener listener); void addForcedAppStandbyListener(@NonNull ForcedAppStandbyListener listener); /** * A listener to listen to forced-app-standby changes that should affect services. * @return {code true} if the given UID/package has been in forced app standby mode. */ interface ServiceStateListener { boolean isAppInForcedAppStandby(int uid, @NonNull String packageName); /** * A listener to listen to forced-app-standby changes that should affect services etc. */ interface ForcedAppStandbyListener { /** * Called when an app goes in/out of forced app standby. */ void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby); /** * Called when an app goes into forced app standby and its foreground * services need to be removed from that state. * Called when all apps' forced-app-standby states need to be re-evaluated, due to * enable/disable certain feature flags. */ void stopForegroundServicesForUidPackage(int uid, String packageName); void updateForcedAppStandbyForAllApps(); } }
apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +85 −10 Original line number Diff line number Diff line Loading @@ -60,8 +60,10 @@ import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; /** * Class to keep track of the information related to "force app standby", which includes: Loading Loading @@ -160,16 +162,46 @@ public class AppStateTrackerImpl implements AppStateTracker { @GuardedBy("mLock") boolean mForcedAppStandbyEnabled; /** * A lock-free set of (uid, packageName) pairs in forced app standby mode. * * <p> * It's bascially shadowing the {@link #mRunAnyRestrictedPackages} together with * the {@link #mForcedAppStandbyEnabled} and the {@link #mForceAllAppsStandby} - mutations on * them would result in copy-on-write. * * Note: when {@link #mForcedAppStandbyEnabled} is {@code false}, it'll be set to an empty set. * when {@link #mForceAllAppsStandby} is {@code true}, it'll be set to null; * </p> */ volatile Set<Pair<Integer, String>> mForcedAppStandbyUidPackages = Collections.emptySet(); @Override public void addServiceStateListener(@NonNull ServiceStateListener listener) { public void addForcedAppStandbyListener(@NonNull ForcedAppStandbyListener listener) { addListener(new Listener() { @Override public void stopForegroundServicesForUidPackage(int uid, String packageName) { listener.stopForegroundServicesForUidPackage(uid, packageName); public void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby) { listener.updateForceAppStandbyForUidPackage(uid, packageName, standby); } @Override public void updateForcedAppStandbyForAllApps() { listener.updateForcedAppStandbyForAllApps(); } }); } @Override public boolean isAppInForcedAppStandby(int uid, @NonNull String packageName) { final Set<Pair<Integer, String>> fasUidPkgs = mForcedAppStandbyUidPackages; if (fasUidPkgs == null) { // Meaning the mForceAllAppsStandby is true. return true; } return fasUidPkgs.contains(Pair.create(uid, packageName)); } interface Stats { int UID_FG_STATE_CHANGED = 0; int UID_ACTIVE_STATE_CHANGED = 1; Loading Loading @@ -233,6 +265,7 @@ public class AppStateTrackerImpl implements AppStateTracker { return; } mForcedAppStandbyEnabled = enabled; updateForcedAppStandbyUidPackagesLocked(); if (DEBUG) { Slog.d(TAG, "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled); Loading Loading @@ -277,7 +310,11 @@ public class AppStateTrackerImpl implements AppStateTracker { if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) { Slog.v(TAG, "Package " + packageName + "/" + uid + " toggled into fg service restriction"); stopForegroundServicesForUidPackage(uid, packageName); updateForceAppStandbyForUidPackage(uid, packageName, true); } else { Slog.v(TAG, "Package " + packageName + "/" + uid + " toggled out of fg service restriction"); updateForceAppStandbyForUidPackage(uid, packageName, false); } } Loading Loading @@ -342,6 +379,7 @@ public class AppStateTrackerImpl implements AppStateTracker { private void onForceAllAppsStandbyChanged(AppStateTrackerImpl sender) { updateAllJobs(); updateAllAlarms(); updateForcedAppStandbyForAllApps(); } /** Loading @@ -366,10 +404,17 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** * Called when an app goes into forced app standby and its foreground * services need to be removed from that state. * Called when an app goes in/out of forced app standby. */ public void stopForegroundServicesForUidPackage(int uid, String packageName) { public void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby) { } /** * Called when all apps' forced-app-standby states need to be re-evaluated due to changes of * feature flags such as {@link #mForcedAppStandbyEnabled} or {@link #mForceAllAppsStandby}. */ public void updateForcedAppStandbyForAllApps() { } /** Loading Loading @@ -438,10 +483,13 @@ public class AppStateTrackerImpl implements AppStateTracker { final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); // No need to notify for state change as all the alarms and jobs should be // removed too. synchronized (mLock) { mExemptedBucketPackages.remove(userId, pkgName); mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName)); updateForcedAppStandbyUidPackagesLocked(); mActiveUids.delete(uid); } } break; } } Loading Loading @@ -580,6 +628,29 @@ public class AppStateTrackerImpl implements AppStateTracker { } } } updateForcedAppStandbyUidPackagesLocked(); } /** * Update the {@link #mForcedAppStandbyUidPackages} upon mutations on * {@link #mRunAnyRestrictedPackages}, {@link #mForcedAppStandbyEnabled} or * {@link #mForceAllAppsStandby}. */ @GuardedBy("mLock") private void updateForcedAppStandbyUidPackagesLocked() { if (!mForcedAppStandbyEnabled) { mForcedAppStandbyUidPackages = Collections.emptySet(); return; } if (mForceAllAppsStandby) { mForcedAppStandbyUidPackages = null; return; } Set<Pair<Integer, String>> fasUidPkgs = new ArraySet<>(); for (int i = 0, size = mRunAnyRestrictedPackages.size(); i < size; i++) { fasUidPkgs.add(mRunAnyRestrictedPackages.valueAt(i)); } mForcedAppStandbyUidPackages = Collections.unmodifiableSet(fasUidPkgs); } private void updateForceAllAppStandbyState() { Loading @@ -601,6 +672,7 @@ public class AppStateTrackerImpl implements AppStateTracker { return; } mForceAllAppsStandby = enable; updateForcedAppStandbyUidPackagesLocked(); mHandler.notifyForceAllAppsStandbyChanged(); } Loading Loading @@ -645,6 +717,7 @@ public class AppStateTrackerImpl implements AppStateTracker { } else { mRunAnyRestrictedPackages.removeAt(index); } updateForcedAppStandbyUidPackagesLocked(); return true; } Loading Loading @@ -896,6 +969,7 @@ public class AppStateTrackerImpl implements AppStateTracker { if (unblockAlarms) { l.unblockAllUnrestrictedAlarms(); } l.updateForcedAppStandbyForAllApps(); } mStatLogger.logDurationStat( Stats.FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED, start); Loading Loading @@ -966,6 +1040,7 @@ public class AppStateTrackerImpl implements AppStateTracker { mRunAnyRestrictedPackages.removeAt(i); } } updateForcedAppStandbyUidPackagesLocked(); cleanUpArrayForUser(mActiveUids, removedUserId); mExemptedBucketPackages.remove(removedUserId); } Loading
core/java/android/app/ApplicationExitInfo.java +9 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,15 @@ public final class ApplicationExitInfo implements Parcelable { */ public static final int SUBREASON_ISOLATED_NOT_NEEDED = 17; /** * The process was killed because it's in forced-app-standby state, and it's cached and * its uid state is idle; this would be set only when the reason is {@link #REASON_OTHER}. * * For internal use only. * @hide */ public static final int SUBREASON_CACHED_IDLE_FORCED_APP_STANDBY = 18; // If there is any OEM code which involves additional app kill reasons, it should // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000. Loading
core/proto/android/app/appexit_enums.proto +7 −2 Original line number Diff line number Diff line Loading @@ -213,10 +213,15 @@ enum AppExitSubReasonCode { * The process was killed because it's isolated and was in a cached state. */ SUBREASON_ISOLATED_NOT_NEEDED = 17; } /** * The relative importance level that the system places on a process. * The process was killed because it's in forced-app-standby state, and it's cached and * its uid state is idle; this would be set only when the reason is {@link #REASON_OTHER}. */ SUBREASON_CACHED_IDLE_FORCED_APP_STANDBY = 18; } /** * The relative importance level that the system places on a process. * Keep sync with the definitions in * {@link android.app.ActivityManager.RunningAppProcessInfo} */ Loading
services/core/java/com/android/server/am/ActiveServices.java +16 −4 Original line number Diff line number Diff line Loading @@ -309,12 +309,24 @@ public final class ActiveServices { * Watch for apps being put into forced app standby, so we can step their fg * services down. */ class ForcedStandbyListener implements AppStateTracker.ServiceStateListener { class ForcedStandbyListener implements AppStateTracker.ForcedAppStandbyListener { @Override public void stopForegroundServicesForUidPackage(final int uid, final String packageName) { public void updateForceAppStandbyForUidPackage(int uid, String packageName, boolean standby) { synchronized (mAm) { if (standby) { stopAllForegroundServicesLocked(uid, packageName); } mAm.mProcessList.updateForceAppStandbyForUidPackageLocked( uid, packageName, standby); } } @Override public void updateForcedAppStandbyForAllApps() { synchronized (mAm) { mAm.mProcessList.updateForcedAppStandbyForAllAppsLocked(); } } } Loading Loading @@ -499,7 +511,7 @@ public final class ActiveServices { void systemServicesReady() { AppStateTracker ast = LocalServices.getService(AppStateTracker.class); ast.addServiceStateListener(new ForcedStandbyListener()); ast.addForcedAppStandbyListener(new ForcedStandbyListener()); mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class); setAllowListWhileInUsePermissionInFgs(); } Loading