ActivityStarter.java revision 854809c074aabebf5b6520c361d1d3c7c22066d2
1package com.android.server.am;
2
3import static android.app.ActivityManager.StackId;
4import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
5import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
6import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
7import static android.app.ActivityManager.StackId.HOME_STACK_ID;
8import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
9import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
10import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
11import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
12import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE;
13import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
14import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
15import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
16import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
17import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
18import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
19import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
20import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
21import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
22import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
23import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
24import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
25import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
26import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
27import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
28import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
29import static com.android.server.am.ActivityManagerService.ANIMATE;
30import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
31import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
32import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
33import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
34import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
35import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
36import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
37
38import android.app.Activity;
39import android.app.ActivityManager;
40import android.app.ActivityOptions;
41import android.app.AppGlobals;
42import android.app.IActivityContainer;
43import android.app.IActivityManager;
44import android.app.IApplicationThread;
45import android.app.KeyguardManager;
46import android.app.PendingIntent;
47import android.app.ProfilerInfo;
48import android.content.ComponentName;
49import android.content.Context;
50import android.content.IIntentSender;
51import android.content.Intent;
52import android.content.IntentSender;
53import android.content.pm.ActivityInfo;
54import android.content.pm.ApplicationInfo;
55import android.content.pm.ResolveInfo;
56import android.content.pm.UserInfo;
57import android.content.res.Configuration;
58import android.graphics.Rect;
59import android.os.Binder;
60import android.os.Build;
61import android.os.Bundle;
62import android.os.IBinder;
63import android.os.RemoteException;
64import android.os.SystemClock;
65import android.os.UserHandle;
66import android.os.UserManager;
67import android.service.voice.IVoiceInteractionSession;
68import android.util.EventLog;
69import android.util.Slog;
70import android.view.Display;
71
72import com.android.internal.app.HeavyWeightSwitcherActivity;
73import com.android.internal.app.IVoiceInteractor;
74import com.android.internal.widget.LockPatternUtils;
75import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
76import com.android.server.wm.WindowManagerService;
77
78import java.util.ArrayList;
79
80/**
81 * Controller for interpreting how and then launching activities.
82 *
83 * This class collects all the logic for determining how an intent and flags should be turned into
84 * an activity and associated task and stack.
85 */
86public class ActivityStarter {
87    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
88    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
89    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
90    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
91    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
92
93    private final ActivityManagerService mService;
94    private final ActivityStackSupervisor mSupervisor;
95    private WindowManagerService mWindowManager;
96
97    final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
98
99    ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
100        mService = service;
101        mSupervisor = supervisor;
102    }
103
104    final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
105            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
106            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
107            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
108            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
109            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
110            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
111            TaskRecord inTask) {
112        int err = ActivityManager.START_SUCCESS;
113
114        ProcessRecord callerApp = null;
115        if (caller != null) {
116            callerApp = mService.getRecordForAppLocked(caller);
117            if (callerApp != null) {
118                callingPid = callerApp.pid;
119                callingUid = callerApp.info.uid;
120            } else {
121                Slog.w(TAG, "Unable to find app for caller " + caller
122                        + " (pid=" + callingPid + ") when starting: "
123                        + intent.toString());
124                err = ActivityManager.START_PERMISSION_DENIED;
125            }
126        }
127
128        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
129
130        if (err == ActivityManager.START_SUCCESS) {
131            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
132                    + "} from uid " + callingUid
133                    + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
134                    Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
135                    (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
136                            container.mActivityDisplay.mDisplayId)));
137        }
138
139        ActivityRecord sourceRecord = null;
140        ActivityRecord resultRecord = null;
141        if (resultTo != null) {
142            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
143            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
144                    "Will send result to " + resultTo + " " + sourceRecord);
145            if (sourceRecord != null) {
146                if (requestCode >= 0 && !sourceRecord.finishing) {
147                    resultRecord = sourceRecord;
148                }
149            }
150        }
151
152        final int launchFlags = intent.getFlags();
153
154        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
155            // Transfer the result target from the source activity to the new
156            // one being started, including any failures.
157            if (requestCode >= 0) {
158                ActivityOptions.abort(options);
159                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
160            }
161            resultRecord = sourceRecord.resultTo;
162            if (resultRecord != null && !resultRecord.isInStackLocked()) {
163                resultRecord = null;
164            }
165            resultWho = sourceRecord.resultWho;
166            requestCode = sourceRecord.requestCode;
167            sourceRecord.resultTo = null;
168            if (resultRecord != null) {
169                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
170            }
171            if (sourceRecord.launchedFromUid == callingUid) {
172                // The new activity is being launched from the same uid as the previous
173                // activity in the flow, and asking to forward its result back to the
174                // previous.  In this case the activity is serving as a trampoline between
175                // the two, so we also want to update its launchedFromPackage to be the
176                // same as the previous activity.  Note that this is safe, since we know
177                // these two packages come from the same uid; the caller could just as
178                // well have supplied that same package name itself.  This specifially
179                // deals with the case of an intent picker/chooser being launched in the app
180                // flow to redirect to an activity picked by the user, where we want the final
181                // activity to consider it to have been launched by the previous app activity.
182                callingPackage = sourceRecord.launchedFromPackage;
183            }
184        }
185
186        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
187            // We couldn't find a class that can handle the given Intent.
188            // That's the end of that!
189            err = ActivityManager.START_INTENT_NOT_RESOLVED;
190        }
191
192        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
193            // We couldn't find the specific class specified in the Intent.
194            // Also the end of the line.
195            err = ActivityManager.START_CLASS_NOT_FOUND;
196        }
197
198        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
199                && sourceRecord.task.voiceSession != null) {
200            // If this activity is being launched as part of a voice session, we need
201            // to ensure that it is safe to do so.  If the upcoming activity will also
202            // be part of the voice session, we can only launch it if it has explicitly
203            // said it supports the VOICE category, or it is a part of the calling app.
204            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
205                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
206                try {
207                    intent.addCategory(Intent.CATEGORY_VOICE);
208                    if (!AppGlobals.getPackageManager().activitySupportsIntent(
209                            intent.getComponent(), intent, resolvedType)) {
210                        Slog.w(TAG,
211                                "Activity being started in current voice task does not support voice: "
212                                        + intent);
213                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
214                    }
215                } catch (RemoteException e) {
216                    Slog.w(TAG, "Failure checking voice capabilities", e);
217                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
218                }
219            }
220        }
221
222        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
223            // If the caller is starting a new voice session, just make sure the target
224            // is actually allowing it to run this way.
225            try {
226                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
227                        intent, resolvedType)) {
228                    Slog.w(TAG,
229                            "Activity being started in new voice task does not support: "
230                                    + intent);
231                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
232                }
233            } catch (RemoteException e) {
234                Slog.w(TAG, "Failure checking voice capabilities", e);
235                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
236            }
237        }
238
239        final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
240
241        if (err != ActivityManager.START_SUCCESS) {
242            if (resultRecord != null) {
243                resultStack.sendActivityResultLocked(-1,
244                        resultRecord, resultWho, requestCode,
245                        Activity.RESULT_CANCELED, null);
246            }
247            ActivityOptions.abort(options);
248            return err;
249        }
250
251        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
252                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
253                resultRecord, resultStack);
254        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
255                callingPid, resolvedType, aInfo.applicationInfo);
256
257        if (mService.mController != null) {
258            try {
259                // The Intent we give to the watcher has the extra data
260                // stripped off, since it can contain private information.
261                Intent watchIntent = intent.cloneFilter();
262                abort |= !mService.mController.activityStarting(watchIntent,
263                        aInfo.applicationInfo.packageName);
264            } catch (RemoteException e) {
265                mService.mController = null;
266            }
267        }
268
269        UserInfo user = mSupervisor.getUserInfo(userId);
270        KeyguardManager km = (KeyguardManager) mService.mContext
271                .getSystemService(Context.KEYGUARD_SERVICE);
272        if (user.isManagedProfile()
273                && LockPatternUtils.isSeparateWorkChallengeEnabled()
274                && km.isDeviceLocked(userId)) {
275            IIntentSender target = mService.getIntentSenderLocked(
276                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
277                    Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
278                    new String[]{ resolvedType },
279                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
280                            | PendingIntent.FLAG_IMMUTABLE, null);
281            final int flags = intent.getFlags();
282            final Intent newIntent = km.createConfirmDeviceCredentialIntent(null, null, user.id);
283            if (newIntent != null) {
284                intent = newIntent;
285                intent.setFlags(flags
286                        | Intent.FLAG_ACTIVITY_NEW_TASK
287                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
288                intent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
289                intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
290
291                resolvedType = null;
292                callingUid = realCallingUid;
293                callingPid = realCallingPid;
294
295                UserInfo parent = UserManager.get(mService.mContext).getProfileParent(userId);
296                rInfo = mSupervisor.resolveIntent(intent, resolvedType, parent.id);
297                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
298                        null /*profilerInfo*/);
299            }
300        }
301
302        if (abort) {
303            if (resultRecord != null) {
304                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
305                        Activity.RESULT_CANCELED, null);
306            }
307            // We pretend to the caller that it was really started, but
308            // they will just get a cancel result.
309            ActivityOptions.abort(options);
310            return ActivityManager.START_SUCCESS;
311        }
312
313        // If permissions need a review before any of the app components can run, we
314        // launch the review activity and pass a pending intent to start the activity
315        // we are to launching now after the review is completed.
316        if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
317            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
318                    aInfo.packageName, userId)) {
319                IIntentSender target = mService.getIntentSenderLocked(
320                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
321                        callingUid, userId, null, null, 0, new Intent[]{intent},
322                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
323                                | PendingIntent.FLAG_ONE_SHOT, null);
324
325                final int flags = intent.getFlags();
326                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
327                newIntent.setFlags(flags
328                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
329                newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
330                newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
331                if (resultRecord != null) {
332                    newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
333                }
334                intent = newIntent;
335
336                resolvedType = null;
337                callingUid = realCallingUid;
338                callingPid = realCallingPid;
339
340                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
341                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
342                        null /*profilerInfo*/);
343
344                if (DEBUG_PERMISSIONS_REVIEW) {
345                    Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
346                            true, false) + "} from uid " + callingUid + " on display "
347                            + (container == null ? (mSupervisor.mFocusedStack == null ?
348                            Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
349                            (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
350                                    container.mActivityDisplay.mDisplayId)));
351                }
352            }
353        }
354
355        // If we have an ephemeral app, abort the process of launching the resolved intent.
356        // Instead, launch the ephemeral installer. Once the installer is finished, it
357        // starts either the intent we resolved here [on install error] or the ephemeral
358        // app [on install success].
359        if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
360            // Create a pending intent to start the intent resolved here.
361            final IIntentSender failureTarget = mService.getIntentSenderLocked(
362                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
363                    Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
364                    new String[]{ resolvedType },
365                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
366                            | PendingIntent.FLAG_IMMUTABLE, null);
367
368            // Create a pending intent to start the ephemeral application; force it to be
369            // directed to the ephemeral package.
370            ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
371            final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
372                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
373                    Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
374                    new String[]{ resolvedType },
375                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
376                            | PendingIntent.FLAG_IMMUTABLE, null);
377
378            int flags = intent.getFlags();
379            intent = new Intent();
380            intent.setFlags(flags
381                    | Intent.FLAG_ACTIVITY_NEW_TASK
382                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
383            intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
384                    rInfo.ephemeralResolveInfo.getPackageName());
385            intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
386            intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
387
388            resolvedType = null;
389            callingUid = realCallingUid;
390            callingPid = realCallingPid;
391
392            rInfo = rInfo.ephemeralInstaller;
393            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
394        }
395
396        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
397                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
398                requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
399                options);
400        if (outActivity != null) {
401            outActivity[0] = r;
402        }
403
404        if (r.appTimeTracker == null && sourceRecord != null) {
405            // If the caller didn't specify an explicit time tracker, we want to continue
406            // tracking under any it has.
407            r.appTimeTracker = sourceRecord.appTimeTracker;
408        }
409
410        final ActivityStack stack = mSupervisor.mFocusedStack;
411        if (voiceSession == null && (stack.mResumedActivity == null
412                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
413            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
414                    realCallingPid, realCallingUid, "Activity start")) {
415                PendingActivityLaunch pal =  new PendingActivityLaunch(r,
416                        sourceRecord, startFlags, stack, callerApp);
417                mPendingActivityLaunches.add(pal);
418                ActivityOptions.abort(options);
419                return ActivityManager.START_SWITCHES_CANCELED;
420            }
421        }
422
423        if (mService.mDidAppSwitch) {
424            // This is the second allowed switch since we stopped switches,
425            // so now just generally allow switches.  Use case: user presses
426            // home (switches disabled, switch to home, mDidAppSwitch now true);
427            // user taps a home icon (coming from home so allowed, we hit here
428            // and now allow anyone to switch again).
429            mService.mAppSwitchesAllowedTime = 0;
430        } else {
431            mService.mDidAppSwitch = true;
432        }
433
434        doPendingActivityLaunchesLocked(false);
435
436        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession,
437                voiceInteractor, startFlags, true, options, inTask);
438
439        if (err < 0) {
440            // If someone asked to have the keyguard dismissed on the next
441            // activity start, but we are not actually doing an activity
442            // switch...  just dismiss the keyguard now, because we
443            // probably want to see whatever is behind it.
444            mSupervisor.notifyActivityDrawnForKeyguard();
445        }
446        return err;
447    }
448
449    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
450        mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
451        startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
452                null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
453                null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
454                0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
455                0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
456                false /*ignoreTargetSecurity*/, false /*componentSpecified*/,  null /*outActivity*/,
457                null /*container*/, null /*inTask*/);
458        if (mSupervisor.inResumeTopActivity) {
459            // If we are in resume section already, home activity will be initialized, but not
460            // resumed (to avoid recursive resume) and will stay that way until something pokes it
461            // again. We need to schedule another resume.
462            mSupervisor.scheduleResumeTopActivities();
463        }
464    }
465
466    final int startActivityMayWait(IApplicationThread caller, int callingUid,
467            String callingPackage, Intent intent, String resolvedType,
468            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
469            IBinder resultTo, String resultWho, int requestCode, int startFlags,
470            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
471            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
472            IActivityContainer iContainer, TaskRecord inTask) {
473        // Refuse possible leaked file descriptors
474        if (intent != null && intent.hasFileDescriptors()) {
475            throw new IllegalArgumentException("File descriptors passed in Intent");
476        }
477        boolean componentSpecified = intent.getComponent() != null;
478
479        // Save a copy in case ephemeral needs it
480        final Intent ephemeralIntent = new Intent(intent);
481        // Don't modify the client's object!
482        intent = new Intent(intent);
483
484        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
485        // Collect information about the target of the Intent.
486        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
487
488        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
489        ActivityStackSupervisor.ActivityContainer container =
490                (ActivityStackSupervisor.ActivityContainer)iContainer;
491        synchronized (mService) {
492            if (container != null && container.mParentActivity != null &&
493                    container.mParentActivity.state != RESUMED) {
494                // Cannot start a child activity if the parent is not resumed.
495                return ActivityManager.START_CANCELED;
496            }
497            final int realCallingPid = Binder.getCallingPid();
498            final int realCallingUid = Binder.getCallingUid();
499            int callingPid;
500            if (callingUid >= 0) {
501                callingPid = -1;
502            } else if (caller == null) {
503                callingPid = realCallingPid;
504                callingUid = realCallingUid;
505            } else {
506                callingPid = callingUid = -1;
507            }
508
509            final ActivityStack stack;
510            if (container == null || container.mStack.isOnHomeDisplay()) {
511                stack = mSupervisor.mFocusedStack;
512            } else {
513                stack = container.mStack;
514            }
515            stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
516            if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
517                    "Starting activity when config will change = " + stack.mConfigWillChange);
518
519            final long origId = Binder.clearCallingIdentity();
520
521            if (aInfo != null &&
522                    (aInfo.applicationInfo.privateFlags
523                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
524                // This may be a heavy-weight process!  Check to see if we already
525                // have another, different heavy-weight process running.
526                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
527                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
528                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
529                            || !heavy.processName.equals(aInfo.processName))) {
530                        int appCallingUid = callingUid;
531                        if (caller != null) {
532                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
533                            if (callerApp != null) {
534                                appCallingUid = callerApp.info.uid;
535                            } else {
536                                Slog.w(TAG, "Unable to find app for caller " + caller
537                                        + " (pid=" + callingPid + ") when starting: "
538                                        + intent.toString());
539                                ActivityOptions.abort(options);
540                                return ActivityManager.START_PERMISSION_DENIED;
541                            }
542                        }
543
544                        IIntentSender target = mService.getIntentSenderLocked(
545                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
546                                appCallingUid, userId, null, null, 0, new Intent[] { intent },
547                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
548                                        | PendingIntent.FLAG_ONE_SHOT, null);
549
550                        Intent newIntent = new Intent();
551                        if (requestCode >= 0) {
552                            // Caller is requesting a result.
553                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
554                        }
555                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
556                                new IntentSender(target));
557                        if (heavy.activities.size() > 0) {
558                            ActivityRecord hist = heavy.activities.get(0);
559                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
560                                    hist.packageName);
561                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
562                                    hist.task.taskId);
563                        }
564                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
565                                aInfo.packageName);
566                        newIntent.setFlags(intent.getFlags());
567                        newIntent.setClassName("android",
568                                HeavyWeightSwitcherActivity.class.getName());
569                        intent = newIntent;
570                        resolvedType = null;
571                        caller = null;
572                        callingUid = Binder.getCallingUid();
573                        callingPid = Binder.getCallingPid();
574                        componentSpecified = true;
575                        rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
576                        aInfo = rInfo != null ? rInfo.activityInfo : null;
577                        if (aInfo != null) {
578                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
579                        }
580                    }
581                }
582            }
583
584            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
585                    aInfo, rInfo, voiceSession, voiceInteractor,
586                    resultTo, resultWho, requestCode, callingPid,
587                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
588                    options, ignoreTargetSecurity, componentSpecified, null, container, inTask);
589
590            Binder.restoreCallingIdentity(origId);
591
592            if (stack.mConfigWillChange) {
593                // If the caller also wants to switch to a new configuration,
594                // do so now.  This allows a clean switch, as we are waiting
595                // for the current activity to pause (so we will not destroy
596                // it), and have not yet started the next activity.
597                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
598                        "updateConfiguration()");
599                stack.mConfigWillChange = false;
600                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
601                        "Updating to new configuration after starting activity.");
602                mService.updateConfigurationLocked(config, null, false);
603            }
604
605            if (outResult != null) {
606                outResult.result = res;
607                if (res == ActivityManager.START_SUCCESS) {
608                    mSupervisor.mWaitingActivityLaunched.add(outResult);
609                    do {
610                        try {
611                            mService.wait();
612                        } catch (InterruptedException e) {
613                        }
614                    } while (!outResult.timeout && outResult.who == null);
615                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
616                    ActivityRecord r = stack.topRunningActivityLocked();
617                    if (r.nowVisible && r.state == RESUMED) {
618                        outResult.timeout = false;
619                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
620                        outResult.totalTime = 0;
621                        outResult.thisTime = 0;
622                    } else {
623                        outResult.thisTime = SystemClock.uptimeMillis();
624                        mSupervisor.mWaitingActivityVisible.add(outResult);
625                        do {
626                            try {
627                                mService.wait();
628                            } catch (InterruptedException e) {
629                            }
630                        } while (!outResult.timeout && outResult.who == null);
631                    }
632                }
633            }
634
635            return res;
636        }
637    }
638
639    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
640            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
641            boolean doResume, ActivityOptions options, TaskRecord inTask) {
642        final Intent intent = r.intent;
643        final int callingUid = r.launchedFromUid;
644
645        final Rect newBounds = getOverrideBounds(r, options, inTask);
646        final boolean overrideBounds = newBounds != null;
647
648        // In some flows in to this function, we retrieve the task record and hold on to it
649        // without a lock before calling back in to here...  so the task at this point may
650        // not actually be in recents.  Check for that, and if it isn't in recents just
651        // consider it invalid.
652        if (inTask != null && !inTask.inRecents) {
653            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
654            inTask = null;
655        }
656
657        final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
658        final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
659        final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
660        int launchFlags = adjustLaunchFlagsToDocumentMode(r, launchSingleInstance, launchSingleTask,
661                intent.getFlags());
662        final boolean launchTaskBehind = r.mLaunchTaskBehind
663                && !launchSingleTask && !launchSingleInstance
664                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
665
666        if (r.resultTo != null && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
667                && r.resultTo.task.stack != null) {
668            // For whatever reason this activity is being launched into a new
669            // task...  yet the caller has requested a result back.  Well, that
670            // is pretty messed up, so instead immediately send back a cancel
671            // and let the new task continue launched as normal without a
672            // dependency on its originator.
673            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
674            r.resultTo.task.stack.sendActivityResultLocked(-1,
675                    r.resultTo, r.resultWho, r.requestCode,
676                    Activity.RESULT_CANCELED, null);
677            r.resultTo = null;
678        }
679
680        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
681            launchFlags |= FLAG_ACTIVITY_NEW_TASK;
682        }
683
684        // If we are actually going to launch in to a new task, there are some cases where
685        // we further want to do multiple task.
686        if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
687            if (launchTaskBehind
688                    || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
689                launchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
690            }
691        }
692
693        // We'll invoke onUserLeaving before onPause only if the launching
694        // activity did not explicitly state that this is an automated launch.
695        mSupervisor.mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
696        if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
697                "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
698
699        // If the caller has asked not to resume at this point, we make note
700        // of this in the record so that we can skip it when trying to find
701        // the top running activity.
702        if (!doResume || !mSupervisor.okToShowLocked(r)) {
703            r.delayedResume = true;
704            doResume = false;
705        }
706
707        final ActivityRecord notTop =
708                (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
709
710        // If the onlyIfNeeded flag is set, then we can do this if the activity
711        // being launched is the same as the one making the call...  or, as
712        // a special case, if we do not know the caller then we count the
713        // current top activity as the caller.
714        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
715            ActivityRecord checkedCaller = sourceRecord;
716            if (checkedCaller == null) {
717                checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
718                        notTop);
719            }
720            if (!checkedCaller.realActivity.equals(r.realActivity)) {
721                // Caller is not the same as launcher, so always needed.
722                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
723            }
724        }
725
726        boolean addingToTask = false;
727        TaskRecord reuseTask = null;
728
729        // If the caller is not coming from another activity, but has given us an
730        // explicit task into which they would like us to launch the new activity,
731        // then let's see about doing that.
732        if (sourceRecord == null && inTask != null && inTask.stack != null) {
733            final Intent baseIntent = inTask.getBaseIntent();
734            final ActivityRecord root = inTask.getRootActivity();
735            if (baseIntent == null) {
736                ActivityOptions.abort(options);
737                throw new IllegalArgumentException("Launching into task without base intent: "
738                        + inTask);
739            }
740
741            // If this task is empty, then we are adding the first activity -- it
742            // determines the root, and must be launching as a NEW_TASK.
743            if (launchSingleInstance || launchSingleTask) {
744                if (!baseIntent.getComponent().equals(r.intent.getComponent())) {
745                    ActivityOptions.abort(options);
746                    throw new IllegalArgumentException("Trying to launch singleInstance/Task "
747                            + r + " into different task " + inTask);
748                }
749                if (root != null) {
750                    ActivityOptions.abort(options);
751                    throw new IllegalArgumentException("Caller with inTask " + inTask
752                            + " has root " + root + " but target is singleInstance/Task");
753                }
754            }
755
756            // If task is empty, then adopt the interesting intent launch flags in to the
757            // activity being started.
758            if (root == null) {
759                final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK
760                        | FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
761                        | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
762                launchFlags = (launchFlags&~flagsOfInterest)
763                        | (baseIntent.getFlags()&flagsOfInterest);
764                intent.setFlags(launchFlags);
765                inTask.setIntent(r);
766                addingToTask = true;
767
768                // If the task is not empty and the caller is asking to start it as the root
769                // of a new task, then we don't actually want to start this on the task.  We
770                // will bring the task to the front, and possibly give it a new intent.
771            } else if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
772                addingToTask = false;
773
774            } else {
775                addingToTask = true;
776            }
777
778            reuseTask = inTask;
779        } else {
780            inTask = null;
781            // Launch ResolverActivity in the source task, so that it stays in the task
782            // bounds when in freeform workspace.
783            // Also put noDisplay activities in the source task. These by itself can
784            // be placed in any task/stack, however it could launch other activities
785            // like ResolverActivity, and we want those to stay in the original task.
786            if ((r.isResolverActivity() || r.noDisplay) && sourceRecord != null
787                    && sourceRecord.isFreeform())  {
788                addingToTask = true;
789            }
790        }
791
792        if (inTask == null) {
793            if (sourceRecord == null) {
794                // This activity is not being started from another...  in this
795                // case we -always- start a new task.
796                if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
797                    Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
798                            "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
799                    launchFlags |= FLAG_ACTIVITY_NEW_TASK;
800                }
801            } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
802                // The original activity who is starting us is running as a single
803                // instance...  this new activity it is starting must go on its
804                // own task.
805                launchFlags |= FLAG_ACTIVITY_NEW_TASK;
806            } else if (launchSingleInstance || launchSingleTask) {
807                // The activity being started is a single instance...  it always
808                // gets launched into its own task.
809                launchFlags |= FLAG_ACTIVITY_NEW_TASK;
810            }
811        }
812
813        ActivityInfo newTaskInfo = null;
814        Intent newTaskIntent = null;
815        final ActivityStack sourceStack;
816        if (sourceRecord != null) {
817            if (sourceRecord.finishing) {
818                // If the source is finishing, we can't further count it as our source.  This
819                // is because the task it is associated with may now be empty and on its way out,
820                // so we don't want to blindly throw it in to that task.  Instead we will take
821                // the NEW_TASK flow and try to find a task for it. But save the task information
822                // so it can be used when creating the new task.
823                if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
824                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
825                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
826                    launchFlags |= FLAG_ACTIVITY_NEW_TASK;
827                    newTaskInfo = sourceRecord.info;
828                    newTaskIntent = sourceRecord.task.intent;
829                }
830                sourceRecord = null;
831                sourceStack = null;
832            } else {
833                sourceStack = sourceRecord.task.stack;
834            }
835        } else {
836            sourceStack = null;
837        }
838
839        boolean movedHome = false;
840        ActivityStack targetStack;
841
842        intent.setFlags(launchFlags);
843        final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;
844
845        ActivityRecord intentActivity = getReusableIntentActivity(r, inTask, intent,
846                launchSingleInstance, launchSingleTask, launchFlags);
847        if (intentActivity != null) {
848            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused
849            // but still needs to be a lock task mode violation since the task gets
850            // cleared out and the device would otherwise leave the locked task.
851            if (mSupervisor.isLockTaskModeViolation(intentActivity.task,
852                    (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
853                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
854                mSupervisor.showLockTaskToast();
855                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
856                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
857            }
858            if (r.task == null) {
859                r.task = intentActivity.task;
860            }
861            if (intentActivity.task.intent == null) {
862                // This task was started because of movement of the activity based on affinity...
863                // Now that we are actually launching it, we can assign the base intent.
864                intentActivity.task.setIntent(r);
865            }
866
867            targetStack = intentActivity.task.stack;
868            targetStack.mLastPausedActivity = null;
869            // If the target task is not in the front, then we need
870            // to bring it to the front...  except...  well, with
871            // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
872            // to have the same behavior as if a new instance was
873            // being started, which means not bringing it to the front
874            // if the caller is not itself in the front.
875            final ActivityStack focusStack = mSupervisor.getFocusedStack();
876            ActivityRecord curTop = (focusStack == null)
877                    ? null : focusStack.topRunningNonDelayedActivityLocked(notTop);
878            boolean movedToFront = false;
879            if (curTop != null && (curTop.task != intentActivity.task ||
880                    curTop.task != focusStack.topTask())) {
881                r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
882                if (sourceRecord == null || (sourceStack.topActivity() != null &&
883                        sourceStack.topActivity().task == sourceRecord.task)) {
884                    // We really do want to push this one into the user's face, right now.
885                    if (launchTaskBehind && sourceRecord != null) {
886                        intentActivity.setTaskToAffiliateWith(sourceRecord.task);
887                    }
888                    movedHome = true;
889                    final ActivityStack launchStack =
890                            getLaunchStack(r, launchFlags, r.task, options, true);
891                    if (launchStack == null || launchStack == targetStack) {
892                        // We only want to move to the front, if we aren't going to launch on a
893                        // different stack. If we launch on a different stack, we will put the
894                        // task on top there.
895                        targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation,
896                                options, r.appTimeTracker, "bringingFoundTaskToFront");
897                        movedToFront = true;
898                    }
899                    if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
900                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
901                        // Caller wants to appear on home activity.
902                        intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
903                    }
904                    options = null;
905                }
906            }
907            if (!movedToFront && doResume) {
908                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + targetStack
909                        + " from " + intentActivity);
910                targetStack.moveToFront("intentActivityFound");
911            }
912
913            // If the caller has requested that the target task be
914            // reset, then do so.
915            if ((launchFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
916                intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
917            }
918            if ((startFlags & ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
919                // We don't need to start a new activity, and
920                // the client said not to do anything if that
921                // is the case, so this is it!  And for paranoia, make
922                // sure we have correctly resumed the top activity.
923                if (doResume) {
924                    mSupervisor.resumeFocusedStackTopActivityLocked(targetStack, null, options);
925
926                    // Make sure to notify Keyguard as well if we are not running an app
927                    // transition later.
928                    if (!movedToFront) {
929                        mSupervisor.notifyActivityDrawnForKeyguard();
930                    }
931                } else {
932                    ActivityOptions.abort(options);
933                }
934                mSupervisor.updateUserStackLocked(r.userId, targetStack);
935                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
936            }
937            if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
938                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
939                // The caller has requested to completely replace any
940                // existing task with its new activity.  Well that should
941                // not be too hard...
942                reuseTask = intentActivity.task;
943                reuseTask.performClearTaskLocked();
944                reuseTask.setIntent(r);
945            } else if ((launchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
946                    || launchSingleInstance || launchSingleTask) {
947                // In this situation we want to remove all activities
948                // from the task up to the one being started.  In most
949                // cases this means we are resetting the task to its
950                // initial state.
951                ActivityRecord top = intentActivity.task.performClearTaskLocked(r, launchFlags);
952                if (top != null) {
953                    if (top.frontOfTask) {
954                        // Activity aliases may mean we use different
955                        // intents for the top activity, so make sure
956                        // the task now has the identity of the new
957                        // intent.
958                        top.task.setIntent(r);
959                    }
960                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
961                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
962                } else {
963                    // A special case: we need to start the activity because it is not
964                    // currently running, and the caller has asked to clear the current
965                    // task to have this activity at the top.
966                    addingToTask = true;
967                    // Now pretend like this activity is being started by the top of its
968                    // task, so it is put in the right place.
969                    sourceRecord = intentActivity;
970                    TaskRecord task = sourceRecord.task;
971                    if (task != null && task.stack == null) {
972                        // Target stack got cleared when we all activities were removed
973                        // above. Go ahead and reset it.
974                        targetStack = computeStackFocus(sourceRecord, false /* newTask */,
975                                null /* bounds */, launchFlags, options);
976                        targetStack.addTask(task,
977                                !launchTaskBehind /* toTop */, "startActivityUnchecked");
978                    }
979
980                }
981            } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
982                // In this case the top activity on the task is the
983                // same as the one being launched, so we take that
984                // as a request to bring the task to the foreground.
985                // If the top activity in the task is the root
986                // activity, deliver this new intent to it if it
987                // desires.
988                if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 || launchSingleTop)
989                        && intentActivity.realActivity.equals(r.realActivity)) {
990                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
991                            intentActivity.task);
992                    if (intentActivity.frontOfTask) {
993                        intentActivity.task.setIntent(r);
994                    }
995                    intentActivity.deliverNewIntentLocked(callingUid, r.intent,
996                            r.launchedFromPackage);
997                } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
998                    // In this case we are launching the root activity
999                    // of the task, but with a different intent.  We
1000                    // should start a new instance on top.
1001                    addingToTask = true;
1002                    sourceRecord = intentActivity;
1003                }
1004            } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1005                // In this case an activity is being launched in to an
1006                // existing task, without resetting that task.  This
1007                // is typically the situation of launching an activity
1008                // from a notification or shortcut.  We want to place
1009                // the new activity on top of the current task.
1010                addingToTask = true;
1011                sourceRecord = intentActivity;
1012            } else if (!intentActivity.task.rootWasReset) {
1013                // In this case we are launching in to an existing task
1014                // that has not yet been started from its front door.
1015                // The current task has been brought to the front.
1016                // Ideally, we'd probably like to place this new task
1017                // at the bottom of its stack, but that's a little hard
1018                // to do with the current organization of the code so
1019                // for now we'll just drop it.
1020                intentActivity.task.setIntent(r);
1021            }
1022            if (!addingToTask && reuseTask == null) {
1023                // We didn't do anything...  but it was needed (a.k.a., client
1024                // don't use that intent!)  And for paranoia, make
1025                // sure we have correctly resumed the top activity.
1026                if (doResume) {
1027                    mSupervisor.resumeFocusedStackTopActivityLocked(targetStack, null, options);
1028                    if (!movedToFront) {
1029                        // Make sure to notify Keyguard as well if we are not running an app
1030                        // transition later.
1031                        mSupervisor.notifyActivityDrawnForKeyguard();
1032                    }
1033                } else {
1034                    ActivityOptions.abort(options);
1035                }
1036                mSupervisor.updateUserStackLocked(r.userId, targetStack);
1037                return ActivityManager.START_TASK_TO_FRONT;
1038            }
1039        }
1040
1041        //String uri = r.intent.toURI();
1042        //Intent intent2 = new Intent(uri);
1043        //Slog.i(TAG, "Given intent: " + r.intent);
1044        //Slog.i(TAG, "URI is: " + uri);
1045        //Slog.i(TAG, "To intent: " + intent2);
1046
1047        if (r.packageName != null) {
1048            // If the activity being launched is the same as the one currently
1049            // at the top, then we need to check if it should only be launched
1050            // once.
1051            ActivityStack topStack = mSupervisor.mFocusedStack;
1052            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
1053            final boolean dontStart = top != null && r.resultTo == null
1054                    && top.realActivity.equals(r.realActivity) && top.userId == r.userId
1055                    && top.app != null && top.app.thread != null
1056                    && ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1057                    || launchSingleTop || launchSingleTask);
1058            if (dontStart) {
1059                ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
1060                // For paranoia, make sure we have correctly resumed the top activity.
1061                topStack.mLastPausedActivity = null;
1062                if (doResume) {
1063                    mSupervisor.resumeFocusedStackTopActivityLocked();
1064                }
1065                ActivityOptions.abort(options);
1066                if ((startFlags & ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1067                    // We don't need to start a new activity, and the client said not to do
1068                    // anything if that is the case, so this is it!
1069                    return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1070                }
1071                top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
1072                return ActivityManager.START_DELIVERED_TO_TOP;
1073            }
1074        } else {
1075            if (r.resultTo != null && r.resultTo.task.stack != null) {
1076                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1077                        r.requestCode, Activity.RESULT_CANCELED, null);
1078            }
1079            ActivityOptions.abort(options);
1080            return ActivityManager.START_CLASS_NOT_FOUND;
1081        }
1082
1083        boolean newTask = false;
1084        boolean keepCurTransition = false;
1085
1086        final TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ?
1087                sourceRecord.task : null;
1088
1089        // Should this be considered a new task?
1090        if (r.resultTo == null && inTask == null && !addingToTask
1091                && (launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1092            newTask = true;
1093            targetStack = computeStackFocus(r, newTask, newBounds, launchFlags, options);
1094            if (doResume) {
1095                targetStack.moveToFront("startingNewTask");
1096            }
1097
1098            if (reuseTask == null) {
1099                r.setTask(targetStack.createTaskRecord(mSupervisor.getNextTaskId(),
1100                        newTaskInfo != null ? newTaskInfo : r.info,
1101                        newTaskIntent != null ? newTaskIntent : intent,
1102                        voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
1103                        taskToAffiliate);
1104                if (overrideBounds) {
1105                    r.task.updateOverrideConfiguration(newBounds);
1106                }
1107                if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1108                        "Starting new activity " + r + " in new task " + r.task);
1109            } else {
1110                r.setTask(reuseTask, taskToAffiliate);
1111            }
1112            if (mSupervisor.isLockTaskModeViolation(r.task)) {
1113                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1114                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1115            }
1116            if (!movedHome) {
1117                if ((launchFlags &
1118                        (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1119                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1120                    // Caller wants to appear on home activity, so before starting
1121                    // their own activity we will bring home to the front.
1122                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1123                }
1124            }
1125        } else if (sourceRecord != null) {
1126            final TaskRecord sourceTask = sourceRecord.task;
1127            if (mSupervisor.isLockTaskModeViolation(sourceTask)) {
1128                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1129                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1130            }
1131            // We only want to allow changing stack if the target task is not the top one,
1132            // otherwise we would move the launching task to the other side, rather than show
1133            // two side by side.
1134            final boolean launchToSideAllowed = sourceTask.stack.topTask() != sourceTask;
1135            targetStack = getLaunchStack(r, launchFlags, r.task, options, launchToSideAllowed);
1136
1137            if (targetStack == null) {
1138                targetStack = sourceTask.stack;
1139            } else if (targetStack != sourceTask.stack) {
1140                mSupervisor.moveTaskToStackLocked(sourceTask.taskId, targetStack.mStackId,
1141                        ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1142            }
1143            if (doResume) {
1144                targetStack.moveToFront("sourceStackToFront");
1145            }
1146            final TaskRecord topTask = targetStack.topTask();
1147            if (topTask != sourceTask) {
1148                targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
1149                        r.appTimeTracker, "sourceTaskToFront");
1150            }
1151            if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1152                // In this case, we are adding the activity to an existing
1153                // task, but the caller has asked to clear that task if the
1154                // activity is already running.
1155                ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
1156                keepCurTransition = true;
1157                if (top != null) {
1158                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1159                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
1160                    // For paranoia, make sure we have correctly
1161                    // resumed the top activity.
1162                    targetStack.mLastPausedActivity = null;
1163                    if (doResume) {
1164                        mSupervisor.resumeFocusedStackTopActivityLocked();
1165                    }
1166                    ActivityOptions.abort(options);
1167                    return ActivityManager.START_DELIVERED_TO_TOP;
1168                }
1169            } else if (!addingToTask &&
1170                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1171                // In this case, we are launching an activity in our own task
1172                // that may already be running somewhere in the history, and
1173                // we want to shuffle it to the front of the stack if so.
1174                final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
1175                if (top != null) {
1176                    final TaskRecord task = top.task;
1177                    task.moveActivityToFrontLocked(top);
1178                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
1179                    top.updateOptionsLocked(options);
1180                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
1181                    targetStack.mLastPausedActivity = null;
1182                    if (doResume) {
1183                        mSupervisor.resumeFocusedStackTopActivityLocked();
1184                    }
1185                    return ActivityManager.START_DELIVERED_TO_TOP;
1186                }
1187            }
1188            // An existing activity is starting this new activity, so we want
1189            // to keep the new one in the same task as the one that is starting
1190            // it.
1191            r.setTask(sourceTask, null);
1192            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
1193                    + " in existing task " + r.task + " from source " + sourceRecord);
1194
1195        } else if (inTask != null) {
1196            // The caller is asking that the new activity be started in an explicit
1197            // task it has provided to us.
1198            if (mSupervisor.isLockTaskModeViolation(inTask)) {
1199                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1200                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1201            }
1202            if (overrideBounds) {
1203                inTask.updateOverrideConfiguration(newBounds);
1204                int stackId = inTask.getLaunchStackId();
1205                if (stackId != inTask.stack.mStackId) {
1206                    mSupervisor.moveTaskToStackUncheckedLocked(
1207                            inTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
1208                }
1209            }
1210            targetStack = inTask.stack;
1211            targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker,
1212                    "inTaskToFront");
1213
1214            // Check whether we should actually launch the new activity in to the task,
1215            // or just reuse the current activity on top.
1216            ActivityRecord top = inTask.getTopActivity();
1217            if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1218                if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1219                        || launchSingleTop || launchSingleTask) {
1220                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
1221                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1222                        // We don't need to start a new activity, and
1223                        // the client said not to do anything if that
1224                        // is the case, so this is it!
1225                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1226                    }
1227                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
1228                    return ActivityManager.START_DELIVERED_TO_TOP;
1229                }
1230            }
1231
1232            if (!addingToTask) {
1233                // We don't actually want to have this activity added to the task, so just
1234                // stop here but still tell the caller that we consumed the intent.
1235                ActivityOptions.abort(options);
1236                return ActivityManager.START_TASK_TO_FRONT;
1237            }
1238
1239            r.setTask(inTask, null);
1240            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
1241                    + " in explicit task " + r.task);
1242
1243        } else {
1244            // This not being started from an existing activity, and not part
1245            // of a new task...  just put it in the top task, though these days
1246            // this case should never happen.
1247            targetStack = computeStackFocus(r, newTask, null /* bounds */, launchFlags, options);
1248            if (doResume) {
1249                targetStack.moveToFront("addingToTopTask");
1250            }
1251            ActivityRecord prev = targetStack.topActivity();
1252            r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(
1253                    mSupervisor.getNextTaskId(), r.info, intent, null, null, true), null);
1254            mWindowManager.moveTaskToTop(r.task.taskId);
1255            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
1256                    + " in new guessed " + r.task);
1257        }
1258
1259        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1260                intent, r.getUriPermissionsLocked(), r.userId);
1261
1262        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
1263            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1264        }
1265        if (newTask) {
1266            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1267        }
1268        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
1269        targetStack.mLastPausedActivity = null;
1270        targetStack.startActivityLocked(r, newTask, keepCurTransition, options);
1271        if (doResume) {
1272            if (!launchTaskBehind) {
1273                // TODO: Remove this code after verification that all the decision points above
1274                // moved targetStack to the front which will also set the focus activity.
1275                mService.setFocusedActivityLocked(r, "startedActivity");
1276            }
1277            mSupervisor.resumeFocusedStackTopActivityLocked(targetStack, r, options);
1278        } else {
1279            targetStack.addRecentActivityLocked(r);
1280        }
1281        mSupervisor.updateUserStackLocked(r.userId, targetStack);
1282
1283        if (!r.task.mResizeable && mSupervisor.isStackDockedInEffect(targetStack.mStackId)) {
1284            mSupervisor.showNonResizeableDockToast(r.task.taskId);
1285        }
1286
1287        return ActivityManager.START_SUCCESS;
1288    }
1289
1290    private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1291            boolean launchSingleTask, int launchFlags) {
1292        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1293                (launchSingleInstance || launchSingleTask)) {
1294            // We have a conflict between the Intent and the Activity manifest, manifest wins.
1295            Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1296                    "\"singleInstance\" or \"singleTask\"");
1297            launchFlags &=
1298                    ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1299        } else {
1300            switch (r.info.documentLaunchMode) {
1301                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1302                    break;
1303                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1304                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1305                    break;
1306                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1307                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1308                    break;
1309                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1310                    launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1311                    break;
1312            }
1313        }
1314        return launchFlags;
1315    }
1316
1317    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
1318            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
1319            Bundle bOptions, int userId) {
1320        if (intents == null) {
1321            throw new NullPointerException("intents is null");
1322        }
1323        if (resolvedTypes == null) {
1324            throw new NullPointerException("resolvedTypes is null");
1325        }
1326        if (intents.length != resolvedTypes.length) {
1327            throw new IllegalArgumentException("intents are length different than resolvedTypes");
1328        }
1329
1330
1331        int callingPid;
1332        if (callingUid >= 0) {
1333            callingPid = -1;
1334        } else if (caller == null) {
1335            callingPid = Binder.getCallingPid();
1336            callingUid = Binder.getCallingUid();
1337        } else {
1338            callingPid = callingUid = -1;
1339        }
1340        final long origId = Binder.clearCallingIdentity();
1341        try {
1342            synchronized (mService) {
1343                ActivityRecord[] outActivity = new ActivityRecord[1];
1344                for (int i=0; i<intents.length; i++) {
1345                    Intent intent = intents[i];
1346                    if (intent == null) {
1347                        continue;
1348                    }
1349
1350                    // Refuse possible leaked file descriptors
1351                    if (intent != null && intent.hasFileDescriptors()) {
1352                        throw new IllegalArgumentException("File descriptors passed in Intent");
1353                    }
1354
1355                    boolean componentSpecified = intent.getComponent() != null;
1356
1357                    // Don't modify the client's object!
1358                    intent = new Intent(intent);
1359
1360                    // Collect information about the target of the Intent.
1361                    ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
1362                            null, userId);
1363                    // TODO: New, check if this is correct
1364                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
1365
1366                    if (aInfo != null &&
1367                            (aInfo.applicationInfo.privateFlags
1368                                    & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
1369                        throw new IllegalArgumentException(
1370                                "FLAG_CANT_SAVE_STATE not supported here");
1371                    }
1372
1373                    ActivityOptions options = ActivityOptions.fromBundle(
1374                            i == intents.length - 1 ? bOptions : null);
1375                    int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
1376                            resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
1377                            callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
1378                            options, false, componentSpecified, outActivity, null, null);
1379                    if (res < 0) {
1380                        return res;
1381                    }
1382
1383                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
1384                }
1385            }
1386        } finally {
1387            Binder.restoreCallingIdentity(origId);
1388        }
1389
1390        return ActivityManager.START_SUCCESS;
1391    }
1392
1393    final void doPendingActivityLaunchesLocked(boolean doResume) {
1394        while (!mPendingActivityLaunches.isEmpty()) {
1395            PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1396
1397            try {
1398                startActivityUncheckedLocked(pal.r, pal.sourceRecord, null, null,
1399                        pal.startFlags, doResume && mPendingActivityLaunches.isEmpty(),
1400                        null, null);
1401            } catch (Exception e) {
1402                Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1403                pal.sendErrorResult(e.getMessage());
1404            }
1405        }
1406    }
1407
1408    private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
1409            int launchFlags, ActivityOptions aOptions) {
1410        final TaskRecord task = r.task;
1411        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1412            return mSupervisor.mHomeStack;
1413        }
1414
1415        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions, true);
1416        if (stack != null) {
1417            return stack;
1418        }
1419
1420        if (task != null && task.stack != null) {
1421            stack = task.stack;
1422            if (stack.isOnHomeDisplay()) {
1423                if (mSupervisor.mFocusedStack != stack) {
1424                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1425                            "computeStackFocus: Setting " + "focused stack to r=" + r
1426                                    + " task=" + task);
1427                } else {
1428                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1429                            "computeStackFocus: Focused stack already="
1430                                    + mSupervisor.mFocusedStack);
1431                }
1432            }
1433            return stack;
1434        }
1435
1436        final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1437        if (container != null) {
1438            // The first time put it on the desired stack, after this put on task stack.
1439            r.mInitialActivityContainer = null;
1440            return container.mStack;
1441        }
1442
1443        // The fullscreen stack can contain any task regardless of if the task is resizeable
1444        // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1445        // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1446        // we can also put it in the focused stack.
1447        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1448        final boolean canUseFocusedStack =
1449                focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1450                        || focusedStackId == DOCKED_STACK_ID
1451                        || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeable());
1452        if (canUseFocusedStack && (!newTask
1453                || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1454            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1455                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1456            return mSupervisor.mFocusedStack;
1457        }
1458
1459        // We first try to put the task in the first dynamic stack.
1460        final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1461        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1462            stack = homeDisplayStacks.get(stackNdx);
1463            if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1464                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1465                        "computeStackFocus: Setting focused stack=" + stack);
1466                return stack;
1467            }
1468        }
1469
1470        // If there is no suitable dynamic stack then we figure out which static stack to use.
1471        final int stackId = task != null ? task.getLaunchStackId() :
1472                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1473                        FULLSCREEN_WORKSPACE_STACK_ID;
1474        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1475        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1476                + r + " stackId=" + stack.mStackId);
1477        return stack;
1478    }
1479
1480    private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1481            ActivityOptions aOptions, boolean launchToSideAllowed) {
1482        final int launchStackId =
1483                (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1484
1485        if (isValidLaunchStackId(launchStackId, r)) {
1486            return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
1487        }
1488
1489        if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_TO_SIDE) == 0) {
1490            return null;
1491        }
1492
1493        // The parent activity doesn't want to launch the activity on top of itself, but
1494        // instead tries to put it onto other side in side-by-side mode.
1495        final ActivityStack parentStack = task != null ? task.stack
1496                : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1497                : mSupervisor.mFocusedStack;
1498        if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1499            // If parent was in docked stack, the natural place to launch another activity
1500            // will be fullscreen, so it can appear alongside the docked window.
1501            return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1502        } else {
1503            // If the parent is not in the docked stack, we check if there is docked window
1504            // and if yes, we will launch into that stack. If not, we just put the new
1505            // activity into parent's stack, because we can't find a better place.
1506            final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
1507            if (stack != null && !stack.isStackVisibleLocked()) {
1508                // There is a docked stack, but it isn't visible, so we can't launch into that.
1509                return null;
1510            } else {
1511                return stack;
1512            }
1513        }
1514    }
1515
1516    private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1517        if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1518                || !StackId.isStaticStack(stackId)) {
1519            return false;
1520        }
1521
1522        final boolean resizeable = r.isResizeable() || mService.mForceResizableActivities;
1523
1524        if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !resizeable) {
1525            return false;
1526        }
1527
1528        if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1529            return false;
1530        }
1531
1532        final boolean supportsPip = mService.mSupportsPictureInPicture
1533                && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1534        if (stackId == PINNED_STACK_ID && !supportsPip) {
1535            return false;
1536        }
1537        return true;
1538    }
1539
1540    /**
1541     * Decide whether the new activity should be inserted into an existing task. Returns null if not
1542     * or an ActivityRecord with the task into which the new activity should be added.
1543     */
1544    private ActivityRecord getReusableIntentActivity(ActivityRecord r, TaskRecord inTask,
1545            Intent intent, boolean launchSingleInstance, boolean launchSingleTask,
1546            int launchFlags) {
1547        // We may want to try to place the new activity in to an existing task.  We always
1548        // do this if the target activity is singleTask or singleInstance; we will also do
1549        // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1550        // us to still place it in a new task: multi task, always doc mode, or being asked to
1551        // launch this as a new task behind the current one.
1552        boolean putIntoExistingTask = ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1553                (launchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1554                || launchSingleInstance || launchSingleTask;
1555        // If bring to front is requested, and no result is requested and we have not
1556        // been given an explicit task to launch in to, and
1557        // we can find a task that was started with this same
1558        // component, then instead of launching bring that one to the front.
1559        putIntoExistingTask &= inTask == null && r.resultTo == null;
1560        ActivityRecord intentActivity = null;
1561        if (putIntoExistingTask) {
1562            // See if there is a task to bring to the front.  If this is
1563            // a SINGLE_INSTANCE activity, there can be one and only one
1564            // instance of it in the history, and it is always in its own
1565            // unique task, so we do a special search.
1566            intentActivity = launchSingleInstance ? mSupervisor.findActivityLocked(intent, r.info)
1567                    : mSupervisor.findTaskLocked(r);
1568        }
1569        return intentActivity;
1570    }
1571
1572    Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1573        Rect newBounds = null;
1574        if (options != null && (r.isResizeable() || (inTask != null && inTask.mResizeable))) {
1575            if (mSupervisor.canUseActivityOptionsLaunchBounds(
1576                    options, options.getLaunchStackId())) {
1577                newBounds = options.getLaunchBounds();
1578            }
1579        }
1580        return newBounds;
1581    }
1582
1583    void setWindowManager(WindowManagerService wm) {
1584        mWindowManager = wm;
1585    }
1586
1587    void removePendingActivityLaunchesLocked(ActivityStack stack) {
1588        for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1589            PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1590            if (pal.stack == stack) {
1591                mPendingActivityLaunches.remove(palNdx);
1592            }
1593        }
1594    }
1595}
1596