Merge "Extend "headless system" app-standby exemption" into tm-dev
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user