*/
int[] mDeviceIdleTempWhitelist = new int[0];
+ static final class PendingTempWhitelist {
+ final int targetUid;
+ final long duration;
+ final String tag;
+
+ PendingTempWhitelist(int _targetUid, long _duration, String _tag) {
+ targetUid = _targetUid;
+ duration = _duration;
+ tag = _tag;
+ }
+ }
+
+ final SparseArray<PendingTempWhitelist> mPendingTempWhitelist = new SparseArray<>();
+
/**
* Information about and control over application operations
*/
static final int NOTIFY_VR_SLEEPING_MSG = 65;
static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
+ static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int START_USER_SWITCH_FG_MSG = 712;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
+ case PUSH_TEMP_WHITELIST_UI_MSG: {
+ pushTempWhitelist();
+ } break;
}
}
}
// This is the first appearance of the uid, report it now!
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Creating new process uid: " + uidRec);
- if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0) {
+ if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0
+ || mPendingTempWhitelist.indexOfKey(proc.uid) >= 0) {
uidRec.setWhitelist = uidRec.curWhitelist = true;
}
uidRec.updateHasInternetPermission();
}
}
- /**
- * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
- */
- void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) {
- if (DEBUG_WHITELISTS) {
- Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", "
- + targetUid + ", " + duration + ")");
- }
-
- if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
- != PackageManager.PERMISSION_GRANTED) {
- synchronized (mPidsSelfLocked) {
- final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
- if (pr == null) {
- Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid "
- + callerPid);
- return;
- }
- if (!pr.whitelistManager) {
- if (DEBUG_WHITELISTS) {
- Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid
- + ": pid " + callerPid + " is not allowed");
- }
- return;
- }
- }
- }
-
- final long token = Binder.clearCallingIdentity();
- try {
- mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(targetUid, duration,
- true, "pe from uid:" + callerUid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
@Override
public void cancelIntentSender(IIntentSender sender) {
if (!(sender instanceof PendingIntentRecord)) {
boolean isOnDeviceIdleWhitelistLocked(int uid) {
final int appId = UserHandle.getAppId(uid);
return Arrays.binarySearch(mDeviceIdleWhitelist, appId) >= 0
- || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0;
+ || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0
+ || mPendingTempWhitelist.indexOfKey(uid) >= 0;
}
private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) {
}
pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
+ if (mPendingTempWhitelist.size() > 0) {
+ pw.println(" mPendingTempWhitelist:");
+ for (int i = 0; i < mPendingTempWhitelist.size(); i++) {
+ PendingTempWhitelist ptw = mPendingTempWhitelist.valueAt(i);
+ pw.print(" ");
+ UserHandle.formatUid(pw, ptw.targetUid);
+ pw.print(": ");
+ TimeUtils.formatDuration(ptw.duration, pw);
+ pw.print(" ");
+ pw.println(ptw.tag);
+ }
+ }
}
if (dumpPackage == null) {
pw.println(" mWakefulness="
enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE);
}
+ /**
+ * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
+ */
+ void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
+ long duration, String tag) {
+ if (DEBUG_WHITELISTS) {
+ Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", "
+ + targetUid + ", " + duration + ")");
+ }
+
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
+ if (pr == null) {
+ Slog.w(TAG, "tempWhitelistForPendingIntentLocked() no ProcessRecord for pid "
+ + callerPid);
+ return;
+ }
+ if (!pr.whitelistManager) {
+ if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
+ != PackageManager.PERMISSION_GRANTED) {
+ if (DEBUG_WHITELISTS) {
+ Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid
+ + ": pid " + callerPid + " is not allowed");
+ }
+ return;
+ }
+ }
+ }
+
+ tempWhitelistUidLocked(targetUid, duration, tag);
+ }
+
+ /**
+ * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
+ */
+ void tempWhitelistUidLocked(int targetUid, long duration, String tag) {
+ mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag));
+ setUidTempWhitelistStateLocked(targetUid, true);
+ mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget();
+ }
+
+ void pushTempWhitelist() {
+ final int N;
+ final PendingTempWhitelist[] list;
+
+ // First copy out the pending changes... we need to leave them in the map for now,
+ // in case someone needs to check what is coming up while we don't have the lock held.
+ synchronized(this) {
+ N = mPendingTempWhitelist.size();
+ list = new PendingTempWhitelist[N];
+ for (int i = 0; i < N; i++) {
+ list[i] = mPendingTempWhitelist.valueAt(i);
+ }
+ }
+
+ // Now safely dispatch changes to device idle controller.
+ for (int i = 0; i < N; i++) {
+ PendingTempWhitelist ptw = list[i];
+ mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid,
+ ptw.duration, true, ptw.tag);
+ }
+
+ // And now we can safely remove them from the map.
+ synchronized(this) {
+ for (int i = 0; i < N; i++) {
+ PendingTempWhitelist ptw = list[i];
+ int index = mPendingTempWhitelist.indexOfKey(ptw.targetUid);
+ if (index >= 0 && mPendingTempWhitelist.valueAt(index) == ptw) {
+ mPendingTempWhitelist.removeAt(index);
+ }
+ }
+ }
+ }
+
final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) {
boolean changed = false;
for (int i=mActiveUids.size()-1; i>=0; i--) {
}
}
+ final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) {
+ boolean changed = false;
+ final UidRecord uidRec = mActiveUids.get(uid);
+ if (uidRec != null && uidRec.curWhitelist != onWhitelist) {
+ uidRec.curWhitelist = onWhitelist;
+ updateOomAdjLocked();
+ }
+ }
+
final void trimApplications() {
synchronized (this) {
int i;
if (intent != null) intent.setDefusable(true);
if (options != null) options.setDefusable(true);
- if (whitelistDuration > 0 && !canceled) {
- // Must call before acquiring the lock. It's possible the method return before sending
- // the intent due to some validations inside the lock, in which case the UID shouldn't
- // be whitelisted, but since the whitelist is temporary, that would be ok.
- owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid,
- whitelistDuration);
- }
-
synchronized (owner) {
final ActivityContainer activityContainer = (ActivityContainer)container;
if (activityContainer != null && activityContainer.mParentActivity != null &&
resolvedType = key.requestResolvedType;
}
+ if (whitelistDuration > 0) {
+ StringBuilder tag = new StringBuilder(64);
+ tag.append("pendingintent:");
+ UserHandle.formatUid(tag, Binder.getCallingUid());
+ tag.append(":");
+ if (finalIntent.getAction() != null) {
+ tag.append(finalIntent.getAction());
+ } else if (finalIntent.getComponent() != null) {
+ finalIntent.getComponent().appendShortString(tag);
+ } else if (finalIntent.getData() != null) {
+ tag.append(finalIntent.getData());
+ }
+ owner.tempWhitelistForPendingIntentLocked(Binder.getCallingPid(),
+ Binder.getCallingUid(), uid, whitelistDuration, tag.toString());
+ }
+
final long origId = Binder.clearCallingIdentity();
boolean sendFinish = finishedReceiver != null;