Temporarily whitelist an app for network during doze
API to allow an app to be whitelisted for network and wakelock
access for a short period. So even if the device is in idle
mode, such apps can be given a chance to download the payload
related to a high priority cloud-to-device message.
This API is meant for system apps only.
A new permission CHANGE_DEVICE_IDLE_TEMP_WHITELIST is required
to make this call.
Bug: 21525864
Change-Id: Id7a761a664f21af5d7ff55aa56e8df98d15511ca
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 792d4ba..7673af4 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -283,9 +283,12 @@
/**
* UIDs that have been white-listed to always be able to have network access
* in power save mode.
+ * TODO: An int array might be sufficient
*/
private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
+ private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
+
/** Set of ifaces that are metered. */
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Set of over-limit templates that have been notified. */
@@ -371,6 +374,19 @@
}
}
+ void updatePowerSaveTempWhitelistLocked() {
+ try {
+ final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist();
+ mPowerSaveTempWhitelistAppIds.clear();
+ if (whitelist != null) {
+ for (int uid : whitelist) {
+ mPowerSaveTempWhitelistAppIds.put(uid, true);
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
public void systemReady() {
if (!isBandwidthControlEnabled()) {
Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
@@ -392,6 +408,7 @@
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
}
}
}
@@ -404,6 +421,7 @@
if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
updateNotificationsLocked();
}
}
@@ -428,6 +446,7 @@
// listen for changes to power save whitelist
final IntentFilter whitelistFilter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
+ whitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
// watch for network interfaces to be claimed
@@ -496,8 +515,13 @@
public void onReceive(Context context, Intent intent) {
// on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
synchronized (mRulesLock) {
- updatePowerSaveWhitelistLocked();
- updateRulesForGlobalChangeLocked(false);
+ if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(intent.getAction())) {
+ updatePowerSaveWhitelistLocked();
+ updateRulesForGlobalChangeLocked(false);
+ } else {
+ updatePowerSaveTempWhitelistLocked();
+ updateRulesForTempWhitelistChangeLocked();
+ }
}
}
};
@@ -2019,6 +2043,17 @@
}
}
+ void updateRulesForTempWhitelistChangeLocked() {
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (UserInfo user : users) {
+ for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
+ int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
+ int uid = UserHandle.getUid(user.id, appId);
+ updateRulesForUidLocked(uid);
+ }
+ }
+ }
+
private static boolean isUidValidForRules(int uid) {
// allow rules on specific system services, and any apps
if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
@@ -2065,8 +2100,10 @@
// derive active rules based on policy and active state
+ int appId = UserHandle.getAppId(uid);
int uidRules = RULE_ALLOW_ALL;
- if (uidIdle && !mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid))) {
+ if (uidIdle && !mPowerSaveWhitelistAppIds.get(appId)
+ && !mPowerSaveTempWhitelistAppIds.get(appId)) {
uidRules = RULE_REJECT_ALL;
} else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
// uid in background, and policy says to block metered data
@@ -2077,7 +2114,8 @@
uidRules = RULE_REJECT_METERED;
}
} else if (mRestrictPower || mDeviceIdleMode) {
- final boolean whitelisted = mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid));
+ final boolean whitelisted = mPowerSaveWhitelistAppIds.get(appId)
+ || mPowerSaveTempWhitelistAppIds.get(appId);
if (!whitelisted && !uidForeground
&& (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) {
// uid is in background, restrict power use mode is on (so we want to