diff options
| author | 2019-01-12 14:20:38 +0000 | |
|---|---|---|
| committer | 2019-01-12 14:20:38 +0000 | |
| commit | ceeadaed26425b59d509eb2c9e152cb422c68a65 (patch) | |
| tree | e7a5ed01f010553a8631a035e9b9ae73e564a32e | |
| parent | 6c6528f648405cb89112e2f90d5d71359136c1a7 (diff) | |
| parent | c8aa91bd0a0af06146f1ba60aa049c77316fff59 (diff) | |
Merge "Temporarily whitelist processes to open activities from background when service-based PendingIntent was whitelisted"
6 files changed, 50 insertions, 7 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 9d44e58112c5..c90e40411240 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -258,8 +258,8 @@ public abstract class ActivityManagerInternal { Bundle resultExtras, String requiredPermission, Bundle bOptions, boolean serialized, boolean sticky, int userId, boolean allowBackgroundActivityStarts); public abstract ComponentName startServiceInPackage(int uid, Intent service, - String resolvedType, boolean fgRequired, String callingPackage, int userId) - throws TransactionTooLargeException; + String resolvedType, boolean fgRequired, String callingPackage, int userId, + boolean allowBackgroundActivityStarts) throws TransactionTooLargeException; public abstract void disconnectActivityFromServices(Object connectionHolder); public abstract void cleanUpServices(int userId, ComponentName component, Intent baseIntent); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 8ca4193a064f..bab9a6535376 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -130,6 +130,9 @@ public final class ActiveServices { // calling startForeground() before we ANR + stop it. static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000; + // For how long after a whitelisted service's start its process can start a background activity + private static final int SERVICE_BG_ACTIVITY_START_TIMEOUT_MS = 10*1000; + final ActivityManagerService mAm; // Maximum number of services that we allow to start in the background @@ -398,6 +401,14 @@ public final class ActiveServices { ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { + return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, + callingPackage, userId, false); + } + + ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, + int callingPid, int callingUid, boolean fgRequired, String callingPackage, + final int userId, boolean allowBackgroundActivityStarts) + throws TransactionTooLargeException { if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType + " args=" + service.getExtras()); @@ -622,10 +633,28 @@ public final class ActiveServices { } } + if (allowBackgroundActivityStarts) { + ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); + if (proc != null) { + proc.addAllowBackgroundActivityStartsToken(r); + // schedule removal of the whitelisting token after the timeout + removeAllowBackgroundActivityStartsServiceToken(proc, r, + SERVICE_BG_ACTIVITY_START_TIMEOUT_MS); + } + } ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; } + private void removeAllowBackgroundActivityStartsServiceToken(ProcessRecord proc, + ServiceRecord r, int delayMillis) { + mAm.mHandler.postDelayed(() -> { + if (proc != null) { + proc.removeAllowBackgroundActivityStartsToken(r); + } + }, delayMillis); + } + private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r, String callingPackage, int callingUid, Intent service, boolean callerFg, final int userId) { @@ -752,6 +781,9 @@ public final class ActiveServices { if (r.record != null) { final long origId = Binder.clearCallingIdentity(); try { + // immediately remove bg activity whitelisting token if there was one + removeAllowBackgroundActivityStartsServiceToken(callerApp, r.record, + 0 /* delayMillis */); stopServiceLocked(r.record); } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bb239acb5c60..26141f7d7066 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -19495,8 +19495,8 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public ComponentName startServiceInPackage(int uid, Intent service, String resolvedType, - boolean fgRequired, String callingPackage, int userId) - throws TransactionTooLargeException { + boolean fgRequired, String callingPackage, int userId, + boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { synchronized(ActivityManagerService.this) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "startServiceInPackage: " + service + " type=" + resolvedType); @@ -19504,7 +19504,8 @@ public class ActivityManagerService extends IActivityManager.Stub ComponentName res; try { res = mServices.startServiceLocked(null, service, - resolvedType, -1, uid, fgRequired, callingPackage, userId); + resolvedType, -1, uid, fgRequired, callingPackage, userId, + allowBackgroundActivityStarts); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index b675d9d4f9cf..98c9ad66bc5c 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -51,6 +51,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub { public static final int FLAG_ACTIVITY_SENDER = 1 << 0; public static final int FLAG_BROADCAST_SENDER = 1 << 1; + public static final int FLAG_SERVICE_SENDER = 1 << 2; final PendingIntentController controller; final Key key; @@ -62,6 +63,7 @@ public final class PendingIntentRecord extends IIntentSender.Stub { private RemoteCallbackList<IResultReceiver> mCancelCallbacks; private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>(); private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>(); + private ArraySet<IBinder> mAllowBgActivityStartsForServiceSender = new ArraySet<>(); String stringName; String lastTagPrefix; @@ -228,6 +230,9 @@ public final class PendingIntentRecord extends IIntentSender.Stub { if ((flags & FLAG_BROADCAST_SENDER) != 0) { mAllowBgActivityStartsForBroadcastSender.add(token); } + if ((flags & FLAG_SERVICE_SENDER) != 0) { + mAllowBgActivityStartsForServiceSender.add(token); + } } public void registerCancelListenerLocked(IResultReceiver receiver) { @@ -426,7 +431,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub { try { controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType, key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE, - key.packageName, userId); + key.packageName, userId, + mAllowBgActivityStartsForServiceSender.contains(whitelistToken)); } catch (RuntimeException e) { Slog.w(TAG, "Unable to send startService intent", e); } catch (TransactionTooLargeException e) { diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 0d0824a74cdd..054c83080d98 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -1142,11 +1142,13 @@ final class ProcessRecord implements WindowProcessListener { } void addAllowBackgroundActivityStartsToken(Binder entity) { + if (entity == null) return; mAllowBackgroundActivityStartsTokens.add(entity); mWindowProcessController.setAllowBackgroundActivityStarts(true); } void removeAllowBackgroundActivityStartsToken(Binder entity) { + if (entity == null) return; mAllowBackgroundActivityStartsTokens.remove(entity); mWindowProcessController.setAllowBackgroundActivityStarts( !mAllowBackgroundActivityStartsTokens.isEmpty()); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index c68e0f98325e..7ecdad27c505 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -77,6 +77,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER; import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER; +import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER; import static com.android.server.utils.PriorityDump.PRIORITY_ARG; import static com.android.server.utils.PriorityDump.PRIORITY_ARG_CRITICAL; import static com.android.server.utils.PriorityDump.PRIORITY_ARG_NORMAL; @@ -4452,7 +4453,8 @@ public class NotificationManagerService extends SystemService { am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(), WHITELIST_TOKEN, duration); am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(), - WHITELIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER)); + WHITELIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER + | FLAG_SERVICE_SENDER)); } } } |