diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl index cc2af215c2c62..827170144deab 100644 --- a/core/java/android/os/IDeviceIdleController.aidl +++ b/core/java/android/os/IDeviceIdleController.aidl @@ -23,6 +23,11 @@ import android.os.UserHandle; interface IDeviceIdleController { void addPowerSaveWhitelistApp(String name); void removePowerSaveWhitelistApp(String name); + /* Removes an app from the system whitelist. Calling restoreSystemPowerWhitelistApp will add + the app back into the system whitelist */ + void removeSystemPowerWhitelistApp(String name); + void restoreSystemPowerWhitelistApp(String name); + String[] getRemovedSystemPowerWhitelistApps(); String[] getSystemPowerWhitelistExceptIdle(); String[] getSystemPowerWhitelist(); String[] getUserPowerWhitelist(); diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index abbc89e45c993..3a6478ea85ea5 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -307,6 +307,12 @@ public class DeviceIdleController extends SystemService */ private int[] mTempWhitelistAppIdArray = new int[0]; + /** + * Apps in the system whitelist that have been taken out (probably because the user wanted to). + * They can be restored back by calling restoreAppToSystemWhitelist(String). + */ + private ArrayMap mRemovedFromSystemWhitelistApps = new ArrayMap<>(); + private static final int EVENT_NULL = 0; private static final int EVENT_NORMAL = 1; private static final int EVENT_LIGHT_IDLE = 2; @@ -1162,6 +1168,38 @@ public class DeviceIdleController extends SystemService } } + @Override public void removeSystemPowerWhitelistApp(String name) { + if (DEBUG) { + Slog.d(TAG, "removeAppFromSystemWhitelist(name = " + name + ")"); + } + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + long ident = Binder.clearCallingIdentity(); + try { + removeSystemPowerWhitelistAppInternal(name); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override public void restoreSystemPowerWhitelistApp(String name) { + if (DEBUG) { + Slog.d(TAG, "restoreAppToSystemWhitelist(name = " + name + ")"); + } + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + long ident = Binder.clearCallingIdentity(); + try { + restoreSystemPowerWhitelistAppInternal(name); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + public String[] getRemovedSystemPowerWhitelistApps() { + return getRemovedSystemPowerWhitelistAppsInternal(); + } + @Override public String[] getSystemPowerWhitelistExceptIdle() { return getSystemPowerWhitelistExceptIdleInternal(); } @@ -1504,6 +1542,42 @@ public class DeviceIdleController extends SystemService } } + void resetSystemPowerWhitelistInternal() { + synchronized (this) { + mPowerSaveWhitelistApps.putAll(mRemovedFromSystemWhitelistApps); + mRemovedFromSystemWhitelistApps.clear(); + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + } + } + + public boolean restoreSystemPowerWhitelistAppInternal(String name) { + synchronized (this) { + if (!mRemovedFromSystemWhitelistApps.containsKey(name)) { + return false; + } + mPowerSaveWhitelistApps.put(name, mRemovedFromSystemWhitelistApps.remove(name)); + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + return true; + } + } + + public boolean removeSystemPowerWhitelistAppInternal(String name) { + synchronized (this) { + if (!mPowerSaveWhitelistApps.containsKey(name)) { + return false; + } + mRemovedFromSystemWhitelistApps.put(name, mPowerSaveWhitelistApps.remove(name)); + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + return true; + } + } + public boolean addPowerSaveWhitelistExceptIdleInternal(String name) { synchronized (this) { try { @@ -1565,6 +1639,17 @@ public class DeviceIdleController extends SystemService } } + public String[] getRemovedSystemPowerWhitelistAppsInternal() { + synchronized (this) { + int size = mRemovedFromSystemWhitelistApps.size(); + final String[] apps = new String[size]; + for (int i = 0; i < size; i++) { + apps[i] = mRemovedFromSystemWhitelistApps.keyAt(i); + } + return apps; + } + } + public String[] getUserPowerWhitelistInternal() { synchronized (this) { int size = mPowerSaveWhitelistUserApps.size(); @@ -2481,21 +2566,31 @@ public class DeviceIdleController extends SystemService } String tagName = parser.getName(); - if (tagName.equals("wl")) { - String name = parser.getAttributeValue(null, "n"); - if (name != null) { - try { - ApplicationInfo ai = pm.getApplicationInfo(name, - PackageManager.MATCH_ANY_USER); - mPowerSaveWhitelistUserApps.put(ai.packageName, - UserHandle.getAppId(ai.uid)); - } catch (PackageManager.NameNotFoundException e) { + switch (tagName) { + case "wl": + String name = parser.getAttributeValue(null, "n"); + if (name != null) { + try { + ApplicationInfo ai = pm.getApplicationInfo(name, + PackageManager.MATCH_ANY_USER); + mPowerSaveWhitelistUserApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } catch (PackageManager.NameNotFoundException e) { + } } - } - } else { - Slog.w(TAG, "Unknown element under : " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); + break; + case "un-wl": + final String packageName = parser.getAttributeValue(null, "n"); + if (mPowerSaveWhitelistApps.containsKey(packageName)) { + mRemovedFromSystemWhitelistApps.put(packageName, + mPowerSaveWhitelistApps.remove(packageName)); + } + break; + default: + Slog.w(TAG, "Unknown element under : " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + break; } } @@ -2556,6 +2651,11 @@ public class DeviceIdleController extends SystemService out.attribute(null, "n", name); out.endTag(null, "wl"); } + for (int i = 0; i < mRemovedFromSystemWhitelistApps.size(); i++) { + out.startTag(null, "un-wl"); + out.attribute(null, "n", mRemovedFromSystemWhitelistApps.keyAt(i)); + out.endTag(null, "un-wl"); + } out.endTag(null, "config"); out.endDocument(); } @@ -2584,6 +2684,13 @@ public class DeviceIdleController extends SystemService pw.println(" Print currently whitelisted apps."); pw.println(" whitelist [package ...]"); pw.println(" Add (prefix with +) or remove (prefix with -) packages."); + pw.println(" sys-whitelist [package ...|reset]"); + pw.println(" Prefix the package with '-' to remove it from the system whitelist or '+'" + + " to put it back in the system whitelist."); + pw.println(" Note that only packages that were" + + " earlier removed from the system whitelist can be added back."); + pw.println(" reset will reset the whitelist to the original state"); + pw.println(" Prints the system whitelist if no arguments are specified"); pw.println(" except-idle-whitelist [package ...|reset]"); pw.println(" Prefix the package with '+' to add it to whitelist or " + "'=' to check if it is already whitelisted"); @@ -2944,6 +3051,50 @@ public class DeviceIdleController extends SystemService } finally { Binder.restoreCallingIdentity(token); } + } else if ("sys-whitelist".equals(cmd)) { + String arg = shell.getNextArg(); + if (arg != null) { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + final long token = Binder.clearCallingIdentity(); + try { + if ("reset".equals(arg)) { + resetSystemPowerWhitelistInternal(); + } else { + do { + if (arg.length() < 1 + || (arg.charAt(0) != '-' && arg.charAt(0) != '+')) { + pw.println("Package must be prefixed with + or - " + arg); + return -1; + } + final char op = arg.charAt(0); + final String pkg = arg.substring(1); + switch (op) { + case '+': + if (restoreSystemPowerWhitelistAppInternal(pkg)) { + pw.println("Restored " + pkg); + } + break; + case '-': + if (removeSystemPowerWhitelistAppInternal(pkg)) { + pw.println("Removed " + pkg); + } + break; + } + } while ((arg = shell.getNextArg()) != null); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } else { + synchronized (this) { + for (int j=0; j 0) { + pw.println(" Removed from whitelist system apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mRemovedFromSystemWhitelistApps.keyAt(i)); + } + } size = mPowerSaveWhitelistUserApps.size(); if (size > 0) { pw.println(" Whitelist user apps:");