Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +291 −281 Original line number Diff line number Diff line Loading @@ -29,12 +29,12 @@ import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; import static com.android.server.am.ActivityManagerDebugConfig.*; import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; Loading Loading @@ -76,7 +76,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; Loading Loading @@ -107,7 +106,6 @@ import android.os.TransactionTooLargeException; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.os.storage.StorageManager; import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; Loading @@ -123,7 +121,6 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.InputEvent; import android.view.Surface; import android.widget.Toast; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; Loading Loading @@ -1549,7 +1546,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // to ensure that it is safe to do so. If the upcoming activity will also // be part of the voice session, we can only launch it if it has explicitly // said it supports the VOICE category, or it is a part of the calling app. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { try { intent.addCategory(Intent.CATEGORY_VOICE); Loading Loading @@ -1596,63 +1593,9 @@ public final class ActivityStackSupervisor implements DisplayListener { return err; } boolean abort = false; final int startAnyPerm = mService.checkPermission( START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm != PERMISSION_GRANTED) { final int componentRestriction = getComponentRestrictionForCallingPackage( aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity); final int actionRestriction = getActionRestrictionForCallingPackage( intent.getAction(), callingPackage, callingPid, callingUid); if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } String msg; if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " with revoked permission " + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()); } else if (!aInfo.exported) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " not exported from uid " + aInfo.applicationInfo.uid; } else { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + aInfo.permission; } Slog.w(TAG, msg); throw new SecurityException(msg); } if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) { String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + AppOpsManager.permissionToOp( ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction())); Slog.w(TAG, message); abort = true; } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) { String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission); Slog.w(TAG, message); abort = true; } } boolean abort = !checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp, resultRecord, resultStack); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); Loading Loading @@ -1682,7 +1625,7 @@ public final class ActivityStackSupervisor implements DisplayListener { | PendingIntent.FLAG_IMMUTABLE, null); int flags = intent.getFlags(); intent = km.createConfirmDeviceCredentialIntent(null, null); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK intent.addFlags(FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); Loading Loading @@ -1801,6 +1744,66 @@ public final class ActivityStackSupervisor implements DisplayListener { return err; } private boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, boolean ignoreTargetSecurity, ProcessRecord callerApp, ActivityRecord resultRecord, ActivityStack resultStack) { final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm == PERMISSION_GRANTED) { return true; } final int componentRestriction = getComponentRestrictionForCallingPackage( aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity); final int actionRestriction = getActionRestrictionForCallingPackage( intent.getAction(), callingPackage, callingPid, callingUid); if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } final String msg; if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " with revoked permission " + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()); } else if (!aInfo.exported) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " not exported from uid " + aInfo.applicationInfo.uid; } else { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + aInfo.permission; } Slog.w(TAG, msg); throw new SecurityException(msg); } if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) { final String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + AppOpsManager.permissionToOp( ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction())); Slog.w(TAG, message); return false; } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) { final String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission); Slog.w(TAG, message); return false; } return true; } private UserInfo getUserInfo(int userId) { final long identity = Binder.clearCallingIdentity(); try { Loading Loading @@ -1879,7 +1882,7 @@ public final class ActivityStackSupervisor implements DisplayListener { return ACTIVITY_RESTRICTION_NONE; } ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) { private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) { final TaskRecord task = r.task; if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) { Loading Loading @@ -1994,7 +1997,7 @@ public final class ActivityStackSupervisor implements DisplayListener { Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " + "\"singleInstance\" or \"singleTask\""); launchFlags &= ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK); } else { switch (r.info.documentLaunchMode) { case ActivityInfo.DOCUMENT_LAUNCH_NONE: Loading @@ -2006,7 +2009,7 @@ public final class ActivityStackSupervisor implements DisplayListener { launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; break; case ActivityInfo.DOCUMENT_LAUNCH_NEVER: launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK; launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK; break; } } Loading @@ -2015,7 +2018,7 @@ public final class ActivityStackSupervisor implements DisplayListener { && !launchSingleTask && !launchSingleInstance && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0; if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 if (r.resultTo != null && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 && r.resultTo.task.stack != null) { // For whatever reason this activity is being launched into a new // task... yet the caller has requested a result back. Well, that Loading @@ -2030,15 +2033,15 @@ public final class ActivityStackSupervisor implements DisplayListener { } if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } // If we are actually going to launch in to a new task, there are some cases where // we further want to do multiple task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { if (launchTaskBehind || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) { launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK; launchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK; } } Loading Loading @@ -2107,8 +2110,8 @@ public final class ActivityStackSupervisor implements DisplayListener { // If task is empty, then adopt the interesting intent launch flags in to the // activity being started. if (root == null) { final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; launchFlags = (launchFlags&~flagsOfInterest) | (baseIntent.getFlags()&flagsOfInterest); Loading @@ -2119,7 +2122,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // If the task is not empty and the caller is asking to start it as the root // of a new task, then we don't actually want to start this on the task. We // will bring the task to the front, and possibly give it a new intent. } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { } else if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { addingToTask = false; } else { Loading @@ -2143,20 +2146,20 @@ public final class ActivityStackSupervisor implements DisplayListener { if (sourceRecord == null) { // This activity is not being started from another... in this // case we -always- start a new task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { Slog.w(TAG, "startActivity called from non-Activity context; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // The original activity who is starting us is running as a single // instance... this new activity it is starting must go on its // own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } else if (launchSingleInstance || launchSingleTask) { // The activity being started is a single instance... it always // gets launched into its own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } } Loading @@ -2170,10 +2173,10 @@ public final class ActivityStackSupervisor implements DisplayListener { // so we don't want to blindly throw it in to that task. Instead we will take // the NEW_TASK flow and try to find a task for it. But save the task information // so it can be used when creating the new task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } Loading @@ -2192,25 +2195,8 @@ public final class ActivityStackSupervisor implements DisplayListener { intent.setFlags(launchFlags); final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0; // We may want to try to place the new activity in to an existing task. We always // do this if the target activity is singleTask or singleInstance; we will also do // this if NEW_TASK has been requested, and there is not an additional qualifier telling // us to still place it in a new task: multi task, always doc mode, or being asked to // launch this as a new task behind the current one. if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || launchSingleInstance || launchSingleTask) { // If bring to front is requested, and no result is requested and we have not // been given an explicit task to launch in to, and // we can find a task that was started with this same // component, then instead of launching bring that one to the front. if (inTask == null && r.resultTo == null) { // See if there is a task to bring to the front. If this is // a SINGLE_INSTANCE activity, there can be one and only one // instance of it in the history, and it is always in its own // unique task, so we do a special search. ActivityRecord intentActivity = !launchSingleInstance ? findTaskLocked(r) : findActivityLocked(intent, r.info); ActivityRecord intentActivity = getReusableIntentActivity(r, inTask, intent, launchSingleInstance, launchSingleTask, launchFlags); if (intentActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused // but still needs to be a lock task mode violation since the task gets Loading @@ -2226,10 +2212,8 @@ public final class ActivityStackSupervisor implements DisplayListener { r.task = intentActivity.task; } if (intentActivity.task.intent == null) { // This task was started because of movement of // the activity based on affinity... now that we // are actually launching it, we can assign the // base intent. // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. intentActivity.task.setIntent(r); } targetStack = intentActivity.task.stack; Loading Loading @@ -2257,8 +2241,7 @@ public final class ActivityStackSupervisor implements DisplayListener { targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation, options, r.appTimeTracker, "bringingFoundTaskToFront"); movedToFront = true; if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); Loading Loading @@ -2310,8 +2293,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // from the task up to the one being started. In most // cases this means we are resetting the task to its // initial state. ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags); ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags); if (top != null) { if (top.frontOfTask) { // Activity aliases may mean we use different Loading @@ -2320,8 +2302,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // intent. top.task.setIntent(r); } ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage); } else { // A special case: we need to start the activity because it is not Loading Loading @@ -2401,8 +2382,6 @@ public final class ActivityStackSupervisor implements DisplayListener { return ActivityManager.START_TASK_TO_FRONT; } } } } //String uri = r.intent.toURI(); //Intent intent2 = new Intent(uri); Loading Loading @@ -2460,7 +2439,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // Should this be considered a new task? if (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; targetStack = computeStackFocus(r, newTask, newBounds); if (doResume) { Loading Loading @@ -2646,6 +2625,37 @@ public final class ActivityStackSupervisor implements DisplayListener { return ActivityManager.START_SUCCESS; } /** * Decide whether the new activity should be inserted into an existing task. Returns null if not * or an ActivityRecord with the task into which the new activity should be added. */ private ActivityRecord getReusableIntentActivity(ActivityRecord r, TaskRecord inTask, Intent intent, boolean launchSingleInstance, boolean launchSingleTask, int launchFlags) { // We may want to try to place the new activity in to an existing task. We always // do this if the target activity is singleTask or singleInstance; we will also do // this if NEW_TASK has been requested, and there is not an additional qualifier telling // us to still place it in a new task: multi task, always doc mode, or being asked to // launch this as a new task behind the current one. boolean putIntoExistingTask = ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || launchSingleInstance || launchSingleTask; // If bring to front is requested, and no result is requested and we have not // been given an explicit task to launch in to, and // we can find a task that was started with this same // component, then instead of launching bring that one to the front. putIntoExistingTask &= inTask == null && r.resultTo == null; ActivityRecord intentActivity = null; if (putIntoExistingTask) { // See if there is a task to bring to the front. If this is // a SINGLE_INSTANCE activity, there can be one and only one // instance of it in the history, and it is always in its own // unique task, so we do a special search. intentActivity = launchSingleInstance ? findActivityLocked(intent, r.info) : findTaskLocked(r); } return intentActivity; } final void doPendingActivityLaunchesLocked(boolean doResume) { while (!mPendingActivityLaunches.isEmpty()) { PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); Loading Loading @@ -4708,8 +4718,8 @@ public final class ActivityStackSupervisor implements DisplayListener { } class ActivityContainer extends android.app.IActivityContainer.Stub { final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION; final static int FORCE_NEW_TASK_FLAGS = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION; final int mStackId; IActivityContainerCallback mCallback = null; final ActivityStack mStack; Loading Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +291 −281 Original line number Diff line number Diff line Loading @@ -29,12 +29,12 @@ import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; import static com.android.server.am.ActivityManagerDebugConfig.*; import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; Loading Loading @@ -76,7 +76,6 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.content.res.Configuration; Loading Loading @@ -107,7 +106,6 @@ import android.os.TransactionTooLargeException; import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.os.storage.StorageManager; import android.provider.MediaStore; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; Loading @@ -123,7 +121,6 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.InputEvent; import android.view.Surface; import android.widget.Toast; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.app.IVoiceInteractor; Loading Loading @@ -1549,7 +1546,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // to ensure that it is safe to do so. If the upcoming activity will also // be part of the voice session, we can only launch it if it has explicitly // said it supports the VOICE category, or it is a part of the calling app. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { try { intent.addCategory(Intent.CATEGORY_VOICE); Loading Loading @@ -1596,63 +1593,9 @@ public final class ActivityStackSupervisor implements DisplayListener { return err; } boolean abort = false; final int startAnyPerm = mService.checkPermission( START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm != PERMISSION_GRANTED) { final int componentRestriction = getComponentRestrictionForCallingPackage( aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity); final int actionRestriction = getActionRestrictionForCallingPackage( intent.getAction(), callingPackage, callingPid, callingUid); if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } String msg; if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " with revoked permission " + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()); } else if (!aInfo.exported) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " not exported from uid " + aInfo.applicationInfo.uid; } else { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + aInfo.permission; } Slog.w(TAG, msg); throw new SecurityException(msg); } if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) { String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + AppOpsManager.permissionToOp( ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction())); Slog.w(TAG, message); abort = true; } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) { String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission); Slog.w(TAG, message); abort = true; } } boolean abort = !checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp, resultRecord, resultStack); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); Loading Loading @@ -1682,7 +1625,7 @@ public final class ActivityStackSupervisor implements DisplayListener { | PendingIntent.FLAG_IMMUTABLE, null); int flags = intent.getFlags(); intent = km.createConfirmDeviceCredentialIntent(null, null); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK intent.addFlags(FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); Loading Loading @@ -1801,6 +1744,66 @@ public final class ActivityStackSupervisor implements DisplayListener { return err; } private boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, boolean ignoreTargetSecurity, ProcessRecord callerApp, ActivityRecord resultRecord, ActivityStack resultStack) { final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid); if (startAnyPerm == PERMISSION_GRANTED) { return true; } final int componentRestriction = getComponentRestrictionForCallingPackage( aInfo, callingPackage, callingPid, callingUid, ignoreTargetSecurity); final int actionRestriction = getActionRestrictionForCallingPackage( intent.getAction(), callingPackage, callingPid, callingUid); if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { if (resultRecord != null) { resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, Activity.RESULT_CANCELED, null); } final String msg; if (actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " with revoked permission " + ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction()); } else if (!aInfo.exported) { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " not exported from uid " + aInfo.applicationInfo.uid; } else { msg = "Permission Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + aInfo.permission; } Slog.w(TAG, msg); throw new SecurityException(msg); } if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) { final String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + AppOpsManager.permissionToOp( ACTION_TO_RUNTIME_PERMISSION.get(intent.getAction())); Slog.w(TAG, message); return false; } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) { final String message = "Appop Denial: starting " + intent.toString() + " from " + callerApp + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires appop " + AppOpsManager.permissionToOp(aInfo.permission); Slog.w(TAG, message); return false; } return true; } private UserInfo getUserInfo(int userId) { final long identity = Binder.clearCallingIdentity(); try { Loading Loading @@ -1879,7 +1882,7 @@ public final class ActivityStackSupervisor implements DisplayListener { return ACTIVITY_RESTRICTION_NONE; } ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) { private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) { final TaskRecord task = r.task; if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) { Loading Loading @@ -1994,7 +1997,7 @@ public final class ActivityStackSupervisor implements DisplayListener { Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " + "\"singleInstance\" or \"singleTask\""); launchFlags &= ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK); } else { switch (r.info.documentLaunchMode) { case ActivityInfo.DOCUMENT_LAUNCH_NONE: Loading @@ -2006,7 +2009,7 @@ public final class ActivityStackSupervisor implements DisplayListener { launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT; break; case ActivityInfo.DOCUMENT_LAUNCH_NEVER: launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK; launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK; break; } } Loading @@ -2015,7 +2018,7 @@ public final class ActivityStackSupervisor implements DisplayListener { && !launchSingleTask && !launchSingleInstance && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0; if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 if (r.resultTo != null && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 && r.resultTo.task.stack != null) { // For whatever reason this activity is being launched into a new // task... yet the caller has requested a result back. Well, that Loading @@ -2030,15 +2033,15 @@ public final class ActivityStackSupervisor implements DisplayListener { } if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } // If we are actually going to launch in to a new task, there are some cases where // we further want to do multiple task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { if (launchTaskBehind || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) { launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK; launchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK; } } Loading Loading @@ -2107,8 +2110,8 @@ public final class ActivityStackSupervisor implements DisplayListener { // If task is empty, then adopt the interesting intent launch flags in to the // activity being started. if (root == null) { final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; launchFlags = (launchFlags&~flagsOfInterest) | (baseIntent.getFlags()&flagsOfInterest); Loading @@ -2119,7 +2122,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // If the task is not empty and the caller is asking to start it as the root // of a new task, then we don't actually want to start this on the task. We // will bring the task to the front, and possibly give it a new intent. } else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { } else if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { addingToTask = false; } else { Loading @@ -2143,20 +2146,20 @@ public final class ActivityStackSupervisor implements DisplayListener { if (sourceRecord == null) { // This activity is not being started from another... in this // case we -always- start a new task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) { Slog.w(TAG, "startActivity called from non-Activity context; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { // The original activity who is starting us is running as a single // instance... this new activity it is starting must go on its // own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } else if (launchSingleInstance || launchSingleTask) { // The activity being started is a single instance... it always // gets launched into its own task. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; } } Loading @@ -2170,10 +2173,10 @@ public final class ActivityStackSupervisor implements DisplayListener { // so we don't want to blindly throw it in to that task. Instead we will take // the NEW_TASK flow and try to find a task for it. But save the task information // so it can be used when creating the new task. if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; launchFlags |= FLAG_ACTIVITY_NEW_TASK; newTaskInfo = sourceRecord.info; newTaskIntent = sourceRecord.task.intent; } Loading @@ -2192,25 +2195,8 @@ public final class ActivityStackSupervisor implements DisplayListener { intent.setFlags(launchFlags); final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0; // We may want to try to place the new activity in to an existing task. We always // do this if the target activity is singleTask or singleInstance; we will also do // this if NEW_TASK has been requested, and there is not an additional qualifier telling // us to still place it in a new task: multi task, always doc mode, or being asked to // launch this as a new task behind the current one. if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || launchSingleInstance || launchSingleTask) { // If bring to front is requested, and no result is requested and we have not // been given an explicit task to launch in to, and // we can find a task that was started with this same // component, then instead of launching bring that one to the front. if (inTask == null && r.resultTo == null) { // See if there is a task to bring to the front. If this is // a SINGLE_INSTANCE activity, there can be one and only one // instance of it in the history, and it is always in its own // unique task, so we do a special search. ActivityRecord intentActivity = !launchSingleInstance ? findTaskLocked(r) : findActivityLocked(intent, r.info); ActivityRecord intentActivity = getReusableIntentActivity(r, inTask, intent, launchSingleInstance, launchSingleTask, launchFlags); if (intentActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused // but still needs to be a lock task mode violation since the task gets Loading @@ -2226,10 +2212,8 @@ public final class ActivityStackSupervisor implements DisplayListener { r.task = intentActivity.task; } if (intentActivity.task.intent == null) { // This task was started because of movement of // the activity based on affinity... now that we // are actually launching it, we can assign the // base intent. // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. intentActivity.task.setIntent(r); } targetStack = intentActivity.task.stack; Loading Loading @@ -2257,8 +2241,7 @@ public final class ActivityStackSupervisor implements DisplayListener { targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation, options, r.appTimeTracker, "bringingFoundTaskToFront"); movedToFront = true; if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); Loading Loading @@ -2310,8 +2293,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // from the task up to the one being started. In most // cases this means we are resetting the task to its // initial state. ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags); ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags); if (top != null) { if (top.frontOfTask) { // Activity aliases may mean we use different Loading @@ -2320,8 +2302,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // intent. top.task.setIntent(r); } ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage); } else { // A special case: we need to start the activity because it is not Loading Loading @@ -2401,8 +2382,6 @@ public final class ActivityStackSupervisor implements DisplayListener { return ActivityManager.START_TASK_TO_FRONT; } } } } //String uri = r.intent.toURI(); //Intent intent2 = new Intent(uri); Loading Loading @@ -2460,7 +2439,7 @@ public final class ActivityStackSupervisor implements DisplayListener { // Should this be considered a new task? if (r.resultTo == null && inTask == null && !addingToTask && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; targetStack = computeStackFocus(r, newTask, newBounds); if (doResume) { Loading Loading @@ -2646,6 +2625,37 @@ public final class ActivityStackSupervisor implements DisplayListener { return ActivityManager.START_SUCCESS; } /** * Decide whether the new activity should be inserted into an existing task. Returns null if not * or an ActivityRecord with the task into which the new activity should be added. */ private ActivityRecord getReusableIntentActivity(ActivityRecord r, TaskRecord inTask, Intent intent, boolean launchSingleInstance, boolean launchSingleTask, int launchFlags) { // We may want to try to place the new activity in to an existing task. We always // do this if the target activity is singleTask or singleInstance; we will also do // this if NEW_TASK has been requested, and there is not an additional qualifier telling // us to still place it in a new task: multi task, always doc mode, or being asked to // launch this as a new task behind the current one. boolean putIntoExistingTask = ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 && (launchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0) || launchSingleInstance || launchSingleTask; // If bring to front is requested, and no result is requested and we have not // been given an explicit task to launch in to, and // we can find a task that was started with this same // component, then instead of launching bring that one to the front. putIntoExistingTask &= inTask == null && r.resultTo == null; ActivityRecord intentActivity = null; if (putIntoExistingTask) { // See if there is a task to bring to the front. If this is // a SINGLE_INSTANCE activity, there can be one and only one // instance of it in the history, and it is always in its own // unique task, so we do a special search. intentActivity = launchSingleInstance ? findActivityLocked(intent, r.info) : findTaskLocked(r); } return intentActivity; } final void doPendingActivityLaunchesLocked(boolean doResume) { while (!mPendingActivityLaunches.isEmpty()) { PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); Loading Loading @@ -4708,8 +4718,8 @@ public final class ActivityStackSupervisor implements DisplayListener { } class ActivityContainer extends android.app.IActivityContainer.Stub { final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION; final static int FORCE_NEW_TASK_FLAGS = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION; final int mStackId; IActivityContainerCallback mCallback = null; final ActivityStack mStack; Loading