From 081056475ea6f580fb0390d008c051f8f38175a7 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Tue, 26 Sep 2017 14:45:30 -0700 Subject: [PATCH] Added apis for changing the system whitelist We want the user to be able to remove apps that are added in the system whitelist. The user can restore them back later if they want. Test: cts-tradefed run cts-dev -m CtsDeviceIdleHostTestCases Bug: 63528174 Change-Id: Ia2f908c5fac84e28772d85b303be68b70efac8ba --- .../android/os/IDeviceIdleController.aidl | 5 + .../android/server/DeviceIdleController.java | 187 ++++++++++++++++-- 2 files changed, 178 insertions(+), 14 deletions(-) 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:");