Loading apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +87 −13 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.CrossProfileAppsInternal; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; Loading Loading @@ -283,6 +284,12 @@ public class AppStandbyController implements AppStandbyInternal { * start is the first usage of the app */ long mInitialForegroundServiceStartTimeoutMillis; /** * User usage that would elevate an app's standby bucket will also elevate the standby bucket of * cross profile connected apps. Explicit standby bucket setting via * {@link #setAppStandbyBucket(String, int, int, int, int)} will not be propagated. */ boolean mLinkCrossProfileApps; private volatile boolean mAppIdleEnabled; private boolean mIsCharging; Loading Loading @@ -445,10 +452,12 @@ public class AppStandbyController implements AppStandbyInternal { continue; } if (!packageName.equals(providerPkgName)) { final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); synchronized (mAppIdleLock) { reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_SYNC_ADAPTER, elapsedRealtime, mSyncAdapterTimeoutMillis); reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_SYNC_ADAPTER, elapsedRealtime, mSyncAdapterTimeoutMillis, linkedProfiles); } } } catch (PackageManager.NameNotFoundException e) { Loading Loading @@ -477,10 +486,10 @@ public class AppStandbyController implements AppStandbyInternal { } final long elapsedRealtime = mInjector.elapsedRealtime(); final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); synchronized (mAppIdleLock) { reportNoninteractiveUsageLocked(packageName, userId, bucketToPromote, usageReason, elapsedRealtime, durationMillis); reportNoninteractiveUsageCrossUserLocked(packageName, userId, bucketToPromote, usageReason, elapsedRealtime, durationMillis, linkedProfiles); } } Loading @@ -492,10 +501,11 @@ public class AppStandbyController implements AppStandbyInternal { final int currentBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime); if (currentBucket == STANDBY_BUCKET_NEVER) { final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); // Bring the app out of the never bucket reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_WORKING_SET, REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED, elapsedRealtime, mUnexemptedSyncScheduledTimeoutMillis); reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_WORKING_SET, REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED, elapsedRealtime, mUnexemptedSyncScheduledTimeoutMillis, linkedProfiles); } } } Loading @@ -504,14 +514,39 @@ public class AppStandbyController implements AppStandbyInternal { if (!mAppIdleEnabled) return; final long elapsedRealtime = mInjector.elapsedRealtime(); final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); synchronized (mAppIdleLock) { reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_EXEMPTED_SYNC_START, elapsedRealtime, mExemptedSyncStartTimeoutMillis); mExemptedSyncStartTimeoutMillis, linkedProfiles); } } /** * Helper method to report indirect user usage of an app and handle reporting the usage * against cross profile connected apps. <br> * Use {@link #reportNoninteractiveUsageLocked(String, int, int, int, long, long)} if * cross profile connected apps do not need to be handled. */ private void reportNoninteractiveUsageCrossUserLocked(String packageName, int userId, int bucket, int subReason, long elapsedRealtime, long nextCheckDelay, List<UserHandle> otherProfiles) { reportNoninteractiveUsageLocked(packageName, userId, bucket, subReason, elapsedRealtime, nextCheckDelay); final int size = otherProfiles.size(); for (int profileIndex = 0; profileIndex < size; profileIndex++) { final int otherUserId = otherProfiles.get(profileIndex).getIdentifier(); reportNoninteractiveUsageLocked(packageName, otherUserId, bucket, subReason, elapsedRealtime, nextCheckDelay); } } /** * Helper method to report indirect user usage of an app. <br> * Use * {@link #reportNoninteractiveUsageCrossUserLocked(String, int, int, int, long, long, List)} * if cross profile connected apps need to be handled. */ private void reportNoninteractiveUsageLocked(String packageName, int userId, int bucket, int subReason, long elapsedRealtime, long nextCheckDelay) { final AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId, bucket, Loading Loading @@ -766,8 +801,16 @@ public class AppStandbyController implements AppStandbyInternal { || eventType == UsageEvents.Event.SLICE_PINNED || eventType == UsageEvents.Event.SLICE_PINNED_PRIV || eventType == UsageEvents.Event.FOREGROUND_SERVICE_START)) { final String pkg = event.getPackageName(); final List<UserHandle> linkedProfiles = getCrossProfileTargets(pkg, userId); synchronized (mAppIdleLock) { reportEventLocked(event.getPackageName(), eventType, elapsedRealtime, userId); reportEventLocked(pkg, eventType, elapsedRealtime, userId); final int size = linkedProfiles.size(); for (int profileIndex = 0; profileIndex < size; profileIndex++) { final int linkedUserId = linkedProfiles.get(profileIndex).getIdentifier(); reportEventLocked(pkg, eventType, elapsedRealtime, linkedUserId); } } } } Loading Loading @@ -826,6 +869,16 @@ public class AppStandbyController implements AppStandbyInternal { } } /** * Note: don't call this with the lock held since it makes calls to other system services. */ private @NonNull List<UserHandle> getCrossProfileTargets(String pkg, int userId) { synchronized (mAppIdleLock) { if (!mLinkCrossProfileApps) return Collections.emptyList(); } return mInjector.getValidCrossProfileTargets(pkg, userId); } private int usageEventToSubReason(int eventType) { switch (eventType) { case UsageEvents.Event.ACTIVITY_RESUMED: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND; Loading Loading @@ -1589,6 +1642,7 @@ public class AppStandbyController implements AppStandbyInternal { private PackageManagerInternal mPackageManagerInternal; private DisplayManager mDisplayManager; private PowerManager mPowerManager; private CrossProfileAppsInternal mCrossProfileAppsInternal; int mBootPhase; /** * The minimum amount of time required since the last user interaction before an app can be Loading Loading @@ -1620,6 +1674,8 @@ public class AppStandbyController implements AppStandbyInternal { Context.DISPLAY_SERVICE); mPowerManager = mContext.getSystemService(PowerManager.class); mBatteryManager = mContext.getSystemService(BatteryManager.class); mCrossProfileAppsInternal = LocalServices.getService( CrossProfileAppsInternal.class); final ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); Loading Loading @@ -1727,6 +1783,17 @@ public class AppStandbyController implements AppStandbyInternal { public boolean isDeviceIdleMode() { return mPowerManager.isDeviceIdleMode(); } public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) { final int uid = mPackageManagerInternal.getPackageUidInternal(pkg, 0, userId); if (uid < 0 || !mPackageManagerInternal.getPackage(uid).isCrossProfile() || !mCrossProfileAppsInternal .verifyUidHasInteractAcrossProfilePermission(pkg, uid)) { return Collections.emptyList(); } return mCrossProfileAppsInternal.getTargetUserProfiles(pkg, userId); } } class AppStandbyHandler extends Handler { Loading Loading @@ -1857,6 +1924,8 @@ public class AppStandbyController implements AppStandbyInternal { "initial_foreground_service_start_duration"; private static final String KEY_AUTO_RESTRICTED_BUCKET_DELAY_MS = "auto_restricted_bucket_delay_ms"; private static final String KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = "cross_profile_apps_share_standby_buckets"; public static final long DEFAULT_STRONG_USAGE_TIMEOUT = 1 * ONE_HOUR; public static final long DEFAULT_NOTIFICATION_TIMEOUT = 12 * ONE_HOUR; public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR; Loading @@ -1868,6 +1937,7 @@ public class AppStandbyController implements AppStandbyInternal { public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE; public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT = 30 * ONE_MINUTE; public static final long DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS = ONE_DAY; public static final boolean DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = true; private final KeyValueListParser mParser = new KeyValueListParser(','); Loading Loading @@ -1973,6 +2043,10 @@ public class AppStandbyController implements AppStandbyInternal { mParser.getDurationMillis(KEY_AUTO_RESTRICTED_BUCKET_DELAY_MS, COMPRESS_TIME ? ONE_MINUTE : DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS)); mLinkCrossProfileApps = mParser.getBoolean( KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS, DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS); } // Check if app_idle_enabled has changed. Do this after getting the rest of the settings Loading core/java/android/provider/Settings.java +1 −0 Original line number Diff line number Diff line Loading @@ -11509,6 +11509,7 @@ public final class Settings { * exempted_sync_duration (long) * system_interaction_duration (long) * initial_foreground_service_start_duration (long) * cross_profile_apps_share_standby_buckets (boolean) * </pre> * * <p> Loading services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +47 −4 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.ArraySet; import android.view.Display; Loading @@ -83,6 +84,7 @@ import org.junit.runner.RunWith; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; Loading @@ -101,6 +103,8 @@ public class AppStandbyControllerTests { private static final int UID_EXEMPTED_1 = 10001; private static final int USER_ID = 0; private static final int USER_ID2 = 10; private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2); private static final int USER_ID3 = 11; private static final String PACKAGE_UNKNOWN = "com.example.unknown"; Loading Loading @@ -150,6 +154,8 @@ public class AppStandbyControllerTests { boolean mDisplayOn; DisplayManager.DisplayListener mDisplayListener; String mBoundWidgetPackage = PACKAGE_EXEMPTED_1; int[] mRunningUsers = new int[] {USER_ID}; List<UserHandle> mCrossProfileTargets = Collections.emptyList(); MyInjector(Context context, Looper looper) { super(context, looper); Loading Loading @@ -212,7 +218,7 @@ public class AppStandbyControllerTests { @Override int[] getRunningUserIds() { return new int[] {USER_ID}; return mRunningUsers; } @Override Loading Loading @@ -248,6 +254,11 @@ public class AppStandbyControllerTests { return false; } @Override public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) { return mCrossProfileTargets; } // Internal methods void setDisplayOn(boolean on) { Loading Loading @@ -379,10 +390,15 @@ public class AppStandbyControllerTests { } private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) { assertTimeout(controller, elapsedTime, bucket, USER_ID); } private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket, int userId) { mInjector.mElapsedRealtime = elapsedTime; controller.checkIdleStates(USER_ID); controller.checkIdleStates(userId); assertEquals(bucket, controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime, controller.getAppStandbyBucket(PACKAGE_1, userId, mInjector.mElapsedRealtime, false)); } Loading @@ -397,7 +413,11 @@ public class AppStandbyControllerTests { } private int getStandbyBucket(AppStandbyController controller, String packageName) { return controller.getAppStandbyBucket(packageName, USER_ID, mInjector.mElapsedRealtime, return getStandbyBucket(USER_ID, controller, packageName); } private int getStandbyBucket(int userId, AppStandbyController controller, String packageName) { return controller.getAppStandbyBucket(packageName, userId, mInjector.mElapsedRealtime, true); } Loading Loading @@ -1012,6 +1032,29 @@ public class AppStandbyControllerTests { assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID); } @Test public void testUserInteraction_CrossProfile() throws Exception { mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3}; mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2); reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); assertEquals("Cross profile connected package bucket should be elevated on usage", STANDBY_BUCKET_ACTIVE, getStandbyBucket(USER_ID2, mController, PACKAGE_1)); assertEquals("Not Cross profile connected package bucket should not be elevated on usage", STANDBY_BUCKET_NEVER, getStandbyBucket(USER_ID3, mController, PACKAGE_1)); assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID); assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID2); assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID); assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID2); mInjector.mCrossProfileTargets = Collections.emptyList(); reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); assertEquals("No longer cross profile connected package bucket should not be " + "elevated on usage", STANDBY_BUCKET_WORKING_SET, getStandbyBucket(USER_ID2, mController, PACKAGE_1)); } private String getAdminAppsStr(int userId) { return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId)); } Loading Loading
apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +87 −13 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.CrossProfileAppsInternal; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; Loading Loading @@ -283,6 +284,12 @@ public class AppStandbyController implements AppStandbyInternal { * start is the first usage of the app */ long mInitialForegroundServiceStartTimeoutMillis; /** * User usage that would elevate an app's standby bucket will also elevate the standby bucket of * cross profile connected apps. Explicit standby bucket setting via * {@link #setAppStandbyBucket(String, int, int, int, int)} will not be propagated. */ boolean mLinkCrossProfileApps; private volatile boolean mAppIdleEnabled; private boolean mIsCharging; Loading Loading @@ -445,10 +452,12 @@ public class AppStandbyController implements AppStandbyInternal { continue; } if (!packageName.equals(providerPkgName)) { final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); synchronized (mAppIdleLock) { reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_SYNC_ADAPTER, elapsedRealtime, mSyncAdapterTimeoutMillis); reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_SYNC_ADAPTER, elapsedRealtime, mSyncAdapterTimeoutMillis, linkedProfiles); } } } catch (PackageManager.NameNotFoundException e) { Loading Loading @@ -477,10 +486,10 @@ public class AppStandbyController implements AppStandbyInternal { } final long elapsedRealtime = mInjector.elapsedRealtime(); final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); synchronized (mAppIdleLock) { reportNoninteractiveUsageLocked(packageName, userId, bucketToPromote, usageReason, elapsedRealtime, durationMillis); reportNoninteractiveUsageCrossUserLocked(packageName, userId, bucketToPromote, usageReason, elapsedRealtime, durationMillis, linkedProfiles); } } Loading @@ -492,10 +501,11 @@ public class AppStandbyController implements AppStandbyInternal { final int currentBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime); if (currentBucket == STANDBY_BUCKET_NEVER) { final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); // Bring the app out of the never bucket reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_WORKING_SET, REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED, elapsedRealtime, mUnexemptedSyncScheduledTimeoutMillis); reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_WORKING_SET, REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED, elapsedRealtime, mUnexemptedSyncScheduledTimeoutMillis, linkedProfiles); } } } Loading @@ -504,14 +514,39 @@ public class AppStandbyController implements AppStandbyInternal { if (!mAppIdleEnabled) return; final long elapsedRealtime = mInjector.elapsedRealtime(); final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId); synchronized (mAppIdleLock) { reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_EXEMPTED_SYNC_START, elapsedRealtime, mExemptedSyncStartTimeoutMillis); mExemptedSyncStartTimeoutMillis, linkedProfiles); } } /** * Helper method to report indirect user usage of an app and handle reporting the usage * against cross profile connected apps. <br> * Use {@link #reportNoninteractiveUsageLocked(String, int, int, int, long, long)} if * cross profile connected apps do not need to be handled. */ private void reportNoninteractiveUsageCrossUserLocked(String packageName, int userId, int bucket, int subReason, long elapsedRealtime, long nextCheckDelay, List<UserHandle> otherProfiles) { reportNoninteractiveUsageLocked(packageName, userId, bucket, subReason, elapsedRealtime, nextCheckDelay); final int size = otherProfiles.size(); for (int profileIndex = 0; profileIndex < size; profileIndex++) { final int otherUserId = otherProfiles.get(profileIndex).getIdentifier(); reportNoninteractiveUsageLocked(packageName, otherUserId, bucket, subReason, elapsedRealtime, nextCheckDelay); } } /** * Helper method to report indirect user usage of an app. <br> * Use * {@link #reportNoninteractiveUsageCrossUserLocked(String, int, int, int, long, long, List)} * if cross profile connected apps need to be handled. */ private void reportNoninteractiveUsageLocked(String packageName, int userId, int bucket, int subReason, long elapsedRealtime, long nextCheckDelay) { final AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId, bucket, Loading Loading @@ -766,8 +801,16 @@ public class AppStandbyController implements AppStandbyInternal { || eventType == UsageEvents.Event.SLICE_PINNED || eventType == UsageEvents.Event.SLICE_PINNED_PRIV || eventType == UsageEvents.Event.FOREGROUND_SERVICE_START)) { final String pkg = event.getPackageName(); final List<UserHandle> linkedProfiles = getCrossProfileTargets(pkg, userId); synchronized (mAppIdleLock) { reportEventLocked(event.getPackageName(), eventType, elapsedRealtime, userId); reportEventLocked(pkg, eventType, elapsedRealtime, userId); final int size = linkedProfiles.size(); for (int profileIndex = 0; profileIndex < size; profileIndex++) { final int linkedUserId = linkedProfiles.get(profileIndex).getIdentifier(); reportEventLocked(pkg, eventType, elapsedRealtime, linkedUserId); } } } } Loading Loading @@ -826,6 +869,16 @@ public class AppStandbyController implements AppStandbyInternal { } } /** * Note: don't call this with the lock held since it makes calls to other system services. */ private @NonNull List<UserHandle> getCrossProfileTargets(String pkg, int userId) { synchronized (mAppIdleLock) { if (!mLinkCrossProfileApps) return Collections.emptyList(); } return mInjector.getValidCrossProfileTargets(pkg, userId); } private int usageEventToSubReason(int eventType) { switch (eventType) { case UsageEvents.Event.ACTIVITY_RESUMED: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND; Loading Loading @@ -1589,6 +1642,7 @@ public class AppStandbyController implements AppStandbyInternal { private PackageManagerInternal mPackageManagerInternal; private DisplayManager mDisplayManager; private PowerManager mPowerManager; private CrossProfileAppsInternal mCrossProfileAppsInternal; int mBootPhase; /** * The minimum amount of time required since the last user interaction before an app can be Loading Loading @@ -1620,6 +1674,8 @@ public class AppStandbyController implements AppStandbyInternal { Context.DISPLAY_SERVICE); mPowerManager = mContext.getSystemService(PowerManager.class); mBatteryManager = mContext.getSystemService(BatteryManager.class); mCrossProfileAppsInternal = LocalServices.getService( CrossProfileAppsInternal.class); final ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); Loading Loading @@ -1727,6 +1783,17 @@ public class AppStandbyController implements AppStandbyInternal { public boolean isDeviceIdleMode() { return mPowerManager.isDeviceIdleMode(); } public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) { final int uid = mPackageManagerInternal.getPackageUidInternal(pkg, 0, userId); if (uid < 0 || !mPackageManagerInternal.getPackage(uid).isCrossProfile() || !mCrossProfileAppsInternal .verifyUidHasInteractAcrossProfilePermission(pkg, uid)) { return Collections.emptyList(); } return mCrossProfileAppsInternal.getTargetUserProfiles(pkg, userId); } } class AppStandbyHandler extends Handler { Loading Loading @@ -1857,6 +1924,8 @@ public class AppStandbyController implements AppStandbyInternal { "initial_foreground_service_start_duration"; private static final String KEY_AUTO_RESTRICTED_BUCKET_DELAY_MS = "auto_restricted_bucket_delay_ms"; private static final String KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = "cross_profile_apps_share_standby_buckets"; public static final long DEFAULT_STRONG_USAGE_TIMEOUT = 1 * ONE_HOUR; public static final long DEFAULT_NOTIFICATION_TIMEOUT = 12 * ONE_HOUR; public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR; Loading @@ -1868,6 +1937,7 @@ public class AppStandbyController implements AppStandbyInternal { public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE; public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT = 30 * ONE_MINUTE; public static final long DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS = ONE_DAY; public static final boolean DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = true; private final KeyValueListParser mParser = new KeyValueListParser(','); Loading Loading @@ -1973,6 +2043,10 @@ public class AppStandbyController implements AppStandbyInternal { mParser.getDurationMillis(KEY_AUTO_RESTRICTED_BUCKET_DELAY_MS, COMPRESS_TIME ? ONE_MINUTE : DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS)); mLinkCrossProfileApps = mParser.getBoolean( KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS, DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS); } // Check if app_idle_enabled has changed. Do this after getting the rest of the settings Loading
core/java/android/provider/Settings.java +1 −0 Original line number Diff line number Diff line Loading @@ -11509,6 +11509,7 @@ public final class Settings { * exempted_sync_duration (long) * system_interaction_duration (long) * initial_foreground_service_start_duration (long) * cross_profile_apps_share_standby_buckets (boolean) * </pre> * * <p> Loading
services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +47 −4 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.ArraySet; import android.view.Display; Loading @@ -83,6 +84,7 @@ import org.junit.runner.RunWith; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; Loading @@ -101,6 +103,8 @@ public class AppStandbyControllerTests { private static final int UID_EXEMPTED_1 = 10001; private static final int USER_ID = 0; private static final int USER_ID2 = 10; private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2); private static final int USER_ID3 = 11; private static final String PACKAGE_UNKNOWN = "com.example.unknown"; Loading Loading @@ -150,6 +154,8 @@ public class AppStandbyControllerTests { boolean mDisplayOn; DisplayManager.DisplayListener mDisplayListener; String mBoundWidgetPackage = PACKAGE_EXEMPTED_1; int[] mRunningUsers = new int[] {USER_ID}; List<UserHandle> mCrossProfileTargets = Collections.emptyList(); MyInjector(Context context, Looper looper) { super(context, looper); Loading Loading @@ -212,7 +218,7 @@ public class AppStandbyControllerTests { @Override int[] getRunningUserIds() { return new int[] {USER_ID}; return mRunningUsers; } @Override Loading Loading @@ -248,6 +254,11 @@ public class AppStandbyControllerTests { return false; } @Override public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) { return mCrossProfileTargets; } // Internal methods void setDisplayOn(boolean on) { Loading Loading @@ -379,10 +390,15 @@ public class AppStandbyControllerTests { } private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) { assertTimeout(controller, elapsedTime, bucket, USER_ID); } private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket, int userId) { mInjector.mElapsedRealtime = elapsedTime; controller.checkIdleStates(USER_ID); controller.checkIdleStates(userId); assertEquals(bucket, controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime, controller.getAppStandbyBucket(PACKAGE_1, userId, mInjector.mElapsedRealtime, false)); } Loading @@ -397,7 +413,11 @@ public class AppStandbyControllerTests { } private int getStandbyBucket(AppStandbyController controller, String packageName) { return controller.getAppStandbyBucket(packageName, USER_ID, mInjector.mElapsedRealtime, return getStandbyBucket(USER_ID, controller, packageName); } private int getStandbyBucket(int userId, AppStandbyController controller, String packageName) { return controller.getAppStandbyBucket(packageName, userId, mInjector.mElapsedRealtime, true); } Loading Loading @@ -1012,6 +1032,29 @@ public class AppStandbyControllerTests { assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID); } @Test public void testUserInteraction_CrossProfile() throws Exception { mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3}; mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2); reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); assertEquals("Cross profile connected package bucket should be elevated on usage", STANDBY_BUCKET_ACTIVE, getStandbyBucket(USER_ID2, mController, PACKAGE_1)); assertEquals("Not Cross profile connected package bucket should not be elevated on usage", STANDBY_BUCKET_NEVER, getStandbyBucket(USER_ID3, mController, PACKAGE_1)); assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID); assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID2); assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID); assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID2); mInjector.mCrossProfileTargets = Collections.emptyList(); reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); assertEquals("No longer cross profile connected package bucket should not be " + "elevated on usage", STANDBY_BUCKET_WORKING_SET, getStandbyBucket(USER_ID2, mController, PACKAGE_1)); } private String getAdminAppsStr(int userId) { return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId)); } Loading