Loading apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +52 −13 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import android.content.pm.CrossProfileAppsInternal; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.hardware.display.DisplayManager; import android.net.NetworkScoreManager; Loading Loading @@ -219,7 +220,8 @@ public class AppStandbyController private static final int HEADLESS_APP_CHECK_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS; | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_SYSTEM_ONLY; // To name the lock for stack traces static class Lock {} Loading Loading @@ -253,7 +255,7 @@ public class AppStandbyController private final SparseArray<Set<String>> mActiveAdminApps = new SparseArray<>(); /** * Set of system apps that are headless (don't have any declared activities, enabled or * Set of system apps that are headless (don't have any "front door" activities, enabled or * disabled). Presence in this map indicates that the app is a headless system app. */ @GuardedBy("mHeadlessSystemApps") Loading Loading @@ -1942,7 +1944,7 @@ public class AppStandbyController try { PackageInfo pi = mPackageManager.getPackageInfoAsUser( packageName, HEADLESS_APP_CHECK_FLAGS, userId); evaluateSystemAppException(pi); maybeUpdateHeadlessSystemAppCache(pi); } catch (PackageManager.NameNotFoundException e) { synchronized (mHeadlessSystemApps) { mHeadlessSystemApps.remove(packageName); Loading @@ -1950,19 +1952,31 @@ public class AppStandbyController } } /** Returns true if the exception status changed. */ private boolean evaluateSystemAppException(@Nullable PackageInfo pkgInfo) { /** * Update the "headless system app" cache. * * @return true if the cache is updated. */ private boolean maybeUpdateHeadlessSystemAppCache(@Nullable PackageInfo pkgInfo) { if (pkgInfo == null || pkgInfo.applicationInfo == null || (!pkgInfo.applicationInfo.isSystemApp() && !pkgInfo.applicationInfo.isUpdatedSystemApp())) { return false; } final Intent frontDoorActivityIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_LAUNCHER) .setPackage(pkgInfo.packageName); List<ResolveInfo> res = mPackageManager.queryIntentActivitiesAsUser(frontDoorActivityIntent, HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); return updateHeadlessSystemAppCache(pkgInfo.packageName, ArrayUtils.isEmpty(res)); } private boolean updateHeadlessSystemAppCache(String packageName, boolean add) { synchronized (mHeadlessSystemApps) { if (pkgInfo.activities == null || pkgInfo.activities.length == 0) { // Headless system app. return mHeadlessSystemApps.add(pkgInfo.packageName); if (add) { return mHeadlessSystemApps.add(packageName); } else { return mHeadlessSystemApps.remove(pkgInfo.packageName); return mHeadlessSystemApps.remove(packageName); } } } Loading Loading @@ -1999,20 +2013,45 @@ public class AppStandbyController } } /** Returns the packages that have launcher icons. */ private Set<String> getSystemPackagesWithLauncherActivities() { final Intent intent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> activities = mPackageManager.queryIntentActivitiesAsUser(intent, HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); final ArraySet<String> ret = new ArraySet<>(); for (ResolveInfo ri : activities) { ret.add(ri.activityInfo.packageName); } return ret; } /** Call on system boot to get the initial set of headless system apps. */ private void loadHeadlessSystemAppCache() { Slog.d(TAG, "Loading headless system app cache. appIdleEnabled=" + mAppIdleEnabled); final long start = SystemClock.uptimeMillis(); final List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); final Set<String> systemLauncherActivities = getSystemPackagesWithLauncherActivities(); final int packageCount = packages.size(); for (int i = 0; i < packageCount; i++) { PackageInfo pkgInfo = packages.get(i); if (pkgInfo != null && evaluateSystemAppException(pkgInfo)) { final PackageInfo pkgInfo = packages.get(i); if (pkgInfo == null) { continue; } final String pkg = pkgInfo.packageName; final boolean isHeadLess = !systemLauncherActivities.contains(pkg); if (updateHeadlessSystemAppCache(pkg, isHeadLess)) { mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, UserHandle.USER_SYSTEM, -1, pkgInfo.packageName) UserHandle.USER_SYSTEM, -1, pkg) .sendToTarget(); } } final long end = SystemClock.uptimeMillis(); Slog.d(TAG, "Loaded headless system app cache in " + (end - start) + " ms:" + " appIdleEnabled=" + mAppIdleEnabled); } @Override Loading services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +30 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,10 @@ import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.intThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; Loading @@ -76,11 +79,13 @@ import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Looper; Loading Loading @@ -118,6 +123,7 @@ import java.util.Random; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * Unit test for AppStandbyController. Loading Loading @@ -421,8 +427,31 @@ public class AppStandbyControllerTests { pib.packageName = PACKAGE_BACKGROUND_LOCATION; packages.add(pib); doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt()); // Set up getInstalledPackagesAsUser(). doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt()); // Set up getInstalledPackagesAsUser() for "MATCH_ONLY_SYSTEM" doReturn( packages.stream().filter(pinfo -> pinfo.applicationInfo.isSystemApp()) .collect(Collectors.toList()) ).when(mockPm).getInstalledPackagesAsUser( intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), anyInt()); // Set up queryIntentActivitiesAsUser() final ArrayList<ResolveInfo> systemFrontDoorActivities = new ArrayList<>(); final ResolveInfo frontDoorActivity = new ResolveInfo(); frontDoorActivity.activityInfo = new ActivityInfo(); frontDoorActivity.activityInfo.packageName = pis.packageName; systemFrontDoorActivities.add(frontDoorActivity); doReturn(systemFrontDoorActivities).when(mockPm) .queryIntentActivitiesAsUser(any(Intent.class), intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), anyInt()); // Set up other APIs. try { for (int i = 0; i < packages.size(); ++i) { PackageInfo pkg = packages.get(i); Loading Loading
apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +52 −13 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import android.content.pm.CrossProfileAppsInternal; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.hardware.display.DisplayManager; import android.net.NetworkScoreManager; Loading Loading @@ -219,7 +220,8 @@ public class AppStandbyController private static final int HEADLESS_APP_CHECK_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS; | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_SYSTEM_ONLY; // To name the lock for stack traces static class Lock {} Loading Loading @@ -253,7 +255,7 @@ public class AppStandbyController private final SparseArray<Set<String>> mActiveAdminApps = new SparseArray<>(); /** * Set of system apps that are headless (don't have any declared activities, enabled or * Set of system apps that are headless (don't have any "front door" activities, enabled or * disabled). Presence in this map indicates that the app is a headless system app. */ @GuardedBy("mHeadlessSystemApps") Loading Loading @@ -1942,7 +1944,7 @@ public class AppStandbyController try { PackageInfo pi = mPackageManager.getPackageInfoAsUser( packageName, HEADLESS_APP_CHECK_FLAGS, userId); evaluateSystemAppException(pi); maybeUpdateHeadlessSystemAppCache(pi); } catch (PackageManager.NameNotFoundException e) { synchronized (mHeadlessSystemApps) { mHeadlessSystemApps.remove(packageName); Loading @@ -1950,19 +1952,31 @@ public class AppStandbyController } } /** Returns true if the exception status changed. */ private boolean evaluateSystemAppException(@Nullable PackageInfo pkgInfo) { /** * Update the "headless system app" cache. * * @return true if the cache is updated. */ private boolean maybeUpdateHeadlessSystemAppCache(@Nullable PackageInfo pkgInfo) { if (pkgInfo == null || pkgInfo.applicationInfo == null || (!pkgInfo.applicationInfo.isSystemApp() && !pkgInfo.applicationInfo.isUpdatedSystemApp())) { return false; } final Intent frontDoorActivityIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_LAUNCHER) .setPackage(pkgInfo.packageName); List<ResolveInfo> res = mPackageManager.queryIntentActivitiesAsUser(frontDoorActivityIntent, HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); return updateHeadlessSystemAppCache(pkgInfo.packageName, ArrayUtils.isEmpty(res)); } private boolean updateHeadlessSystemAppCache(String packageName, boolean add) { synchronized (mHeadlessSystemApps) { if (pkgInfo.activities == null || pkgInfo.activities.length == 0) { // Headless system app. return mHeadlessSystemApps.add(pkgInfo.packageName); if (add) { return mHeadlessSystemApps.add(packageName); } else { return mHeadlessSystemApps.remove(pkgInfo.packageName); return mHeadlessSystemApps.remove(packageName); } } } Loading Loading @@ -1999,20 +2013,45 @@ public class AppStandbyController } } /** Returns the packages that have launcher icons. */ private Set<String> getSystemPackagesWithLauncherActivities() { final Intent intent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> activities = mPackageManager.queryIntentActivitiesAsUser(intent, HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); final ArraySet<String> ret = new ArraySet<>(); for (ResolveInfo ri : activities) { ret.add(ri.activityInfo.packageName); } return ret; } /** Call on system boot to get the initial set of headless system apps. */ private void loadHeadlessSystemAppCache() { Slog.d(TAG, "Loading headless system app cache. appIdleEnabled=" + mAppIdleEnabled); final long start = SystemClock.uptimeMillis(); final List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( HEADLESS_APP_CHECK_FLAGS, UserHandle.USER_SYSTEM); final Set<String> systemLauncherActivities = getSystemPackagesWithLauncherActivities(); final int packageCount = packages.size(); for (int i = 0; i < packageCount; i++) { PackageInfo pkgInfo = packages.get(i); if (pkgInfo != null && evaluateSystemAppException(pkgInfo)) { final PackageInfo pkgInfo = packages.get(i); if (pkgInfo == null) { continue; } final String pkg = pkgInfo.packageName; final boolean isHeadLess = !systemLauncherActivities.contains(pkg); if (updateHeadlessSystemAppCache(pkg, isHeadLess)) { mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, UserHandle.USER_SYSTEM, -1, pkgInfo.packageName) UserHandle.USER_SYSTEM, -1, pkg) .sendToTarget(); } } final long end = SystemClock.uptimeMillis(); Slog.d(TAG, "Loaded headless system app cache in " + (end - start) + " ms:" + " appIdleEnabled=" + mAppIdleEnabled); } @Override Loading
services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +30 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,10 @@ import static org.mockito.AdditionalMatchers.not; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.intThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; Loading @@ -76,11 +79,13 @@ import android.app.usage.UsageStatsManagerInternal; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.Looper; Loading Loading @@ -118,6 +123,7 @@ import java.util.Random; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * Unit test for AppStandbyController. Loading Loading @@ -421,8 +427,31 @@ public class AppStandbyControllerTests { pib.packageName = PACKAGE_BACKGROUND_LOCATION; packages.add(pib); doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt()); // Set up getInstalledPackagesAsUser(). doReturn(packages).when(mockPm).getInstalledPackagesAsUser(anyInt(), anyInt()); // Set up getInstalledPackagesAsUser() for "MATCH_ONLY_SYSTEM" doReturn( packages.stream().filter(pinfo -> pinfo.applicationInfo.isSystemApp()) .collect(Collectors.toList()) ).when(mockPm).getInstalledPackagesAsUser( intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), anyInt()); // Set up queryIntentActivitiesAsUser() final ArrayList<ResolveInfo> systemFrontDoorActivities = new ArrayList<>(); final ResolveInfo frontDoorActivity = new ResolveInfo(); frontDoorActivity.activityInfo = new ActivityInfo(); frontDoorActivity.activityInfo.packageName = pis.packageName; systemFrontDoorActivities.add(frontDoorActivity); doReturn(systemFrontDoorActivities).when(mockPm) .queryIntentActivitiesAsUser(any(Intent.class), intThat(i -> (i & PackageManager.MATCH_SYSTEM_ONLY) != 0), anyInt()); // Set up other APIs. try { for (int i = 0; i < packages.size(); ++i) { PackageInfo pkg = packages.get(i); Loading