Merge "Fix issue #22989030: Separate battery whitelists" into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f0e5501e09
@ -76,6 +76,13 @@ public abstract class UsageStatsManagerInternal {
|
||||
*/
|
||||
public abstract boolean isAppIdle(String packageName, int userId);
|
||||
|
||||
/**
|
||||
* Returns all of the uids for a given user where all packages associating with that uid
|
||||
* are in the app idle state -- there are no associated apps that are not idle. This means
|
||||
* all of the returned uids can be safely considered app idle.
|
||||
*/
|
||||
public abstract int[] getIdleUidsForUser(int userId);
|
||||
|
||||
/**
|
||||
* @return True if currently app idle parole mode is on. This means all idle apps are allow to
|
||||
* run for a short period of time.
|
||||
|
@ -22,10 +22,14 @@ import android.os.UserHandle;
|
||||
interface IDeviceIdleController {
|
||||
void addPowerSaveWhitelistApp(String name);
|
||||
void removePowerSaveWhitelistApp(String name);
|
||||
String[] getSystemPowerWhitelistExceptIdle();
|
||||
String[] getSystemPowerWhitelist();
|
||||
String[] getFullPowerWhitelistExceptIdle();
|
||||
String[] getFullPowerWhitelist();
|
||||
int[] getAppIdWhitelistExceptIdle();
|
||||
int[] getAppIdWhitelist();
|
||||
int[] getAppIdTempWhitelist();
|
||||
boolean isPowerSaveWhitelistExceptIdleApp(String name);
|
||||
boolean isPowerSaveWhitelistApp(String name);
|
||||
void addPowerSaveTempWhitelistApp(String name, long duration, int userId, String reason);
|
||||
long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
|
||||
|
@ -183,6 +183,14 @@ public class SparseIntArray implements Cloneable {
|
||||
return mValues[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Directly set the value at a particular index.
|
||||
* @hide
|
||||
*/
|
||||
public void setValueAt(int index, int value) {
|
||||
mValues[index] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index for which {@link #keyAt} would return the
|
||||
* specified key, or a negative number if the specified
|
||||
|
@ -141,6 +141,6 @@
|
||||
|
||||
<!-- These are the standard packages that are white-listed to always have internet
|
||||
access while in power save mode, even if they aren't in the foreground. -->
|
||||
<allow-in-power-save package="com.android.providers.downloads" />
|
||||
<allow-in-power-save-except-idle package="com.android.providers.downloads" />
|
||||
|
||||
</permissions>
|
||||
|
@ -113,6 +113,7 @@ public class DeviceIdleController extends SystemService
|
||||
private Display mCurDisplay;
|
||||
private AnyMotionDetector mAnyMotionDetector;
|
||||
private boolean mEnabled;
|
||||
private boolean mForceIdle;
|
||||
private boolean mScreenOn;
|
||||
private boolean mCharging;
|
||||
private boolean mSigMotionActive;
|
||||
@ -151,7 +152,14 @@ public class DeviceIdleController extends SystemService
|
||||
public final AtomicFile mConfigFile;
|
||||
|
||||
/**
|
||||
* Package names the system has white-listed to opt out of power save restrictions.
|
||||
* Package names the system has white-listed to opt out of power save restrictions,
|
||||
* except for device idle mode.
|
||||
*/
|
||||
private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
|
||||
|
||||
/**
|
||||
* Package names the system has white-listed to opt out of power save restrictions for
|
||||
* all modes.
|
||||
*/
|
||||
private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
|
||||
|
||||
@ -160,11 +168,30 @@ public class DeviceIdleController extends SystemService
|
||||
*/
|
||||
private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
|
||||
|
||||
/**
|
||||
* App IDs of built-in system apps that have been white-listed except for idle modes.
|
||||
*/
|
||||
private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
|
||||
= new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
* App IDs of built-in system apps that have been white-listed.
|
||||
*/
|
||||
private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
* App IDs that have been white-listed to opt out of power save restrictions, except
|
||||
* for device idle modes.
|
||||
*/
|
||||
private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
* Current app IDs that are in the complete power save white list, but shouldn't be
|
||||
* excluded from idle modes. This array can be shared with others because it will not be
|
||||
* modified once set.
|
||||
*/
|
||||
private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
|
||||
|
||||
/**
|
||||
* App IDs that have been white-listed to opt out of power save restrictions.
|
||||
*/
|
||||
@ -583,14 +610,26 @@ public class DeviceIdleController extends SystemService
|
||||
removePowerSaveWhitelistAppInternal(name);
|
||||
}
|
||||
|
||||
@Override public String[] getSystemPowerWhitelistExceptIdle() {
|
||||
return getSystemPowerWhitelistExceptIdleInternal();
|
||||
}
|
||||
|
||||
@Override public String[] getSystemPowerWhitelist() {
|
||||
return getSystemPowerWhitelistInternal();
|
||||
}
|
||||
|
||||
@Override public String[] getFullPowerWhitelistExceptIdle() {
|
||||
return getFullPowerWhitelistExceptIdleInternal();
|
||||
}
|
||||
|
||||
@Override public String[] getFullPowerWhitelist() {
|
||||
return getFullPowerWhitelistInternal();
|
||||
}
|
||||
|
||||
@Override public int[] getAppIdWhitelistExceptIdle() {
|
||||
return getAppIdWhitelistExceptIdleInternal();
|
||||
}
|
||||
|
||||
@Override public int[] getAppIdWhitelist() {
|
||||
return getAppIdWhitelistInternal();
|
||||
}
|
||||
@ -599,6 +638,10 @@ public class DeviceIdleController extends SystemService
|
||||
return getAppIdTempWhitelistInternal();
|
||||
}
|
||||
|
||||
@Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
|
||||
return isPowerSaveWhitelistExceptIdleAppInternal(name);
|
||||
}
|
||||
|
||||
@Override public boolean isPowerSaveWhitelistApp(String name) {
|
||||
return isPowerSaveWhitelistAppInternal(name);
|
||||
}
|
||||
@ -679,6 +722,19 @@ public class DeviceIdleController extends SystemService
|
||||
mEnabled = getContext().getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enableAutoPowerModes);
|
||||
SystemConfig sysConfig = SystemConfig.getInstance();
|
||||
ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
|
||||
for (int i=0; i<allowPowerExceptIdle.size(); i++) {
|
||||
String pkg = allowPowerExceptIdle.valueAt(i);
|
||||
try {
|
||||
ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
|
||||
if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
int appid = UserHandle.getAppId(ai.uid);
|
||||
mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
|
||||
mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
}
|
||||
ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
|
||||
for (int i=0; i<allowPower.size(); i++) {
|
||||
String pkg = allowPower.valueAt(i);
|
||||
@ -686,6 +742,10 @@ public class DeviceIdleController extends SystemService
|
||||
ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
|
||||
if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
int appid = UserHandle.getAppId(ai.uid);
|
||||
// These apps are on both the whitelist-except-idle as well
|
||||
// as the full whitelist, so they apply in all cases.
|
||||
mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
|
||||
mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
|
||||
mPowerSaveWhitelistApps.put(ai.packageName, appid);
|
||||
mPowerSaveWhitelistSystemAppIds.put(appid, true);
|
||||
}
|
||||
@ -783,17 +843,45 @@ public class DeviceIdleController extends SystemService
|
||||
return false;
|
||||
}
|
||||
|
||||
public String[] getSystemPowerWhitelistExceptIdleInternal() {
|
||||
synchronized (this) {
|
||||
int size = mPowerSaveWhitelistAppsExceptIdle.size();
|
||||
String[] apps = new String[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getSystemPowerWhitelistInternal() {
|
||||
synchronized (this) {
|
||||
int size = mPowerSaveWhitelistApps.size();
|
||||
String[] apps = new String[size];
|
||||
for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
apps[i] = mPowerSaveWhitelistApps.keyAt(i);
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getFullPowerWhitelistExceptIdleInternal() {
|
||||
synchronized (this) {
|
||||
int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
|
||||
String[] apps = new String[size];
|
||||
int cur = 0;
|
||||
for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
|
||||
apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
|
||||
cur++;
|
||||
}
|
||||
for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
|
||||
apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
|
||||
cur++;
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getFullPowerWhitelistInternal() {
|
||||
synchronized (this) {
|
||||
int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
|
||||
@ -811,6 +899,13 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
|
||||
synchronized (this) {
|
||||
return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
|
||||
|| mPowerSaveWhitelistUserApps.containsKey(packageName);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPowerSaveWhitelistAppInternal(String packageName) {
|
||||
synchronized (this) {
|
||||
return mPowerSaveWhitelistApps.containsKey(packageName)
|
||||
@ -818,6 +913,12 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getAppIdWhitelistExceptIdleInternal() {
|
||||
synchronized (this) {
|
||||
return mPowerSaveWhitelistExceptIdleAppIdArray;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getAppIdWhitelistInternal() {
|
||||
synchronized (this) {
|
||||
return mPowerSaveWhitelistAllAppIdArray;
|
||||
@ -921,6 +1022,9 @@ public class DeviceIdleController extends SystemService
|
||||
Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
|
||||
}
|
||||
updateTempWhitelistAppIdsLocked();
|
||||
if (mNetworkPolicyTempWhitelistCallback != null) {
|
||||
mHandler.post(mNetworkPolicyTempWhitelistCallback);
|
||||
}
|
||||
reportTempWhitelistChangedLocked();
|
||||
try {
|
||||
mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
|
||||
@ -949,23 +1053,31 @@ public class DeviceIdleController extends SystemService
|
||||
if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
|
||||
if (!screenOn && mScreenOn) {
|
||||
mScreenOn = false;
|
||||
if (!mForceIdle) {
|
||||
becomeInactiveIfAppropriateLocked();
|
||||
}
|
||||
} else if (screenOn) {
|
||||
mScreenOn = true;
|
||||
if (!mForceIdle) {
|
||||
becomeActiveLocked("screen", Process.myUid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateChargingLocked(boolean charging) {
|
||||
if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
|
||||
if (!charging && mCharging) {
|
||||
mCharging = false;
|
||||
if (!mForceIdle) {
|
||||
becomeInactiveIfAppropriateLocked();
|
||||
}
|
||||
} else if (charging) {
|
||||
mCharging = charging;
|
||||
if (!mForceIdle) {
|
||||
becomeActiveLocked("charging", Process.myUid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scheduleReportActiveLocked(String activeReason, int activeUid) {
|
||||
Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
|
||||
@ -989,7 +1101,7 @@ public class DeviceIdleController extends SystemService
|
||||
|
||||
void becomeInactiveIfAppropriateLocked() {
|
||||
if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
|
||||
if (!mScreenOn && !mCharging && mEnabled && mState == STATE_ACTIVE) {
|
||||
if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
|
||||
// Screen has turned off; we are now going to become inactive and start
|
||||
// waiting to see if we will ultimately go idle.
|
||||
mState = STATE_INACTIVE;
|
||||
@ -1010,6 +1122,15 @@ public class DeviceIdleController extends SystemService
|
||||
becomeInactiveIfAppropriateLocked();
|
||||
}
|
||||
|
||||
void exitForceIdleLocked() {
|
||||
if (mForceIdle) {
|
||||
mForceIdle = false;
|
||||
if (mScreenOn || mCharging) {
|
||||
becomeActiveLocked("exit-force-idle", Process.myUid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stepIdleStateLocked() {
|
||||
if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
|
||||
EventLogTags.writeDeviceIdleStep();
|
||||
@ -1138,20 +1259,28 @@ public class DeviceIdleController extends SystemService
|
||||
mNextAlarmTime, mSensingAlarmIntent);
|
||||
}
|
||||
|
||||
private void updateWhitelistAppIdsLocked() {
|
||||
mPowerSaveWhitelistAllAppIds.clear();
|
||||
for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) {
|
||||
mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true);
|
||||
private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
|
||||
ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
|
||||
outAppIds.clear();
|
||||
for (int i=0; i<systemApps.size(); i++) {
|
||||
outAppIds.put(systemApps.valueAt(i), true);
|
||||
}
|
||||
for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
|
||||
mPowerSaveWhitelistAllAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true);
|
||||
for (int i=0; i<userApps.size(); i++) {
|
||||
outAppIds.put(userApps.valueAt(i), true);
|
||||
}
|
||||
int size = mPowerSaveWhitelistAllAppIds.size();
|
||||
int size = outAppIds.size();
|
||||
int[] appids = new int[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
appids[i] = mPowerSaveWhitelistAllAppIds.keyAt(i);
|
||||
appids[i] = outAppIds.keyAt(i);
|
||||
}
|
||||
mPowerSaveWhitelistAllAppIdArray = appids;
|
||||
return appids;
|
||||
}
|
||||
|
||||
private void updateWhitelistAppIdsLocked() {
|
||||
mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
|
||||
mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
|
||||
mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
|
||||
mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
|
||||
if (mLocalPowerManager != null) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Setting wakelock whitelist to "
|
||||
@ -1320,6 +1449,9 @@ public class DeviceIdleController extends SystemService
|
||||
pw.println("Commands:");
|
||||
pw.println(" step");
|
||||
pw.println(" Immediately step to next state, without waiting for alarm.");
|
||||
pw.println(" force-idle");
|
||||
pw.println(" Force directly into idle mode, regardless of other device state.");
|
||||
pw.println(" Use \"step\" to get out.");
|
||||
pw.println(" disable");
|
||||
pw.println(" Completely disable device idle mode.");
|
||||
pw.println(" enable");
|
||||
@ -1362,6 +1494,7 @@ public class DeviceIdleController extends SystemService
|
||||
synchronized (this) {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
exitForceIdleLocked();
|
||||
stepIdleStateLocked();
|
||||
pw.print("Stepped to: "); pw.println(stateToString(mState));
|
||||
} finally {
|
||||
@ -1369,6 +1502,33 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if ("force-idle".equals(arg)) {
|
||||
synchronized (this) {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (!mEnabled) {
|
||||
pw.println("Unable to go idle; not enabled");
|
||||
return;
|
||||
}
|
||||
mForceIdle = true;
|
||||
becomeInactiveIfAppropriateLocked();
|
||||
int curState = mState;
|
||||
while (curState != STATE_IDLE) {
|
||||
stepIdleStateLocked();
|
||||
if (curState == mState) {
|
||||
pw.print("Unable to go idle; stopped at ");
|
||||
pw.println(stateToString(mState));
|
||||
exitForceIdleLocked();
|
||||
return;
|
||||
}
|
||||
curState = mState;
|
||||
}
|
||||
pw.println("Now forced in to idle mode");
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if ("disable".equals(arg)) {
|
||||
synchronized (this) {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
@ -1387,6 +1547,7 @@ public class DeviceIdleController extends SystemService
|
||||
synchronized (this) {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
exitForceIdleLocked();
|
||||
if (!mEnabled) {
|
||||
mEnabled = true;
|
||||
becomeInactiveIfAppropriateLocked();
|
||||
@ -1431,6 +1592,12 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
} else {
|
||||
synchronized (this) {
|
||||
for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
|
||||
pw.print("system-excidle,");
|
||||
pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
|
||||
pw.print(",");
|
||||
pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
|
||||
}
|
||||
for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
|
||||
pw.print("system,");
|
||||
pw.print(mPowerSaveWhitelistApps.keyAt(j));
|
||||
@ -1481,7 +1648,15 @@ public class DeviceIdleController extends SystemService
|
||||
synchronized (this) {
|
||||
mConstants.dump(pw);
|
||||
|
||||
int size = mPowerSaveWhitelistApps.size();
|
||||
int size = mPowerSaveWhitelistAppsExceptIdle.size();
|
||||
if (size > 0) {
|
||||
pw.println(" Whitelist (except idle) system apps:");
|
||||
for (int i = 0; i < size; i++) {
|
||||
pw.print(" ");
|
||||
pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
|
||||
}
|
||||
}
|
||||
size = mPowerSaveWhitelistApps.size();
|
||||
if (size > 0) {
|
||||
pw.println(" Whitelist system apps:");
|
||||
for (int i = 0; i < size; i++) {
|
||||
@ -1497,6 +1672,15 @@ public class DeviceIdleController extends SystemService
|
||||
pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
|
||||
}
|
||||
}
|
||||
size = mPowerSaveWhitelistExceptIdleAppIds.size();
|
||||
if (size > 0) {
|
||||
pw.println(" Whitelist (except idle) all app ids:");
|
||||
for (int i = 0; i < size; i++) {
|
||||
pw.print(" ");
|
||||
pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
size = mPowerSaveWhitelistAllAppIds.size();
|
||||
if (size > 0) {
|
||||
pw.println(" Whitelist all app ids:");
|
||||
@ -1531,6 +1715,7 @@ public class DeviceIdleController extends SystemService
|
||||
}
|
||||
|
||||
pw.print(" mEnabled="); pw.println(mEnabled);
|
||||
pw.print(" mForceIdle="); pw.println(mForceIdle);
|
||||
pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
|
||||
pw.print(" mCurDisplay="); pw.println(mCurDisplay);
|
||||
pw.print(" mScreenOn="); pw.println(mScreenOn);
|
||||
|
@ -83,6 +83,11 @@ public class SystemConfig {
|
||||
// system configuration files.
|
||||
final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
|
||||
|
||||
// These are the packages that are white-listed to be able to run in the
|
||||
// background while in power save mode (but not whitelisted from device idle modes),
|
||||
// as read from the configuration files.
|
||||
final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
|
||||
|
||||
// These are the packages that are white-listed to be able to run in the
|
||||
// background while in power save mode, as read from the configuration files.
|
||||
final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
|
||||
@ -123,6 +128,10 @@ public class SystemConfig {
|
||||
return mPermissions;
|
||||
}
|
||||
|
||||
public ArraySet<String> getAllowInPowerSaveExceptIdle() {
|
||||
return mAllowInPowerSaveExceptIdle;
|
||||
}
|
||||
|
||||
public ArraySet<String> getAllowInPowerSave() {
|
||||
return mAllowInPowerSave;
|
||||
}
|
||||
@ -329,6 +338,17 @@ public class SystemConfig {
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
continue;
|
||||
|
||||
} else if ("allow-in-power-save-except-idle".equals(name) && !onlyFeatures) {
|
||||
String pkgname = parser.getAttributeValue(null, "package");
|
||||
if (pkgname == null) {
|
||||
Slog.w(TAG, "<allow-in-power-save-except-idle> without package in "
|
||||
+ permFile + " at " + parser.getPositionDescription());
|
||||
} else {
|
||||
mAllowInPowerSaveExceptIdle.add(pkgname);
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
continue;
|
||||
|
||||
} else if ("allow-in-power-save".equals(name) && !onlyFeatures) {
|
||||
String pkgname = parser.getAttributeValue(null, "package");
|
||||
if (pkgname == null) {
|
||||
|
@ -39,6 +39,7 @@ import static android.net.NetworkPolicy.WARNING_DISABLED;
|
||||
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
|
||||
import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE;
|
||||
@ -46,7 +47,6 @@ import static android.net.NetworkPolicyManager.POLICY_NONE;
|
||||
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
||||
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
|
||||
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
|
||||
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
|
||||
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
|
||||
import static android.net.NetworkPolicyManager.dumpPolicy;
|
||||
import static android.net.NetworkPolicyManager.dumpRules;
|
||||
@ -282,6 +282,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
/** Set of states for the child firewall chains. True if the chain is active. */
|
||||
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
* UIDs that have been white-listed to always be able to have network access
|
||||
* in power save mode, except device idle (doze) still applies.
|
||||
* TODO: An int array might be sufficient
|
||||
*/
|
||||
private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
|
||||
|
||||
/**
|
||||
* UIDs that have been white-listed to always be able to have network access
|
||||
* in power save mode.
|
||||
@ -302,9 +309,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
/** Foreground at UID granularity. */
|
||||
final SparseIntArray mUidState = new SparseIntArray();
|
||||
|
||||
/** The current maximum process state that we are considering to be foreground. */
|
||||
private int mCurForegroundState = ActivityManager.PROCESS_STATE_TOP;
|
||||
|
||||
private final RemoteCallbackList<INetworkPolicyListener>
|
||||
mListeners = new RemoteCallbackList<>();
|
||||
|
||||
@ -365,7 +369,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
void updatePowerSaveWhitelistLocked() {
|
||||
try {
|
||||
final int[] whitelist = mDeviceIdleController.getAppIdWhitelist();
|
||||
int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
|
||||
mPowerSaveWhitelistExceptIdleAppIds.clear();
|
||||
if (whitelist != null) {
|
||||
for (int uid : whitelist) {
|
||||
mPowerSaveWhitelistExceptIdleAppIds.put(uid, true);
|
||||
}
|
||||
}
|
||||
whitelist = mDeviceIdleController.getAppIdWhitelist();
|
||||
mPowerSaveWhitelistAppIds.clear();
|
||||
if (whitelist != null) {
|
||||
for (int uid : whitelist) {
|
||||
@ -425,7 +436,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
if (mRestrictPower != enabled) {
|
||||
mRestrictPower = enabled;
|
||||
updateRulesForGlobalChangeLocked(true);
|
||||
updateRulesForTempWhitelistChangeLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,9 +447,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
readPolicyLocked();
|
||||
|
||||
if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
|
||||
updateRulesForGlobalChangeLocked(true);
|
||||
updateRulesForTempWhitelistChangeLocked();
|
||||
updateRulesForGlobalChangeLocked(false);
|
||||
updateNotificationsLocked();
|
||||
} else {
|
||||
// If we are not in any special mode, we just need to make sure the current
|
||||
// app idle state is updated.
|
||||
updateRulesForAppIdleLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1907,7 +1920,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
fout.print("Restrict background: "); fout.println(mRestrictBackground);
|
||||
fout.print("Restrict power: "); fout.println(mRestrictPower);
|
||||
fout.print("Device idle: "); fout.println(mDeviceIdleMode);
|
||||
fout.print("Current foreground state: "); fout.println(mCurForegroundState);
|
||||
fout.println("Network policies:");
|
||||
fout.increaseIndent();
|
||||
for (int i = 0; i < mNetworkPolicy.size(); i++) {
|
||||
@ -1931,6 +1943,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
fout.decreaseIndent();
|
||||
|
||||
size = mPowerSaveWhitelistExceptIdleAppIds.size();
|
||||
if (size > 0) {
|
||||
fout.println("Power save whitelist (except idle) app ids:");
|
||||
fout.increaseIndent();
|
||||
for (int i = 0; i < size; i++) {
|
||||
fout.print("UID=");
|
||||
fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
|
||||
fout.print(": ");
|
||||
fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
|
||||
fout.println();
|
||||
}
|
||||
fout.decreaseIndent();
|
||||
}
|
||||
|
||||
size = mPowerSaveWhitelistAppIds.size();
|
||||
if (size > 0) {
|
||||
fout.println("Power save whitelist app ids:");
|
||||
@ -1960,7 +1986,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
|
||||
fout.print(" state=");
|
||||
fout.print(state);
|
||||
fout.print(state <= mCurForegroundState ? " (fg)" : " (bg)");
|
||||
fout.print(state <= ActivityManager.PROCESS_STATE_TOP ? " (fg)" : " (bg)");
|
||||
|
||||
fout.print(" rules=");
|
||||
final int rulesIndex = mUidRules.indexOfKey(uid);
|
||||
@ -1988,7 +2014,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
boolean isUidForegroundLocked(int uid) {
|
||||
// only really in foreground when screen is also on
|
||||
return mScreenOn && mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY)
|
||||
<= mCurForegroundState;
|
||||
<= ActivityManager.PROCESS_STATE_TOP;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2024,8 +2050,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
}
|
||||
|
||||
void updateRulesForUidStateChangeLocked(int uid, int oldUidState, int newUidState) {
|
||||
final boolean oldForeground = oldUidState <= mCurForegroundState;
|
||||
final boolean newForeground = newUidState <= mCurForegroundState;
|
||||
final boolean oldForeground = oldUidState <= ActivityManager.PROCESS_STATE_TOP;
|
||||
final boolean newForeground = newUidState <= ActivityManager.PROCESS_STATE_TOP;
|
||||
if (oldForeground != newForeground) {
|
||||
updateRulesForUidLocked(uid);
|
||||
}
|
||||
@ -2049,7 +2075,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
// only update rules for anyone with foreground activities
|
||||
final int size = mUidState.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (mUidState.valueAt(i) <= mCurForegroundState) {
|
||||
if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_TOP) {
|
||||
final int uid = mUidState.keyAt(i);
|
||||
updateRulesForUidLocked(uid);
|
||||
}
|
||||
@ -2069,10 +2095,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
for (int ui = users.size() - 1; ui >= 0; ui--) {
|
||||
UserInfo user = users.get(ui);
|
||||
for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
|
||||
if (mPowerSaveTempWhitelistAppIds.valueAt(i)) {
|
||||
int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
|
||||
int uid = UserHandle.getUid(user.id, appId);
|
||||
uidRules.put(uid, FIREWALL_RULE_ALLOW);
|
||||
}
|
||||
}
|
||||
for (int i = mPowerSaveWhitelistAppIds.size() - 1; i >= 0; i--) {
|
||||
int appId = mPowerSaveWhitelistAppIds.keyAt(i);
|
||||
int uid = UserHandle.getUid(user.id, appId);
|
||||
@ -2089,6 +2117,45 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
|
||||
}
|
||||
|
||||
void updateRuleForDeviceIdleLocked(int uid) {
|
||||
if (mDeviceIdleMode) {
|
||||
int appId = UserHandle.getAppId(uid);
|
||||
if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
|
||||
|| isProcStateAllowedWhileIdle(mUidState.get(uid))) {
|
||||
setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_ALLOW);
|
||||
} else {
|
||||
setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateRulesForAppIdleLocked() {
|
||||
// Fully update the app idle firewall chain.
|
||||
SparseIntArray uidRules = new SparseIntArray();
|
||||
final List<UserInfo> users = mUserManager.getUsers();
|
||||
for (int ui = users.size() - 1; ui >= 0; ui--) {
|
||||
UserInfo user = users.get(ui);
|
||||
int[] idleUids = mUsageStats.getIdleUidsForUser(user.id);
|
||||
for (int uid : idleUids) {
|
||||
if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) {
|
||||
uidRules.put(uid, FIREWALL_RULE_DENY);
|
||||
}
|
||||
}
|
||||
}
|
||||
setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules);
|
||||
}
|
||||
|
||||
void updateRuleForAppIdleLocked(int uid) {
|
||||
if (!isUidValidForRules(uid)) return;
|
||||
|
||||
int appId = UserHandle.getAppId(uid);
|
||||
if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)) {
|
||||
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
|
||||
} else {
|
||||
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateRulesForAppIdleParoleLocked() {
|
||||
boolean enableChain = !mUsageStats.isAppIdleParoleOn();
|
||||
enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
|
||||
@ -2101,14 +2168,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
|
||||
// If we are in restrict power mode, we allow all important apps
|
||||
// to have data access. Otherwise, we restrict data access to only
|
||||
// the top apps.
|
||||
mCurForegroundState = (!mRestrictBackground && mRestrictPower)
|
||||
? ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
|
||||
: ActivityManager.PROCESS_STATE_TOP;
|
||||
|
||||
updateRulesForDeviceIdleLocked();
|
||||
updateRulesForAppIdleLocked();
|
||||
|
||||
// update rules for all installed applications
|
||||
final List<UserInfo> users = mUserManager.getUsers();
|
||||
@ -2138,10 +2199,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
for (UserInfo user : users) {
|
||||
for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
|
||||
int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
|
||||
boolean isAllow = mPowerSaveTempWhitelistAppIds.valueAt(i);
|
||||
int uid = UserHandle.getUid(user.id, appId);
|
||||
updateRulesForUidLocked(uid);
|
||||
setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, !isAllow);
|
||||
updateRuleForAppIdleLocked(uid);
|
||||
updateRuleForDeviceIdleLocked(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2188,16 +2248,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
|
||||
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
|
||||
final boolean uidForeground = isUidForegroundLocked(uid);
|
||||
final boolean uidIdle = isUidIdle(uid);
|
||||
|
||||
// derive active rules based on policy and active state
|
||||
|
||||
int appId = UserHandle.getAppId(uid);
|
||||
int uidRules = RULE_ALLOW_ALL;
|
||||
if (uidIdle && !mPowerSaveWhitelistAppIds.get(appId)
|
||||
&& !mPowerSaveTempWhitelistAppIds.get(appId)) {
|
||||
uidRules = RULE_REJECT_ALL;
|
||||
} else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
|
||||
if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
|
||||
// uid in background, and policy says to block metered data
|
||||
uidRules = RULE_REJECT_METERED;
|
||||
} else if (mRestrictBackground) {
|
||||
@ -2206,7 +2262,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
uidRules = RULE_REJECT_METERED;
|
||||
}
|
||||
} else if (mRestrictPower) {
|
||||
final boolean whitelisted = mPowerSaveWhitelistAppIds.get(appId)
|
||||
final boolean whitelisted = mPowerSaveWhitelistExceptIdleAppIds.get(appId)
|
||||
|| mPowerSaveTempWhitelistAppIds.get(appId);
|
||||
if (!whitelisted && !uidForeground
|
||||
&& (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) {
|
||||
@ -2232,13 +2288,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
setUidNetworkRules(uid, rejectMetered);
|
||||
}
|
||||
|
||||
// Update firewall rules if necessary
|
||||
final boolean oldFirewallReject = (oldRules & RULE_REJECT_ALL) != 0;
|
||||
final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0;
|
||||
if (oldFirewallReject != firewallReject) {
|
||||
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, firewallReject);
|
||||
}
|
||||
|
||||
// dispatch changed rule to existing listeners
|
||||
if (oldRules != uidRules) {
|
||||
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
|
||||
@ -2260,7 +2309,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
try {
|
||||
int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
|
||||
synchronized (mRulesLock) {
|
||||
updateRulesForUidLocked(uid);
|
||||
updateRuleForAppIdleLocked(uid);
|
||||
}
|
||||
} catch (NameNotFoundException nnfe) {
|
||||
}
|
||||
@ -2422,10 +2471,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
|
||||
/**
|
||||
* Add or remove a uid to the firewall blacklist for all network ifaces.
|
||||
*/
|
||||
private void setUidFirewallRule(int chain, int uid, boolean rejectOnAll) {
|
||||
private void setUidFirewallRule(int chain, int uid, int rule) {
|
||||
try {
|
||||
mNetworkManager.setFirewallUidRule(chain, uid,
|
||||
rejectOnAll ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW);
|
||||
mNetworkManager.setFirewallUidRule(chain, uid, rule);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.wtf(TAG, "problem setting firewall uid rules", e);
|
||||
} catch (RemoteException e) {
|
||||
|
@ -35,6 +35,7 @@ import android.content.ContentResolver;
|
||||
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.ParceledListSlice;
|
||||
@ -65,6 +66,7 @@ import android.util.AtomicFile;
|
||||
import android.util.KeyValueListParser;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.view.Display;
|
||||
|
||||
@ -799,7 +801,10 @@ public class UsageStatsService extends SystemService implements
|
||||
}
|
||||
if (packageName.equals("android")) return false;
|
||||
try {
|
||||
if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) {
|
||||
// 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 (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
|
||||
return false;
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
@ -825,6 +830,72 @@ public class UsageStatsService extends SystemService implements
|
||||
return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime);
|
||||
}
|
||||
|
||||
int[] getIdleUidsForUser(int userId) {
|
||||
if (!mAppIdleEnabled) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
final long timeNow;
|
||||
final UserUsageStatsService userService;
|
||||
final long screenOnTime;
|
||||
synchronized (mLock) {
|
||||
timeNow = checkAndGetTimeLocked();
|
||||
userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
|
||||
screenOnTime = getScreenOnTimeLocked(timeNow);
|
||||
}
|
||||
|
||||
List<ApplicationInfo> apps;
|
||||
try {
|
||||
ParceledListSlice<ApplicationInfo> slice
|
||||
= AppGlobals.getPackageManager().getInstalledApplications(0, userId);
|
||||
apps = slice.getList();
|
||||
} catch (RemoteException e) {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
// State of each uid. Key is the uid. Value lower 16 bits is the number of apps
|
||||
// associated with that uid, upper 16 bits is the number of those apps that is idle.
|
||||
SparseIntArray uidStates = new SparseIntArray();
|
||||
|
||||
// Now resolve all app state. Iterating over all apps, keeping track of how many
|
||||
// we find for each uid and how many of those are idle.
|
||||
for (int i = apps.size()-1; i >= 0; i--) {
|
||||
ApplicationInfo ai = apps.get(i);
|
||||
|
||||
// Check whether this app is idle.
|
||||
boolean idle = isAppIdleFiltered(ai.packageName, userId, userService, timeNow,
|
||||
screenOnTime);
|
||||
|
||||
int index = uidStates.indexOfKey(ai.uid);
|
||||
if (index < 0) {
|
||||
uidStates.put(ai.uid, 1 + (idle ? 1<<16 : 0));
|
||||
} else {
|
||||
int value = uidStates.valueAt(index);
|
||||
uidStates.setValueAt(index, value + 1 + (idle ? 1<<16 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
int numIdle = 0;
|
||||
for (int i = uidStates.size() - 1; i >= 0; i--) {
|
||||
int value = uidStates.valueAt(i);
|
||||
if ((value&0x7fff) == (value>>16)) {
|
||||
numIdle++;
|
||||
}
|
||||
}
|
||||
|
||||
int[] res = new int[numIdle];
|
||||
numIdle = 0;
|
||||
for (int i = uidStates.size() - 1; i >= 0; i--) {
|
||||
int value = uidStates.valueAt(i);
|
||||
if ((value&0x7fff) == (value>>16)) {
|
||||
res[numIdle] = uidStates.keyAt(i);
|
||||
numIdle++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void setAppIdle(String packageName, boolean idle, int userId) {
|
||||
if (packageName == null) return;
|
||||
|
||||
@ -1283,6 +1354,11 @@ public class UsageStatsService extends SystemService implements
|
||||
return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdleUidsForUser(int userId) {
|
||||
return UsageStatsService.this.getIdleUidsForUser(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAppIdleParoleOn() {
|
||||
return mAppIdleParoled;
|
||||
|
Reference in New Issue
Block a user