summaryrefslogtreecommitdiffstats
path: root/services/core/java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2015-05-29 15:35:26 -0700
committerAmith Yamasani <yamasani@google.com>2015-06-02 11:05:03 -0700
commitaf575b9f8e1b59be9c8862b6a65c0dcb88145a23 (patch)
treec2bbc1b2a63b28a7de83b04d83010c56ee2771fc /services/core/java
parent242b9c4eee9d42d02fd2259ffe2124234653aaf2 (diff)
downloadframeworks_base-af575b9f8e1b59be9c8862b6a65c0dcb88145a23.zip
frameworks_base-af575b9f8e1b59be9c8862b6a65c0dcb88145a23.tar.gz
frameworks_base-af575b9f8e1b59be9c8862b6a65c0dcb88145a23.tar.bz2
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
Diffstat (limited to 'services/core/java')
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java201
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java46
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java19
3 files changed, 247 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 9b7b2d3..e9759c3 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -16,14 +16,19 @@
package com.android.server;
+import android.Manifest;
+import android.app.ActivityManagerNative;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
@@ -47,7 +52,9 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
import android.view.Display;
@@ -55,6 +62,7 @@ import android.view.Display;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.AtomicFile;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
@@ -72,6 +80,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
/**
* Keeps track of device idleness and drives low power mode based on that.
@@ -79,7 +88,8 @@ import java.nio.charset.StandardCharsets;
public class DeviceIdleController extends SystemService {
private static final String TAG = "DeviceIdleController";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG = false;
+ private static final boolean COMPRESS_TIME = false;
public static final String SERVICE_NAME = "deviceidle";
@@ -94,29 +104,31 @@ public class DeviceIdleController extends SystemService {
* immediately after going inactive just because we don't want to be continually running
* the significant motion sensor whenever the screen is off.
*/
- private static final long DEFAULT_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L
- : 2 * 60 * 1000L;
+ private static final long DEFAULT_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L
+ : 3 * 60 * 1000L;
/**
* This is the time, after seeing motion, that we wait after becoming inactive from
* that until we start looking for motion again.
*/
- private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !DEBUG ? 10*60*1000L
+ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L
: 60 * 1000L;
/**
* This is the time, after the inactive timeout elapses, that we will wait looking
* for significant motion until we truly consider the device to be idle.
*/
- private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L
- : 2 * 60 * 1000L;
+ private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L
+ : 3 * 60 * 1000L;
/**
* This is the initial time, after being idle, that we will allow ourself to be back
* in the IDLE_PENDING state allowing the system to run normally until we return to idle.
*/
- private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L;
+ private static final long DEFAULT_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 5*60*1000L
+ : 30 * 1000L;
/**
* Maximum pending idle timeout (time spent running) we will be allowed to use.
*/
- private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L;
+ private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L
+ : 60 * 1000L;
/**
* Scaling factor to apply to current pending idle timeout each time we cycle through
* that state.
@@ -126,13 +138,13 @@ public class DeviceIdleController extends SystemService {
* This is the initial time that we want to sit in the idle state before waking up
* again to return to pending idle and allowing normal work to run.
*/
- private static final long DEFAULT_IDLE_TIMEOUT = !DEBUG ? 60*60*1000L
- : 5 * 60 * 1000L;
+ private static final long DEFAULT_IDLE_TIMEOUT = !COMPRESS_TIME ? 60*60*1000L
+ : 6 * 60 * 1000L;
/**
* Maximum idle duration we will be allowed to use.
*/
- private static final long DEFAULT_MAX_IDLE_TIMEOUT = !DEBUG ? 6*60*60*1000L
- : 10 * 60 * 1000L;
+ private static final long DEFAULT_MAX_IDLE_TIMEOUT = !COMPRESS_TIME ? 6*60*60*1000L
+ : 30 * 60 * 1000L;
/**
* Scaling factor to apply to current idle timeout each time we cycle through that state.
*/
@@ -141,8 +153,13 @@ public class DeviceIdleController extends SystemService {
* This is the minimum time we will allow until the next upcoming alarm for us to
* actually go in to idle mode.
*/
- private static final long DEFAULT_MIN_TIME_TO_ALARM = !DEBUG ? 60*60*1000L
- : 5 * 60 * 1000L;
+ private static final long DEFAULT_MIN_TIME_TO_ALARM = !COMPRESS_TIME ? 60*60*1000L
+ : 6 * 60 * 1000L;
+
+ /**
+ * Max amount of time to temporarily whitelist an app when it receives a high priority tickle.
+ */
+ private static final long MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L;
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
@@ -210,6 +227,17 @@ public class DeviceIdleController extends SystemService {
*/
private int[] mPowerSaveWhitelistAppIdArray = new int[0];
+ /**
+ * List of end times for UIDs that are temporarily marked as being allowed to access
+ * the network and acquire wakelocks. Times are in milliseconds.
+ */
+ private SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray();
+
+ /**
+ * Current app IDs of temporarily whitelist apps for high-priority messages.
+ */
+ private int[] mTempWhitelistAppIdArray = new int[0];
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
@@ -252,6 +280,7 @@ public class DeviceIdleController extends SystemService {
static final int MSG_REPORT_IDLE_ON = 2;
static final int MSG_REPORT_IDLE_OFF = 3;
static final int MSG_REPORT_ACTIVE = 4;
+ static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -294,6 +323,10 @@ public class DeviceIdleController extends SystemService {
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
} break;
+ case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
+ int uid = msg.arg1;
+ checkTempAppWhitelistTimeout(uid);
+ } break;
}
}
}
@@ -325,10 +358,39 @@ public class DeviceIdleController extends SystemService {
return getAppIdWhitelistInternal();
}
+ @Override public int[] getAppIdTempWhitelist() {
+ return getAppIdTempWhitelistInternal();
+ }
+
@Override public boolean isPowerSaveWhitelistApp(String name) {
return isPowerSaveWhitelistAppInternal(name);
}
+ @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
+ int userId) throws RemoteException {
+ getContext().enforceCallingPermission(
+ Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ "No permission to change device idle whitelist");
+ userId = ActivityManagerNative.getDefault().handleIncomingUser(
+ Binder.getCallingPid(),
+ Binder.getCallingUid(),
+ userId,
+ /*allowAll=*/ false,
+ /*requireFull=*/ false,
+ "addAppBrieflyToWhitelist", null);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ PackageInfo pi = AppGlobals.getPackageManager()
+ .getPackageInfo(packageName, 0, userId);
+ if (pi == null) return;
+ DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(packageName,
+ duration, userId);
+ } catch (RemoteException re) {
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
DeviceIdleController.this.dump(fd, pw, args);
}
@@ -481,6 +543,70 @@ public class DeviceIdleController extends SystemService {
}
}
+ public int[] getAppIdTempWhitelistInternal() {
+ synchronized (this) {
+ return mTempWhitelistAppIdArray;
+ }
+ }
+
+ /**
+ * Adds an app to the temporary whitelist and resets the endTime for granting the
+ * app an exemption to access network and acquire wakelocks.
+ */
+ public void addPowerSaveTempWhitelistAppInternal(String packageName, long duration,
+ int userId) {
+ if (duration > MAX_TEMP_APP_WHITELIST_DURATION) {
+ duration = MAX_TEMP_APP_WHITELIST_DURATION;
+ }
+ try {
+ int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
+ int appId = UserHandle.getAppId(uid);
+ final long timeNow = System.currentTimeMillis();
+ synchronized (this) {
+ long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
+ // Set the new end time
+ mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration);
+ if (DEBUG) {
+ Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
+ }
+ if (currentEndTime == 0) {
+ // No pending timeout for the app id, post a delayed message
+ postTempActiveTimeoutMessage(appId, duration);
+ updateTempWhitelistAppIdsLocked();
+ reportTempWhitelistChangedLocked();
+ }
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+
+ private void postTempActiveTimeoutMessage(int uid, long delay) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
+ delay);
+ }
+
+ void checkTempAppWhitelistTimeout(int uid) {
+ final long timeNow = System.currentTimeMillis();
+ synchronized (this) {
+ long endTime = mTempWhitelistAppIdEndTimes.get(uid);
+ if (endTime == 0) {
+ // Nothing to do
+ return;
+ }
+ if (timeNow >= endTime) {
+ mTempWhitelistAppIdEndTimes.delete(uid);
+ if (DEBUG) {
+ Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
+ }
+ updateTempWhitelistAppIdsLocked();
+ reportTempWhitelistChangedLocked();
+ } else {
+ // Need more time
+ postTempActiveTimeoutMessage(uid, endTime - timeNow);
+ }
+ }
+ }
+
void updateDisplayLocked() {
mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
// We consider any situation where the display is showing something to be it on,
@@ -659,14 +785,41 @@ public class DeviceIdleController extends SystemService {
}
mPowerSaveWhitelistAppIdArray = appids;
if (mLocalPowerManager != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Setting wakelock whitelist to "
+ + Arrays.toString(mPowerSaveWhitelistAppIdArray));
+ }
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
}
}
+ private void updateTempWhitelistAppIdsLocked() {
+ final int size = mTempWhitelistAppIdEndTimes.size();
+ if (mTempWhitelistAppIdArray.length != size) {
+ mTempWhitelistAppIdArray = new int[size];
+ }
+ for (int i = 0; i < size; i++) {
+ mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
+ }
+ if (mLocalPowerManager != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Setting wakelock temp whitelist to "
+ + Arrays.toString(mTempWhitelistAppIdArray));
+ }
+ mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
+ }
+ }
+
private void reportPowerSaveWhitelistChangedLocked() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- getContext().sendBroadcast(intent);
+ getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
+ }
+
+ private void reportTempWhitelistChangedLocked() {
+ Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
}
void readConfigFileLocked() {
@@ -817,11 +970,18 @@ public class DeviceIdleController extends SystemService {
}
if (args != null) {
+ int userId = UserHandle.USER_OWNER;
for (int i=0; i<args.length; i++) {
String arg = args[i];
if ("-h".equals(arg)) {
dumpHelp(pw);
return;
+ } else if ("-u".equals(arg)) {
+ i++;
+ if (i < args.length) {
+ arg = args[i];
+ userId = Integer.parseInt(arg);
+ }
} else if ("-a".equals(arg)) {
// Ignore, we always dump all.
} else if ("step".equals(arg)) {
@@ -873,6 +1033,17 @@ public class DeviceIdleController extends SystemService {
}
}
return;
+ } else if ("tempwhitelist".equals(arg)) {
+ i++;
+ if (i >= args.length) {
+ pw.println("At least one package name must be specified");
+ return;
+ }
+ while (i < args.length) {
+ arg = args[i];
+ i++;
+ addPowerSaveTempWhitelistAppInternal(arg, 10000L, userId);
+ }
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
pw.println("Unknown option: " + arg);
return;
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
/**
* 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
}
}
+ 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
}
}
}
@@ -404,6 +421,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
updateNotificationsLocked();
}
}
@@ -428,6 +446,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
// 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 class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
}
}
+ 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
// 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 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
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
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c1fe984..3af97db 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -438,6 +438,9 @@ public final class PowerManagerService extends SystemService
// Set of app ids that we will always respect the wake locks for.
int[] mDeviceIdleWhitelist = new int[0];
+ // Set of app ids that are temporarily allowed to acquire wakelocks due to high-pri message
+ int[] mDeviceIdleTempWhitelist = new int[0];
+
private final SparseIntArray mUidState = new SparseIntArray();
// True if theater mode is enabled
@@ -2320,6 +2323,15 @@ public final class PowerManagerService extends SystemService
}
}
+ void setDeviceIdleTempWhitelistInternal(int[] appids) {
+ synchronized (mLock) {
+ mDeviceIdleTempWhitelist = appids;
+ if (mDeviceIdleMode) {
+ updateWakeLockDisabledStatesLocked();
+ }
+ }
+ }
+
void updateUidProcStateInternal(int uid, int procState) {
synchronized (mLock) {
mUidState.put(uid, procState);
@@ -2372,6 +2384,7 @@ public final class PowerManagerService extends SystemService
// for application uids that are not whitelisted.
if (appid >= Process.FIRST_APPLICATION_UID &&
Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
+ Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
mUidState.get(wakeLock.mOwnerUid,
ActivityManager.PROCESS_STATE_CACHED_EMPTY)
> ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -2579,6 +2592,7 @@ public final class PowerManagerService extends SystemService
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
pw.println(" mDeviceIdleMode=" + mDeviceIdleMode);
pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
+ pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
@@ -3478,6 +3492,11 @@ public final class PowerManagerService extends SystemService
}
@Override
+ public void setDeviceIdleTempWhitelist(int[] appids) {
+ setDeviceIdleTempWhitelistInternal(appids);
+ }
+
+ @Override
public void updateUidProcState(int uid, int procState) {
updateUidProcStateInternal(uid, procState);
}