diff options
7 files changed, 82 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 2f1f91e1734a..026430b5469d 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -333,7 +333,8 @@ public final class ActiveServices { } r.delayed = false; try { - startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true); + startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true, + false); } catch (TransactionTooLargeException e) { // Ignore, nobody upstack cares. } @@ -643,7 +644,8 @@ public final class ActiveServices { SERVICE_BG_ACTIVITY_START_TIMEOUT_MS); } } - ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); + ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting, + allowBackgroundActivityStarts); return cmp; } @@ -702,7 +704,8 @@ public final class ActiveServices { } ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, - boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { + boolean callerFg, boolean addToStarting, boolean allowBackgroundActivityStarts) + throws TransactionTooLargeException { ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); @@ -713,7 +716,8 @@ public final class ActiveServices { synchronized (r.stats.getBatteryStats()) { r.stats.startRunningLocked(); } - String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); + String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false, + allowBackgroundActivityStarts); if (error != null) { return new ComponentName("!!", error); } @@ -1645,7 +1649,7 @@ public final class ActiveServices { try { bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), - callerFg, false, false); + callerFg, false, false, false); } catch (RemoteException e) { /* ignore - local call */ } @@ -1748,7 +1752,7 @@ public final class ActiveServices { if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, - permissionsReviewRequired) != null) { + permissionsReviewRequired, false) != null) { return 0; } } @@ -2418,7 +2422,8 @@ public final class ActiveServices { return; } try { - bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false, + false); } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } @@ -2463,8 +2468,8 @@ public final class ActiveServices { } private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, - boolean whileRestarting, boolean permissionsReviewRequired) - throws TransactionTooLargeException { + boolean whileRestarting, boolean permissionsReviewRequired, + boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { //Slog.i(TAG, "Bring up service:"); //r.dump(" "); @@ -2575,6 +2580,13 @@ public final class ActiveServices { } } + if (app != null && allowBackgroundActivityStarts) { + app.addAllowBackgroundActivityStartsToken(r); + // schedule removal of the whitelisting token after the timeout + removeAllowBackgroundActivityStartsServiceToken(app, r, + SERVICE_BG_ACTIVITY_START_TIMEOUT_MS); + } + if (r.fgRequired) { if (DEBUG_FOREGROUND_SERVICE) { Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 94fc552fa1c2..380cc25e15d9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -14997,7 +14997,7 @@ public class ActivityManagerService extends IActivityManager.Stub oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo, oldRecord.intent, Activity.RESULT_CANCELED, null, null, - false, false, oldRecord.userId); + false, false, oldRecord.userId, oldRecord); } catch (RemoteException e) { Slog.w(TAG, "Failure [" + queue.mQueueName + "] sending broadcast result of " diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a11ebfd3e419..f0b137a6ccb1 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -74,6 +74,9 @@ public final class BroadcastQueue { static final int MAX_BROADCAST_SUMMARY_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 25 : 300; + // For how long after a whitelisted receiver's start its process can start a background activity + private static final int RECEIVER_BG_ACTIVITY_START_TIMEOUT_MS = 10_000; + final ActivityManagerService mService; /** @@ -551,13 +554,23 @@ public final class BroadcastQueue { void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, - boolean ordered, boolean sticky, int sendingUser) throws RemoteException { + boolean ordered, boolean sticky, int sendingUser, BroadcastRecord br) + throws RemoteException { // Send the intent to the receiver asynchronously using one-way binder calls. if (app != null) { if (app.thread != null) { // If we have an app thread, do the call through that so it is // correctly ordered with other one-way calls. try { + if (br.allowBackgroundActivityStarts) { + app.addAllowBackgroundActivityStartsToken(br); + // schedule removal of the whitelisting token after the timeout + mHandler.postDelayed(() -> { + if (app != null) { + app.removeAllowBackgroundActivityStartsToken(br); + } + }, RECEIVER_BG_ACTIVITY_START_TIMEOUT_MS); + } app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser, app.getReportedProcState()); // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting @@ -783,7 +796,7 @@ public final class BroadcastQueue { } else { performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, - r.resultExtras, r.ordered, r.initialSticky, r.userId); + r.resultExtras, r.ordered, r.initialSticky, r.userId, r); } if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; @@ -1082,7 +1095,7 @@ public final class BroadcastQueue { } performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, - r.resultData, r.resultExtras, false, false, r.userId); + r.resultData, r.resultExtras, false, false, r.userId, r); // Set this to null so that the reference // (local and remote) isn't kept in the mBroadcastHistory. r.resultTo = null; diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index 0b27a8ad77dc..af56352b8cc0 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -384,6 +384,9 @@ public final class PendingIntentRecord extends IIntentSender.Stub { final boolean allowTrampoline = uid != callingUid && controller.mAtmInternal.isUidForeground(callingUid); + // note: we on purpose don't pass in the information about the PendingIntent's creator, + // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because + // it's not unusual for the creator's process to not be alive at this time switch (key.type) { case ActivityManager.INTENT_SENDER_ACTIVITY: try { diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 1d71d8764bf7..678a896bddbc 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -753,8 +753,8 @@ class ActivityStarter { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "shouldAbortBackgroundActivityStart"); abortBackgroundStart = shouldAbortBackgroundActivityStart(callingUid, callingPid, - callingPackage, realCallingUid, callerApp, originatingPendingIntent, - allowBackgroundActivityStart, intent); + callingPackage, realCallingUid, realCallingPid, callerApp, + originatingPendingIntent, allowBackgroundActivityStart, intent); } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } @@ -914,22 +914,14 @@ class ActivityStarter { } private boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid, - final String callingPackage, int realCallingUid, WindowProcessController callerApp, - PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart, - Intent intent) { + final String callingPackage, int realCallingUid, int realCallingPid, + WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent, + boolean allowBackgroundActivityStart, Intent intent) { // don't abort for the most important UIDs if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID || callingUid == Process.NFC_UID) { return false; } - // don't abort if the callerApp has any visible activity - if (callerApp != null && callerApp.hasForegroundActivities()) { - return false; - } - // don't abort if the callerApp is instrumenting with background activity starts privileges - if (callerApp != null && callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) { - return false; - } // don't abort if the callingUid is in the foreground or is a persistent system process final int callingUidProcState = mService.getUidStateLocked(callingUid); final boolean callingUidHasAnyVisibleWindow = @@ -967,9 +959,26 @@ class ActivityStarter { return false; } } - // don't abort if the caller is currently temporarily whitelisted - if (callerApp != null && callerApp.areBackgroundActivityStartsAllowed()) { - return false; + // If we don't have callerApp at this point, no caller was provided to startActivity(). + // That's the case for PendingIntent-based starts, since the creator's process might not be + // up and alive. If that's the case, we retrieve the WindowProcessController for the send() + // caller, so that we can make the decision based on its foreground/whitelisted state. + if (callerApp == null) { + callerApp = mService.getProcessController(realCallingPid, realCallingUid); + } + if (callerApp != null) { + // don't abort if the callerApp has any visible activity + if (callerApp.hasForegroundActivities()) { + return false; + } + // don't abort if the callerApp is instrumenting with background activity starts privs + if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) { + return false; + } + // don't abort if the caller is currently temporarily whitelisted + if (callerApp.areBackgroundActivityStartsAllowed()) { + return false; + } } // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid) @@ -996,6 +1005,7 @@ class ActivityStarter { + "; originatingPendingIntent: " + originatingPendingIntent + "; isBgStartWhitelisted: " + allowBackgroundActivityStart + "; intent: " + intent + + "; callerApp: " + callerApp + "]"); // log aborted activity start to TRON if (mService.isActivityStartsLoggingEnabled()) { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index b6bac6131986..7aa34819692b 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -5666,6 +5666,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return null; } + WindowProcessController getProcessController(int pid, int uid) { + final ArrayMap<String, SparseArray<WindowProcessController>> pmap = mProcessNames.getMap(); + for (int i = pmap.size()-1; i >= 0; i--) { + final SparseArray<WindowProcessController> procs = pmap.valueAt(i); + for (int j = procs.size() - 1; j >= 0; j--) { + final WindowProcessController proc = procs.valueAt(j); + if (UserHandle.isApp(uid) && proc.getPid() == pid && proc.mUid == uid) { + return proc; + } + } + } + return null; + } + int getUidStateLocked(int uid) { return mActiveUids.get(uid, PROCESS_STATE_NONEXISTENT); } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 0fb900a6eaf4..465f4131ee8e 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -986,7 +986,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio @Override public String toString() { - return mOwner.toString(); + return mOwner != null ? mOwner.toString() : null; } public void dump(PrintWriter pw, String prefix) { |