From 95465200b0f652c48d40ca1028238763dd647900 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 15 Sep 2014 16:21:55 -0700 Subject: [PATCH] Fix issue #17507017: took ~3 seconds to move an app to the foreground This is because of the 5 second timeout from when the user can bring home to the foreground until regular third party apps can launch an activity on top of it. Activities launched from notifications look like they are being launched by the app, so get impacted by the timeout. Fix this be also looking at the actual caller to see if they are allowed to pop in front regardless of the timeout. Change-Id: I63fbc2bcabf585e6d2810a2309f0613fdf91fdf5 --- .../server/am/ActivityManagerService.java | 45 ++++++++++--------- .../com/android/server/am/ActivityStack.java | 2 +- .../server/am/ActivityStackSupervisor.java | 35 ++++++++------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 95d33e77ccb54..6d8e10574fe57 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3360,7 +3360,7 @@ public final class ActivityManagerService extends ActivityManagerNative intent.setComponent(new ComponentName( ri.activityInfo.packageName, ri.activityInfo.name)); mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo, - null, null, null, null, 0, 0, 0, null, 0, null, false, null, null, + null, null, null, null, 0, 0, 0, null, 0, 0, 0, null, false, null, null, null); } } @@ -3759,8 +3759,8 @@ public final class ActivityManagerService extends ActivityManagerNative final long origId = Binder.clearCallingIdentity(); int res = mStackSupervisor.startActivityLocked(r.app.thread, intent, r.resolvedType, aInfo, null, null, resultTo != null ? resultTo.appToken : null, - resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage, 0, - options, false, null, null, null); + resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage, + -1, r.launchedFromUid, 0, options, false, null, null, null); Binder.restoreCallingIdentity(origId); r.finishing = wasFinishing; @@ -8482,7 +8482,7 @@ public final class ActivityManagerService extends ActivityManagerNative void moveTaskToFrontLocked(int taskId, int flags, Bundle options) { if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(), - Binder.getCallingUid(), "Task to front")) { + Binder.getCallingUid(), -1, -1, "Task to front")) { ActivityOptions.abort(options); return; } @@ -8524,7 +8524,7 @@ public final class ActivityManagerService extends ActivityManagerNative ActivityStack stack = tr.stack; if (stack.mResumedActivity != null && stack.mResumedActivity.task == tr) { if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(), - Binder.getCallingUid(), "Task to back")) { + Binder.getCallingUid(), -1, -1, "Task to back")) { return; } } @@ -8576,7 +8576,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(this) { if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(), - Binder.getCallingUid(), "Task backwards")) { + Binder.getCallingUid(), -1, -1, "Task backwards")) { return; } final long origId = Binder.clearCallingIdentity(); @@ -10120,20 +10120,31 @@ public final class ActivityManagerService extends ActivityManagerNative } } - boolean checkAppSwitchAllowedLocked(int callingPid, int callingUid, - String name) { + boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid, + int callingPid, int callingUid, String name) { if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) { return true; } - final int perm = checkComponentPermission( - android.Manifest.permission.STOP_APP_SWITCHES, callingPid, - callingUid, -1, true); + int perm = checkComponentPermission( + android.Manifest.permission.STOP_APP_SWITCHES, sourcePid, + sourceUid, -1, true); if (perm == PackageManager.PERMISSION_GRANTED) { return true; } - - Slog.w(TAG, name + " request from " + callingUid + " stopped"); + + // If the actual IPC caller is different from the logical source, then + // also see if they are allowed to control app switches. + if (callingUid != -1 && callingUid != sourceUid) { + perm = checkComponentPermission( + android.Manifest.permission.STOP_APP_SWITCHES, callingPid, + callingUid, -1, true); + if (perm == PackageManager.PERMISSION_GRANTED) { + return true; + } + } + + Slog.w(TAG, name + " request from " + sourceUid + " stopped"); return false; } @@ -18944,13 +18955,7 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("Unable to find task ID " + mTaskId); } if (tr.getRootActivity() != null) { - long origId = Binder.clearCallingIdentity(); - try { - moveTaskToFrontLocked(tr.taskId, 0, null); - return; - } finally { - Binder.restoreCallingIdentity(origId); - } + moveTaskToFrontLocked(tr.taskId, 0, null); } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index e224ac01cde9e..2c07879561906 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2949,7 +2949,7 @@ final class ActivityStack { int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent, null, aInfo, null, null, parent.appToken, null, 0, -1, parent.launchedFromUid, parent.launchedFromPackage, - 0, null, true, null, null, null); + -1, parent.launchedFromUid, 0, null, true, null, null, null); foundParentInTask = res == ActivityManager.START_SUCCESS; } catch (RemoteException e) { foundParentInTask = false; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 7b6a20206124e..49404937344c1 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -785,8 +785,8 @@ public final class ActivityStackSupervisor implements DisplayListener { void startHomeActivity(Intent intent, ActivityInfo aInfo) { moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE); - startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0, - null, false, null, null, null); + startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, + 0, 0, 0, null, false, null, null, null); } final int startActivityMayWait(IApplicationThread caller, int callingUid, @@ -810,12 +810,14 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityContainer container = (ActivityContainer)iContainer; synchronized (mService) { + final int realCallingPid = Binder.getCallingPid(); + final int realCallingUid = Binder.getCallingUid(); int callingPid; if (callingUid >= 0) { callingPid = -1; } else if (caller == null) { - callingPid = Binder.getCallingPid(); - callingUid = Binder.getCallingUid(); + callingPid = realCallingPid; + callingUid = realCallingUid; } else { callingPid = callingUid = -1; } @@ -841,11 +843,11 @@ public final class ActivityStackSupervisor implements DisplayListener { if (mService.mHeavyWeightProcess != null && (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) { - int realCallingUid = callingUid; + int appCallingUid = callingUid; if (caller != null) { ProcessRecord callerApp = mService.getRecordForAppLocked(caller); if (callerApp != null) { - realCallingUid = callerApp.info.uid; + appCallingUid = callerApp.info.uid; } else { Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " @@ -857,7 +859,7 @@ public final class ActivityStackSupervisor implements DisplayListener { IIntentSender target = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, "android", - realCallingUid, userId, null, null, 0, new Intent[] { intent }, + appCallingUid, userId, null, null, 0, new Intent[] { intent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null); @@ -903,7 +905,8 @@ public final class ActivityStackSupervisor implements DisplayListener { int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, - requestCode, callingPid, callingUid, callingPackage, startFlags, options, + requestCode, callingPid, callingUid, callingPackage, + realCallingPid, realCallingUid, startFlags, options, componentSpecified, null, container, inTask); Binder.restoreCallingIdentity(origId); @@ -1017,7 +1020,8 @@ public final class ActivityStackSupervisor implements DisplayListener { theseOptions = null; } int res = startActivityLocked(caller, intent, resolvedTypes[i], - aInfo, null, null, resultTo, null, -1, callingPid, callingUid, callingPackage, + aInfo, null, null, resultTo, null, -1, callingPid, callingUid, + callingPackage, callingPid, callingUid, 0, theseOptions, componentSpecified, outActivity, null, null); if (res < 0) { return res; @@ -1248,7 +1252,8 @@ public final class ActivityStackSupervisor implements DisplayListener { Intent intent, String resolvedType, ActivityInfo aInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, - int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options, + int callingPid, int callingUid, String callingPackage, + int realCallingPid, int realCallingUid, int startFlags, Bundle options, boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container, TaskRecord inTask) { int err = ActivityManager.START_SUCCESS; @@ -1293,8 +1298,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final int launchFlags = intent.getFlags(); - if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 - && sourceRecord != null) { + if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { // Transfer the result target from the source activity to the new // one being started, including any failures. if (requestCode >= 0) { @@ -1344,8 +1348,8 @@ public final class ActivityStackSupervisor implements DisplayListener { if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { try { - if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(), - intent, resolvedType)) { + if (!AppGlobals.getPackageManager().activitySupportsIntent( + intent.getComponent(), intent, resolvedType)) { err = ActivityManager.START_NOT_VOICE_COMPATIBLE; } } catch (RemoteException e) { @@ -1439,7 +1443,8 @@ public final class ActivityStackSupervisor implements DisplayListener { final ActivityStack stack = getFocusedStack(); if (voiceSession == null && (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) { - if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) { + if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, + realCallingPid, realCallingUid, "Activity start")) { PendingActivityLaunch pal = new PendingActivityLaunch(r, sourceRecord, startFlags, stack); mPendingActivityLaunches.add(pal);