blob: 654459386329caf671d37bbb2d38349301bc29de [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 Leef9d49542017-06-26 16:27:32 -070020import static android.app.ActivityManager.START_ABORTED;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080021import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080022import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27import static android.app.ActivityManager.START_SUCCESS;
28import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale854809c2015-12-27 16:18:19 -080029import static android.app.ActivityManager.StackId;
Winson Chung83471632016-12-13 11:02:12 -080030import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080031import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
32import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
33import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080034import static android.app.ActivityManager.StackId.HOME_STACK_ID;
35import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
36import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080037import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Andrii Kulian4ede3e02017-01-12 11:52:31 -080038import static android.app.ActivityManager.StackId.isDynamicStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080039import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
40import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010041import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080042import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080043import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080044import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080045import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080046import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
47import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080048import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
49import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
50import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
51import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
52import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080053import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080054import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
56import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
57import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080058import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070059import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080060import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
62import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080063import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080064import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
65import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
66import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
67import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
71import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
72import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
73import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
74import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080075import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -080076import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080077import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080078import 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.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080083import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080084import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080085import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080086import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
87import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
88
Todd Kennedye9910222017-02-21 16:00:11 -080089import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080090import android.app.ActivityManager;
91import android.app.ActivityOptions;
92import android.app.AppGlobals;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080093import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.app.PendingIntent;
95import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070096import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.content.IIntentSender;
98import android.content.Intent;
99import android.content.IntentSender;
100import android.content.pm.ActivityInfo;
101import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -0800102import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000103import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800104import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000105import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.content.res.Configuration;
107import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700108import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800109import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import android.os.Bundle;
111import android.os.IBinder;
112import android.os.RemoteException;
113import android.os.SystemClock;
114import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000115import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800116import android.service.voice.IVoiceInteractionSession;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700117import android.text.TextUtils;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800118import android.util.EventLog;
119import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800120
121import com.android.internal.app.HeavyWeightSwitcherActivity;
122import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800123import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800124import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800125import com.android.server.wm.WindowManagerService;
126
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700127import java.io.PrintWriter;
128import java.text.DateFormat;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800129import java.util.ArrayList;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700130import java.util.Date;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800131
132/**
133 * Controller for interpreting how and then launching activities.
134 *
135 * This class collects all the logic for determining how an intent and flags should be turned into
136 * an activity and associated task and stack.
137 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800138class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800139 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
140 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
141 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
142 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
143 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
144
145 private final ActivityManagerService mService;
146 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000147 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800148 private WindowManagerService mWindowManager;
149
150 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
151
Wale Ogunwale01d66562015-12-29 08:19:19 -0800152 // Share state variable among methods when starting an activity.
153 private ActivityRecord mStartActivity;
154 private Intent mIntent;
155 private int mCallingUid;
156 private ActivityOptions mOptions;
157
158 private boolean mLaunchSingleTop;
159 private boolean mLaunchSingleInstance;
160 private boolean mLaunchSingleTask;
161 private boolean mLaunchTaskBehind;
162 private int mLaunchFlags;
163
164 private Rect mLaunchBounds;
165
166 private ActivityRecord mNotTop;
167 private boolean mDoResume;
168 private int mStartFlags;
169 private ActivityRecord mSourceRecord;
David Stevensc6b91c62017-02-08 14:23:58 -0800170 private int mSourceDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800171
172 private TaskRecord mInTask;
173 private boolean mAddingToTask;
174 private TaskRecord mReuseTask;
175
176 private ActivityInfo mNewTaskInfo;
177 private Intent mNewTaskIntent;
178 private ActivityStack mSourceStack;
179 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700180 // Indicates that we moved other task and are going to put something on top soon, so
181 // we don't want to show it redundantly or accidentally change what's shown below.
182 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800183 private boolean mMovedToFront;
184 private boolean mNoAnimation;
185 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700186 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700187 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800188
189 private IVoiceInteractionSession mVoiceSession;
190 private IVoiceInteractor mVoiceInteractor;
191
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700192 private boolean mUsingVr2dDisplay;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800193
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700194 // Last home activity record we attempted to start
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700195 private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700196 // The result of the last home activity we attempted to start.
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700197 private int mLastHomeActivityStartResult;
198 // Last activity record we attempted to start
199 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
200 // The result of the last activity we attempted to start.
201 private int mLastStartActivityResult;
202 // Time in milli seconds we attempted to start the last activity.
203 private long mLastStartActivityTimeMs;
204 // The reason we were trying to start the last activity
205 private String mLastStartReason;
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700206
Wale Ogunwale01d66562015-12-29 08:19:19 -0800207 private void reset() {
208 mStartActivity = null;
209 mIntent = null;
210 mCallingUid = -1;
211 mOptions = null;
212
213 mLaunchSingleTop = false;
214 mLaunchSingleInstance = false;
215 mLaunchSingleTask = false;
216 mLaunchTaskBehind = false;
217 mLaunchFlags = 0;
218
219 mLaunchBounds = null;
220
221 mNotTop = null;
222 mDoResume = false;
223 mStartFlags = 0;
224 mSourceRecord = null;
David Stevensc6b91c62017-02-08 14:23:58 -0800225 mSourceDisplayId = INVALID_DISPLAY;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800226
227 mInTask = null;
228 mAddingToTask = false;
229 mReuseTask = null;
230
231 mNewTaskInfo = null;
232 mNewTaskIntent = null;
233 mSourceStack = null;
234
235 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700236 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800237 mMovedToFront = false;
238 mNoAnimation = false;
239 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700240 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800241
242 mVoiceSession = null;
243 mVoiceInteractor = null;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800244
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700245 mUsingVr2dDisplay = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800246 }
247
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800248 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
249 mService = service;
250 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000251 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700252 mUsingVr2dDisplay = false;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800253 }
254
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700255 int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
256 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
257 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
258 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
259 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
260 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700261 ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700262
263 if (TextUtils.isEmpty(reason)) {
264 throw new IllegalArgumentException("Need to specify a reason.");
265 }
266 mLastStartReason = reason;
267 mLastStartActivityTimeMs = System.currentTimeMillis();
268 mLastStartActivityRecord[0] = null;
269
270 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
271 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
272 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
273 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700274 inTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700275
276 if (outActivity != null) {
277 // mLastStartActivityRecord[0] is set in the call to startActivity above.
278 outActivity[0] = mLastStartActivityRecord[0];
279 }
Bryce Leef9d49542017-06-26 16:27:32 -0700280
281 // Aborted results are treated as successes externally, but we must track them internally.
282 return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700283 }
284
285 /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
286 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800287 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
288 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
289 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
290 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
291 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700292 ActivityRecord[] outActivity, TaskRecord inTask) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800293 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700294 // Pull the optional Ephemeral Installer-only bundle out of the options early.
295 final Bundle verificationBundle
296 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800297
298 ProcessRecord callerApp = null;
299 if (caller != null) {
300 callerApp = mService.getRecordForAppLocked(caller);
301 if (callerApp != null) {
302 callingPid = callerApp.pid;
303 callingUid = callerApp.info.uid;
304 } else {
305 Slog.w(TAG, "Unable to find app for caller " + caller
306 + " (pid=" + callingPid + ") when starting: "
307 + intent.toString());
308 err = ActivityManager.START_PERMISSION_DENIED;
309 }
310 }
311
312 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
313
314 if (err == ActivityManager.START_SUCCESS) {
315 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800316 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800317 }
318
319 ActivityRecord sourceRecord = null;
320 ActivityRecord resultRecord = null;
321 if (resultTo != null) {
322 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
323 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
324 "Will send result to " + resultTo + " " + sourceRecord);
325 if (sourceRecord != null) {
326 if (requestCode >= 0 && !sourceRecord.finishing) {
327 resultRecord = sourceRecord;
328 }
329 }
330 }
331
332 final int launchFlags = intent.getFlags();
333
334 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
335 // Transfer the result target from the source activity to the new
336 // one being started, including any failures.
337 if (requestCode >= 0) {
338 ActivityOptions.abort(options);
339 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
340 }
341 resultRecord = sourceRecord.resultTo;
342 if (resultRecord != null && !resultRecord.isInStackLocked()) {
343 resultRecord = null;
344 }
345 resultWho = sourceRecord.resultWho;
346 requestCode = sourceRecord.requestCode;
347 sourceRecord.resultTo = null;
348 if (resultRecord != null) {
349 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
350 }
351 if (sourceRecord.launchedFromUid == callingUid) {
352 // The new activity is being launched from the same uid as the previous
353 // activity in the flow, and asking to forward its result back to the
354 // previous. In this case the activity is serving as a trampoline between
355 // the two, so we also want to update its launchedFromPackage to be the
356 // same as the previous activity. Note that this is safe, since we know
357 // these two packages come from the same uid; the caller could just as
358 // well have supplied that same package name itself. This specifially
359 // deals with the case of an intent picker/chooser being launched in the app
360 // flow to redirect to an activity picked by the user, where we want the final
361 // activity to consider it to have been launched by the previous app activity.
362 callingPackage = sourceRecord.launchedFromPackage;
363 }
364 }
365
366 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
367 // We couldn't find a class that can handle the given Intent.
368 // That's the end of that!
369 err = ActivityManager.START_INTENT_NOT_RESOLVED;
370 }
371
372 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
373 // We couldn't find the specific class specified in the Intent.
374 // Also the end of the line.
375 err = ActivityManager.START_CLASS_NOT_FOUND;
376 }
377
378 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700379 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800380 // If this activity is being launched as part of a voice session, we need
381 // to ensure that it is safe to do so. If the upcoming activity will also
382 // be part of the voice session, we can only launch it if it has explicitly
383 // said it supports the VOICE category, or it is a part of the calling app.
384 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
385 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
386 try {
387 intent.addCategory(Intent.CATEGORY_VOICE);
388 if (!AppGlobals.getPackageManager().activitySupportsIntent(
389 intent.getComponent(), intent, resolvedType)) {
390 Slog.w(TAG,
391 "Activity being started in current voice task does not support voice: "
392 + intent);
393 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
394 }
395 } catch (RemoteException e) {
396 Slog.w(TAG, "Failure checking voice capabilities", e);
397 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
398 }
399 }
400 }
401
402 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
403 // If the caller is starting a new voice session, just make sure the target
404 // is actually allowing it to run this way.
405 try {
406 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
407 intent, resolvedType)) {
408 Slog.w(TAG,
409 "Activity being started in new voice task does not support: "
410 + intent);
411 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
412 }
413 } catch (RemoteException e) {
414 Slog.w(TAG, "Failure checking voice capabilities", e);
415 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
416 }
417 }
418
Andrii Kulian02b7a832016-10-06 23:11:56 -0700419 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800420
Wale Ogunwale01d66562015-12-29 08:19:19 -0800421 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800422 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800423 resultStack.sendActivityResultLocked(
424 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800425 }
426 ActivityOptions.abort(options);
427 return err;
428 }
429
430 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
431 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100432 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800433 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
434 callingPid, resolvedType, aInfo.applicationInfo);
435
436 if (mService.mController != null) {
437 try {
438 // The Intent we give to the watcher has the extra data
439 // stripped off, since it can contain private information.
440 Intent watchIntent = intent.cloneFilter();
441 abort |= !mService.mController.activityStarting(watchIntent,
442 aInfo.applicationInfo.packageName);
443 } catch (RemoteException e) {
444 mService.mController = null;
445 }
446 }
447
Rubin Xu58d25992016-01-21 17:47:13 +0000448 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100449 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
450 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000451 intent = mInterceptor.mIntent;
452 rInfo = mInterceptor.mRInfo;
453 aInfo = mInterceptor.mAInfo;
454 resolvedType = mInterceptor.mResolvedType;
455 inTask = mInterceptor.mInTask;
456 callingPid = mInterceptor.mCallingPid;
457 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100458 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800459 if (abort) {
460 if (resultRecord != null) {
461 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800462 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800463 }
464 // We pretend to the caller that it was really started, but
465 // they will just get a cancel result.
466 ActivityOptions.abort(options);
Bryce Leef9d49542017-06-26 16:27:32 -0700467 return START_ABORTED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800468 }
469
470 // If permissions need a review before any of the app components can run, we
471 // launch the review activity and pass a pending intent to start the activity
472 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700473 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800474 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
475 aInfo.packageName, userId)) {
476 IIntentSender target = mService.getIntentSenderLocked(
477 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
478 callingUid, userId, null, null, 0, new Intent[]{intent},
479 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
480 | PendingIntent.FLAG_ONE_SHOT, null);
481
482 final int flags = intent.getFlags();
483 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
484 newIntent.setFlags(flags
485 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
486 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
487 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
488 if (resultRecord != null) {
489 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
490 }
491 intent = newIntent;
492
493 resolvedType = null;
494 callingUid = realCallingUid;
495 callingPid = realCallingPid;
496
497 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
498 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
499 null /*profilerInfo*/);
500
501 if (DEBUG_PERMISSIONS_REVIEW) {
502 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
503 true, false) + "} from uid " + callingUid + " on display "
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700504 + (mSupervisor.mFocusedStack == null
505 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800506 }
507 }
508 }
509
510 // If we have an ephemeral app, abort the process of launching the resolved intent.
511 // Instead, launch the ephemeral installer. Once the installer is finished, it
512 // starts either the intent we resolved here [on install error] or the ephemeral
513 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800514 if (rInfo != null && rInfo.auxiliaryInfo != null) {
515 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700516 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800517 resolvedType = null;
518 callingUid = realCallingUid;
519 callingPid = realCallingPid;
520
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800521 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
522 }
523
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800524 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
525 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
526 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700527 mSupervisor, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800528 if (outActivity != null) {
529 outActivity[0] = r;
530 }
531
532 if (r.appTimeTracker == null && sourceRecord != null) {
533 // If the caller didn't specify an explicit time tracker, we want to continue
534 // tracking under any it has.
535 r.appTimeTracker = sourceRecord.appTimeTracker;
536 }
537
538 final ActivityStack stack = mSupervisor.mFocusedStack;
539 if (voiceSession == null && (stack.mResumedActivity == null
540 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
541 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
542 realCallingPid, realCallingUid, "Activity start")) {
543 PendingActivityLaunch pal = new PendingActivityLaunch(r,
544 sourceRecord, startFlags, stack, callerApp);
545 mPendingActivityLaunches.add(pal);
546 ActivityOptions.abort(options);
547 return ActivityManager.START_SWITCHES_CANCELED;
548 }
549 }
550
551 if (mService.mDidAppSwitch) {
552 // This is the second allowed switch since we stopped switches,
553 // so now just generally allow switches. Use case: user presses
554 // home (switches disabled, switch to home, mDidAppSwitch now true);
555 // user taps a home icon (coming from home so allowed, we hit here
556 // and now allow anyone to switch again).
557 mService.mAppSwitchesAllowedTime = 0;
558 } else {
559 mService.mDidAppSwitch = true;
560 }
561
562 doPendingActivityLaunchesLocked(false);
563
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800564 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
Bryce Lee4a194382017-04-04 14:32:48 -0700565 options, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800566 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800567
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800568 /**
569 * Creates a launch intent for the given auxiliary resolution data.
570 */
Todd Kennedye9910222017-02-21 16:00:11 -0800571 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700572 Intent originalIntent, String callingPackage, Bundle verificationBundle,
573 String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800574 if (auxiliaryResponse.needsPhaseTwo) {
575 // request phase two resolution
576 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700577 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
578 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800579 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700580 return InstantAppResolver.buildEphemeralInstallerIntent(
581 Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
582 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
583 resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
Todd Kennedyd0084f72017-07-28 13:56:14 -0700584 auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
585 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800586 }
587
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800588 void postStartActivityProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700589 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
590 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800591
Bryce Lee7f936862017-05-09 15:33:18 -0700592 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800593 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800594 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800595
Chong Zhang5022da32016-06-21 16:31:37 -0700596 // We're waiting for an activity launch to finish, but that activity simply
597 // brought another activity to front. Let startActivityMayWait() know about
598 // this, so it waits for the new activity to become visible instead.
599 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
600 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
601 }
602
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800603 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700604 final ActivityStack currentStack = r.getStack();
605 if (currentStack != null) {
606 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800607 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700608 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800609 }
610
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700611 if (startedActivityStackId == DOCKED_STACK_ID) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100612 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700613 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
614 if (homeStackVisible) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100615 // We launch an activity while being in home stack, which means either launcher or
616 // recents into docked stack. We don't want the launched activity to be alone in a
617 // docked stack, so we want to immediately launch recents too.
618 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700619 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100620 }
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700621 return;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800622 }
623
Winson Chunge6385a22017-05-02 18:15:16 -0700624 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
Winson Chunge0c3d5d2017-05-04 18:25:21 -0700625 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
Winson Chunge6385a22017-05-02 18:15:16 -0700626 if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
627 || result == START_DELIVERED_TO_TOP || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800628 // The activity was already running in the pinned stack so it wasn't started, but either
629 // brought to the front or the new intent was delivered to it since it was already in
630 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700631 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
632 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800633 return;
634 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800635 }
636
637 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800638 mSupervisor.moveHomeStackTaskToTop(reason);
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700639 mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
640 null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
641 null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
642 null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
643 null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
644 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
645 false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700646 null /*inTask*/, "startHomeActivity: " + reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800647 if (mSupervisor.inResumeTopActivity) {
648 // If we are in resume section already, home activity will be initialized, but not
649 // resumed (to avoid recursive resume) and will stay that way until something pokes it
650 // again. We need to schedule another resume.
651 mSupervisor.scheduleResumeTopActivities();
652 }
653 }
654
Robin Lee5d592422017-01-18 13:48:15 +0000655 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100656 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
657 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
658 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000659 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
660 : ActivityOptions.makeBasic());
Bryce Leeaf691c02017-03-20 14:20:22 -0700661 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000662 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100663 }
Tony Mak853304c2016-04-18 15:17:41 +0100664
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800665 final int startActivityMayWait(IApplicationThread caller, int callingUid,
666 String callingPackage, Intent intent, String resolvedType,
667 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
668 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700669 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700670 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700671 TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800672 // Refuse possible leaked file descriptors
673 if (intent != null && intent.hasFileDescriptors()) {
674 throw new IllegalArgumentException("File descriptors passed in Intent");
675 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500676 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800677 boolean componentSpecified = intent.getComponent() != null;
678
679 // Save a copy in case ephemeral needs it
680 final Intent ephemeralIntent = new Intent(intent);
681 // Don't modify the client's object!
682 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700683 if (componentSpecified
684 && intent.getData() != null
685 && Intent.ACTION_VIEW.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700686 && mService.getPackageManagerInternalLocked()
687 .isInstantAppInstallerComponent(intent.getComponent())) {
688 // intercept intents targeted directly to the ephemeral installer the
689 // ephemeral installer should never be started with a raw URL; instead
690 // adjust the intent so it looks like a "normal" instant app launch
691 intent.setComponent(null /*component*/);
692 componentSpecified = false;
693 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800694
695 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000696 if (rInfo == null) {
697 UserInfo userInfo = mSupervisor.getUserInfo(userId);
698 if (userInfo != null && userInfo.isManagedProfile()) {
699 // Special case for managed profiles, if attempting to launch non-cryto aware
700 // app in a locked managed profile from an unlocked parent allow it to resolve
701 // as user will be sent via confirm credentials to unlock the profile.
702 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700703 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000704 long token = Binder.clearCallingIdentity();
705 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700706 UserInfo parent = userManager.getProfileParent(userId);
707 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
708 && userManager.isUserUnlockingOrUnlocked(parent.id)
709 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000710 } finally {
711 Binder.restoreCallingIdentity(token);
712 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700713 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000714 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600715 PackageManager.MATCH_DIRECT_BOOT_AWARE
716 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000717 }
718 }
719 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800720 // Collect information about the target of the Intent.
721 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
722
723 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800724 synchronized (mService) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800725 final int realCallingPid = Binder.getCallingPid();
726 final int realCallingUid = Binder.getCallingUid();
727 int callingPid;
728 if (callingUid >= 0) {
729 callingPid = -1;
730 } else if (caller == null) {
731 callingPid = realCallingPid;
732 callingUid = realCallingUid;
733 } else {
734 callingPid = callingUid = -1;
735 }
736
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700737 final ActivityStack stack = mSupervisor.mFocusedStack;
Andrii Kulian8072d112016-09-16 11:11:01 -0700738 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700739 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800740 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
741 "Starting activity when config will change = " + stack.mConfigWillChange);
742
743 final long origId = Binder.clearCallingIdentity();
744
745 if (aInfo != null &&
746 (aInfo.applicationInfo.privateFlags
747 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
748 // This may be a heavy-weight process! Check to see if we already
749 // have another, different heavy-weight process running.
750 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
751 final ProcessRecord heavy = mService.mHeavyWeightProcess;
752 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
753 || !heavy.processName.equals(aInfo.processName))) {
754 int appCallingUid = callingUid;
755 if (caller != null) {
756 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
757 if (callerApp != null) {
758 appCallingUid = callerApp.info.uid;
759 } else {
760 Slog.w(TAG, "Unable to find app for caller " + caller
761 + " (pid=" + callingPid + ") when starting: "
762 + intent.toString());
763 ActivityOptions.abort(options);
764 return ActivityManager.START_PERMISSION_DENIED;
765 }
766 }
767
768 IIntentSender target = mService.getIntentSenderLocked(
769 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
770 appCallingUid, userId, null, null, 0, new Intent[] { intent },
771 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
772 | PendingIntent.FLAG_ONE_SHOT, null);
773
774 Intent newIntent = new Intent();
775 if (requestCode >= 0) {
776 // Caller is requesting a result.
777 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
778 }
779 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
780 new IntentSender(target));
781 if (heavy.activities.size() > 0) {
782 ActivityRecord hist = heavy.activities.get(0);
783 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
784 hist.packageName);
785 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -0700786 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800787 }
788 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
789 aInfo.packageName);
790 newIntent.setFlags(intent.getFlags());
791 newIntent.setClassName("android",
792 HeavyWeightSwitcherActivity.class.getName());
793 intent = newIntent;
794 resolvedType = null;
795 caller = null;
796 callingUid = Binder.getCallingUid();
797 callingPid = Binder.getCallingPid();
798 componentSpecified = true;
799 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
800 aInfo = rInfo != null ? rInfo.activityInfo : null;
801 if (aInfo != null) {
802 aInfo = mService.getActivityInfoForUser(aInfo, userId);
803 }
804 }
805 }
806 }
807
Jorim Jaggi275561a2016-02-23 10:11:02 -0500808 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800809 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
810 aInfo, rInfo, voiceSession, voiceInteractor,
811 resultTo, resultWho, requestCode, callingPid,
812 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700813 options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
814 reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800815
816 Binder.restoreCallingIdentity(origId);
817
818 if (stack.mConfigWillChange) {
819 // If the caller also wants to switch to a new configuration,
820 // do so now. This allows a clean switch, as we are waiting
821 // for the current activity to pause (so we will not destroy
822 // it), and have not yet started the next activity.
823 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
824 "updateConfiguration()");
825 stack.mConfigWillChange = false;
826 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
827 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700828 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800829 }
830
831 if (outResult != null) {
832 outResult.result = res;
833 if (res == ActivityManager.START_SUCCESS) {
834 mSupervisor.mWaitingActivityLaunched.add(outResult);
835 do {
836 try {
837 mService.wait();
838 } catch (InterruptedException e) {
839 }
Chong Zhang5022da32016-06-21 16:31:37 -0700840 } while (outResult.result != START_TASK_TO_FRONT
841 && !outResult.timeout && outResult.who == null);
842 if (outResult.result == START_TASK_TO_FRONT) {
843 res = START_TASK_TO_FRONT;
844 }
845 }
846 if (res == START_TASK_TO_FRONT) {
Bryce Lee4a194382017-04-04 14:32:48 -0700847 final ActivityRecord r = outRecord[0];
848
849 // ActivityRecord may represent a different activity, but it should not be in
850 // the resumed state.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800851 if (r.nowVisible && r.state == RESUMED) {
852 outResult.timeout = false;
Bryce Lee4a194382017-04-04 14:32:48 -0700853 outResult.who = r.realActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800854 outResult.totalTime = 0;
855 outResult.thisTime = 0;
856 } else {
857 outResult.thisTime = SystemClock.uptimeMillis();
Bryce Lee4a194382017-04-04 14:32:48 -0700858 mSupervisor.waitActivityVisible(r.realActivity, outResult);
859 // Note: the timeout variable is not currently not ever set.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800860 do {
861 try {
862 mService.wait();
863 } catch (InterruptedException e) {
864 }
865 } while (!outResult.timeout && outResult.who == null);
866 }
867 }
868 }
869
Bryce Lee4a194382017-04-04 14:32:48 -0700870 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800871 return res;
872 }
873 }
874
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800875 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
876 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700877 Bundle bOptions, int userId, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800878 if (intents == null) {
879 throw new NullPointerException("intents is null");
880 }
881 if (resolvedTypes == null) {
882 throw new NullPointerException("resolvedTypes is null");
883 }
884 if (intents.length != resolvedTypes.length) {
885 throw new IllegalArgumentException("intents are length different than resolvedTypes");
886 }
887
Makoto Onukid67b1872016-07-21 16:26:36 -0700888 final int realCallingPid = Binder.getCallingPid();
889 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800890
891 int callingPid;
892 if (callingUid >= 0) {
893 callingPid = -1;
894 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700895 callingPid = realCallingPid;
896 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800897 } else {
898 callingPid = callingUid = -1;
899 }
900 final long origId = Binder.clearCallingIdentity();
901 try {
902 synchronized (mService) {
903 ActivityRecord[] outActivity = new ActivityRecord[1];
904 for (int i=0; i<intents.length; i++) {
905 Intent intent = intents[i];
906 if (intent == null) {
907 continue;
908 }
909
910 // Refuse possible leaked file descriptors
911 if (intent != null && intent.hasFileDescriptors()) {
912 throw new IllegalArgumentException("File descriptors passed in Intent");
913 }
914
915 boolean componentSpecified = intent.getComponent() != null;
916
917 // Don't modify the client's object!
918 intent = new Intent(intent);
919
920 // Collect information about the target of the Intent.
921 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
922 null, userId);
923 // TODO: New, check if this is correct
924 aInfo = mService.getActivityInfoForUser(aInfo, userId);
925
926 if (aInfo != null &&
927 (aInfo.applicationInfo.privateFlags
928 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
929 throw new IllegalArgumentException(
930 "FLAG_CANT_SAVE_STATE not supported here");
931 }
932
933 ActivityOptions options = ActivityOptions.fromBundle(
934 i == intents.length - 1 ? bOptions : null);
935 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
936 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700937 callingPid, callingUid, callingPackage,
938 realCallingPid, realCallingUid, 0,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700939 options, false, componentSpecified, outActivity, null, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800940 if (res < 0) {
941 return res;
942 }
943
944 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
945 }
946 }
947 } finally {
948 Binder.restoreCallingIdentity(origId);
949 }
950
Wale Ogunwale01d66562015-12-29 08:19:19 -0800951 return START_SUCCESS;
952 }
953
Bryce Lee28d80422017-07-21 13:25:13 -0700954 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
Bryce Lee834abec2017-01-09 16:18:14 -0800955 boolean sendHint = forceSend;
956
957 if (!sendHint) {
958 // If not forced, send power hint when the activity's process is different than the
959 // current resumed activity.
960 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
961 sendHint = resumedActivity == null
962 || resumedActivity.app == null
Bryce Lee28d80422017-07-21 13:25:13 -0700963 || !resumedActivity.app.equals(targetActivity.app);
Bryce Lee834abec2017-01-09 16:18:14 -0800964 }
965
966 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700967 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700968 mPowerHintSent = true;
969 }
970 }
971
Wei Wang65c7a152016-06-02 18:51:22 -0700972 void sendPowerHintForLaunchEndIfNeeded() {
973 // Trigger launch power hint if activity is launched
974 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700975 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700976 mPowerHintSent = false;
977 }
978 }
979
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800980 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
981 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700982 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
983 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800984 int result = START_CANCELED;
985 try {
986 mService.mWindowManager.deferSurfaceLayout();
987 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700988 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800989 } finally {
990 // If we are not able to proceed, disassociate the activity from the task. Leaving an
991 // activity in an incomplete state can lead to issues, such as performing operations
992 // without a window container.
Bryce Leea3b0e3f02017-05-17 16:45:36 -0700993 if (!ActivityManager.isStartResultSuccessful(result)
Bryce Lee7f936862017-05-09 15:33:18 -0700994 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700995 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800996 }
997 mService.mWindowManager.continueSurfaceLayout();
998 }
999
Matthew Ng0e205602017-03-22 14:23:25 -07001000 postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001001 mTargetStack);
1002
1003 return result;
1004 }
1005
1006 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001007 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1008 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001009 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1010 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001011
1012 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1013 voiceInteractor);
1014
1015 computeLaunchingTaskFlags();
1016
1017 computeSourceStack();
1018
1019 mIntent.setFlags(mLaunchFlags);
1020
Bryce Lee4a194382017-04-04 14:32:48 -07001021 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001022
Jorim Jaggi2adba072016-03-03 13:43:39 +01001023 final int preferredLaunchStackId =
1024 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001025 final int preferredLaunchDisplayId =
1026 (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001027
Bryce Lee4a194382017-04-04 14:32:48 -07001028 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001029 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1030 // still needs to be a lock task mode violation since the task gets cleared out and
1031 // the device would otherwise leave the locked task.
Bryce Lee4a194382017-04-04 14:32:48 -07001032 if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001033 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1034 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1035 mSupervisor.showLockTaskToast();
1036 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1037 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1038 }
1039
Bryce Leeaf691c02017-03-20 14:20:22 -07001040 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001041 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001042 }
Bryce Lee4a194382017-04-04 14:32:48 -07001043 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001044 // This task was started because of movement of the activity based on affinity...
1045 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001046 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001047 }
1048
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001049 // This code path leads to delivering a new intent, we want to make sure we schedule it
1050 // as the first operation, in case the activity will be resumed as a result of later
1051 // operations.
1052 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001053 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001054 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Lee4a194382017-04-04 14:32:48 -07001055 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001056
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001057 // In this situation we want to remove all activities from the task up to the one
1058 // being started. In most cases this means we are resetting the task to its initial
1059 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001060 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1061 mLaunchFlags);
1062
Bryce Lee4a194382017-04-04 14:32:48 -07001063 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001064 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1065 // task reference is needed in the call below to
1066 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001067 if (reusedActivity.getTask() == null) {
1068 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001069 }
1070
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001071 if (top != null) {
1072 if (top.frontOfTask) {
1073 // Activity aliases may mean we use different intents for the top activity,
1074 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001075 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001076 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001077 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001078 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1079 mStartActivity.launchedFromPackage);
1080 }
1081 }
1082
Bryce Lee28d80422017-07-21 13:25:13 -07001083 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001084
Bryce Lee4a194382017-04-04 14:32:48 -07001085 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001086
Bryce Lee89cd19a2017-05-17 15:18:35 -07001087 final ActivityRecord outResult =
1088 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1089
1090 // When there is a reused activity and the current result is a trampoline activity,
1091 // set the reused activity as the result.
1092 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1093 outActivity[0] = reusedActivity;
1094 }
1095
Wale Ogunwale01d66562015-12-29 08:19:19 -08001096 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1097 // We don't need to start a new activity, and the client said not to do anything
1098 // if that is the case, so this is it! And for paranoia, make sure we have
1099 // correctly resumed the top activity.
1100 resumeTargetStackIfNeeded();
1101 return START_RETURN_INTENT_TO_CALLER;
1102 }
Bryce Lee4a194382017-04-04 14:32:48 -07001103 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001104
1105 if (!mAddingToTask && mReuseTask == null) {
1106 // We didn't do anything... but it was needed (a.k.a., client don't use that
1107 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1108 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001109 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001110 outActivity[0] = reusedActivity;
1111 }
Bryce Lee28d80422017-07-21 13:25:13 -07001112
Wale Ogunwale01d66562015-12-29 08:19:19 -08001113 return START_TASK_TO_FRONT;
1114 }
1115 }
1116
1117 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001118 final ActivityStack sourceStack = mStartActivity.resultTo != null
1119 ? mStartActivity.resultTo.getStack() : null;
1120 if (sourceStack != null) {
1121 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1122 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1123 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001124 }
1125 ActivityOptions.abort(mOptions);
1126 return START_CLASS_NOT_FOUND;
1127 }
1128
1129 // If the activity being launched is the same as the one currently at the top, then
1130 // we need to check if it should only be launched once.
1131 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001132 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001133 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1134 final boolean dontStart = top != null && mStartActivity.resultTo == null
1135 && top.realActivity.equals(mStartActivity.realActivity)
1136 && top.userId == mStartActivity.userId
1137 && top.app != null && top.app.thread != null
1138 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1139 || mLaunchSingleTop || mLaunchSingleTask);
1140 if (dontStart) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001141 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001142 // For paranoia, make sure we have correctly resumed the top activity.
1143 topStack.mLastPausedActivity = null;
1144 if (mDoResume) {
1145 mSupervisor.resumeFocusedStackTopActivityLocked();
1146 }
1147 ActivityOptions.abort(mOptions);
1148 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1149 // We don't need to start a new activity, and the client said not to do
1150 // anything if that is the case, so this is it!
1151 return START_RETURN_INTENT_TO_CALLER;
1152 }
1153 top.deliverNewIntentLocked(
1154 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001155
1156 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1157 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001158 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1159 preferredLaunchDisplayId, topStack.mStackId);
Chong Zhangd44063c2016-04-08 11:52:30 -07001160
Wale Ogunwale01d66562015-12-29 08:19:19 -08001161 return START_DELIVERED_TO_TOP;
1162 }
1163
1164 boolean newTask = false;
1165 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001166 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001167
1168 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001169 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001170 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1171 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1172 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001173 result = setTaskFromReuseOrCreateNewTask(
1174 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001175 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001176 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001177 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001178 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001179 } else {
1180 // This not being started from an existing activity, and not part of a new task...
1181 // just put it in the top task, though these days this case should never happen.
1182 setTaskToCurrentTopOrCreateNewTask();
1183 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001184 if (result != START_SUCCESS) {
1185 return result;
1186 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001187
1188 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1189 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001190 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1191 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001192 if (mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001193 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001194 }
1195 if (newTask) {
1196 EventLog.writeEvent(
Bryce Leeaf691c02017-03-20 14:20:22 -07001197 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1198 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001199 }
1200 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001201 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001202 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001203
Bryce Lee28d80422017-07-21 13:25:13 -07001204 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001205
Winson Chungb5c41b72016-12-07 15:00:47 -08001206 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1207 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001208 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001209 final ActivityRecord topTaskActivity =
1210 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001211 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001212 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1213 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001214 // If the activity is not focusable, we can't resume it, but still would like to
1215 // make sure it becomes visible as it starts (this will also trigger entry
1216 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001217 // Also, we don't want to resume activities in a task that currently has an overlay
1218 // as the starting activity just needs to be in the visible paused state until the
1219 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001220 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001221 // Go ahead and tell window manager to execute app transition for this activity
1222 // since the app transition will not be triggered through the resume channel.
1223 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001224 } else {
Winson Chung32066032016-11-04 11:55:21 -07001225 // If the target stack was not previously focusable (previous top running activity
1226 // on that stack was not visible) then any prior calls to move the stack to the
1227 // will not update the focused stack. If starting the new activity now allows the
1228 // task stack to be focusable, then ensure that we now update the focused stack
1229 // accordingly.
1230 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1231 mTargetStack.moveToFront("startActivityUnchecked");
1232 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001233 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1234 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001235 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001236 } else {
1237 mTargetStack.addRecentActivityLocked(mStartActivity);
1238 }
1239 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1240
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001241 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1242 preferredLaunchDisplayId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001243
1244 return START_SUCCESS;
1245 }
1246
1247 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1248 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1249 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1250 reset();
1251
1252 mStartActivity = r;
1253 mIntent = r.intent;
1254 mOptions = options;
1255 mCallingUid = r.launchedFromUid;
1256 mSourceRecord = sourceRecord;
1257 mVoiceSession = voiceSession;
1258 mVoiceInteractor = voiceInteractor;
1259
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001260 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
David Stevensc6b91c62017-02-08 14:23:58 -08001261
Wale Ogunwale01d66562015-12-29 08:19:19 -08001262 mLaunchBounds = getOverrideBounds(r, options, inTask);
1263
1264 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1265 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1266 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1267 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1268 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1269 mLaunchTaskBehind = r.mLaunchTaskBehind
1270 && !mLaunchSingleTask && !mLaunchSingleInstance
1271 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1272
1273 sendNewTaskResultRequestIfNeeded();
1274
1275 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1276 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1277 }
1278
1279 // If we are actually going to launch in to a new task, there are some cases where
1280 // we further want to do multiple task.
1281 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1282 if (mLaunchTaskBehind
1283 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1284 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1285 }
1286 }
1287
1288 // We'll invoke onUserLeaving before onPause only if the launching
1289 // activity did not explicitly state that this is an automated launch.
1290 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1291 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1292 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1293
1294 // If the caller has asked not to resume at this point, we make note
1295 // of this in the record so that we can skip it when trying to find
1296 // the top running activity.
1297 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001298 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001299 r.delayedResume = true;
1300 mDoResume = false;
1301 }
1302
Winson Chungcbcadc92017-01-12 15:54:12 -08001303 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1304 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001305 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001306 if (!mOptions.canTaskOverlayResume()) {
1307 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1308 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1309 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001310
Winson Chungcbcadc92017-01-12 15:54:12 -08001311 // The caller specifies that we'd like to be avoided to be moved to the front,
1312 // so be it!
1313 mDoResume = false;
1314 mAvoidMoveToFront = true;
1315 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001316 }
1317 }
1318
Wale Ogunwale01d66562015-12-29 08:19:19 -08001319 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1320
1321 mInTask = inTask;
1322 // In some flows in to this function, we retrieve the task record and hold on to it
1323 // without a lock before calling back in to here... so the task at this point may
1324 // not actually be in recents. Check for that, and if it isn't in recents just
1325 // consider it invalid.
1326 if (inTask != null && !inTask.inRecents) {
1327 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1328 mInTask = null;
1329 }
1330
1331 mStartFlags = startFlags;
1332 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1333 // is the same as the one making the call... or, as a special case, if we do not know
1334 // the caller then we count the current top activity as the caller.
1335 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1336 ActivityRecord checkedCaller = sourceRecord;
1337 if (checkedCaller == null) {
1338 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1339 mNotTop);
1340 }
1341 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1342 // Caller is not the same as launcher, so always needed.
1343 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1344 }
1345 }
1346
1347 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1348 }
1349
1350 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001351 final ActivityStack sourceStack = mStartActivity.resultTo != null
1352 ? mStartActivity.resultTo.getStack() : null;
1353 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001354 // For whatever reason this activity is being launched into a new task...
1355 // yet the caller has requested a result back. Well, that is pretty messed up,
1356 // so instead immediately send back a cancel and let the new task continue launched
1357 // as normal without a dependency on its originator.
1358 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001359 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1360 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1361 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001362 mStartActivity.resultTo = null;
1363 }
1364 }
1365
1366 private void computeLaunchingTaskFlags() {
1367 // If the caller is not coming from another activity, but has given us an explicit task into
1368 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001369 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001370 final Intent baseIntent = mInTask.getBaseIntent();
1371 final ActivityRecord root = mInTask.getRootActivity();
1372 if (baseIntent == null) {
1373 ActivityOptions.abort(mOptions);
1374 throw new IllegalArgumentException("Launching into task without base intent: "
1375 + mInTask);
1376 }
1377
1378 // If this task is empty, then we are adding the first activity -- it
1379 // determines the root, and must be launching as a NEW_TASK.
1380 if (mLaunchSingleInstance || mLaunchSingleTask) {
1381 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1382 ActivityOptions.abort(mOptions);
1383 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1384 + mStartActivity + " into different task " + mInTask);
1385 }
1386 if (root != null) {
1387 ActivityOptions.abort(mOptions);
1388 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1389 + " has root " + root + " but target is singleInstance/Task");
1390 }
1391 }
1392
1393 // If task is empty, then adopt the interesting intent launch flags in to the
1394 // activity being started.
1395 if (root == null) {
1396 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1397 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1398 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1399 | (baseIntent.getFlags() & flagsOfInterest);
1400 mIntent.setFlags(mLaunchFlags);
1401 mInTask.setIntent(mStartActivity);
1402 mAddingToTask = true;
1403
1404 // If the task is not empty and the caller is asking to start it as the root of
1405 // a new task, then we don't actually want to start this on the task. We will
1406 // bring the task to the front, and possibly give it a new intent.
1407 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1408 mAddingToTask = false;
1409
1410 } else {
1411 mAddingToTask = true;
1412 }
1413
1414 mReuseTask = mInTask;
1415 } else {
1416 mInTask = null;
1417 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1418 // when in freeform workspace.
1419 // Also put noDisplay activities in the source task. These by itself can be placed
1420 // in any task/stack, however it could launch other activities like ResolverActivity,
1421 // and we want those to stay in the original task.
1422 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1423 && mSourceRecord.isFreeform()) {
1424 mAddingToTask = true;
1425 }
1426 }
1427
1428 if (mInTask == null) {
1429 if (mSourceRecord == null) {
1430 // This activity is not being started from another... in this
1431 // case we -always- start a new task.
1432 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1433 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1434 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1435 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1436 }
1437 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1438 // The original activity who is starting us is running as a single
1439 // instance... this new activity it is starting must go on its
1440 // own task.
1441 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1442 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1443 // The activity being started is a single instance... it always
1444 // gets launched into its own task.
1445 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1446 }
1447 }
1448 }
1449
1450 private void computeSourceStack() {
1451 if (mSourceRecord == null) {
1452 mSourceStack = null;
1453 return;
1454 }
1455 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001456 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001457 return;
1458 }
1459
1460 // If the source is finishing, we can't further count it as our source. This is because the
1461 // task it is associated with may now be empty and on its way out, so we don't want to
1462 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1463 // a task for it. But save the task information so it can be used when creating the new task.
1464 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1465 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1466 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1467 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1468 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001469
1470 // It is not guaranteed that the source record will have a task associated with it. For,
1471 // example, if this method is being called for processing a pending activity launch, it
1472 // is possible that the activity has been removed from the task after the launch was
1473 // enqueued.
1474 final TaskRecord sourceTask = mSourceRecord.getTask();
1475 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001476 }
1477 mSourceRecord = null;
1478 mSourceStack = null;
1479 }
1480
1481 /**
1482 * Decide whether the new activity should be inserted into an existing task. Returns null
1483 * if not or an ActivityRecord with the task into which the new activity should be added.
1484 */
1485 private ActivityRecord getReusableIntentActivity() {
1486 // We may want to try to place the new activity in to an existing task. We always
1487 // do this if the target activity is singleTask or singleInstance; we will also do
1488 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1489 // us to still place it in a new task: multi task, always doc mode, or being asked to
1490 // launch this as a new task behind the current one.
1491 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1492 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1493 || mLaunchSingleInstance || mLaunchSingleTask;
1494 // If bring to front is requested, and no result is requested and we have not been given
1495 // an explicit task to launch in to, and we can find a task that was started with this
1496 // same component, then instead of launching bring that one to the front.
1497 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1498 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001499 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1500 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1501 intentActivity = task != null ? task.getTopActivity() : null;
1502 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001503 if (mLaunchSingleInstance) {
1504 // There can be one and only one instance of single instance activity in the
1505 // history, and it is always in its own unique task, so we do a special search.
Bryce Lee28d80422017-07-21 13:25:13 -07001506 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1507 mStartActivity.isHomeActivity());
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001508 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1509 // For the launch adjacent case we only want to put the activity in an existing
1510 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001511 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1512 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001513 } else {
1514 // Otherwise find the best task to put the activity in.
David Stevensc6b91c62017-02-08 14:23:58 -08001515 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001516 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001517 }
1518 return intentActivity;
1519 }
1520
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001521 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001522 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1523 * then return the Vr mode's virtual display ID. If not, if the source activity has
1524 * a explicit display ID set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001525 */
1526 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001527 // Check if the Activity is a VR activity. If so, the activity should be launched in
1528 // main display.
1529 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1530 return DEFAULT_DISPLAY;
1531 }
1532
1533 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001534 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001535 if (displayId != INVALID_DISPLAY) {
1536 if (DEBUG_STACK) {
1537 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1538 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001539 mUsingVr2dDisplay = true;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001540 return displayId;
1541 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001542
1543 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1544 // If the activity has a displayId set explicitly, launch it on the same displayId.
1545 if (displayId != INVALID_DISPLAY) {
1546 return displayId;
1547 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001548 return DEFAULT_DISPLAY;
1549 }
1550
1551 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001552 * Figure out which task and activity to bring to front when we have found an existing matching
1553 * activity record in history. May also clear the task if needed.
1554 * @param intentActivity Existing matching activity.
1555 * @return {@link ActivityRecord} brought to front.
1556 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001557 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001558 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001559 mTargetStack.mLastPausedActivity = null;
1560 // If the target task is not in the front, then we need to bring it to the front...
1561 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1562 // the same behavior as if a new instance was being started, which means not bringing it
1563 // to the front if the caller is not itself in the front.
1564 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1565 ActivityRecord curTop = (focusStack == null)
1566 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1567
Bryce Leeaf691c02017-03-20 14:20:22 -07001568 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1569 if (topTask != null
1570 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001571 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001572 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1573 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
Bryce Leeaf691c02017-03-20 14:20:22 -07001574 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001575 // We really do want to push this one into the user's face, right now.
1576 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001577 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001578 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001579 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001580
1581 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1582 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1583 // So no point resuming any of the activities here, it just wastes one extra
1584 // resuming, plus enter AND exit transitions.
1585 // Here we only want to bring the target stack forward. Transition will be applied
1586 // to the new activity that's started after the old ones are gone.
1587 final boolean willClearTask =
1588 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1589 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1590 if (!willClearTask) {
1591 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001592 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1593 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001594 if (launchStack == null || launchStack == mTargetStack) {
1595 // We only want to move to the front, if we aren't going to launch on a
1596 // different stack. If we launch on a different stack, we will put the
1597 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001598 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001599 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1600 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001601 } else if (launchStack.mStackId == DOCKED_STACK_ID
1602 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1603 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1604 // If we want to launch adjacent and mTargetStack is not the computed
1605 // launch stack - move task to top of computed stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001606 intentTask.reparent(launchStack.mStackId, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001607 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1608 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001609 } else {
1610 // TODO: This should be reevaluated in MW v2.
1611 // We choose to move task to front instead of launching it adjacent
1612 // when specific stack was requested explicitly and it appeared to be
1613 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001614 mTargetStack.moveTaskToFrontLocked(intentTask,
1615 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001616 "bringToFrontInsteadOfAdjacentLaunch");
1617 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001618 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001619 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1620 // Target and computed stacks are on different displays and we've
1621 // found a matching task - move the existing instance to that display and
1622 // move it to front.
Bryce Leeaf691c02017-03-20 14:20:22 -07001623 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001624 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1625 "reparentToDisplay");
1626 mMovedToFront = true;
Bryce Lee4ff7da92017-07-17 10:39:24 -07001627 } else if (launchStack.getStackId() == StackId.HOME_STACK_ID
1628 && mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
1629 // It is possible for the home activity to be in another stack initially.
1630 // For example, the activity may have been initially started with an intent
1631 // which placed it in the fullscreen stack. To ensure the proper handling of
1632 // the activity based on home stack assumptions, we must move it over.
1633 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
1634 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1635 "reparentingHome");
1636 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001637 }
1638 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001639
1640 // We are moving a task to the front, use starting window to hide initial drawn
1641 // delay.
1642 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1643 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001644 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001645 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001646 }
1647 }
1648 if (!mMovedToFront && mDoResume) {
1649 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1650 + " from " + intentActivity);
1651 mTargetStack.moveToFront("intentActivityFound");
1652 }
1653
Bryce Leeaf691c02017-03-20 14:20:22 -07001654 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001655 DEFAULT_DISPLAY, mTargetStack.mStackId);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001656
Wale Ogunwale01d66562015-12-29 08:19:19 -08001657 // If the caller has requested that the target task be reset, then do so.
1658 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1659 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1660 }
1661 return intentActivity;
1662 }
1663
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001664 private void updateTaskReturnToType(
1665 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001666 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001667 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1668 // Caller wants to appear on home activity.
1669 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1670 return;
Winson Chung83471632016-12-13 11:02:12 -08001671 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001672 // Task will be launched over the home stack, so return home.
1673 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1674 return;
Winson Chung83471632016-12-13 11:02:12 -08001675 } else if (focusedStack != null && focusedStack != task.getStack() &&
1676 focusedStack.isAssistantStack()) {
1677 // Task was launched over the assistant stack, so return there
1678 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1679 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001680 }
1681
1682 // Else we are coming from an application stack so return to an application.
1683 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1684 }
1685
Wale Ogunwale01d66562015-12-29 08:19:19 -08001686 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1687 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1688 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1689 // The caller has requested to completely replace any existing task with its new
1690 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001691 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1692 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001693 // of history or if it is finished immediately), thus disassociating the task. Also note
1694 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1695 // launching another activity.
1696 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1697 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001698 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001699 task.performClearTaskLocked();
1700 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001701 mReuseTask.setIntent(mStartActivity);
1702
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001703 // When we clear the task - focus will be adjusted, which will bring another task
1704 // to top before we launch the activity we need. This will temporary swap their
1705 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1706 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001707 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1708 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001709 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001710 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001711 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001712 // A special case: we need to start the activity because it is not currently
1713 // running, and the caller has asked to clear the current task to have this
1714 // activity at the top.
1715 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001716
1717 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001718 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001719 // Now pretend like this activity is being started by the top of its task, so it
1720 // is put in the right place.
1721 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001722 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001723 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001724 // Target stack got cleared when we all activities were removed above.
1725 // Go ahead and reset it.
1726 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1727 null /* bounds */, mLaunchFlags, mOptions);
1728 mTargetStack.addTask(task,
1729 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1730 }
1731 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001732 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001733 // In this case the top activity on the task is the same as the one being launched,
1734 // so we take that as a request to bring the task to the foreground. If the top
1735 // activity in the task is the root activity, deliver this new intent to it if it
1736 // desires.
1737 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1738 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001739 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Bryce Leeaf691c02017-03-20 14:20:22 -07001740 intentActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001741 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001742 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001743 }
1744 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1745 mStartActivity.launchedFromPackage);
Bryce Leeaf691c02017-03-20 14:20:22 -07001746 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001747 // In this case we are launching the root activity of the task, but with a
1748 // different intent. We should start a new instance on top.
1749 mAddingToTask = true;
1750 mSourceRecord = intentActivity;
1751 }
1752 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1753 // In this case an activity is being launched in to an existing task, without
1754 // resetting that task. This is typically the situation of launching an activity
1755 // from a notification or shortcut. We want to place the new activity on top of the
1756 // current task.
1757 mAddingToTask = true;
1758 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001759 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001760 // In this case we are launching into an existing task that has not yet been started
1761 // from its front door. The current task has been brought to the front. Ideally,
1762 // we'd probably like to place this new task at the bottom of its stack, but that's
1763 // a little hard to do with the current organization of the code so for now we'll
1764 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001765 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001766 }
1767 }
1768
1769 private void resumeTargetStackIfNeeded() {
1770 if (mDoResume) {
1771 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001772 } else {
1773 ActivityOptions.abort(mOptions);
1774 }
1775 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1776 }
1777
Chong Zhang6cda19c2016-06-14 19:07:56 -07001778 private int setTaskFromReuseOrCreateNewTask(
1779 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1780 mTargetStack = computeStackFocus(
1781 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1782
1783 // Do no move the target stack to front yet, as we might bail if
1784 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001785
1786 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001787 final TaskRecord task = mTargetStack.createTaskRecord(
1788 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001789 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001790 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1791 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001792 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001793 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001794 final int stackId = mTargetStack.mStackId;
1795 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001796 mService.resizeStack(
1797 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001798 } else {
Bryce Leeaf691c02017-03-20 14:20:22 -07001799 mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001800 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001801 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001802 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001803 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001804 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001805 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1806 }
1807
1808 if (taskToAffiliate != null) {
1809 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001810 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001811
Bryce Leeaf691c02017-03-20 14:20:22 -07001812 if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001813 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1814 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1815 }
1816
1817 if (!mMovedOtherTask) {
1818 // If stack id is specified in activity options, usually it means that activity is
1819 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1820 // that case we check the target stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001821 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
Chong Zhang6cda19c2016-06-14 19:07:56 -07001822 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1823 }
1824 if (mDoResume) {
1825 mTargetStack.moveToFront("reuseOrNewTask");
1826 }
1827 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001828 }
1829
1830 private int setTaskFromSourceRecord() {
Bryce Leeaf691c02017-03-20 14:20:22 -07001831 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001832 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1833 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1834 }
1835
Bryce Leeaf691c02017-03-20 14:20:22 -07001836 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001837 final ActivityStack sourceStack = mSourceRecord.getStack();
Andrii Kulian02689a72017-07-06 14:28:59 -07001838 // We only want to allow changing stack in two cases:
1839 // 1. If the target task is not the top one. Otherwise we would move the launching task to
1840 // the other side, rather than show two side by side.
1841 // 2. If activity is not allowed on target display.
1842 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
1843 : sourceStack.mDisplayId;
1844 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
1845 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001846 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001847 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001848 mOptions);
Andrii Kulian02689a72017-07-06 14:28:59 -07001849 // If target stack is not found now - we can't just rely on the source stack, as it may
1850 // be not suitable. Let's check other displays.
1851 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
1852 // Can't use target display, lets find a stack on the source display.
1853 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
1854 sourceStack.mDisplayId, mStartActivity);
1855 }
1856 if (mTargetStack == null) {
1857 // There are no suitable stacks on the target and source display(s). Look on all
1858 // displays.
1859 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
1860 mStartActivity, -1 /* currentFocus */);
1861 }
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001862 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001863
1864 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001865 mTargetStack = sourceStack;
1866 } else if (mTargetStack != sourceStack) {
Winson Chung74666102017-02-22 17:49:24 -08001867 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1868 !ANIMATE, DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001869 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001870
Wale Ogunwale01d66562015-12-29 08:19:19 -08001871 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001872 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001873 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1874 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001875 } else if (mDoResume) {
1876 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001877 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001878
Wale Ogunwale01d66562015-12-29 08:19:19 -08001879 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1880 // In this case, we are adding the activity to an existing task, but the caller has
1881 // asked to clear that task if the activity is already running.
1882 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1883 mKeepCurTransition = true;
1884 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001885 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001886 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1887 // For paranoia, make sure we have correctly resumed the top activity.
1888 mTargetStack.mLastPausedActivity = null;
1889 if (mDoResume) {
1890 mSupervisor.resumeFocusedStackTopActivityLocked();
1891 }
1892 ActivityOptions.abort(mOptions);
1893 return START_DELIVERED_TO_TOP;
1894 }
1895 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1896 // In this case, we are launching an activity in our own task that may already be
1897 // running somewhere in the history, and we want to shuffle it to the front of the
1898 // stack if so.
1899 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1900 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001901 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001902 task.moveActivityToFrontLocked(top);
1903 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001904 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001905 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1906 mTargetStack.mLastPausedActivity = null;
1907 if (mDoResume) {
1908 mSupervisor.resumeFocusedStackTopActivityLocked();
1909 }
1910 return START_DELIVERED_TO_TOP;
1911 }
1912 }
1913
1914 // An existing activity is starting this new activity, so we want to keep the new one in
1915 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001916 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001917 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001918 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001919 return START_SUCCESS;
1920 }
1921
1922 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001923 // The caller is asking that the new activity be started in an explicit
1924 // task it has provided to us.
1925 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1926 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1927 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1928 }
1929
Andrii Kulian02b7a832016-10-06 23:11:56 -07001930 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001931
1932 // Check whether we should actually launch the new activity in to the task,
1933 // or just reuse the current activity on top.
1934 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001935 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1936 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001937 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1938 || mLaunchSingleTop || mLaunchSingleTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001939 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1940 mStartActivity.appTimeTracker, "inTaskToFront");
Bryce Leeaf691c02017-03-20 14:20:22 -07001941 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001942 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1943 // We don't need to start a new activity, and the client said not to do
1944 // anything if that is the case, so this is it!
1945 return START_RETURN_INTENT_TO_CALLER;
1946 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001947 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1948 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001949 return START_DELIVERED_TO_TOP;
1950 }
1951 }
1952
1953 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001954 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1955 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001956 // We don't actually want to have this activity added to the task, so just
1957 // stop here but still tell the caller that we consumed the intent.
1958 ActivityOptions.abort(mOptions);
1959 return START_TASK_TO_FRONT;
1960 }
1961
Yorke Lee64512522017-03-24 13:09:35 -07001962 if (mLaunchBounds != null) {
1963 mInTask.updateOverrideConfiguration(mLaunchBounds);
1964 int stackId = mInTask.getLaunchStackId();
1965 if (stackId != mInTask.getStackId()) {
1966 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1967 DEFER_RESUME, "inTaskToFront");
1968 stackId = mInTask.getStackId();
1969 mTargetStack = mInTask.getStack();
1970 }
1971 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1972 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1973 }
1974 }
1975
1976 mTargetStack.moveTaskToFrontLocked(
1977 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1978
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001979 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1980 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001981 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001982
1983 return START_SUCCESS;
1984 }
1985
1986 private void setTaskToCurrentTopOrCreateNewTask() {
1987 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1988 mOptions);
1989 if (mDoResume) {
1990 mTargetStack.moveToFront("addingToTopTask");
1991 }
1992 final ActivityRecord prev = mTargetStack.topActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07001993 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001994 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1995 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001996 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1997 mTargetStack.positionChildWindowContainerAtTop(task);
1998 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001999 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002000 }
2001
2002 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002003 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002004 parent.addActivityToTop(mStartActivity);
2005 } else {
2006 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2007 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002008 }
2009
2010 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2011 boolean launchSingleTask, int launchFlags) {
2012 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2013 (launchSingleInstance || launchSingleTask)) {
2014 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2015 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2016 "\"singleInstance\" or \"singleTask\"");
2017 launchFlags &=
2018 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2019 } else {
2020 switch (r.info.documentLaunchMode) {
2021 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2022 break;
2023 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2024 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2025 break;
2026 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2027 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2028 break;
2029 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2030 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2031 break;
2032 }
2033 }
2034 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002035 }
2036
2037 final void doPendingActivityLaunchesLocked(boolean doResume) {
2038 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08002039 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2040 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002041 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08002042 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
Bryce Lee4a194382017-04-04 14:32:48 -07002043 null, null /*outRecords*/);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002044 } catch (Exception e) {
2045 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2046 pal.sendErrorResult(e.getMessage());
2047 }
2048 }
2049 }
2050
2051 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08002052 int launchFlags, ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002053 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002054 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002055 if (stack != null) {
2056 return stack;
2057 }
2058
Andrii Kulian02b7a832016-10-06 23:11:56 -07002059 final ActivityStack currentStack = task != null ? task.getStack() : null;
2060 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002061 if (mSupervisor.mFocusedStack != currentStack) {
2062 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2063 "computeStackFocus: Setting " + "focused stack to r=" + r
2064 + " task=" + task);
2065 } else {
2066 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2067 "computeStackFocus: Focused stack already="
2068 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002069 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002070 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002071 }
2072
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002073 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002074 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2075 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2076 return mSupervisor.mFocusedStack;
2077 }
2078
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002079 if (mSourceDisplayId != DEFAULT_DISPLAY) {
2080 // Try to put the activity in a stack on a secondary display.
2081 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2082 if (stack == null) {
2083 // If source display is not suitable - look for topmost valid stack in the system.
2084 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2085 "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
2086 + ", looking on all displays.");
2087 stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
2088 }
2089 }
2090 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002091 // We first try to put the task in the first dynamic stack on home display.
2092 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2093 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2094 stack = homeDisplayStacks.get(stackNdx);
2095 if (isDynamicStack(stack.mStackId)) {
2096 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2097 "computeStackFocus: Setting focused stack=" + stack);
2098 return stack;
2099 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002100 }
David Stevensc6b91c62017-02-08 14:23:58 -08002101 // If there is no suitable dynamic stack then we figure out which static stack to use.
2102 final int stackId = task != null ? task.getLaunchStackId() :
2103 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2104 FULLSCREEN_WORKSPACE_STACK_ID;
2105 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002106 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002107 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2108 + r + " stackId=" + stack.mStackId);
2109 return stack;
2110 }
2111
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002112 /** Check if provided activity record can launch in currently focused stack. */
2113 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002114 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2115 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2116 final boolean canUseFocusedStack;
2117 switch (focusedStackId) {
2118 case FULLSCREEN_WORKSPACE_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002119 // The fullscreen stack can contain any task regardless of if the task is resizeable
2120 // 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 -08002121 canUseFocusedStack = true;
2122 break;
Winson Chung83471632016-12-13 11:02:12 -08002123 case ASSISTANT_STACK_ID:
2124 canUseFocusedStack = r.isAssistantActivity();
2125 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002126 case DOCKED_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002127 // Any activity which supports split screen can go in the docked stack.
Winson Chungd3395382016-12-13 11:49:09 -08002128 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002129 break;
2130 case FREEFORM_WORKSPACE_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002131 // Any activity which supports freeform can go in the freeform stack.
Winson Chungd3395382016-12-13 11:49:09 -08002132 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002133 break;
2134 default:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002135 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2136 // resizeable task.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002137 canUseFocusedStack = isDynamicStack(focusedStackId)
2138 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002139 }
2140
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002141 return canUseFocusedStack && !newTask
David Stevensc6b91c62017-02-08 14:23:58 -08002142 // We strongly prefer to launch activities on the same display as their source.
2143 && (mSourceDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002144 }
2145
Wale Ogunwale854809c2015-12-27 16:18:19 -08002146 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002147 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002148 // We are reusing a task, keep the stack!
2149 if (mReuseTask != null) {
2150 return mReuseTask.getStack();
2151 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002152
Winson Chung83471632016-12-13 11:02:12 -08002153 // If the activity is of a specific type, return the associated stack, creating it if
2154 // necessary
2155 if (r.isHomeActivity()) {
2156 return mSupervisor.mHomeStack;
2157 }
2158 if (r.isRecentsActivity()) {
2159 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2160 }
2161 if (r.isAssistantActivity()) {
2162 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2163 }
2164
Andrii Kulian16802aa2016-11-02 12:21:33 -07002165 final int launchDisplayId =
2166 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2167
Wale Ogunwale854809c2015-12-27 16:18:19 -08002168 final int launchStackId =
2169 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2170
Andrii Kulian16802aa2016-11-02 12:21:33 -07002171 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2172 throw new IllegalArgumentException(
2173 "Stack and display id can't be set at the same time.");
2174 }
2175
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002176 if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002177 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07002178 }
2179 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08002180 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2181 // for this activity, so we put the activity in the fullscreen stack.
2182 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08002183 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07002184 if (launchDisplayId != INVALID_DISPLAY) {
2185 // Stack id has higher priority than display id.
2186 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2187 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002188
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07002189 // If we are using Vr2d display, find the virtual display stack.
2190 if (mUsingVr2dDisplay) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002191 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2192 if (DEBUG_STACK) {
2193 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2194 ", on virtual display stack:" + as.toString());
2195 }
2196 return as;
2197 }
2198
2199 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2200 || mSourceDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002201 return null;
2202 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002203 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002204
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002205 // The parent activity doesn't want to launch the activity on top of itself, but
2206 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002207 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002208
2209 if (parentStack != mSupervisor.mFocusedStack) {
2210 // If task's parent stack is not focused - use it during adjacent launch.
2211 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002212 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002213 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2214 // If task is already on top of focused stack - use it. We don't want to move the
2215 // existing focused task to adjacent stack, just deliver new intent in this case.
2216 return mSupervisor.mFocusedStack;
2217 }
2218
Winson Chung83471632016-12-13 11:02:12 -08002219 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002220 // If parent was in docked stack, the natural place to launch another activity
2221 // will be fullscreen, so it can appear alongside the docked window.
2222 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2223 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002224 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002225 // If the parent is not in the docked stack, we check if there is docked window
2226 // and if yes, we will launch into that stack. If not, we just put the new
2227 // activity into parent's stack, because we can't find a better place.
2228 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2229 if (dockedStack != null
Wale Ogunwalecd501ec2017-04-07 08:53:41 -07002230 && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002231 // There is a docked stack, but it isn't visible, so we can't launch into that.
2232 return null;
2233 } else {
2234 return dockedStack;
2235 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002236 }
2237 }
2238 }
2239
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002240 boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002241 switch (stackId) {
2242 case INVALID_STACK_ID:
2243 case HOME_STACK_ID:
2244 return false;
2245 case FULLSCREEN_WORKSPACE_STACK_ID:
2246 return true;
2247 case FREEFORM_WORKSPACE_STACK_ID:
2248 return r.supportsFreeform();
2249 case DOCKED_STACK_ID:
2250 return r.supportsSplitScreen();
2251 case PINNED_STACK_ID:
2252 return r.supportsPictureInPicture();
2253 case RECENTS_STACK_ID:
2254 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002255 case ASSISTANT_STACK_ID:
2256 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002257 default:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002258 if (StackId.isDynamicStack(stackId)) {
2259 return r.canBeLaunchedOnDisplay(displayId);
Andrii Kulian4acfd852017-01-26 19:43:13 -08002260 }
Winson Chungd3395382016-12-13 11:49:09 -08002261 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2262 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002263 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002264 }
2265
Wale Ogunwale854809c2015-12-27 16:18:19 -08002266 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2267 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002268 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002269 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2270 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002271 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002272 }
2273 }
2274 return newBounds;
2275 }
2276
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002277 void setWindowManager(WindowManagerService wm) {
2278 mWindowManager = wm;
2279 }
2280
2281 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2282 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2283 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2284 if (pal.stack == stack) {
2285 mPendingActivityLaunches.remove(palNdx);
2286 }
2287 }
2288 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002289
2290 static boolean isDocumentLaunchesIntoExisting(int flags) {
2291 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2292 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2293 }
liulvpingcfa825f2016-09-26 20:00:15 +08002294
2295 boolean clearPendingActivityLaunchesLocked(String packageName) {
2296 boolean didSomething = false;
2297
2298 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2299 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2300 ActivityRecord r = pal.r;
2301 if (r != null && r.packageName.equals(packageName)) {
2302 mPendingActivityLaunches.remove(palNdx);
2303 didSomething = true;
2304 }
2305 }
2306 return didSomething;
2307 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002308
Dianne Hackborne676ec72017-07-25 10:55:08 -07002309 void dump(PrintWriter pw, String prefix, String dumpPackage) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002310 prefix = prefix + " ";
2311
Dianne Hackborne676ec72017-07-25 10:55:08 -07002312 if (dumpPackage != null) {
2313 if ((mLastStartActivityRecord[0] == null ||
2314 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2315 (mLastHomeActivityStartRecord[0] == null ||
2316 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2317 (mStartActivity == null || !dumpPackage.equals(mStartActivity.packageName))) {
2318 pw.print(prefix);
2319 pw.println("(nothing)");
2320 return;
2321 }
2322 }
2323
2324 pw.print(prefix);
2325 pw.print("mCurrentUser=");
2326 pw.println(mSupervisor.mCurrentUser);
2327 pw.print(prefix);
2328 pw.print("mLastStartReason=");
2329 pw.println(mLastStartReason);
2330 pw.print(prefix);
2331 pw.print("mLastStartActivityTimeMs=");
2332 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2333 pw.print(prefix);
2334 pw.print("mLastStartActivityResult=");
2335 pw.println(mLastStartActivityResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002336 ActivityRecord r = mLastStartActivityRecord[0];
2337 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002338 pw.print(prefix);
2339 pw.println("mLastStartActivityRecord:");
2340 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002341 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002342 pw.print(prefix);
2343 pw.print("mLastHomeActivityStartResult=");
2344 pw.println(mLastHomeActivityStartResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002345 r = mLastHomeActivityStartRecord[0];
2346 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002347 pw.print(prefix);
2348 pw.println("mLastHomeActivityStartRecord:");
2349 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002350 }
2351 if (mStartActivity != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002352 pw.print(prefix);
2353 pw.println("mStartActivity:");
2354 mStartActivity.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002355 }
2356 if (mIntent != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002357 pw.print(prefix);
2358 pw.print("mIntent=");
2359 pw.println(mIntent);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002360 }
2361 if (mOptions != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002362 pw.print(prefix);
2363 pw.print("mOptions=");
2364 pw.println(mOptions);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002365 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002366 pw.print(prefix);
2367 pw.print("mLaunchSingleTop=");
2368 pw.print(mLaunchSingleTop);
2369 pw.print(" mLaunchSingleInstance=");
2370 pw.print(mLaunchSingleInstance);
2371 pw.print(" mLaunchSingleTask=");
2372 pw.println(mLaunchSingleTask);
2373 pw.print(prefix);
2374 pw.print("mLaunchFlags=0x");
2375 pw.print(Integer.toHexString(mLaunchFlags));
2376 pw.print(" mDoResume=");
2377 pw.print(mDoResume);
2378 pw.print(" mAddingToTask=");
2379 pw.println(mAddingToTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002380 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002381}