blob: 68036f3af61a4c1ae417c2b3b5ab97590f98fb52 [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;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080020import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080021import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
22import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
23import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
24import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
25import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
26import static android.app.ActivityManager.START_SUCCESS;
27import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale854809c2015-12-27 16:18:19 -080028import static android.app.ActivityManager.StackId;
Winson Chung83471632016-12-13 11:02:12 -080029import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080030import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
31import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
32import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080033import static android.app.ActivityManager.StackId.HOME_STACK_ID;
34import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
35import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080036import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Andrii Kulian4ede3e02017-01-12 11:52:31 -080037import static android.app.ActivityManager.StackId.isDynamicStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
39import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010040import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080041import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080042import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080044import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080045import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
46import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080047import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
48import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
49import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
50import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
51import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080052import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080053import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
54import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
56import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080057import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070058import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080059import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080062import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080063import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
65import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
66import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
71import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
72import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
73import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080074import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -080075import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
77import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
78import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080079import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080080import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
Winson Chung74666102017-02-22 17:49:24 -080081import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080082import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
83import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080084import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080085import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080086import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080087import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
88import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
89
90import static java.lang.Integer.MAX_VALUE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080091
Todd Kennedye9910222017-02-21 16:00:11 -080092import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080093import android.app.ActivityManager;
94import android.app.ActivityOptions;
95import android.app.AppGlobals;
96import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080098import android.app.PendingIntent;
99import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700100import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800101import android.content.ComponentName;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800102import android.content.IIntentSender;
103import android.content.Intent;
104import android.content.IntentSender;
105import android.content.pm.ActivityInfo;
106import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -0800107import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000108import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800109import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000110import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800111import android.content.res.Configuration;
112import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700113import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800114import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800115import android.os.Bundle;
116import android.os.IBinder;
117import android.os.RemoteException;
118import android.os.SystemClock;
119import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000120import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800121import android.service.voice.IVoiceInteractionSession;
122import android.util.EventLog;
123import android.util.Slog;
124import android.view.Display;
125
126import com.android.internal.app.HeavyWeightSwitcherActivity;
127import com.android.internal.app.IVoiceInteractor;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800128import com.android.server.LocalServices;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800129import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800130import com.android.server.pm.InstantAppResolver;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800131import com.android.server.vr.VrManagerInternal;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800132import com.android.server.wm.WindowManagerService;
133
134import java.util.ArrayList;
135
136/**
137 * Controller for interpreting how and then launching activities.
138 *
139 * This class collects all the logic for determining how an intent and flags should be turned into
140 * an activity and associated task and stack.
141 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800142class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800143 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
144 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
145 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
146 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
147 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
148
149 private final ActivityManagerService mService;
150 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000151 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800152 private WindowManagerService mWindowManager;
153
154 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
155
Wale Ogunwale01d66562015-12-29 08:19:19 -0800156 // Share state variable among methods when starting an activity.
157 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700158 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800159 private Intent mIntent;
160 private int mCallingUid;
161 private ActivityOptions mOptions;
162
163 private boolean mLaunchSingleTop;
164 private boolean mLaunchSingleInstance;
165 private boolean mLaunchSingleTask;
166 private boolean mLaunchTaskBehind;
167 private int mLaunchFlags;
168
169 private Rect mLaunchBounds;
170
171 private ActivityRecord mNotTop;
172 private boolean mDoResume;
173 private int mStartFlags;
174 private ActivityRecord mSourceRecord;
David Stevensc6b91c62017-02-08 14:23:58 -0800175 private int mSourceDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800176
177 private TaskRecord mInTask;
178 private boolean mAddingToTask;
179 private TaskRecord mReuseTask;
180
181 private ActivityInfo mNewTaskInfo;
182 private Intent mNewTaskIntent;
183 private ActivityStack mSourceStack;
184 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700185 // Indicates that we moved other task and are going to put something on top soon, so
186 // we don't want to show it redundantly or accidentally change what's shown below.
187 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800188 private boolean mMovedToFront;
189 private boolean mNoAnimation;
190 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700191 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700192 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800193
194 private IVoiceInteractionSession mVoiceSession;
195 private IVoiceInteractor mVoiceInteractor;
196
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800197 private boolean mUsingVrCompatibilityDisplay;
198
Wale Ogunwale01d66562015-12-29 08:19:19 -0800199 private void reset() {
200 mStartActivity = null;
201 mIntent = null;
202 mCallingUid = -1;
203 mOptions = null;
204
205 mLaunchSingleTop = false;
206 mLaunchSingleInstance = false;
207 mLaunchSingleTask = false;
208 mLaunchTaskBehind = false;
209 mLaunchFlags = 0;
210
211 mLaunchBounds = null;
212
213 mNotTop = null;
214 mDoResume = false;
215 mStartFlags = 0;
216 mSourceRecord = null;
David Stevensc6b91c62017-02-08 14:23:58 -0800217 mSourceDisplayId = INVALID_DISPLAY;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800218
219 mInTask = null;
220 mAddingToTask = false;
221 mReuseTask = null;
222
223 mNewTaskInfo = null;
224 mNewTaskIntent = null;
225 mSourceStack = null;
226
227 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700228 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800229 mMovedToFront = false;
230 mNoAnimation = false;
231 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700232 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800233
234 mVoiceSession = null;
235 mVoiceInteractor = null;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800236
237 mUsingVrCompatibilityDisplay = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800238 }
239
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800240 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
241 mService = service;
242 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000243 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800244 mUsingVrCompatibilityDisplay = false;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800245 }
246
247 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
248 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
249 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
250 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
251 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
252 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
253 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
254 TaskRecord inTask) {
255 int err = ActivityManager.START_SUCCESS;
256
257 ProcessRecord callerApp = null;
258 if (caller != null) {
259 callerApp = mService.getRecordForAppLocked(caller);
260 if (callerApp != null) {
261 callingPid = callerApp.pid;
262 callingUid = callerApp.info.uid;
263 } else {
264 Slog.w(TAG, "Unable to find app for caller " + caller
265 + " (pid=" + callingPid + ") when starting: "
266 + intent.toString());
267 err = ActivityManager.START_PERMISSION_DENIED;
268 }
269 }
270
271 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
272
273 if (err == ActivityManager.START_SUCCESS) {
274 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800275 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800276 }
277
278 ActivityRecord sourceRecord = null;
279 ActivityRecord resultRecord = null;
280 if (resultTo != null) {
281 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
282 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
283 "Will send result to " + resultTo + " " + sourceRecord);
284 if (sourceRecord != null) {
285 if (requestCode >= 0 && !sourceRecord.finishing) {
286 resultRecord = sourceRecord;
287 }
288 }
289 }
290
291 final int launchFlags = intent.getFlags();
292
293 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
294 // Transfer the result target from the source activity to the new
295 // one being started, including any failures.
296 if (requestCode >= 0) {
297 ActivityOptions.abort(options);
298 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
299 }
300 resultRecord = sourceRecord.resultTo;
301 if (resultRecord != null && !resultRecord.isInStackLocked()) {
302 resultRecord = null;
303 }
304 resultWho = sourceRecord.resultWho;
305 requestCode = sourceRecord.requestCode;
306 sourceRecord.resultTo = null;
307 if (resultRecord != null) {
308 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
309 }
310 if (sourceRecord.launchedFromUid == callingUid) {
311 // The new activity is being launched from the same uid as the previous
312 // activity in the flow, and asking to forward its result back to the
313 // previous. In this case the activity is serving as a trampoline between
314 // the two, so we also want to update its launchedFromPackage to be the
315 // same as the previous activity. Note that this is safe, since we know
316 // these two packages come from the same uid; the caller could just as
317 // well have supplied that same package name itself. This specifially
318 // deals with the case of an intent picker/chooser being launched in the app
319 // flow to redirect to an activity picked by the user, where we want the final
320 // activity to consider it to have been launched by the previous app activity.
321 callingPackage = sourceRecord.launchedFromPackage;
322 }
323 }
324
325 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
326 // We couldn't find a class that can handle the given Intent.
327 // That's the end of that!
328 err = ActivityManager.START_INTENT_NOT_RESOLVED;
329 }
330
331 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
332 // We couldn't find the specific class specified in the Intent.
333 // Also the end of the line.
334 err = ActivityManager.START_CLASS_NOT_FOUND;
335 }
336
337 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
338 && sourceRecord.task.voiceSession != null) {
339 // If this activity is being launched as part of a voice session, we need
340 // to ensure that it is safe to do so. If the upcoming activity will also
341 // be part of the voice session, we can only launch it if it has explicitly
342 // said it supports the VOICE category, or it is a part of the calling app.
343 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
344 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
345 try {
346 intent.addCategory(Intent.CATEGORY_VOICE);
347 if (!AppGlobals.getPackageManager().activitySupportsIntent(
348 intent.getComponent(), intent, resolvedType)) {
349 Slog.w(TAG,
350 "Activity being started in current voice task does not support voice: "
351 + intent);
352 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
353 }
354 } catch (RemoteException e) {
355 Slog.w(TAG, "Failure checking voice capabilities", e);
356 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
357 }
358 }
359 }
360
361 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
362 // If the caller is starting a new voice session, just make sure the target
363 // is actually allowing it to run this way.
364 try {
365 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
366 intent, resolvedType)) {
367 Slog.w(TAG,
368 "Activity being started in new voice task does not support: "
369 + intent);
370 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
371 }
372 } catch (RemoteException e) {
373 Slog.w(TAG, "Failure checking voice capabilities", e);
374 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
375 }
376 }
377
Andrii Kulian02b7a832016-10-06 23:11:56 -0700378 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800379
Wale Ogunwale01d66562015-12-29 08:19:19 -0800380 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800381 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800382 resultStack.sendActivityResultLocked(
383 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800384 }
385 ActivityOptions.abort(options);
386 return err;
387 }
388
389 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
390 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100391 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800392 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
393 callingPid, resolvedType, aInfo.applicationInfo);
394
395 if (mService.mController != null) {
396 try {
397 // The Intent we give to the watcher has the extra data
398 // stripped off, since it can contain private information.
399 Intent watchIntent = intent.cloneFilter();
400 abort |= !mService.mController.activityStarting(watchIntent,
401 aInfo.applicationInfo.packageName);
402 } catch (RemoteException e) {
403 mService.mController = null;
404 }
405 }
406
Rubin Xu58d25992016-01-21 17:47:13 +0000407 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100408 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
409 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000410 intent = mInterceptor.mIntent;
411 rInfo = mInterceptor.mRInfo;
412 aInfo = mInterceptor.mAInfo;
413 resolvedType = mInterceptor.mResolvedType;
414 inTask = mInterceptor.mInTask;
415 callingPid = mInterceptor.mCallingPid;
416 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100417 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800418 if (abort) {
419 if (resultRecord != null) {
420 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800421 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800422 }
423 // We pretend to the caller that it was really started, but
424 // they will just get a cancel result.
425 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800426 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800427 }
428
429 // If permissions need a review before any of the app components can run, we
430 // launch the review activity and pass a pending intent to start the activity
431 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700432 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800433 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
434 aInfo.packageName, userId)) {
435 IIntentSender target = mService.getIntentSenderLocked(
436 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
437 callingUid, userId, null, null, 0, new Intent[]{intent},
438 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
439 | PendingIntent.FLAG_ONE_SHOT, null);
440
441 final int flags = intent.getFlags();
442 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
443 newIntent.setFlags(flags
444 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
445 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
446 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
447 if (resultRecord != null) {
448 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
449 }
450 intent = newIntent;
451
452 resolvedType = null;
453 callingUid = realCallingUid;
454 callingPid = realCallingPid;
455
456 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
457 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
458 null /*profilerInfo*/);
459
460 if (DEBUG_PERMISSIONS_REVIEW) {
461 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
462 true, false) + "} from uid " + callingUid + " on display "
463 + (container == null ? (mSupervisor.mFocusedStack == null ?
David Stevensc6b91c62017-02-08 14:23:58 -0800464 DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
465 (container.mActivityDisplay == null ? DEFAULT_DISPLAY :
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800466 container.mActivityDisplay.mDisplayId)));
467 }
468 }
469 }
470
471 // If we have an ephemeral app, abort the process of launching the resolved intent.
472 // Instead, launch the ephemeral installer. Once the installer is finished, it
473 // starts either the intent we resolved here [on install error] or the ephemeral
474 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800475 if (rInfo != null && rInfo.auxiliaryInfo != null) {
476 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
477 callingPackage, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800478 resolvedType = null;
479 callingUid = realCallingUid;
480 callingPid = realCallingPid;
481
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800482 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
483 }
484
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800485 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
486 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
487 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
488 mSupervisor, container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800489 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
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800525 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
526 options, inTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800527 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800528
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800529 /**
530 * Creates a launch intent for the given auxiliary resolution data.
531 */
Todd Kennedye9910222017-02-21 16:00:11 -0800532 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800533 Intent originalIntent, String callingPackage, String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800534 if (auxiliaryResponse.needsPhaseTwo) {
535 // request phase two resolution
536 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
537 auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
538 }
Todd Kennedy1fb34042017-03-01 13:56:58 -0800539 return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
540 callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
541 auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
542 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800543 }
544
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800545 void postStartActivityProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700546 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
547 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800548
549 if (result < START_SUCCESS) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800550 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800551 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800552
Chong Zhang5022da32016-06-21 16:31:37 -0700553 // We're waiting for an activity launch to finish, but that activity simply
554 // brought another activity to front. Let startActivityMayWait() know about
555 // this, so it waits for the new activity to become visible instead.
556 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
557 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
558 }
559
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800560 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700561 final ActivityStack currentStack = r.getStack();
562 if (currentStack != null) {
563 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800564 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700565 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800566 }
567
Jorim Jaggi352d5842016-05-19 10:20:28 -0700568 // If we launched the activity from a no display activity that was launched from the home
569 // screen, we also need to start recents to un-minimize the docked stack, since the
570 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700571 // Note that some apps have trampoline activities without noDisplay being set. In that case,
572 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
573 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700574 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
575 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700576 final boolean noDisplayActivityOverHome = sourceRecord != null
577 && sourceRecord.noDisplay
578 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700579 if (startedActivityStackId == DOCKED_STACK_ID
580 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100581 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
582 final ActivityRecord topActivityHomeStack = homeStack != null
583 ? homeStack.topRunningActivityLocked() : null;
584 if (topActivityHomeStack == null
585 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
586 // We launch an activity while being in home stack, which means either launcher or
587 // recents into docked stack. We don't want the launched activity to be alone in a
588 // docked stack, so we want to immediately launch recents too.
589 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700590 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100591 return;
592 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800593 }
594
595 if (startedActivityStackId == PINNED_STACK_ID
596 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
597 // The activity was already running in the pinned stack so it wasn't started, but either
598 // brought to the front or the new intent was delivered to it since it was already in
599 // front. Notify anyone interested in this piece of information.
Winson Chungd95687c2017-03-03 12:06:21 -0800600 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800601 return;
602 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800603 }
604
605 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800606 mSupervisor.moveHomeStackTaskToTop(reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800607 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
608 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
609 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
610 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
611 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700612 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800613 null /*container*/, null /*inTask*/);
614 if (mSupervisor.inResumeTopActivity) {
615 // If we are in resume section already, home activity will be initialized, but not
616 // resumed (to avoid recursive resume) and will stay that way until something pokes it
617 // again. We need to schedule another resume.
618 mSupervisor.scheduleResumeTopActivities();
619 }
620 }
621
Robin Lee5d592422017-01-18 13:48:15 +0000622 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100623 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
624 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
625 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000626 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
627 : ActivityOptions.makeBasic());
Tony Mak646fe992016-04-21 16:43:08 +0100628 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000629 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100630 }
Tony Mak853304c2016-04-18 15:17:41 +0100631
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800632 final int startActivityMayWait(IApplicationThread caller, int callingUid,
633 String callingPackage, Intent intent, String resolvedType,
634 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
635 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700636 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700637 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800638 IActivityContainer iContainer, TaskRecord inTask) {
639 // Refuse possible leaked file descriptors
640 if (intent != null && intent.hasFileDescriptors()) {
641 throw new IllegalArgumentException("File descriptors passed in Intent");
642 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500643 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800644 boolean componentSpecified = intent.getComponent() != null;
645
646 // Save a copy in case ephemeral needs it
647 final Intent ephemeralIntent = new Intent(intent);
648 // Don't modify the client's object!
649 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700650 if (componentSpecified
651 && intent.getData() != null
652 && Intent.ACTION_VIEW.equals(intent.getAction())
653 && intent.hasCategory(Intent.CATEGORY_BROWSABLE)
654 && mService.getPackageManagerInternalLocked()
655 .isInstantAppInstallerComponent(intent.getComponent())) {
656 // intercept intents targeted directly to the ephemeral installer the
657 // ephemeral installer should never be started with a raw URL; instead
658 // adjust the intent so it looks like a "normal" instant app launch
659 intent.setComponent(null /*component*/);
660 componentSpecified = false;
661 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800662
663 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000664 if (rInfo == null) {
665 UserInfo userInfo = mSupervisor.getUserInfo(userId);
666 if (userInfo != null && userInfo.isManagedProfile()) {
667 // Special case for managed profiles, if attempting to launch non-cryto aware
668 // app in a locked managed profile from an unlocked parent allow it to resolve
669 // as user will be sent via confirm credentials to unlock the profile.
670 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700671 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000672 long token = Binder.clearCallingIdentity();
673 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700674 UserInfo parent = userManager.getProfileParent(userId);
675 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
676 && userManager.isUserUnlockingOrUnlocked(parent.id)
677 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000678 } finally {
679 Binder.restoreCallingIdentity(token);
680 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700681 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000682 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600683 PackageManager.MATCH_DIRECT_BOOT_AWARE
684 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000685 }
686 }
687 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800688 // Collect information about the target of the Intent.
689 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
690
691 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
692 ActivityStackSupervisor.ActivityContainer container =
693 (ActivityStackSupervisor.ActivityContainer)iContainer;
694 synchronized (mService) {
695 if (container != null && container.mParentActivity != null &&
696 container.mParentActivity.state != RESUMED) {
697 // Cannot start a child activity if the parent is not resumed.
698 return ActivityManager.START_CANCELED;
699 }
700 final int realCallingPid = Binder.getCallingPid();
701 final int realCallingUid = Binder.getCallingUid();
702 int callingPid;
703 if (callingUid >= 0) {
704 callingPid = -1;
705 } else if (caller == null) {
706 callingPid = realCallingPid;
707 callingUid = realCallingUid;
708 } else {
709 callingPid = callingUid = -1;
710 }
711
712 final ActivityStack stack;
713 if (container == null || container.mStack.isOnHomeDisplay()) {
714 stack = mSupervisor.mFocusedStack;
715 } else {
716 stack = container.mStack;
717 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700718 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700719 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800720 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
721 "Starting activity when config will change = " + stack.mConfigWillChange);
722
723 final long origId = Binder.clearCallingIdentity();
724
725 if (aInfo != null &&
726 (aInfo.applicationInfo.privateFlags
727 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
728 // This may be a heavy-weight process! Check to see if we already
729 // have another, different heavy-weight process running.
730 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
731 final ProcessRecord heavy = mService.mHeavyWeightProcess;
732 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
733 || !heavy.processName.equals(aInfo.processName))) {
734 int appCallingUid = callingUid;
735 if (caller != null) {
736 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
737 if (callerApp != null) {
738 appCallingUid = callerApp.info.uid;
739 } else {
740 Slog.w(TAG, "Unable to find app for caller " + caller
741 + " (pid=" + callingPid + ") when starting: "
742 + intent.toString());
743 ActivityOptions.abort(options);
744 return ActivityManager.START_PERMISSION_DENIED;
745 }
746 }
747
748 IIntentSender target = mService.getIntentSenderLocked(
749 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
750 appCallingUid, userId, null, null, 0, new Intent[] { intent },
751 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
752 | PendingIntent.FLAG_ONE_SHOT, null);
753
754 Intent newIntent = new Intent();
755 if (requestCode >= 0) {
756 // Caller is requesting a result.
757 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
758 }
759 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
760 new IntentSender(target));
761 if (heavy.activities.size() > 0) {
762 ActivityRecord hist = heavy.activities.get(0);
763 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
764 hist.packageName);
765 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
766 hist.task.taskId);
767 }
768 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
769 aInfo.packageName);
770 newIntent.setFlags(intent.getFlags());
771 newIntent.setClassName("android",
772 HeavyWeightSwitcherActivity.class.getName());
773 intent = newIntent;
774 resolvedType = null;
775 caller = null;
776 callingUid = Binder.getCallingUid();
777 callingPid = Binder.getCallingPid();
778 componentSpecified = true;
779 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
780 aInfo = rInfo != null ? rInfo.activityInfo : null;
781 if (aInfo != null) {
782 aInfo = mService.getActivityInfoForUser(aInfo, userId);
783 }
784 }
785 }
786 }
787
Jorim Jaggi275561a2016-02-23 10:11:02 -0500788 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800789 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
790 aInfo, rInfo, voiceSession, voiceInteractor,
791 resultTo, resultWho, requestCode, callingPid,
792 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500793 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
794 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800795
796 Binder.restoreCallingIdentity(origId);
797
798 if (stack.mConfigWillChange) {
799 // If the caller also wants to switch to a new configuration,
800 // do so now. This allows a clean switch, as we are waiting
801 // for the current activity to pause (so we will not destroy
802 // it), and have not yet started the next activity.
803 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
804 "updateConfiguration()");
805 stack.mConfigWillChange = false;
806 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
807 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700808 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800809 }
810
811 if (outResult != null) {
812 outResult.result = res;
813 if (res == ActivityManager.START_SUCCESS) {
814 mSupervisor.mWaitingActivityLaunched.add(outResult);
815 do {
816 try {
817 mService.wait();
818 } catch (InterruptedException e) {
819 }
Chong Zhang5022da32016-06-21 16:31:37 -0700820 } while (outResult.result != START_TASK_TO_FRONT
821 && !outResult.timeout && outResult.who == null);
822 if (outResult.result == START_TASK_TO_FRONT) {
823 res = START_TASK_TO_FRONT;
824 }
825 }
826 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800827 ActivityRecord r = stack.topRunningActivityLocked();
828 if (r.nowVisible && r.state == RESUMED) {
829 outResult.timeout = false;
830 outResult.who = new ComponentName(r.info.packageName, r.info.name);
831 outResult.totalTime = 0;
832 outResult.thisTime = 0;
833 } else {
834 outResult.thisTime = SystemClock.uptimeMillis();
835 mSupervisor.mWaitingActivityVisible.add(outResult);
836 do {
837 try {
838 mService.wait();
839 } catch (InterruptedException e) {
840 }
841 } while (!outResult.timeout && outResult.who == null);
842 }
843 }
844 }
845
Jorim Jaggibe67c902016-04-12 00:53:16 -0700846 final ActivityRecord launchedActivity = mReusedActivity != null
847 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700848 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800849 return res;
850 }
851 }
852
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800853 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
854 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
855 Bundle bOptions, int userId) {
856 if (intents == null) {
857 throw new NullPointerException("intents is null");
858 }
859 if (resolvedTypes == null) {
860 throw new NullPointerException("resolvedTypes is null");
861 }
862 if (intents.length != resolvedTypes.length) {
863 throw new IllegalArgumentException("intents are length different than resolvedTypes");
864 }
865
Makoto Onukid67b1872016-07-21 16:26:36 -0700866 final int realCallingPid = Binder.getCallingPid();
867 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800868
869 int callingPid;
870 if (callingUid >= 0) {
871 callingPid = -1;
872 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700873 callingPid = realCallingPid;
874 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800875 } else {
876 callingPid = callingUid = -1;
877 }
878 final long origId = Binder.clearCallingIdentity();
879 try {
880 synchronized (mService) {
881 ActivityRecord[] outActivity = new ActivityRecord[1];
882 for (int i=0; i<intents.length; i++) {
883 Intent intent = intents[i];
884 if (intent == null) {
885 continue;
886 }
887
888 // Refuse possible leaked file descriptors
889 if (intent != null && intent.hasFileDescriptors()) {
890 throw new IllegalArgumentException("File descriptors passed in Intent");
891 }
892
893 boolean componentSpecified = intent.getComponent() != null;
894
895 // Don't modify the client's object!
896 intent = new Intent(intent);
897
898 // Collect information about the target of the Intent.
899 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
900 null, userId);
901 // TODO: New, check if this is correct
902 aInfo = mService.getActivityInfoForUser(aInfo, userId);
903
904 if (aInfo != null &&
905 (aInfo.applicationInfo.privateFlags
906 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
907 throw new IllegalArgumentException(
908 "FLAG_CANT_SAVE_STATE not supported here");
909 }
910
911 ActivityOptions options = ActivityOptions.fromBundle(
912 i == intents.length - 1 ? bOptions : null);
913 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
914 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700915 callingPid, callingUid, callingPackage,
916 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800917 options, false, componentSpecified, outActivity, null, null);
918 if (res < 0) {
919 return res;
920 }
921
922 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
923 }
924 }
925 } finally {
926 Binder.restoreCallingIdentity(origId);
927 }
928
Wale Ogunwale01d66562015-12-29 08:19:19 -0800929 return START_SUCCESS;
930 }
931
Wei Wang65c7a152016-06-02 18:51:22 -0700932 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
Bryce Lee834abec2017-01-09 16:18:14 -0800933 boolean sendHint = forceSend;
934
935 if (!sendHint) {
936 // If not forced, send power hint when the activity's process is different than the
937 // current resumed activity.
938 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
939 sendHint = resumedActivity == null
940 || resumedActivity.app == null
941 || !resumedActivity.app.equals(mStartActivity.app);
942 }
943
944 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700945 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700946 mPowerHintSent = true;
947 }
948 }
949
Wei Wang65c7a152016-06-02 18:51:22 -0700950 void sendPowerHintForLaunchEndIfNeeded() {
951 // Trigger launch power hint if activity is launched
952 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700953 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700954 mPowerHintSent = false;
955 }
956 }
957
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800958 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
959 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
960 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
961 int result = START_CANCELED;
962 try {
963 mService.mWindowManager.deferSurfaceLayout();
964 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
965 startFlags, doResume, options, inTask);
966 } finally {
967 // If we are not able to proceed, disassociate the activity from the task. Leaving an
968 // activity in an incomplete state can lead to issues, such as performing operations
969 // without a window container.
970 if (result != START_SUCCESS && mStartActivity.task != null) {
971 mStartActivity.task.removeActivity(mStartActivity);
972 }
973 mService.mWindowManager.continueSurfaceLayout();
974 }
975
976 postStartActivityProcessing(r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
977 mTargetStack);
978
979 return result;
980 }
981
982 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -0800983 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
984 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
985 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
986
987 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
988 voiceInteractor);
989
990 computeLaunchingTaskFlags();
991
992 computeSourceStack();
993
994 mIntent.setFlags(mLaunchFlags);
995
Jorim Jaggibe67c902016-04-12 00:53:16 -0700996 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800997
Jorim Jaggi2adba072016-03-03 13:43:39 +0100998 final int preferredLaunchStackId =
999 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1000
Jorim Jaggibe67c902016-04-12 00:53:16 -07001001 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001002 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1003 // still needs to be a lock task mode violation since the task gets cleared out and
1004 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001005 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001006 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1007 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1008 mSupervisor.showLockTaskToast();
1009 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1010 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1011 }
1012
1013 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001014 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001015 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001016 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001017 // This task was started because of movement of the activity based on affinity...
1018 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001019 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001020 }
1021
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001022 // This code path leads to delivering a new intent, we want to make sure we schedule it
1023 // as the first operation, in case the activity will be resumed as a result of later
1024 // operations.
1025 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001026 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001027 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001028 final TaskRecord task = mReusedActivity.task;
1029
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001030 // In this situation we want to remove all activities from the task up to the one
1031 // being started. In most cases this means we are resetting the task to its initial
1032 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001033 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1034 mLaunchFlags);
1035
1036 // The above code can remove {@code mReusedActivity} from the task, leading to the
1037 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1038 // task reference is needed in the call below to
1039 // {@link setTargetStackAndMoveToFrontIfNeeded}.
1040 if (mReusedActivity.task == null) {
1041 mReusedActivity.task = task;
1042 }
1043
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001044 if (top != null) {
1045 if (top.frontOfTask) {
1046 // Activity aliases may mean we use different intents for the top activity,
1047 // so make sure the task now has the identity of the new intent.
1048 top.task.setIntent(mStartActivity);
1049 }
1050 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1051 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1052 mStartActivity.launchedFromPackage);
1053 }
1054 }
1055
Wei Wang65c7a152016-06-02 18:51:22 -07001056 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001057
Jorim Jaggibe67c902016-04-12 00:53:16 -07001058 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001059
1060 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1061 // We don't need to start a new activity, and the client said not to do anything
1062 // if that is the case, so this is it! And for paranoia, make sure we have
1063 // correctly resumed the top activity.
1064 resumeTargetStackIfNeeded();
1065 return START_RETURN_INTENT_TO_CALLER;
1066 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001067 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001068
1069 if (!mAddingToTask && mReuseTask == null) {
1070 // We didn't do anything... but it was needed (a.k.a., client don't use that
1071 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1072 resumeTargetStackIfNeeded();
1073 return START_TASK_TO_FRONT;
1074 }
1075 }
1076
1077 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001078 final ActivityStack sourceStack = mStartActivity.resultTo != null
1079 ? mStartActivity.resultTo.getStack() : null;
1080 if (sourceStack != null) {
1081 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1082 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1083 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001084 }
1085 ActivityOptions.abort(mOptions);
1086 return START_CLASS_NOT_FOUND;
1087 }
1088
1089 // If the activity being launched is the same as the one currently at the top, then
1090 // we need to check if it should only be launched once.
1091 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001092 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001093 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1094 final boolean dontStart = top != null && mStartActivity.resultTo == null
1095 && top.realActivity.equals(mStartActivity.realActivity)
1096 && top.userId == mStartActivity.userId
1097 && top.app != null && top.app.thread != null
1098 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1099 || mLaunchSingleTop || mLaunchSingleTask);
1100 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001101 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001102 // For paranoia, make sure we have correctly resumed the top activity.
1103 topStack.mLastPausedActivity = null;
1104 if (mDoResume) {
1105 mSupervisor.resumeFocusedStackTopActivityLocked();
1106 }
1107 ActivityOptions.abort(mOptions);
1108 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1109 // We don't need to start a new activity, and the client said not to do
1110 // anything if that is the case, so this is it!
1111 return START_RETURN_INTENT_TO_CALLER;
1112 }
1113 top.deliverNewIntentLocked(
1114 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001115
1116 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1117 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1118 mSupervisor.handleNonResizableTaskIfNeeded(
1119 top.task, preferredLaunchStackId, topStack.mStackId);
1120
Wale Ogunwale01d66562015-12-29 08:19:19 -08001121 return START_DELIVERED_TO_TOP;
1122 }
1123
1124 boolean newTask = false;
1125 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1126 ? mSourceRecord.task : null;
1127
1128 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001129 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001130 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1131 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1132 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001133 result = setTaskFromReuseOrCreateNewTask(
1134 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001135 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001136 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001137 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001138 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001139 } else {
1140 // This not being started from an existing activity, and not part of a new task...
1141 // just put it in the top task, though these days this case should never happen.
1142 setTaskToCurrentTopOrCreateNewTask();
1143 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001144 if (result != START_SUCCESS) {
1145 return result;
1146 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001147
1148 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1149 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001150 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1151 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001152 if (mSourceRecord != null) {
1153 mStartActivity.task.setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001154 }
1155 if (newTask) {
1156 EventLog.writeEvent(
1157 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1158 }
1159 ActivityStack.logStartActivity(
1160 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1161 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001162
Wei Wang65c7a152016-06-02 18:51:22 -07001163 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001164
Winson Chungb5c41b72016-12-07 15:00:47 -08001165 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1166 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001167 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001168 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1169 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001170 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1171 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001172 // If the activity is not focusable, we can't resume it, but still would like to
1173 // make sure it becomes visible as it starts (this will also trigger entry
1174 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001175 // Also, we don't want to resume activities in a task that currently has an overlay
1176 // as the starting activity just needs to be in the visible paused state until the
1177 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001178 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001179 // Go ahead and tell window manager to execute app transition for this activity
1180 // since the app transition will not be triggered through the resume channel.
1181 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001182 } else {
Winson Chung32066032016-11-04 11:55:21 -07001183 // If the target stack was not previously focusable (previous top running activity
1184 // on that stack was not visible) then any prior calls to move the stack to the
1185 // will not update the focused stack. If starting the new activity now allows the
1186 // task stack to be focusable, then ensure that we now update the focused stack
1187 // accordingly.
1188 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1189 mTargetStack.moveToFront("startActivityUnchecked");
1190 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001191 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1192 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001193 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001194 } else {
1195 mTargetStack.addRecentActivityLocked(mStartActivity);
1196 }
1197 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1198
Jorim Jaggid53f0922016-04-06 22:16:23 -07001199 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001200 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001201
1202 return START_SUCCESS;
1203 }
1204
1205 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1206 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1207 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1208 reset();
1209
1210 mStartActivity = r;
1211 mIntent = r.intent;
1212 mOptions = options;
1213 mCallingUid = r.launchedFromUid;
1214 mSourceRecord = sourceRecord;
1215 mVoiceSession = voiceSession;
1216 mVoiceInteractor = voiceInteractor;
1217
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001218 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
David Stevensc6b91c62017-02-08 14:23:58 -08001219
Wale Ogunwale01d66562015-12-29 08:19:19 -08001220 mLaunchBounds = getOverrideBounds(r, options, inTask);
1221
1222 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1223 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1224 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1225 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1226 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1227 mLaunchTaskBehind = r.mLaunchTaskBehind
1228 && !mLaunchSingleTask && !mLaunchSingleInstance
1229 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1230
1231 sendNewTaskResultRequestIfNeeded();
1232
1233 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1234 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1235 }
1236
1237 // If we are actually going to launch in to a new task, there are some cases where
1238 // we further want to do multiple task.
1239 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1240 if (mLaunchTaskBehind
1241 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1242 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1243 }
1244 }
1245
1246 // We'll invoke onUserLeaving before onPause only if the launching
1247 // activity did not explicitly state that this is an automated launch.
1248 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1249 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1250 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1251
1252 // If the caller has asked not to resume at this point, we make note
1253 // of this in the record so that we can skip it when trying to find
1254 // the top running activity.
1255 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001256 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001257 r.delayedResume = true;
1258 mDoResume = false;
1259 }
1260
Winson Chungcbcadc92017-01-12 15:54:12 -08001261 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1262 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001263 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001264 if (!mOptions.canTaskOverlayResume()) {
1265 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1266 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1267 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001268
Winson Chungcbcadc92017-01-12 15:54:12 -08001269 // The caller specifies that we'd like to be avoided to be moved to the front,
1270 // so be it!
1271 mDoResume = false;
1272 mAvoidMoveToFront = true;
1273 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001274 }
1275 }
1276
Wale Ogunwale01d66562015-12-29 08:19:19 -08001277 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1278
1279 mInTask = inTask;
1280 // In some flows in to this function, we retrieve the task record and hold on to it
1281 // without a lock before calling back in to here... so the task at this point may
1282 // not actually be in recents. Check for that, and if it isn't in recents just
1283 // consider it invalid.
1284 if (inTask != null && !inTask.inRecents) {
1285 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1286 mInTask = null;
1287 }
1288
1289 mStartFlags = startFlags;
1290 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1291 // is the same as the one making the call... or, as a special case, if we do not know
1292 // the caller then we count the current top activity as the caller.
1293 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1294 ActivityRecord checkedCaller = sourceRecord;
1295 if (checkedCaller == null) {
1296 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1297 mNotTop);
1298 }
1299 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1300 // Caller is not the same as launcher, so always needed.
1301 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1302 }
1303 }
1304
1305 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1306 }
1307
1308 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001309 final ActivityStack sourceStack = mStartActivity.resultTo != null
1310 ? mStartActivity.resultTo.getStack() : null;
1311 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001312 // For whatever reason this activity is being launched into a new task...
1313 // yet the caller has requested a result back. Well, that is pretty messed up,
1314 // so instead immediately send back a cancel and let the new task continue launched
1315 // as normal without a dependency on its originator.
1316 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001317 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1318 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1319 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001320 mStartActivity.resultTo = null;
1321 }
1322 }
1323
1324 private void computeLaunchingTaskFlags() {
1325 // If the caller is not coming from another activity, but has given us an explicit task into
1326 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001327 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001328 final Intent baseIntent = mInTask.getBaseIntent();
1329 final ActivityRecord root = mInTask.getRootActivity();
1330 if (baseIntent == null) {
1331 ActivityOptions.abort(mOptions);
1332 throw new IllegalArgumentException("Launching into task without base intent: "
1333 + mInTask);
1334 }
1335
1336 // If this task is empty, then we are adding the first activity -- it
1337 // determines the root, and must be launching as a NEW_TASK.
1338 if (mLaunchSingleInstance || mLaunchSingleTask) {
1339 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1340 ActivityOptions.abort(mOptions);
1341 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1342 + mStartActivity + " into different task " + mInTask);
1343 }
1344 if (root != null) {
1345 ActivityOptions.abort(mOptions);
1346 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1347 + " has root " + root + " but target is singleInstance/Task");
1348 }
1349 }
1350
1351 // If task is empty, then adopt the interesting intent launch flags in to the
1352 // activity being started.
1353 if (root == null) {
1354 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1355 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1356 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1357 | (baseIntent.getFlags() & flagsOfInterest);
1358 mIntent.setFlags(mLaunchFlags);
1359 mInTask.setIntent(mStartActivity);
1360 mAddingToTask = true;
1361
1362 // If the task is not empty and the caller is asking to start it as the root of
1363 // a new task, then we don't actually want to start this on the task. We will
1364 // bring the task to the front, and possibly give it a new intent.
1365 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1366 mAddingToTask = false;
1367
1368 } else {
1369 mAddingToTask = true;
1370 }
1371
1372 mReuseTask = mInTask;
1373 } else {
1374 mInTask = null;
1375 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1376 // when in freeform workspace.
1377 // Also put noDisplay activities in the source task. These by itself can be placed
1378 // in any task/stack, however it could launch other activities like ResolverActivity,
1379 // and we want those to stay in the original task.
1380 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1381 && mSourceRecord.isFreeform()) {
1382 mAddingToTask = true;
1383 }
1384 }
1385
1386 if (mInTask == null) {
1387 if (mSourceRecord == null) {
1388 // This activity is not being started from another... in this
1389 // case we -always- start a new task.
1390 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1391 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1392 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1393 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1394 }
1395 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1396 // The original activity who is starting us is running as a single
1397 // instance... this new activity it is starting must go on its
1398 // own task.
1399 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1400 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1401 // The activity being started is a single instance... it always
1402 // gets launched into its own task.
1403 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1404 }
1405 }
1406 }
1407
1408 private void computeSourceStack() {
1409 if (mSourceRecord == null) {
1410 mSourceStack = null;
1411 return;
1412 }
1413 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001414 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001415 return;
1416 }
1417
1418 // If the source is finishing, we can't further count it as our source. This is because the
1419 // task it is associated with may now be empty and on its way out, so we don't want to
1420 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1421 // a task for it. But save the task information so it can be used when creating the new task.
1422 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1423 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1424 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1425 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1426 mNewTaskInfo = mSourceRecord.info;
1427 mNewTaskIntent = mSourceRecord.task.intent;
1428 }
1429 mSourceRecord = null;
1430 mSourceStack = null;
1431 }
1432
1433 /**
1434 * Decide whether the new activity should be inserted into an existing task. Returns null
1435 * if not or an ActivityRecord with the task into which the new activity should be added.
1436 */
1437 private ActivityRecord getReusableIntentActivity() {
1438 // We may want to try to place the new activity in to an existing task. We always
1439 // do this if the target activity is singleTask or singleInstance; we will also do
1440 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1441 // us to still place it in a new task: multi task, always doc mode, or being asked to
1442 // launch this as a new task behind the current one.
1443 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1444 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1445 || mLaunchSingleInstance || mLaunchSingleTask;
1446 // If bring to front is requested, and no result is requested and we have not been given
1447 // an explicit task to launch in to, and we can find a task that was started with this
1448 // same component, then instead of launching bring that one to the front.
1449 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1450 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001451 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1452 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1453 intentActivity = task != null ? task.getTopActivity() : null;
1454 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001455 if (mLaunchSingleInstance) {
1456 // There can be one and only one instance of single instance activity in the
1457 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001458 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001459 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1460 // For the launch adjacent case we only want to put the activity in an existing
1461 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001462 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1463 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001464 } else {
1465 // Otherwise find the best task to put the activity in.
David Stevensc6b91c62017-02-08 14:23:58 -08001466 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001467 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001468 }
1469 return intentActivity;
1470 }
1471
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001472 /**
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001473 * Returns the ID of the display to use for a new activity. If the source activity has
1474 * a explicit display ID set, use that to launch the activity. If not and the device is in VR
1475 * mode, then return the Vr mode's virtual display ID.
1476 */
1477 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
1478 int displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1479 // If the activity has a displayId set explicitly, launch it on the same displayId.
1480 if (displayId != INVALID_DISPLAY) {
1481 return displayId;
1482 }
1483
1484 // Check if the Activity is a VR activity. If so, the activity should be launched in
1485 // main display.
1486 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1487 return DEFAULT_DISPLAY;
1488 }
1489
1490 // Get the virtual display id from ActivityManagerService.
1491 displayId = mService.mVrCompatibilityDisplayId;
1492 if (displayId != INVALID_DISPLAY) {
1493 if (DEBUG_STACK) {
1494 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1495 }
1496 mUsingVrCompatibilityDisplay = true;
1497 return displayId;
1498 }
1499 return DEFAULT_DISPLAY;
1500 }
1501
1502 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001503 * Figure out which task and activity to bring to front when we have found an existing matching
1504 * activity record in history. May also clear the task if needed.
1505 * @param intentActivity Existing matching activity.
1506 * @return {@link ActivityRecord} brought to front.
1507 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001508 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001509 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001510 mTargetStack.mLastPausedActivity = null;
1511 // If the target task is not in the front, then we need to bring it to the front...
1512 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1513 // the same behavior as if a new instance was being started, which means not bringing it
1514 // to the front if the caller is not itself in the front.
1515 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1516 ActivityRecord curTop = (focusStack == null)
1517 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1518
Jorim Jaggic875ae72016-04-26 22:41:06 -07001519 if (curTop != null
1520 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1521 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001522 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1523 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1524 mSourceStack.topActivity().task == mSourceRecord.task)) {
1525 // We really do want to push this one into the user's face, right now.
1526 if (mLaunchTaskBehind && mSourceRecord != null) {
1527 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1528 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001529 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001530
1531 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1532 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1533 // So no point resuming any of the activities here, it just wastes one extra
1534 // resuming, plus enter AND exit transitions.
1535 // Here we only want to bring the target stack forward. Transition will be applied
1536 // to the new activity that's started after the old ones are gone.
1537 final boolean willClearTask =
1538 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1539 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1540 if (!willClearTask) {
1541 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001542 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001543 if (launchStack == null || launchStack == mTargetStack) {
1544 // We only want to move to the front, if we aren't going to launch on a
1545 // different stack. If we launch on a different stack, we will put the
1546 // task on top there.
1547 mTargetStack.moveTaskToFrontLocked(
1548 intentActivity.task, mNoAnimation, mOptions,
1549 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1550 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001551 } else if (launchStack.mStackId == DOCKED_STACK_ID
1552 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1553 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1554 // If we want to launch adjacent and mTargetStack is not the computed
1555 // launch stack - move task to top of computed stack.
Winson Chung74666102017-02-22 17:49:24 -08001556 intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
1557 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1558 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001559 } else {
1560 // TODO: This should be reevaluated in MW v2.
1561 // We choose to move task to front instead of launching it adjacent
1562 // when specific stack was requested explicitly and it appeared to be
1563 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1564 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1565 mOptions, mStartActivity.appTimeTracker,
1566 "bringToFrontInsteadOfAdjacentLaunch");
1567 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001568 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001569 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1570 // Target and computed stacks are on different displays and we've
1571 // found a matching task - move the existing instance to that display and
1572 // move it to front.
1573 intentActivity.task.reparent(launchStack.mStackId, ON_TOP,
1574 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1575 "reparentToDisplay");
1576 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001577 }
1578 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001579
1580 // We are moving a task to the front, use starting window to hide initial drawn
1581 // delay.
1582 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1583 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001584 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001585 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001586 }
1587 }
1588 if (!mMovedToFront && mDoResume) {
1589 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1590 + " from " + intentActivity);
1591 mTargetStack.moveToFront("intentActivityFound");
1592 }
1593
Jorim Jaggid53f0922016-04-06 22:16:23 -07001594 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1595 mTargetStack.mStackId);
1596
Wale Ogunwale01d66562015-12-29 08:19:19 -08001597 // If the caller has requested that the target task be reset, then do so.
1598 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1599 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1600 }
1601 return intentActivity;
1602 }
1603
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001604 private void updateTaskReturnToType(
1605 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001606 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001607 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1608 // Caller wants to appear on home activity.
1609 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1610 return;
Winson Chung83471632016-12-13 11:02:12 -08001611 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001612 // Task will be launched over the home stack, so return home.
1613 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1614 return;
Winson Chung83471632016-12-13 11:02:12 -08001615 } else if (focusedStack != null && focusedStack != task.getStack() &&
1616 focusedStack.isAssistantStack()) {
1617 // Task was launched over the assistant stack, so return there
1618 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1619 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001620 }
1621
1622 // Else we are coming from an application stack so return to an application.
1623 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1624 }
1625
Wale Ogunwale01d66562015-12-29 08:19:19 -08001626 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1627 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1628 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1629 // The caller has requested to completely replace any existing task with its new
1630 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001631 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1632 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001633 // of history or if it is finished immediately), thus disassociating the task. Also note
1634 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1635 // launching another activity.
1636 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1637 // already launching one.
1638 final TaskRecord task = intentActivity.task;
1639 task.performClearTaskLocked();
1640 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001641 mReuseTask.setIntent(mStartActivity);
1642
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001643 // When we clear the task - focus will be adjusted, which will bring another task
1644 // to top before we launch the activity we need. This will temporary swap their
1645 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1646 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001647 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1648 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001649 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1650 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001651 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001652 // A special case: we need to start the activity because it is not currently
1653 // running, and the caller has asked to clear the current task to have this
1654 // activity at the top.
1655 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001656
1657 // We are no longer placing the activity in the task we previously thought we were.
1658 mStartActivity.task = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001659 // Now pretend like this activity is being started by the top of its task, so it
1660 // is put in the right place.
1661 mSourceRecord = intentActivity;
1662 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001663 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001664 // Target stack got cleared when we all activities were removed above.
1665 // Go ahead and reset it.
1666 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1667 null /* bounds */, mLaunchFlags, mOptions);
1668 mTargetStack.addTask(task,
1669 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1670 }
1671 }
1672 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1673 // In this case the top activity on the task is the same as the one being launched,
1674 // so we take that as a request to bring the task to the foreground. If the top
1675 // activity in the task is the root activity, deliver this new intent to it if it
1676 // desires.
1677 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1678 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001679 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001680 intentActivity.task);
1681 if (intentActivity.frontOfTask) {
1682 intentActivity.task.setIntent(mStartActivity);
1683 }
1684 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1685 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001686 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001687 // In this case we are launching the root activity of the task, but with a
1688 // different intent. We should start a new instance on top.
1689 mAddingToTask = true;
1690 mSourceRecord = intentActivity;
1691 }
1692 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1693 // In this case an activity is being launched in to an existing task, without
1694 // resetting that task. This is typically the situation of launching an activity
1695 // from a notification or shortcut. We want to place the new activity on top of the
1696 // current task.
1697 mAddingToTask = true;
1698 mSourceRecord = intentActivity;
1699 } else if (!intentActivity.task.rootWasReset) {
1700 // In this case we are launching into an existing task that has not yet been started
1701 // from its front door. The current task has been brought to the front. Ideally,
1702 // we'd probably like to place this new task at the bottom of its stack, but that's
1703 // a little hard to do with the current organization of the code so for now we'll
1704 // just drop it.
1705 intentActivity.task.setIntent(mStartActivity);
1706 }
1707 }
1708
1709 private void resumeTargetStackIfNeeded() {
1710 if (mDoResume) {
1711 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001712 } else {
1713 ActivityOptions.abort(mOptions);
1714 }
1715 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1716 }
1717
Chong Zhang6cda19c2016-06-14 19:07:56 -07001718 private int setTaskFromReuseOrCreateNewTask(
1719 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1720 mTargetStack = computeStackFocus(
1721 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1722
1723 // Do no move the target stack to front yet, as we might bail if
1724 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001725
1726 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001727 final TaskRecord task = mTargetStack.createTaskRecord(
1728 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001729 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001730 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1731 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001732 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001733 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001734 final int stackId = mTargetStack.mStackId;
1735 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001736 mService.resizeStack(
1737 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001738 } else {
1739 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1740 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001741 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001742 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1743 + " in new task " + mStartActivity.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001744 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001745 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1746 }
1747
1748 if (taskToAffiliate != null) {
1749 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001750 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001751
1752 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1753 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1754 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1755 }
1756
1757 if (!mMovedOtherTask) {
1758 // If stack id is specified in activity options, usually it means that activity is
1759 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1760 // that case we check the target stack.
1761 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1762 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1763 }
1764 if (mDoResume) {
1765 mTargetStack.moveToFront("reuseOrNewTask");
1766 }
1767 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001768 }
1769
1770 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001771 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1772 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1773 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1774 }
1775
Wale Ogunwale01d66562015-12-29 08:19:19 -08001776 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001777 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001778 // We only want to allow changing stack if the target task is not the top one,
1779 // otherwise we would move the launching task to the other side, rather than show
1780 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001781 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001782 if (moveStackAllowed) {
1783 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1784 mOptions);
1785 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001786
1787 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001788 mTargetStack = sourceStack;
1789 } else if (mTargetStack != sourceStack) {
Winson Chung74666102017-02-22 17:49:24 -08001790 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1791 !ANIMATE, DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001792 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001793
Wale Ogunwale01d66562015-12-29 08:19:19 -08001794 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001795 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001796 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1797 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001798 } else if (mDoResume) {
1799 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001800 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001801
Wale Ogunwale01d66562015-12-29 08:19:19 -08001802 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1803 // In this case, we are adding the activity to an existing task, but the caller has
1804 // asked to clear that task if the activity is already running.
1805 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1806 mKeepCurTransition = true;
1807 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001808 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001809 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1810 // For paranoia, make sure we have correctly resumed the top activity.
1811 mTargetStack.mLastPausedActivity = null;
1812 if (mDoResume) {
1813 mSupervisor.resumeFocusedStackTopActivityLocked();
1814 }
1815 ActivityOptions.abort(mOptions);
1816 return START_DELIVERED_TO_TOP;
1817 }
1818 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1819 // In this case, we are launching an activity in our own task that may already be
1820 // running somewhere in the history, and we want to shuffle it to the front of the
1821 // stack if so.
1822 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1823 if (top != null) {
1824 final TaskRecord task = top.task;
1825 task.moveActivityToFrontLocked(top);
1826 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001827 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001828 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1829 mTargetStack.mLastPausedActivity = null;
1830 if (mDoResume) {
1831 mSupervisor.resumeFocusedStackTopActivityLocked();
1832 }
1833 return START_DELIVERED_TO_TOP;
1834 }
1835 }
1836
1837 // An existing activity is starting this new activity, so we want to keep the new one in
1838 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001839 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001840 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1841 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1842 return START_SUCCESS;
1843 }
1844
1845 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001846 // The caller is asking that the new activity be started in an explicit
1847 // task it has provided to us.
1848 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1849 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1850 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1851 }
1852
Andrii Kulian02b7a832016-10-06 23:11:56 -07001853 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001854
1855 // Check whether we should actually launch the new activity in to the task,
1856 // or just reuse the current activity on top.
1857 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001858 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1859 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001860 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1861 || mLaunchSingleTop || mLaunchSingleTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001862 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1863 mStartActivity.appTimeTracker, "inTaskToFront");
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001864 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001865 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1866 // We don't need to start a new activity, and the client said not to do
1867 // anything if that is the case, so this is it!
1868 return START_RETURN_INTENT_TO_CALLER;
1869 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001870 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1871 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001872 return START_DELIVERED_TO_TOP;
1873 }
1874 }
1875
1876 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001877 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1878 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001879 // We don't actually want to have this activity added to the task, so just
1880 // stop here but still tell the caller that we consumed the intent.
1881 ActivityOptions.abort(mOptions);
1882 return START_TASK_TO_FRONT;
1883 }
1884
Yorke Lee64512522017-03-24 13:09:35 -07001885 if (mLaunchBounds != null) {
1886 mInTask.updateOverrideConfiguration(mLaunchBounds);
1887 int stackId = mInTask.getLaunchStackId();
1888 if (stackId != mInTask.getStackId()) {
1889 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1890 DEFER_RESUME, "inTaskToFront");
1891 stackId = mInTask.getStackId();
1892 mTargetStack = mInTask.getStack();
1893 }
1894 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1895 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1896 }
1897 }
1898
1899 mTargetStack.moveTaskToFrontLocked(
1900 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1901
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001902 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1903 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1904 + " in explicit task " + mStartActivity.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001905
1906 return START_SUCCESS;
1907 }
1908
1909 private void setTaskToCurrentTopOrCreateNewTask() {
1910 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1911 mOptions);
1912 if (mDoResume) {
1913 mTargetStack.moveToFront("addingToTopTask");
1914 }
1915 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001916 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001917 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1918 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001919 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1920 mTargetStack.positionChildWindowContainerAtTop(task);
1921 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1922 + " in new guessed " + mStartActivity.task);
1923 }
1924
1925 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Winson Chungba7db922017-02-02 10:06:09 -08001926 if (mStartActivity.task == null || mStartActivity.task == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001927 parent.addActivityToTop(mStartActivity);
1928 } else {
1929 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1930 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001931 }
1932
1933 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1934 boolean launchSingleTask, int launchFlags) {
1935 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1936 (launchSingleInstance || launchSingleTask)) {
1937 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1938 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1939 "\"singleInstance\" or \"singleTask\"");
1940 launchFlags &=
1941 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1942 } else {
1943 switch (r.info.documentLaunchMode) {
1944 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1945 break;
1946 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1947 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1948 break;
1949 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1950 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1951 break;
1952 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1953 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1954 break;
1955 }
1956 }
1957 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001958 }
1959
1960 final void doPendingActivityLaunchesLocked(boolean doResume) {
1961 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001962 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1963 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001964 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001965 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
1966 null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001967 } catch (Exception e) {
1968 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1969 pal.sendErrorResult(e.getMessage());
1970 }
1971 }
1972 }
1973
1974 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001975 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001976 final TaskRecord task = r.task;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001977 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001978 if (stack != null) {
1979 return stack;
1980 }
1981
Andrii Kulian02b7a832016-10-06 23:11:56 -07001982 final ActivityStack currentStack = task != null ? task.getStack() : null;
1983 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001984 if (mSupervisor.mFocusedStack != currentStack) {
1985 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1986 "computeStackFocus: Setting " + "focused stack to r=" + r
1987 + " task=" + task);
1988 } else {
1989 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1990 "computeStackFocus: Focused stack already="
1991 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001992 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001993 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001994 }
1995
1996 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1997 if (container != null) {
1998 // The first time put it on the desired stack, after this put on task stack.
1999 r.mInitialActivityContainer = null;
2000 return container.mStack;
2001 }
2002
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002003 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002004 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2005 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2006 return mSupervisor.mFocusedStack;
2007 }
2008
David Stevensc6b91c62017-02-08 14:23:58 -08002009 if (mSourceDisplayId == DEFAULT_DISPLAY) {
2010 // We first try to put the task in the first dynamic stack on home display.
2011 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2012 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2013 stack = homeDisplayStacks.get(stackNdx);
2014 if (isDynamicStack(stack.mStackId)) {
2015 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2016 "computeStackFocus: Setting focused stack=" + stack);
2017 return stack;
2018 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002019 }
David Stevensc6b91c62017-02-08 14:23:58 -08002020 // If there is no suitable dynamic stack then we figure out which static stack to use.
2021 final int stackId = task != null ? task.getLaunchStackId() :
2022 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2023 FULLSCREEN_WORKSPACE_STACK_ID;
2024 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2025 } else {
2026 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002027 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002028 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2029 + r + " stackId=" + stack.mStackId);
2030 return stack;
2031 }
2032
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002033 /** Check if provided activity record can launch in currently focused stack. */
2034 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002035 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2036 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2037 final boolean canUseFocusedStack;
2038 switch (focusedStackId) {
2039 case FULLSCREEN_WORKSPACE_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002040 // The fullscreen stack can contain any task regardless of if the task is resizeable
2041 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002042 canUseFocusedStack = true;
2043 break;
Winson Chung83471632016-12-13 11:02:12 -08002044 case ASSISTANT_STACK_ID:
2045 canUseFocusedStack = r.isAssistantActivity();
2046 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002047 case DOCKED_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002048 // Any activty which supports split screen can go in the docked stack.
Winson Chungd3395382016-12-13 11:49:09 -08002049 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002050 break;
2051 case FREEFORM_WORKSPACE_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002052 // Any activty which supports freeform can go in the freeform stack.
Winson Chungd3395382016-12-13 11:49:09 -08002053 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002054 break;
2055 default:
David Stevensc6b91c62017-02-08 14:23:58 -08002056 // Dynamic stacks behave similarly to the fullscreen stack and can contain any task.
2057 canUseFocusedStack = isDynamicStack(focusedStackId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002058 }
2059
2060 return canUseFocusedStack
David Stevensc6b91c62017-02-08 14:23:58 -08002061 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks())
2062 // We strongly prefer to launch activities on the same display as their source.
2063 && (mSourceDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002064 }
2065
Wale Ogunwale854809c2015-12-27 16:18:19 -08002066 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002067 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07002068
Winson Chung83471632016-12-13 11:02:12 -08002069 // If the activity is of a specific type, return the associated stack, creating it if
2070 // necessary
2071 if (r.isHomeActivity()) {
2072 return mSupervisor.mHomeStack;
2073 }
2074 if (r.isRecentsActivity()) {
2075 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2076 }
2077 if (r.isAssistantActivity()) {
2078 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2079 }
2080
Jorim Jaggib8c58762016-04-20 17:58:29 -07002081 // We are reusing a task, keep the stack!
2082 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002083 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07002084 }
2085
Andrii Kulian16802aa2016-11-02 12:21:33 -07002086 final int launchDisplayId =
2087 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2088
Wale Ogunwale854809c2015-12-27 16:18:19 -08002089 final int launchStackId =
2090 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2091
Andrii Kulian16802aa2016-11-02 12:21:33 -07002092 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2093 throw new IllegalArgumentException(
2094 "Stack and display id can't be set at the same time.");
2095 }
2096
Wale Ogunwale854809c2015-12-27 16:18:19 -08002097 if (isValidLaunchStackId(launchStackId, r)) {
2098 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07002099 }
2100 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08002101 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2102 // for this activity, so we put the activity in the fullscreen stack.
2103 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08002104 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07002105 if (launchDisplayId != INVALID_DISPLAY) {
2106 // Stack id has higher priority than display id.
2107 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2108 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002109
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002110 // If we are using Vr compatibility display, find the virtual display stack.
2111 if (mUsingVrCompatibilityDisplay) {
2112 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2113 if (DEBUG_STACK) {
2114 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2115 ", on virtual display stack:" + as.toString());
2116 }
2117 return as;
2118 }
2119
2120 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2121 || mSourceDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002122 return null;
2123 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002124 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002125
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002126 // The parent activity doesn't want to launch the activity on top of itself, but
2127 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002128 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002129 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2130 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002131
2132 if (parentStack != mSupervisor.mFocusedStack) {
2133 // If task's parent stack is not focused - use it during adjacent launch.
2134 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002135 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002136 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2137 // If task is already on top of focused stack - use it. We don't want to move the
2138 // existing focused task to adjacent stack, just deliver new intent in this case.
2139 return mSupervisor.mFocusedStack;
2140 }
2141
Winson Chung83471632016-12-13 11:02:12 -08002142 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002143 // If parent was in docked stack, the natural place to launch another activity
2144 // will be fullscreen, so it can appear alongside the docked window.
2145 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2146 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002147 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002148 // If the parent is not in the docked stack, we check if there is docked window
2149 // and if yes, we will launch into that stack. If not, we just put the new
2150 // activity into parent's stack, because we can't find a better place.
2151 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2152 if (dockedStack != null
2153 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2154 // There is a docked stack, but it isn't visible, so we can't launch into that.
2155 return null;
2156 } else {
2157 return dockedStack;
2158 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002159 }
2160 }
2161 }
2162
Andrii Kulian16802aa2016-11-02 12:21:33 -07002163 boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002164 switch (stackId) {
2165 case INVALID_STACK_ID:
2166 case HOME_STACK_ID:
2167 return false;
2168 case FULLSCREEN_WORKSPACE_STACK_ID:
2169 return true;
2170 case FREEFORM_WORKSPACE_STACK_ID:
2171 return r.supportsFreeform();
2172 case DOCKED_STACK_ID:
2173 return r.supportsSplitScreen();
2174 case PINNED_STACK_ID:
2175 return r.supportsPictureInPicture();
2176 case RECENTS_STACK_ID:
2177 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002178 case ASSISTANT_STACK_ID:
2179 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002180 default:
Andrii Kulian4acfd852017-01-26 19:43:13 -08002181 if (StackId.isDynamicStack(stackId)) {
2182 return true;
2183 }
Winson Chungd3395382016-12-13 11:49:09 -08002184 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2185 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002186 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002187 }
2188
Wale Ogunwale854809c2015-12-27 16:18:19 -08002189 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2190 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002191 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002192 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2193 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002194 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002195 }
2196 }
2197 return newBounds;
2198 }
2199
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002200 void setWindowManager(WindowManagerService wm) {
2201 mWindowManager = wm;
2202 }
2203
2204 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2205 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2206 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2207 if (pal.stack == stack) {
2208 mPendingActivityLaunches.remove(palNdx);
2209 }
2210 }
2211 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002212
2213 static boolean isDocumentLaunchesIntoExisting(int flags) {
2214 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2215 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2216 }
liulvpingcfa825f2016-09-26 20:00:15 +08002217
2218 boolean clearPendingActivityLaunchesLocked(String packageName) {
2219 boolean didSomething = false;
2220
2221 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2222 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2223 ActivityRecord r = pal.r;
2224 if (r != null && r.packageName.equals(packageName)) {
2225 mPendingActivityLaunches.remove(palNdx);
2226 didSomething = true;
2227 }
2228 }
2229 return didSomething;
2230 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002231}