diff options
author | Kweku Adams <kwekua@google.com> | 2020-06-16 10:11:56 -0700 |
---|---|---|
committer | Kweku Adams <kwekua@google.com> | 2020-06-16 20:15:49 +0000 |
commit | effeb2a6cce8b085535da3729545b2ce72d1a8c6 (patch) | |
tree | e8db88c47fbf8eb6c35e056bf82d33b27499c2f4 /apex/jobscheduler | |
parent | e0ba6d9dffc533e4c175d693e54f55290a8141de (diff) |
Cache power whitelisted apps.
DeviceIdleController sits higher in the lock hierarchy than
AppStandbyController, so ASC shouldn't call out to DIC with its lock
held. In order to know if an app is power whitelisted, ASC needs to call
out to DIC and cache the result outside of holding the lock.
Bug: 158779091
Test: atest CtsBatterySavingTestCases
Test: atest CtsJobSchedulerTestCases
Test: atest CtsUsageStatsTestCases:UsageStatsTest
Test: atest FrameworksServicesTests:AppIdleHistoryTests
Test: atest FrameworksServicesTests:AppStandbyControllerTests
Change-Id: Iff500f3ab00f6881348926604be7ab07693bdf40
Diffstat (limited to 'apex/jobscheduler')
-rw-r--r-- | apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java | 84 |
1 files changed, 67 insertions, 17 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index 062108757349..8b8003d8dbb8 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -82,10 +82,10 @@ import android.os.BatteryStats; import android.os.Build; import android.os.Environment; import android.os.Handler; +import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.PowerManager; -import android.os.PowerWhitelistManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -387,6 +387,7 @@ public class AppStandbyController implements AppStandbyInternal { DeviceStateReceiver deviceStateReceiver = new DeviceStateReceiver(); IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); + deviceStates.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); mContext.registerReceiver(deviceStateReceiver, deviceStates); synchronized (mAppIdleLock) { @@ -442,6 +443,9 @@ public class AppStandbyController implements AppStandbyInternal { mSystemServicesReady = true; + // Offload to handler thread to avoid boot time impact. + mHandler.post(mInjector::updatePowerWhitelistCache); + boolean userFileExists; synchronized (mAppIdleLock) { userFileExists = mAppIdleHistory.userFileExists(UserHandle.USER_SYSTEM); @@ -1080,15 +1084,11 @@ public class AppStandbyController implements AppStandbyInternal { return STANDBY_BUCKET_EXEMPTED; } if (mSystemServicesReady) { - try { - // We allow all whitelisted apps, including those that don't want to be whitelisted - // for idle mode, because app idle (aka app standby) is really not as big an issue - // for controlling who participates vs. doze mode. - if (mInjector.isNonIdleWhitelisted(packageName)) { - return STANDBY_BUCKET_EXEMPTED; - } - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); + // We allow all whitelisted apps, including those that don't want to be whitelisted + // for idle mode, because app idle (aka app standby) is really not as big an issue + // for controlling who participates vs. doze mode. + if (mInjector.isNonIdleWhitelisted(packageName)) { + return STANDBY_BUCKET_EXEMPTED; } if (isActiveDeviceAdmin(packageName, userId)) { @@ -1754,7 +1754,7 @@ public class AppStandbyController implements AppStandbyInternal { } } - /** Call on a system update to temporarily reset system app buckets. */ + /** 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 List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( @@ -1807,8 +1807,6 @@ public class AppStandbyController implements AppStandbyInternal { + "): " + mCarrierPrivilegedApps); } - final long now = System.currentTimeMillis(); - pw.println(); pw.println("Settings:"); @@ -1874,6 +1872,8 @@ public class AppStandbyController implements AppStandbyInternal { } pw.println("]"); pw.println(); + + mInjector.dump(pw); } /** @@ -1890,7 +1890,7 @@ public class AppStandbyController implements AppStandbyInternal { private PackageManagerInternal mPackageManagerInternal; private DisplayManager mDisplayManager; private PowerManager mPowerManager; - private PowerWhitelistManager mPowerWhitelistManager; + private IDeviceIdleController mDeviceIdleController; private CrossProfileAppsInternal mCrossProfileAppsInternal; int mBootPhase; /** @@ -1898,6 +1898,11 @@ public class AppStandbyController implements AppStandbyInternal { * automatically placed in the RESTRICTED bucket. */ long mAutoRestrictedBucketDelayMs = ONE_DAY; + /** + * Cached set of apps that are power whitelisted, including those not whitelisted from idle. + */ + @GuardedBy("mPowerWhitelistedApps") + private final ArraySet<String> mPowerWhitelistedApps = new ArraySet<>(); Injector(Context context, Looper looper) { mContext = context; @@ -1914,7 +1919,8 @@ public class AppStandbyController implements AppStandbyInternal { void onBootPhase(int phase) { if (phase == PHASE_SYSTEM_SERVICES_READY) { - mPowerWhitelistManager = mContext.getSystemService(PowerWhitelistManager.class); + mDeviceIdleController = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); @@ -1965,8 +1971,34 @@ public class AppStandbyController implements AppStandbyInternal { return mBatteryManager.isCharging(); } - boolean isNonIdleWhitelisted(String packageName) throws RemoteException { - return mPowerWhitelistManager.isWhitelisted(packageName, false); + boolean isNonIdleWhitelisted(String packageName) { + if (mBootPhase < PHASE_SYSTEM_SERVICES_READY) { + return false; + } + synchronized (mPowerWhitelistedApps) { + return mPowerWhitelistedApps.contains(packageName); + } + } + + private void updatePowerWhitelistCache() { + if (mBootPhase < PHASE_SYSTEM_SERVICES_READY) { + return; + } + try { + // Don't call out to DeviceIdleController with the lock held. + final String[] whitelistedPkgs = + mDeviceIdleController.getFullPowerWhitelistExceptIdle(); + synchronized (mPowerWhitelistedApps) { + mPowerWhitelistedApps.clear(); + final int len = whitelistedPkgs.length; + for (int i = 0; i < len; ++i) { + mPowerWhitelistedApps.add(whitelistedPkgs[i]); + } + } + } catch (RemoteException e) { + // Should not happen. + Slog.wtf(TAG, "Failed to get power whitelist", e); + } } boolean isRestrictedBucketEnabled() { @@ -2053,6 +2085,19 @@ public class AppStandbyController implements AppStandbyInternal { } return mCrossProfileAppsInternal.getTargetUserProfiles(pkg, userId); } + + void dump(PrintWriter pw) { + pw.println("mPowerWhitelistedApps=["); + synchronized (mPowerWhitelistedApps) { + for (int i = mPowerWhitelistedApps.size() - 1; i >= 0; --i) { + pw.print(" "); + pw.print(mPowerWhitelistedApps.valueAt(i)); + pw.println(","); + } + } + pw.println("]"); + pw.println(); + } } class AppStandbyHandler extends Handler { @@ -2138,6 +2183,11 @@ public class AppStandbyController implements AppStandbyInternal { case BatteryManager.ACTION_DISCHARGING: setChargingState(false); break; + case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED: + if (mSystemServicesReady) { + mHandler.post(mInjector::updatePowerWhitelistCache); + } + break; } } } |