Merge "Extend "headless system" app-standby exemption" into tm-dev

This commit is contained in:
Makoto Onuki
2022-03-10 17:38:22 +00:00
committed by Android (Google) Code Review
2 changed files with 82 additions and 14 deletions

View File

@@ -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;
@@ -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 {}
@@ -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")
@@ -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);
@@ -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);
}
}
}
@@ -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

View File

@@ -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;
@@ -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;
@@ -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.
@@ -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);