blob: e3ca3ea904439c7b89addc23868e12fd57f880de [file] [log] [blame]
Kenny Guyb1b30262016-02-09 16:02:35 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080017package com.android.server.am;
18
Wale Ogunwale01d66562015-12-29 08:19:19 -080019import static android.app.Activity.RESULT_CANCELED;
20import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
21import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
22import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
23import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
24import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
25import static android.app.ActivityManager.START_SUCCESS;
26import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale854809c2015-12-27 16:18:19 -080027import static android.app.ActivityManager.StackId;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080028import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
29import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
30import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080031import static android.app.ActivityManager.StackId.HOME_STACK_ID;
32import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
33import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080034import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
35import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080036import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080037import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080038import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080039import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080040import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
41import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080042import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
43import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
44import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
45import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
46import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080047import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080048import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
49import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
50import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080052import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
53import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
54import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080055import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080056import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
60import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
61import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
64import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
65import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
66import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080067import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080068import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
69import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
70import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080071import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080072import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
73import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
74import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080075import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080077import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080078
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080079import android.app.ActivityManager;
80import android.app.ActivityOptions;
81import android.app.AppGlobals;
82import android.app.IActivityContainer;
83import android.app.IActivityManager;
84import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080085import android.app.PendingIntent;
86import android.app.ProfilerInfo;
87import android.content.ComponentName;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080088import android.content.IIntentSender;
89import android.content.Intent;
90import android.content.IntentSender;
91import android.content.pm.ActivityInfo;
92import android.content.pm.ApplicationInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000093import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000095import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080096import android.content.res.Configuration;
97import android.graphics.Rect;
98import android.os.Binder;
99import android.os.Build;
100import android.os.Bundle;
101import android.os.IBinder;
102import android.os.RemoteException;
103import android.os.SystemClock;
104import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000105import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.service.voice.IVoiceInteractionSession;
107import android.util.EventLog;
108import android.util.Slog;
109import android.view.Display;
110
111import com.android.internal.app.HeavyWeightSwitcherActivity;
112import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800113import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
114import com.android.server.wm.WindowManagerService;
115
116import java.util.ArrayList;
117
118/**
119 * Controller for interpreting how and then launching activities.
120 *
121 * This class collects all the logic for determining how an intent and flags should be turned into
122 * an activity and associated task and stack.
123 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800124class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800125 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
126 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
127 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
128 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
129 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
130
131 private final ActivityManagerService mService;
132 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000133 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800134 private WindowManagerService mWindowManager;
135
136 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
137
Wale Ogunwale01d66562015-12-29 08:19:19 -0800138 // Share state variable among methods when starting an activity.
139 private ActivityRecord mStartActivity;
140 private Intent mIntent;
141 private int mCallingUid;
142 private ActivityOptions mOptions;
143
144 private boolean mLaunchSingleTop;
145 private boolean mLaunchSingleInstance;
146 private boolean mLaunchSingleTask;
147 private boolean mLaunchTaskBehind;
148 private int mLaunchFlags;
149
150 private Rect mLaunchBounds;
151
152 private ActivityRecord mNotTop;
153 private boolean mDoResume;
154 private int mStartFlags;
155 private ActivityRecord mSourceRecord;
156
157 private TaskRecord mInTask;
158 private boolean mAddingToTask;
159 private TaskRecord mReuseTask;
160
161 private ActivityInfo mNewTaskInfo;
162 private Intent mNewTaskIntent;
163 private ActivityStack mSourceStack;
164 private ActivityStack mTargetStack;
165 // TODO: Is the mMoveHome flag really needed?
166 private boolean mMovedHome;
167 private boolean mMovedToFront;
168 private boolean mNoAnimation;
169 private boolean mKeepCurTransition;
170
171 private IVoiceInteractionSession mVoiceSession;
172 private IVoiceInteractor mVoiceInteractor;
173
174 private void reset() {
175 mStartActivity = null;
176 mIntent = null;
177 mCallingUid = -1;
178 mOptions = null;
179
180 mLaunchSingleTop = false;
181 mLaunchSingleInstance = false;
182 mLaunchSingleTask = false;
183 mLaunchTaskBehind = false;
184 mLaunchFlags = 0;
185
186 mLaunchBounds = null;
187
188 mNotTop = null;
189 mDoResume = false;
190 mStartFlags = 0;
191 mSourceRecord = null;
192
193 mInTask = null;
194 mAddingToTask = false;
195 mReuseTask = null;
196
197 mNewTaskInfo = null;
198 mNewTaskIntent = null;
199 mSourceStack = null;
200
201 mTargetStack = null;
202 mMovedHome = false;
203 mMovedToFront = false;
204 mNoAnimation = false;
205 mKeepCurTransition = false;
206
207 mVoiceSession = null;
208 mVoiceInteractor = null;
209 }
210
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800211 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
212 mService = service;
213 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000214 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800215 }
216
217 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
218 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
219 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
220 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
221 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
222 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
223 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
224 TaskRecord inTask) {
225 int err = ActivityManager.START_SUCCESS;
226
227 ProcessRecord callerApp = null;
228 if (caller != null) {
229 callerApp = mService.getRecordForAppLocked(caller);
230 if (callerApp != null) {
231 callingPid = callerApp.pid;
232 callingUid = callerApp.info.uid;
233 } else {
234 Slog.w(TAG, "Unable to find app for caller " + caller
235 + " (pid=" + callingPid + ") when starting: "
236 + intent.toString());
237 err = ActivityManager.START_PERMISSION_DENIED;
238 }
239 }
240
241 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
242
243 if (err == ActivityManager.START_SUCCESS) {
244 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
245 + "} from uid " + callingUid
246 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
247 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
248 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
249 container.mActivityDisplay.mDisplayId)));
250 }
251
252 ActivityRecord sourceRecord = null;
253 ActivityRecord resultRecord = null;
254 if (resultTo != null) {
255 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
256 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
257 "Will send result to " + resultTo + " " + sourceRecord);
258 if (sourceRecord != null) {
259 if (requestCode >= 0 && !sourceRecord.finishing) {
260 resultRecord = sourceRecord;
261 }
262 }
263 }
264
265 final int launchFlags = intent.getFlags();
266
267 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
268 // Transfer the result target from the source activity to the new
269 // one being started, including any failures.
270 if (requestCode >= 0) {
271 ActivityOptions.abort(options);
272 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
273 }
274 resultRecord = sourceRecord.resultTo;
275 if (resultRecord != null && !resultRecord.isInStackLocked()) {
276 resultRecord = null;
277 }
278 resultWho = sourceRecord.resultWho;
279 requestCode = sourceRecord.requestCode;
280 sourceRecord.resultTo = null;
281 if (resultRecord != null) {
282 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
283 }
284 if (sourceRecord.launchedFromUid == callingUid) {
285 // The new activity is being launched from the same uid as the previous
286 // activity in the flow, and asking to forward its result back to the
287 // previous. In this case the activity is serving as a trampoline between
288 // the two, so we also want to update its launchedFromPackage to be the
289 // same as the previous activity. Note that this is safe, since we know
290 // these two packages come from the same uid; the caller could just as
291 // well have supplied that same package name itself. This specifially
292 // deals with the case of an intent picker/chooser being launched in the app
293 // flow to redirect to an activity picked by the user, where we want the final
294 // activity to consider it to have been launched by the previous app activity.
295 callingPackage = sourceRecord.launchedFromPackage;
296 }
297 }
298
299 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
300 // We couldn't find a class that can handle the given Intent.
301 // That's the end of that!
302 err = ActivityManager.START_INTENT_NOT_RESOLVED;
303 }
304
305 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
306 // We couldn't find the specific class specified in the Intent.
307 // Also the end of the line.
308 err = ActivityManager.START_CLASS_NOT_FOUND;
309 }
310
311 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
312 && sourceRecord.task.voiceSession != null) {
313 // If this activity is being launched as part of a voice session, we need
314 // to ensure that it is safe to do so. If the upcoming activity will also
315 // be part of the voice session, we can only launch it if it has explicitly
316 // said it supports the VOICE category, or it is a part of the calling app.
317 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
318 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
319 try {
320 intent.addCategory(Intent.CATEGORY_VOICE);
321 if (!AppGlobals.getPackageManager().activitySupportsIntent(
322 intent.getComponent(), intent, resolvedType)) {
323 Slog.w(TAG,
324 "Activity being started in current voice task does not support voice: "
325 + intent);
326 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
327 }
328 } catch (RemoteException e) {
329 Slog.w(TAG, "Failure checking voice capabilities", e);
330 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
331 }
332 }
333 }
334
335 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
336 // If the caller is starting a new voice session, just make sure the target
337 // is actually allowing it to run this way.
338 try {
339 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
340 intent, resolvedType)) {
341 Slog.w(TAG,
342 "Activity being started in new voice task does not support: "
343 + intent);
344 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
345 }
346 } catch (RemoteException e) {
347 Slog.w(TAG, "Failure checking voice capabilities", e);
348 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
349 }
350 }
351
352 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
353
Wale Ogunwale01d66562015-12-29 08:19:19 -0800354 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800355 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800356 resultStack.sendActivityResultLocked(
357 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800358 }
359 ActivityOptions.abort(options);
360 return err;
361 }
362
363 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
364 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100365 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800366 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
367 callingPid, resolvedType, aInfo.applicationInfo);
368
369 if (mService.mController != null) {
370 try {
371 // The Intent we give to the watcher has the extra data
372 // stripped off, since it can contain private information.
373 Intent watchIntent = intent.cloneFilter();
374 abort |= !mService.mController.activityStarting(watchIntent,
375 aInfo.applicationInfo.packageName);
376 } catch (RemoteException e) {
377 mService.mController = null;
378 }
379 }
380
Rubin Xu58d25992016-01-21 17:47:13 +0000381 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
382 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid);
383 intent = mInterceptor.mIntent;
384 rInfo = mInterceptor.mRInfo;
385 aInfo = mInterceptor.mAInfo;
386 resolvedType = mInterceptor.mResolvedType;
387 inTask = mInterceptor.mInTask;
388 callingPid = mInterceptor.mCallingPid;
389 callingUid = mInterceptor.mCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800390
391 if (abort) {
392 if (resultRecord != null) {
393 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800394 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800395 }
396 // We pretend to the caller that it was really started, but
397 // they will just get a cancel result.
398 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800399 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800400 }
401
402 // If permissions need a review before any of the app components can run, we
403 // launch the review activity and pass a pending intent to start the activity
404 // we are to launching now after the review is completed.
405 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
406 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
407 aInfo.packageName, userId)) {
408 IIntentSender target = mService.getIntentSenderLocked(
409 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
410 callingUid, userId, null, null, 0, new Intent[]{intent},
411 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
412 | PendingIntent.FLAG_ONE_SHOT, null);
413
414 final int flags = intent.getFlags();
415 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
416 newIntent.setFlags(flags
417 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
418 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
419 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
420 if (resultRecord != null) {
421 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
422 }
423 intent = newIntent;
424
425 resolvedType = null;
426 callingUid = realCallingUid;
427 callingPid = realCallingPid;
428
429 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
430 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
431 null /*profilerInfo*/);
432
433 if (DEBUG_PERMISSIONS_REVIEW) {
434 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
435 true, false) + "} from uid " + callingUid + " on display "
436 + (container == null ? (mSupervisor.mFocusedStack == null ?
437 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
438 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
439 container.mActivityDisplay.mDisplayId)));
440 }
441 }
442 }
443
444 // If we have an ephemeral app, abort the process of launching the resolved intent.
445 // Instead, launch the ephemeral installer. Once the installer is finished, it
446 // starts either the intent we resolved here [on install error] or the ephemeral
447 // app [on install success].
448 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
449 // Create a pending intent to start the intent resolved here.
450 final IIntentSender failureTarget = mService.getIntentSenderLocked(
451 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
452 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
453 new String[]{ resolvedType },
454 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
455 | PendingIntent.FLAG_IMMUTABLE, null);
456
457 // Create a pending intent to start the ephemeral application; force it to be
458 // directed to the ephemeral package.
459 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
460 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
461 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
462 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
463 new String[]{ resolvedType },
464 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
465 | PendingIntent.FLAG_IMMUTABLE, null);
466
467 int flags = intent.getFlags();
468 intent = new Intent();
469 intent.setFlags(flags
470 | Intent.FLAG_ACTIVITY_NEW_TASK
471 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
472 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
473 rInfo.ephemeralResolveInfo.getPackageName());
474 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
475 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
476
477 resolvedType = null;
478 callingUid = realCallingUid;
479 callingPid = realCallingPid;
480
481 rInfo = rInfo.ephemeralInstaller;
482 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
483 }
484
485 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
486 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
487 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
488 options);
489 if (outActivity != null) {
490 outActivity[0] = r;
491 }
492
493 if (r.appTimeTracker == null && sourceRecord != null) {
494 // If the caller didn't specify an explicit time tracker, we want to continue
495 // tracking under any it has.
496 r.appTimeTracker = sourceRecord.appTimeTracker;
497 }
498
499 final ActivityStack stack = mSupervisor.mFocusedStack;
500 if (voiceSession == null && (stack.mResumedActivity == null
501 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
502 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
503 realCallingPid, realCallingUid, "Activity start")) {
504 PendingActivityLaunch pal = new PendingActivityLaunch(r,
505 sourceRecord, startFlags, stack, callerApp);
506 mPendingActivityLaunches.add(pal);
507 ActivityOptions.abort(options);
508 return ActivityManager.START_SWITCHES_CANCELED;
509 }
510 }
511
512 if (mService.mDidAppSwitch) {
513 // This is the second allowed switch since we stopped switches,
514 // so now just generally allow switches. Use case: user presses
515 // home (switches disabled, switch to home, mDidAppSwitch now true);
516 // user taps a home icon (coming from home so allowed, we hit here
517 // and now allow anyone to switch again).
518 mService.mAppSwitchesAllowedTime = 0;
519 } else {
520 mService.mDidAppSwitch = true;
521 }
522
523 doPendingActivityLaunchesLocked(false);
524
Wale Ogunwale01d66562015-12-29 08:19:19 -0800525 err = startActivityUnchecked(
526 r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800527 postStartActivityUncheckedProcessing(r, err, stack.mStackId);
528 return err;
529 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800530
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800531 void postStartActivityUncheckedProcessing(
532 ActivityRecord r, int result, int prevFocusedStackId) {
533
534 if (result < START_SUCCESS) {
535 // If someone asked to have the keyguard dismissed on the next activity start,
536 // but we are not actually doing an activity switch... just dismiss the keyguard now,
537 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800538 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800539 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800540 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800541
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800542 int startedActivityStackId = INVALID_STACK_ID;
543 if (r.task != null && r.task.stack != null) {
544 startedActivityStackId = r.task.stack.mStackId;
545 } else if (mTargetStack != null) {
546 startedActivityStackId = mTargetStack.mStackId;
547 }
548
549 if (startedActivityStackId == DOCKED_STACK_ID && prevFocusedStackId == HOME_STACK_ID) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100550 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
551 final ActivityRecord topActivityHomeStack = homeStack != null
552 ? homeStack.topRunningActivityLocked() : null;
553 if (topActivityHomeStack == null
554 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
555 // We launch an activity while being in home stack, which means either launcher or
556 // recents into docked stack. We don't want the launched activity to be alone in a
557 // docked stack, so we want to immediately launch recents too.
558 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
559 mWindowManager.showRecentApps();
560 return;
561 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800562 }
563
564 if (startedActivityStackId == PINNED_STACK_ID
565 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
566 // The activity was already running in the pinned stack so it wasn't started, but either
567 // brought to the front or the new intent was delivered to it since it was already in
568 // front. Notify anyone interested in this piece of information.
569 mService.notifyPinnedActivityRestartAttemptLocked();
570 return;
571 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800572 }
573
574 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
575 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
576 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
577 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
578 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
579 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
580 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
581 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
582 null /*container*/, null /*inTask*/);
583 if (mSupervisor.inResumeTopActivity) {
584 // If we are in resume section already, home activity will be initialized, but not
585 // resumed (to avoid recursive resume) and will stay that way until something pokes it
586 // again. We need to schedule another resume.
587 mSupervisor.scheduleResumeTopActivities();
588 }
589 }
590
591 final int startActivityMayWait(IApplicationThread caller, int callingUid,
592 String callingPackage, Intent intent, String resolvedType,
593 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
594 IBinder resultTo, String resultWho, int requestCode, int startFlags,
595 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
596 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
597 IActivityContainer iContainer, TaskRecord inTask) {
598 // Refuse possible leaked file descriptors
599 if (intent != null && intent.hasFileDescriptors()) {
600 throw new IllegalArgumentException("File descriptors passed in Intent");
601 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500602 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800603 boolean componentSpecified = intent.getComponent() != null;
604
605 // Save a copy in case ephemeral needs it
606 final Intent ephemeralIntent = new Intent(intent);
607 // Don't modify the client's object!
608 intent = new Intent(intent);
609
610 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000611 if (rInfo == null) {
612 UserInfo userInfo = mSupervisor.getUserInfo(userId);
613 if (userInfo != null && userInfo.isManagedProfile()) {
614 // Special case for managed profiles, if attempting to launch non-cryto aware
615 // app in a locked managed profile from an unlocked parent allow it to resolve
616 // as user will be sent via confirm credentials to unlock the profile.
617 UserManager userManager = UserManager.get(mService.mContext);
Tony Mak13436452016-02-24 11:08:38 +0000618 UserInfo parent = null;
619 long token = Binder.clearCallingIdentity();
620 try {
621 parent = userManager.getProfileParent(userId);
622 } finally {
623 Binder.restoreCallingIdentity(token);
624 }
Kenny Guyb1b30262016-02-09 16:02:35 +0000625 if (parent != null
626 && userManager.isUserUnlocked(parent.getUserHandle())
627 && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
628 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600629 PackageManager.MATCH_DIRECT_BOOT_AWARE
630 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000631 }
632 }
633 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800634 // Collect information about the target of the Intent.
635 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
636
637 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
638 ActivityStackSupervisor.ActivityContainer container =
639 (ActivityStackSupervisor.ActivityContainer)iContainer;
640 synchronized (mService) {
641 if (container != null && container.mParentActivity != null &&
642 container.mParentActivity.state != RESUMED) {
643 // Cannot start a child activity if the parent is not resumed.
644 return ActivityManager.START_CANCELED;
645 }
646 final int realCallingPid = Binder.getCallingPid();
647 final int realCallingUid = Binder.getCallingUid();
648 int callingPid;
649 if (callingUid >= 0) {
650 callingPid = -1;
651 } else if (caller == null) {
652 callingPid = realCallingPid;
653 callingUid = realCallingUid;
654 } else {
655 callingPid = callingUid = -1;
656 }
657
658 final ActivityStack stack;
659 if (container == null || container.mStack.isOnHomeDisplay()) {
660 stack = mSupervisor.mFocusedStack;
661 } else {
662 stack = container.mStack;
663 }
664 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
665 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
666 "Starting activity when config will change = " + stack.mConfigWillChange);
667
668 final long origId = Binder.clearCallingIdentity();
669
670 if (aInfo != null &&
671 (aInfo.applicationInfo.privateFlags
672 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
673 // This may be a heavy-weight process! Check to see if we already
674 // have another, different heavy-weight process running.
675 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
676 final ProcessRecord heavy = mService.mHeavyWeightProcess;
677 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
678 || !heavy.processName.equals(aInfo.processName))) {
679 int appCallingUid = callingUid;
680 if (caller != null) {
681 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
682 if (callerApp != null) {
683 appCallingUid = callerApp.info.uid;
684 } else {
685 Slog.w(TAG, "Unable to find app for caller " + caller
686 + " (pid=" + callingPid + ") when starting: "
687 + intent.toString());
688 ActivityOptions.abort(options);
689 return ActivityManager.START_PERMISSION_DENIED;
690 }
691 }
692
693 IIntentSender target = mService.getIntentSenderLocked(
694 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
695 appCallingUid, userId, null, null, 0, new Intent[] { intent },
696 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
697 | PendingIntent.FLAG_ONE_SHOT, null);
698
699 Intent newIntent = new Intent();
700 if (requestCode >= 0) {
701 // Caller is requesting a result.
702 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
703 }
704 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
705 new IntentSender(target));
706 if (heavy.activities.size() > 0) {
707 ActivityRecord hist = heavy.activities.get(0);
708 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
709 hist.packageName);
710 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
711 hist.task.taskId);
712 }
713 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
714 aInfo.packageName);
715 newIntent.setFlags(intent.getFlags());
716 newIntent.setClassName("android",
717 HeavyWeightSwitcherActivity.class.getName());
718 intent = newIntent;
719 resolvedType = null;
720 caller = null;
721 callingUid = Binder.getCallingUid();
722 callingPid = Binder.getCallingPid();
723 componentSpecified = true;
724 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
725 aInfo = rInfo != null ? rInfo.activityInfo : null;
726 if (aInfo != null) {
727 aInfo = mService.getActivityInfoForUser(aInfo, userId);
728 }
729 }
730 }
731 }
732
Jorim Jaggi275561a2016-02-23 10:11:02 -0500733 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800734 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
735 aInfo, rInfo, voiceSession, voiceInteractor,
736 resultTo, resultWho, requestCode, callingPid,
737 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500738 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
739 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800740
741 Binder.restoreCallingIdentity(origId);
742
743 if (stack.mConfigWillChange) {
744 // If the caller also wants to switch to a new configuration,
745 // do so now. This allows a clean switch, as we are waiting
746 // for the current activity to pause (so we will not destroy
747 // it), and have not yet started the next activity.
748 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
749 "updateConfiguration()");
750 stack.mConfigWillChange = false;
751 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
752 "Updating to new configuration after starting activity.");
753 mService.updateConfigurationLocked(config, null, false);
754 }
755
756 if (outResult != null) {
757 outResult.result = res;
758 if (res == ActivityManager.START_SUCCESS) {
759 mSupervisor.mWaitingActivityLaunched.add(outResult);
760 do {
761 try {
762 mService.wait();
763 } catch (InterruptedException e) {
764 }
765 } while (!outResult.timeout && outResult.who == null);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800766 } else if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800767 ActivityRecord r = stack.topRunningActivityLocked();
768 if (r.nowVisible && r.state == RESUMED) {
769 outResult.timeout = false;
770 outResult.who = new ComponentName(r.info.packageName, r.info.name);
771 outResult.totalTime = 0;
772 outResult.thisTime = 0;
773 } else {
774 outResult.thisTime = SystemClock.uptimeMillis();
775 mSupervisor.mWaitingActivityVisible.add(outResult);
776 do {
777 try {
778 mService.wait();
779 } catch (InterruptedException e) {
780 }
781 } while (!outResult.timeout && outResult.who == null);
782 }
783 }
784 }
785
Jorim Jaggi275561a2016-02-23 10:11:02 -0500786 final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
787 : null;
788 final boolean processRunning = outRecord[0] != null &&
789 mService.mProcessNames.get(outRecord[0].processName,
790 outRecord[0].appInfo.uid) != null;
791 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
792 processRunning);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800793 return res;
794 }
795 }
796
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800797 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
798 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
799 Bundle bOptions, int userId) {
800 if (intents == null) {
801 throw new NullPointerException("intents is null");
802 }
803 if (resolvedTypes == null) {
804 throw new NullPointerException("resolvedTypes is null");
805 }
806 if (intents.length != resolvedTypes.length) {
807 throw new IllegalArgumentException("intents are length different than resolvedTypes");
808 }
809
810
811 int callingPid;
812 if (callingUid >= 0) {
813 callingPid = -1;
814 } else if (caller == null) {
815 callingPid = Binder.getCallingPid();
816 callingUid = Binder.getCallingUid();
817 } else {
818 callingPid = callingUid = -1;
819 }
820 final long origId = Binder.clearCallingIdentity();
821 try {
822 synchronized (mService) {
823 ActivityRecord[] outActivity = new ActivityRecord[1];
824 for (int i=0; i<intents.length; i++) {
825 Intent intent = intents[i];
826 if (intent == null) {
827 continue;
828 }
829
830 // Refuse possible leaked file descriptors
831 if (intent != null && intent.hasFileDescriptors()) {
832 throw new IllegalArgumentException("File descriptors passed in Intent");
833 }
834
835 boolean componentSpecified = intent.getComponent() != null;
836
837 // Don't modify the client's object!
838 intent = new Intent(intent);
839
840 // Collect information about the target of the Intent.
841 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
842 null, userId);
843 // TODO: New, check if this is correct
844 aInfo = mService.getActivityInfoForUser(aInfo, userId);
845
846 if (aInfo != null &&
847 (aInfo.applicationInfo.privateFlags
848 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
849 throw new IllegalArgumentException(
850 "FLAG_CANT_SAVE_STATE not supported here");
851 }
852
853 ActivityOptions options = ActivityOptions.fromBundle(
854 i == intents.length - 1 ? bOptions : null);
855 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
856 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
857 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
858 options, false, componentSpecified, outActivity, null, null);
859 if (res < 0) {
860 return res;
861 }
862
863 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
864 }
865 }
866 } finally {
867 Binder.restoreCallingIdentity(origId);
868 }
869
Wale Ogunwale01d66562015-12-29 08:19:19 -0800870 return START_SUCCESS;
871 }
872
873 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
874 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
875 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
876
877 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
878 voiceInteractor);
879
880 computeLaunchingTaskFlags();
881
882 computeSourceStack();
883
884 mIntent.setFlags(mLaunchFlags);
885
886 ActivityRecord intentActivity = getReusableIntentActivity();
887
Jorim Jaggi2adba072016-03-03 13:43:39 +0100888 final int preferredLaunchStackId =
889 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
890
Wale Ogunwale01d66562015-12-29 08:19:19 -0800891 if (intentActivity != null) {
892 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
893 // still needs to be a lock task mode violation since the task gets cleared out and
894 // the device would otherwise leave the locked task.
895 if (mSupervisor.isLockTaskModeViolation(intentActivity.task,
896 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
897 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
898 mSupervisor.showLockTaskToast();
899 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
900 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
901 }
902
903 if (mStartActivity.task == null) {
904 mStartActivity.task = intentActivity.task;
905 }
906 if (intentActivity.task.intent == null) {
907 // This task was started because of movement of the activity based on affinity...
908 // Now that we are actually launching it, we can assign the base intent.
909 intentActivity.task.setIntent(mStartActivity);
910 }
911
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800912 // This code path leads to delivering a new intent, we want to make sure we schedule it
913 // as the first operation, in case the activity will be resumed as a result of later
914 // operations.
915 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
916 || mLaunchSingleInstance || mLaunchSingleTask) {
917 // In this situation we want to remove all activities from the task up to the one
918 // being started. In most cases this means we are resetting the task to its initial
919 // state.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800920 final ActivityRecord top = intentActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800921 mStartActivity, mLaunchFlags);
922 if (top != null) {
923 if (top.frontOfTask) {
924 // Activity aliases may mean we use different intents for the top activity,
925 // so make sure the task now has the identity of the new intent.
926 top.task.setIntent(mStartActivity);
927 }
928 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
929 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
930 mStartActivity.launchedFromPackage);
931 }
932 }
933
Wale Ogunwale01d66562015-12-29 08:19:19 -0800934 intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity);
935
936 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
937 // We don't need to start a new activity, and the client said not to do anything
938 // if that is the case, so this is it! And for paranoia, make sure we have
939 // correctly resumed the top activity.
940 resumeTargetStackIfNeeded();
941 return START_RETURN_INTENT_TO_CALLER;
942 }
943
944 setTaskFromIntentActivity(intentActivity);
945
946 if (!mAddingToTask && mReuseTask == null) {
947 // We didn't do anything... but it was needed (a.k.a., client don't use that
948 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
949 resumeTargetStackIfNeeded();
Jorim Jaggi2adba072016-03-03 13:43:39 +0100950 mSupervisor.showNonResizeableDockToastIfNeeded(mStartActivity.task,
951 preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800952 return START_TASK_TO_FRONT;
953 }
954 }
955
956 if (mStartActivity.packageName == null) {
957 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
958 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
959 -1, mStartActivity.resultTo, mStartActivity.resultWho,
960 mStartActivity.requestCode, RESULT_CANCELED, null);
961 }
962 ActivityOptions.abort(mOptions);
963 return START_CLASS_NOT_FOUND;
964 }
965
966 // If the activity being launched is the same as the one currently at the top, then
967 // we need to check if it should only be launched once.
968 final ActivityStack topStack = mSupervisor.mFocusedStack;
969 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
970 final boolean dontStart = top != null && mStartActivity.resultTo == null
971 && top.realActivity.equals(mStartActivity.realActivity)
972 && top.userId == mStartActivity.userId
973 && top.app != null && top.app.thread != null
974 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
975 || mLaunchSingleTop || mLaunchSingleTask);
976 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800977 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800978 // For paranoia, make sure we have correctly resumed the top activity.
979 topStack.mLastPausedActivity = null;
980 if (mDoResume) {
981 mSupervisor.resumeFocusedStackTopActivityLocked();
982 }
983 ActivityOptions.abort(mOptions);
984 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
985 // We don't need to start a new activity, and the client said not to do
986 // anything if that is the case, so this is it!
987 return START_RETURN_INTENT_TO_CALLER;
988 }
989 top.deliverNewIntentLocked(
990 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Jorim Jaggi2adba072016-03-03 13:43:39 +0100991 mSupervisor.showNonResizeableDockToastIfNeeded(mStartActivity.task,
992 preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800993 return START_DELIVERED_TO_TOP;
994 }
995
996 boolean newTask = false;
997 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
998 ? mSourceRecord.task : null;
999
1000 // Should this be considered a new task?
1001 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1002 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1003 newTask = true;
1004 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1005
1006 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1007 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1008 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1009 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001010 if (!mMovedHome) {
1011 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001012 }
1013 } else if (mSourceRecord != null) {
1014 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1015 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1016 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1017 }
1018
1019 final int result = setTaskFromSourceRecord();
1020 if (result != START_SUCCESS) {
1021 return result;
1022 }
1023 } else if (mInTask != null) {
1024 // The caller is asking that the new activity be started in an explicit
1025 // task it has provided to us.
1026 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1027 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1028 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1029 }
1030
1031 final int result = setTaskFromInTask();
1032 if (result != START_SUCCESS) {
1033 return result;
1034 }
1035 } else {
1036 // This not being started from an existing activity, and not part of a new task...
1037 // just put it in the top task, though these days this case should never happen.
1038 setTaskToCurrentTopOrCreateNewTask();
1039 }
1040
1041 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1042 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1043
1044 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1045 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1046 }
1047 if (newTask) {
1048 EventLog.writeEvent(
1049 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1050 }
1051 ActivityStack.logStartActivity(
1052 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1053 mTargetStack.mLastPausedActivity = null;
1054 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1055 if (mDoResume) {
1056 if (!mLaunchTaskBehind) {
1057 // TODO(b/26381750): Remove this code after verification that all the decision
1058 // points above moved targetStack to the front which will also set the focus
1059 // activity.
1060 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1061 }
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001062 if (mTargetStack.isFocusable()) {
1063 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1064 mOptions);
1065 } else {
1066 // If the activity is not focusable, we can't resume it, but still would like to
1067 // make sure it becomes visible as it starts (this will also trigger entry
1068 // animation). An example of this are PIP activities.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001069 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001070 // Go ahead and tell window manager to execute app transition for this activity
1071 // since the app transition will not be triggered through the resume channel.
1072 mWindowManager.executeAppTransition();
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001073 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001074 } else {
1075 mTargetStack.addRecentActivityLocked(mStartActivity);
1076 }
1077 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1078
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001079 mSupervisor.showNonResizeableDockToastIfNeeded(
1080 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001081
1082 return START_SUCCESS;
1083 }
1084
1085 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1086 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1087 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1088 reset();
1089
1090 mStartActivity = r;
1091 mIntent = r.intent;
1092 mOptions = options;
1093 mCallingUid = r.launchedFromUid;
1094 mSourceRecord = sourceRecord;
1095 mVoiceSession = voiceSession;
1096 mVoiceInteractor = voiceInteractor;
1097
1098 mLaunchBounds = getOverrideBounds(r, options, inTask);
1099
1100 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1101 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1102 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1103 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1104 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1105 mLaunchTaskBehind = r.mLaunchTaskBehind
1106 && !mLaunchSingleTask && !mLaunchSingleInstance
1107 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1108
1109 sendNewTaskResultRequestIfNeeded();
1110
1111 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1112 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1113 }
1114
1115 // If we are actually going to launch in to a new task, there are some cases where
1116 // we further want to do multiple task.
1117 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1118 if (mLaunchTaskBehind
1119 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1120 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1121 }
1122 }
1123
1124 // We'll invoke onUserLeaving before onPause only if the launching
1125 // activity did not explicitly state that this is an automated launch.
1126 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1127 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1128 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1129
1130 // If the caller has asked not to resume at this point, we make note
1131 // of this in the record so that we can skip it when trying to find
1132 // the top running activity.
1133 mDoResume = doResume;
1134 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1135 r.delayedResume = true;
1136 mDoResume = false;
1137 }
1138
1139 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1140
1141 mInTask = inTask;
1142 // In some flows in to this function, we retrieve the task record and hold on to it
1143 // without a lock before calling back in to here... so the task at this point may
1144 // not actually be in recents. Check for that, and if it isn't in recents just
1145 // consider it invalid.
1146 if (inTask != null && !inTask.inRecents) {
1147 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1148 mInTask = null;
1149 }
1150
1151 mStartFlags = startFlags;
1152 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1153 // is the same as the one making the call... or, as a special case, if we do not know
1154 // the caller then we count the current top activity as the caller.
1155 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1156 ActivityRecord checkedCaller = sourceRecord;
1157 if (checkedCaller == null) {
1158 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1159 mNotTop);
1160 }
1161 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1162 // Caller is not the same as launcher, so always needed.
1163 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1164 }
1165 }
1166
1167 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1168 }
1169
1170 private void sendNewTaskResultRequestIfNeeded() {
1171 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1172 && mStartActivity.resultTo.task.stack != null) {
1173 // For whatever reason this activity is being launched into a new task...
1174 // yet the caller has requested a result back. Well, that is pretty messed up,
1175 // so instead immediately send back a cancel and let the new task continue launched
1176 // as normal without a dependency on its originator.
1177 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1178 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1179 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1180 mStartActivity.resultTo = null;
1181 }
1182 }
1183
1184 private void computeLaunchingTaskFlags() {
1185 // If the caller is not coming from another activity, but has given us an explicit task into
1186 // which they would like us to launch the new activity, then let's see about doing that.
1187 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1188 final Intent baseIntent = mInTask.getBaseIntent();
1189 final ActivityRecord root = mInTask.getRootActivity();
1190 if (baseIntent == null) {
1191 ActivityOptions.abort(mOptions);
1192 throw new IllegalArgumentException("Launching into task without base intent: "
1193 + mInTask);
1194 }
1195
1196 // If this task is empty, then we are adding the first activity -- it
1197 // determines the root, and must be launching as a NEW_TASK.
1198 if (mLaunchSingleInstance || mLaunchSingleTask) {
1199 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1200 ActivityOptions.abort(mOptions);
1201 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1202 + mStartActivity + " into different task " + mInTask);
1203 }
1204 if (root != null) {
1205 ActivityOptions.abort(mOptions);
1206 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1207 + " has root " + root + " but target is singleInstance/Task");
1208 }
1209 }
1210
1211 // If task is empty, then adopt the interesting intent launch flags in to the
1212 // activity being started.
1213 if (root == null) {
1214 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1215 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1216 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1217 | (baseIntent.getFlags() & flagsOfInterest);
1218 mIntent.setFlags(mLaunchFlags);
1219 mInTask.setIntent(mStartActivity);
1220 mAddingToTask = true;
1221
1222 // If the task is not empty and the caller is asking to start it as the root of
1223 // a new task, then we don't actually want to start this on the task. We will
1224 // bring the task to the front, and possibly give it a new intent.
1225 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1226 mAddingToTask = false;
1227
1228 } else {
1229 mAddingToTask = true;
1230 }
1231
1232 mReuseTask = mInTask;
1233 } else {
1234 mInTask = null;
1235 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1236 // when in freeform workspace.
1237 // Also put noDisplay activities in the source task. These by itself can be placed
1238 // in any task/stack, however it could launch other activities like ResolverActivity,
1239 // and we want those to stay in the original task.
1240 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1241 && mSourceRecord.isFreeform()) {
1242 mAddingToTask = true;
1243 }
1244 }
1245
1246 if (mInTask == null) {
1247 if (mSourceRecord == null) {
1248 // This activity is not being started from another... in this
1249 // case we -always- start a new task.
1250 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1251 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1252 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1253 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1254 }
1255 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1256 // The original activity who is starting us is running as a single
1257 // instance... this new activity it is starting must go on its
1258 // own task.
1259 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1260 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1261 // The activity being started is a single instance... it always
1262 // gets launched into its own task.
1263 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1264 }
1265 }
1266 }
1267
1268 private void computeSourceStack() {
1269 if (mSourceRecord == null) {
1270 mSourceStack = null;
1271 return;
1272 }
1273 if (!mSourceRecord.finishing) {
1274 mSourceStack = mSourceRecord.task.stack;
1275 return;
1276 }
1277
1278 // If the source is finishing, we can't further count it as our source. This is because the
1279 // task it is associated with may now be empty and on its way out, so we don't want to
1280 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1281 // a task for it. But save the task information so it can be used when creating the new task.
1282 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1283 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1284 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1285 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1286 mNewTaskInfo = mSourceRecord.info;
1287 mNewTaskIntent = mSourceRecord.task.intent;
1288 }
1289 mSourceRecord = null;
1290 mSourceStack = null;
1291 }
1292
1293 /**
1294 * Decide whether the new activity should be inserted into an existing task. Returns null
1295 * if not or an ActivityRecord with the task into which the new activity should be added.
1296 */
1297 private ActivityRecord getReusableIntentActivity() {
1298 // We may want to try to place the new activity in to an existing task. We always
1299 // do this if the target activity is singleTask or singleInstance; we will also do
1300 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1301 // us to still place it in a new task: multi task, always doc mode, or being asked to
1302 // launch this as a new task behind the current one.
1303 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1304 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1305 || mLaunchSingleInstance || mLaunchSingleTask;
1306 // If bring to front is requested, and no result is requested and we have not been given
1307 // an explicit task to launch in to, and we can find a task that was started with this
1308 // same component, then instead of launching bring that one to the front.
1309 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1310 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001311 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1312 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1313 intentActivity = task != null ? task.getTopActivity() : null;
1314 } else if (putIntoExistingTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001315 // See if there is a task to bring to the front. If this is a SINGLE_INSTANCE
1316 // activity, there can be one and only one instance of it in the history, and it is
1317 // always in its own unique task, so we do a special search.
1318 intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info)
1319 : mSupervisor.findTaskLocked(mStartActivity);
1320 }
1321 return intentActivity;
1322 }
1323
1324 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1325 mTargetStack = intentActivity.task.stack;
1326 mTargetStack.mLastPausedActivity = null;
1327 // If the target task is not in the front, then we need to bring it to the front...
1328 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1329 // the same behavior as if a new instance was being started, which means not bringing it
1330 // to the front if the caller is not itself in the front.
1331 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1332 ActivityRecord curTop = (focusStack == null)
1333 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1334
1335 if (curTop != null && (curTop.task != intentActivity.task ||
1336 curTop.task != focusStack.topTask())) {
1337 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1338 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1339 mSourceStack.topActivity().task == mSourceRecord.task)) {
1340 // We really do want to push this one into the user's face, right now.
1341 if (mLaunchTaskBehind && mSourceRecord != null) {
1342 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1343 }
1344 mMovedHome = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001345
1346 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1347 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1348 // So no point resuming any of the activities here, it just wastes one extra
1349 // resuming, plus enter AND exit transitions.
1350 // Here we only want to bring the target stack forward. Transition will be applied
1351 // to the new activity that's started after the old ones are gone.
1352 final boolean willClearTask =
1353 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1354 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1355 if (!willClearTask) {
1356 final ActivityStack launchStack = getLaunchStack(
1357 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, true);
1358 if (launchStack == null || launchStack == mTargetStack) {
1359 // We only want to move to the front, if we aren't going to launch on a
1360 // different stack. If we launch on a different stack, we will put the
1361 // task on top there.
1362 mTargetStack.moveTaskToFrontLocked(
1363 intentActivity.task, mNoAnimation, mOptions,
1364 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1365 mMovedToFront = true;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001366 } else if ((launchStack.mStackId == DOCKED_STACK_ID
1367 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID)
1368 && (mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1369 // If we want to launch adjacent and mTargetStack is not the computed
1370 // launch stack - move task to top of computed stack.
1371 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1372 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1373 ANIMATE);
1374 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001375 }
1376 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001377 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001378 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001379 }
1380 }
1381 if (!mMovedToFront && mDoResume) {
1382 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1383 + " from " + intentActivity);
1384 mTargetStack.moveToFront("intentActivityFound");
1385 }
1386
1387 // If the caller has requested that the target task be reset, then do so.
1388 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1389 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1390 }
1391 return intentActivity;
1392 }
1393
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001394 private void updateTaskReturnToType(
1395 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1396 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1397 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1398 // Caller wants to appear on home activity.
1399 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1400 return;
1401 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1402 // Task will be launched over the home stack, so return home.
1403 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1404 return;
1405 }
1406
1407 // Else we are coming from an application stack so return to an application.
1408 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1409 }
1410
Wale Ogunwale01d66562015-12-29 08:19:19 -08001411 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1412 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1413 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1414 // The caller has requested to completely replace any existing task with its new
1415 // activity. Well that should not be too hard...
1416 mReuseTask = intentActivity.task;
1417 mReuseTask.performClearTaskLocked();
1418 mReuseTask.setIntent(mStartActivity);
1419 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1420 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001421 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1422 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001423 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001424 // A special case: we need to start the activity because it is not currently
1425 // running, and the caller has asked to clear the current task to have this
1426 // activity at the top.
1427 mAddingToTask = true;
1428 // Now pretend like this activity is being started by the top of its task, so it
1429 // is put in the right place.
1430 mSourceRecord = intentActivity;
1431 final TaskRecord task = mSourceRecord.task;
1432 if (task != null && task.stack == null) {
1433 // Target stack got cleared when we all activities were removed above.
1434 // Go ahead and reset it.
1435 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1436 null /* bounds */, mLaunchFlags, mOptions);
1437 mTargetStack.addTask(task,
1438 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1439 }
1440 }
1441 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1442 // In this case the top activity on the task is the same as the one being launched,
1443 // so we take that as a request to bring the task to the foreground. If the top
1444 // activity in the task is the root activity, deliver this new intent to it if it
1445 // desires.
1446 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1447 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001448 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001449 intentActivity.task);
1450 if (intentActivity.frontOfTask) {
1451 intentActivity.task.setIntent(mStartActivity);
1452 }
1453 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1454 mStartActivity.launchedFromPackage);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -08001455 } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001456 // In this case we are launching the root activity of the task, but with a
1457 // different intent. We should start a new instance on top.
1458 mAddingToTask = true;
1459 mSourceRecord = intentActivity;
1460 }
1461 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1462 // In this case an activity is being launched in to an existing task, without
1463 // resetting that task. This is typically the situation of launching an activity
1464 // from a notification or shortcut. We want to place the new activity on top of the
1465 // current task.
1466 mAddingToTask = true;
1467 mSourceRecord = intentActivity;
1468 } else if (!intentActivity.task.rootWasReset) {
1469 // In this case we are launching into an existing task that has not yet been started
1470 // from its front door. The current task has been brought to the front. Ideally,
1471 // we'd probably like to place this new task at the bottom of its stack, but that's
1472 // a little hard to do with the current organization of the code so for now we'll
1473 // just drop it.
1474 intentActivity.task.setIntent(mStartActivity);
1475 }
1476 }
1477
1478 private void resumeTargetStackIfNeeded() {
1479 if (mDoResume) {
1480 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1481 if (!mMovedToFront) {
1482 // Make sure to notify Keyguard as well if we are not running an app transition
1483 // later.
1484 mSupervisor.notifyActivityDrawnForKeyguard();
1485 }
1486 } else {
1487 ActivityOptions.abort(mOptions);
1488 }
1489 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1490 }
1491
1492 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1493 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1494 mOptions);
1495 if (mDoResume) {
1496 mTargetStack.moveToFront("startingNewTask");
1497 }
1498
1499 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001500 final TaskRecord task = mTargetStack.createTaskRecord(
1501 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001502 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1503 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1504 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1505 mStartActivity.setTask(task, taskToAffiliate);
1506 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001507 final int stackId = mTargetStack.mStackId;
1508 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001509 mService.resizeStack(
1510 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001511 } else {
1512 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1513 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001514 }
1515 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1516 "Starting new activity " +
1517 mStartActivity + " in new task " + mStartActivity.task);
1518 } else {
1519 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1520 }
1521 }
1522
1523 private int setTaskFromSourceRecord() {
1524 final TaskRecord sourceTask = mSourceRecord.task;
1525 // We only want to allow changing stack if the target task is not the top one,
1526 // otherwise we would move the launching task to the other side, rather than show
1527 // two side by side.
1528 final boolean launchToSideAllowed = sourceTask.stack.topTask() != sourceTask;
1529 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, launchToSideAllowed);
1530
1531 if (mTargetStack == null) {
1532 mTargetStack = sourceTask.stack;
1533 } else if (mTargetStack != sourceTask.stack) {
1534 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1535 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1536 }
1537 if (mDoResume) {
1538 mTargetStack.moveToFront("sourceStackToFront");
1539 }
1540 final TaskRecord topTask = mTargetStack.topTask();
1541 if (topTask != sourceTask) {
1542 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1543 mStartActivity.appTimeTracker, "sourceTaskToFront");
1544 }
1545 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1546 // In this case, we are adding the activity to an existing task, but the caller has
1547 // asked to clear that task if the activity is already running.
1548 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1549 mKeepCurTransition = true;
1550 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001551 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001552 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1553 // For paranoia, make sure we have correctly resumed the top activity.
1554 mTargetStack.mLastPausedActivity = null;
1555 if (mDoResume) {
1556 mSupervisor.resumeFocusedStackTopActivityLocked();
1557 }
1558 ActivityOptions.abort(mOptions);
1559 return START_DELIVERED_TO_TOP;
1560 }
1561 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1562 // In this case, we are launching an activity in our own task that may already be
1563 // running somewhere in the history, and we want to shuffle it to the front of the
1564 // stack if so.
1565 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1566 if (top != null) {
1567 final TaskRecord task = top.task;
1568 task.moveActivityToFrontLocked(top);
1569 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001570 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001571 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1572 mTargetStack.mLastPausedActivity = null;
1573 if (mDoResume) {
1574 mSupervisor.resumeFocusedStackTopActivityLocked();
1575 }
1576 return START_DELIVERED_TO_TOP;
1577 }
1578 }
1579
1580 // An existing activity is starting this new activity, so we want to keep the new one in
1581 // the same task as the one that is starting it.
1582 mStartActivity.setTask(sourceTask, null);
1583 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1584 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1585 return START_SUCCESS;
1586 }
1587
1588 private int setTaskFromInTask() {
1589 if (mLaunchBounds != null) {
1590 mInTask.updateOverrideConfiguration(mLaunchBounds);
1591 int stackId = mInTask.getLaunchStackId();
1592 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001593 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001594 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001595 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001596 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001597 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001598 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001599 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001600 }
1601 mTargetStack = mInTask.stack;
1602 mTargetStack.moveTaskToFrontLocked(
1603 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1604
1605 // Check whether we should actually launch the new activity in to the task,
1606 // or just reuse the current activity on top.
1607 ActivityRecord top = mInTask.getTopActivity();
1608 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1609 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1610 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001611 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001612 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1613 // We don't need to start a new activity, and the client said not to do
1614 // anything if that is the case, so this is it!
1615 return START_RETURN_INTENT_TO_CALLER;
1616 }
1617 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1618 return START_DELIVERED_TO_TOP;
1619 }
1620 }
1621
1622 if (!mAddingToTask) {
1623 // We don't actually want to have this activity added to the task, so just
1624 // stop here but still tell the caller that we consumed the intent.
1625 ActivityOptions.abort(mOptions);
1626 return START_TASK_TO_FRONT;
1627 }
1628
1629 mStartActivity.setTask(mInTask, null);
1630 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1631 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1632
1633 return START_SUCCESS;
1634 }
1635
1636 private void setTaskToCurrentTopOrCreateNewTask() {
1637 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1638 mOptions);
1639 if (mDoResume) {
1640 mTargetStack.moveToFront("addingToTopTask");
1641 }
1642 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001643 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1644 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1645 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001646 mStartActivity.setTask(task, null);
1647 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1648 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1649 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1650 }
1651
1652 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1653 boolean launchSingleTask, int launchFlags) {
1654 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1655 (launchSingleInstance || launchSingleTask)) {
1656 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1657 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1658 "\"singleInstance\" or \"singleTask\"");
1659 launchFlags &=
1660 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1661 } else {
1662 switch (r.info.documentLaunchMode) {
1663 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1664 break;
1665 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1666 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1667 break;
1668 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1669 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1670 break;
1671 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1672 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1673 break;
1674 }
1675 }
1676 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001677 }
1678
1679 final void doPendingActivityLaunchesLocked(boolean doResume) {
1680 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001681 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1682 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001683 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001684 final int result = startActivityUnchecked(
1685 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1686 postStartActivityUncheckedProcessing(
1687 pal.r, result, mSupervisor.mFocusedStack.mStackId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001688 } catch (Exception e) {
1689 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1690 pal.sendErrorResult(e.getMessage());
1691 }
1692 }
1693 }
1694
1695 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001696 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001697 final TaskRecord task = r.task;
1698 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1699 return mSupervisor.mHomeStack;
1700 }
1701
Wale Ogunwale854809c2015-12-27 16:18:19 -08001702 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions, true);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001703 if (stack != null) {
1704 return stack;
1705 }
1706
1707 if (task != null && task.stack != null) {
1708 stack = task.stack;
1709 if (stack.isOnHomeDisplay()) {
1710 if (mSupervisor.mFocusedStack != stack) {
1711 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1712 "computeStackFocus: Setting " + "focused stack to r=" + r
1713 + " task=" + task);
1714 } else {
1715 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1716 "computeStackFocus: Focused stack already="
1717 + mSupervisor.mFocusedStack);
1718 }
1719 }
1720 return stack;
1721 }
1722
1723 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1724 if (container != null) {
1725 // The first time put it on the desired stack, after this put on task stack.
1726 r.mInitialActivityContainer = null;
1727 return container.mStack;
1728 }
1729
1730 // The fullscreen stack can contain any task regardless of if the task is resizeable
1731 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1732 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1733 // we can also put it in the focused stack.
1734 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001735 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1736 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1737 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001738 if (canUseFocusedStack && (!newTask
1739 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1740 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1741 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1742 return mSupervisor.mFocusedStack;
1743 }
1744
1745 // We first try to put the task in the first dynamic stack.
1746 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1747 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1748 stack = homeDisplayStacks.get(stackNdx);
1749 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1750 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1751 "computeStackFocus: Setting focused stack=" + stack);
1752 return stack;
1753 }
1754 }
1755
1756 // If there is no suitable dynamic stack then we figure out which static stack to use.
1757 final int stackId = task != null ? task.getLaunchStackId() :
1758 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1759 FULLSCREEN_WORKSPACE_STACK_ID;
1760 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1761 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1762 + r + " stackId=" + stack.mStackId);
1763 return stack;
1764 }
1765
Wale Ogunwale854809c2015-12-27 16:18:19 -08001766 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1767 ActivityOptions aOptions, boolean launchToSideAllowed) {
1768 final int launchStackId =
1769 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1770
1771 if (isValidLaunchStackId(launchStackId, r)) {
1772 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001773 } else if (launchStackId == DOCKED_STACK_ID) {
1774 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1775 // for this activity, so we put the activity in the fullscreen stack.
1776 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001777 }
1778
Wale Ogunwale2a25a622016-01-30 11:27:21 -08001779 if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001780 return null;
1781 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001782 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001783
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001784 // The parent activity doesn't want to launch the activity on top of itself, but
1785 // instead tries to put it onto other side in side-by-side mode.
1786 final ActivityStack parentStack = task != null ? task.stack
1787 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1788 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001789
1790 if (parentStack != mSupervisor.mFocusedStack) {
1791 // If task's parent stack is not focused - use it during adjacent launch.
1792 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001793 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001794 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1795 // If task is already on top of focused stack - use it. We don't want to move the
1796 // existing focused task to adjacent stack, just deliver new intent in this case.
1797 return mSupervisor.mFocusedStack;
1798 }
1799
1800 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1801 // If parent was in docked stack, the natural place to launch another activity
1802 // will be fullscreen, so it can appear alongside the docked window.
1803 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1804 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001805 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001806 // If the parent is not in the docked stack, we check if there is docked window
1807 // and if yes, we will launch into that stack. If not, we just put the new
1808 // activity into parent's stack, because we can't find a better place.
1809 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1810 if (dockedStack != null
1811 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1812 // There is a docked stack, but it isn't visible, so we can't launch into that.
1813 return null;
1814 } else {
1815 return dockedStack;
1816 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001817 }
1818 }
1819 }
1820
Wale Ogunwale854809c2015-12-27 16:18:19 -08001821 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1822 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1823 || !StackId.isStaticStack(stackId)) {
1824 return false;
1825 }
1826
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001827 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
1828 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
1829 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001830 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001831
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001832 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1833 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08001834 }
1835
1836 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1837 return false;
1838 }
1839
1840 final boolean supportsPip = mService.mSupportsPictureInPicture
1841 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1842 if (stackId == PINNED_STACK_ID && !supportsPip) {
1843 return false;
1844 }
1845 return true;
1846 }
1847
Wale Ogunwale854809c2015-12-27 16:18:19 -08001848 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1849 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001850 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08001851 if (mSupervisor.canUseActivityOptionsLaunchBounds(
1852 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001853 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08001854 }
1855 }
1856 return newBounds;
1857 }
1858
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001859 void setWindowManager(WindowManagerService wm) {
1860 mWindowManager = wm;
1861 }
1862
1863 void removePendingActivityLaunchesLocked(ActivityStack stack) {
1864 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1865 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1866 if (pal.stack == stack) {
1867 mPendingActivityLaunches.remove(palNdx);
1868 }
1869 }
1870 }
1871}