summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/AppOpsService.java51
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java7
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java219
-rw-r--r--services/core/java/com/android/server/SystemConfig.java20
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java12
-rw-r--r--services/core/java/com/android/server/job/controllers/IdleController.java19
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java136
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/Settings.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java7
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java78
11 files changed, 481 insertions, 79 deletions
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 45c020c..56ebed6 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1245,6 +1245,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
boolean success = false;
+ mUidStates.clear();
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, StandardCharsets.UTF_8.name());
@@ -1448,7 +1449,7 @@ public class AppOpsService extends IAppOpsService.Stub {
XmlSerializer out = new FastXmlSerializer();
out.setOutput(stream, StandardCharsets.UTF_8.name());
out.startDocument(null, true);
- out.startTag(null, "app");
+ out.startTag(null, "app-ops");
final int uidStateCount = mUidStates.size();
for (int i = 0; i < uidStateCount; i++) {
@@ -1541,6 +1542,17 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
+ private void dumpHelp(PrintWriter pw) {
+ pw.println("AppOps service (appops) dump options:");
+ pw.println(" [-h] [CMD]");
+ pw.println(" -h: print this help text.");
+ pw.println("Commands:");
+ pw.println(" write-settings");
+ pw.println(" Immediately write pending changes to storage.");
+ pw.println(" read-settings");
+ pw.println(" Read the last written settings, replacing current state in RAM.");
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -1551,6 +1563,43 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
+ if (args != null) {
+ for (int i=0; i<args.length; i++) {
+ String arg = args[i];
+ if ("-h".equals(arg)) {
+ dumpHelp(pw);
+ return;
+ } else if ("write-settings".equals(arg)) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mHandler.removeCallbacks(mWriteRunner);
+ }
+ writeState();
+ pw.println("Current settings written.");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return;
+ } else if ("read-settings".equals(arg)) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ readState();
+ pw.println("Last settings read.");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return;
+ } else if (arg.length() > 0 && arg.charAt(0) == '-'){
+ pw.println("Unknown option: " + arg);
+ return;
+ } else {
+ pw.println("Unknown command: " + arg);
+ return;
+ }
+ }
+ }
+
synchronized (this) {
pw.println("Current AppOps Service state:");
final long now = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0802d30..6e0c37f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1432,9 +1432,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void enforceChangePermission() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_NETWORK_STATE,
- "ConnectivityService");
+ int uid = Binder.getCallingUid();
+ Settings.checkAndNoteChangeNetworkStateOperation(mContext, uid, Settings
+ .getPackageNameForUid(mContext, uid), true);
+
}
private void enforceTetherAccessPermission() {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 7561c7d..e678bbc 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -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<>();
@@ -161,11 +169,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.
*/
private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
@@ -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,10 +1053,14 @@ public class DeviceIdleController extends SystemService
if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
if (!screenOn && mScreenOn) {
mScreenOn = false;
- becomeInactiveIfAppropriateLocked();
+ if (!mForceIdle) {
+ becomeInactiveIfAppropriateLocked();
+ }
} else if (screenOn) {
mScreenOn = true;
- becomeActiveLocked("screen", Process.myUid());
+ if (!mForceIdle) {
+ becomeActiveLocked("screen", Process.myUid());
+ }
}
}
@@ -960,10 +1068,14 @@ public class DeviceIdleController extends SystemService
if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
if (!charging && mCharging) {
mCharging = false;
- becomeInactiveIfAppropriateLocked();
+ if (!mForceIdle) {
+ becomeInactiveIfAppropriateLocked();
+ }
} else if (charging) {
mCharging = charging;
- becomeActiveLocked("charging", Process.myUid());
+ if (!mForceIdle) {
+ becomeActiveLocked("charging", Process.myUid());
+ }
}
}
@@ -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);
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index ad5406c..cd61347 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -84,6 +84,11 @@ public class SystemConfig {
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) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 83e8db0..aab6374 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2604,7 +2604,8 @@ public class AccountManagerService
// Prune the list down to just the requested type.
visibleAccountTypes = new ArrayList<>();
visibleAccountTypes.add(type);
- } // else aggregate all the visible accounts (it won't matter if the list is empty).
+ } // else aggregate all the visible accounts (it won't matter if the
+ // list is empty).
long identityToken = clearCallingIdentity();
try {
@@ -3788,8 +3789,15 @@ public class AccountManagerService
private List<String> getTypesForCaller(
int callingUid, int userId, boolean isOtherwisePermitted) {
List<String> managedAccountTypes = new ArrayList<>();
+ long identityToken = Binder.clearCallingIdentity();
+ Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> serviceInfos;
+ try {
+ serviceInfos = mAuthenticatorCache.getAllServices(userId);
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
- mAuthenticatorCache.getAllServices(userId)) {
+ serviceInfos) {
final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) {
managedAccountTypes.add(serviceInfo.type.type);
diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java
index 8e2ca18..92df851 100644
--- a/services/core/java/com/android/server/job/controllers/IdleController.java
+++ b/services/core/java/com/android/server/job/controllers/IdleController.java
@@ -108,6 +108,7 @@ public class IdleController extends StateController {
private AlarmManager mAlarm;
private PendingIntent mIdleTriggerIntent;
boolean mIdle;
+ boolean mScreenOn;
public IdlenessTracker() {
mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
@@ -120,6 +121,7 @@ public class IdleController extends StateController {
// At boot we presume that the user has just "interacted" with the
// device in some meaningful way.
mIdle = false;
+ mScreenOn = true;
}
public boolean isIdle() {
@@ -149,12 +151,14 @@ public class IdleController extends StateController {
if (action.equals(Intent.ACTION_SCREEN_ON)
|| action.equals(Intent.ACTION_DREAMING_STOPPED)) {
- // possible transition to not-idle
+ if (DEBUG) {
+ Slog.v(TAG,"exiting idle : " + action);
+ }
+ mScreenOn = true;
+ //cancel the alarm
+ mAlarm.cancel(mIdleTriggerIntent);
if (mIdle) {
- if (DEBUG) {
- Slog.v(TAG, "exiting idle : " + action);
- }
- mAlarm.cancel(mIdleTriggerIntent);
+ // possible transition to not-idle
mIdle = false;
reportNewIdleState(mIdle);
}
@@ -169,11 +173,12 @@ public class IdleController extends StateController {
Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when="
+ when);
}
+ mScreenOn = false;
mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
when, IDLE_WINDOW_SLOP, mIdleTriggerIntent);
} else if (action.equals(ACTION_TRIGGER_IDLE)) {
- // idle time starts now
- if (!mIdle) {
+ // idle time starts now. Do not set mIdle if screen is on.
+ if (!mIdle && !mScreenOn) {
if (DEBUG) {
Slog.v(TAG, "Idle trigger fired @ " + SystemClock.elapsedRealtime());
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 46bda8c..c0d0d13 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -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;
@@ -284,6 +284,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* 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.
* TODO: An int array might be sufficient
*/
@@ -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,9 +2095,11 @@ 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--) {
- int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
- int uid = UserHandle.getUid(user.id, appId);
- uidRules.put(uid, FIREWALL_RULE_ALLOW);
+ 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);
@@ -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) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ce40c28..6a4ae3d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13037,7 +13037,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// they have set the special DELETE_SYSTEM_APP which requests different
// semantics than normal for uninstalling system apps.
if (DEBUG_REMOVE) Slog.d(TAG, "Only deleting for single user");
- ps.setUserState(user.getIdentifier(),
+ final int userId = user.getIdentifier();
+ ps.setUserState(userId,
COMPONENT_ENABLED_STATE_DEFAULT,
false, //installed
true, //stopped
@@ -13045,7 +13046,7 @@ public class PackageManagerService extends IPackageManager.Stub {
false, //hidden
null, null, null,
false, // blockUninstall
- INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
+ ps.readUserState(userId).domainVerificationStatus, 0);
if (!isSystemApp(ps)) {
if (ps.isAnyInstalled(sUserManager.getUserIds())) {
// Other user still have this package installed, so all
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 82ffa47..00d0fe1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4150,6 +4150,9 @@ final class Settings {
if ((perm.info.flags&PermissionInfo.FLAG_COSTS_MONEY) != 0) {
pw.print(", COSTS_MONEY");
}
+ if ((perm.info.flags&PermissionInfo.FLAG_HIDDEN) != 0) {
+ pw.print(", COSTS_HIDDEN");
+ }
if ((perm.info.flags&PermissionInfo.FLAG_INSTALLED) != 0) {
pw.print(", INSTALLED");
}
@@ -4306,7 +4309,8 @@ final class Settings {
pw.println(PermissionInfo.protectionToString(p.protectionLevel));
if (p.perm != null) {
pw.print(" perm="); pw.println(p.perm);
- if (p.perm.info.flags != PermissionInfo.FLAG_INSTALLED) {
+ if ((p.perm.info.flags & PermissionInfo.FLAG_INSTALLED) == 0
+ || (p.perm.info.flags & PermissionInfo.FLAG_HIDDEN) != 0) {
pw.print(" flags=0x"); pw.println(Integer.toHexString(p.perm.info.flags));
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 26e75bd..bc5ef36 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -155,7 +155,6 @@ import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -5367,6 +5366,12 @@ public class WindowManagerService extends IWindowManager.Stub
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
+ // If this isn't coming from the system then don't allow disabling the lockscreen
+ // to bypass security.
+ if (Binder.getCallingUid() != Process.SYSTEM_UID && isKeyguardSecure()) {
+ Log.d(TAG, "current mode is SecurityMode, ignore hide keyguard");
+ return;
+ }
if (token == null) {
throw new IllegalArgumentException("token == null");
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index a433ec4..85f0665 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -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;
@@ -1284,6 +1355,11 @@ public class UsageStatsService extends SystemService implements
}
@Override
+ public int[] getIdleUidsForUser(int userId) {
+ return UsageStatsService.this.getIdleUidsForUser(userId);
+ }
+
+ @Override
public boolean isAppIdleParoleOn() {
return mAppIdleParoled;
}