blob: a145435976fafe4f8fc1292dd4636fe77a8b43be [file] [log] [blame]
Kenny Guyb1b30262016-02-09 16:02:35 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080017package com.android.server.am;
18
Wale Ogunwale01d66562015-12-29 08:19:19 -080019import static android.app.Activity.RESULT_CANCELED;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080020import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080021import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
22import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
23import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
24import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
25import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
26import static android.app.ActivityManager.START_SUCCESS;
27import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale854809c2015-12-27 16:18:19 -080028import static android.app.ActivityManager.StackId;
Winson Chung83471632016-12-13 11:02:12 -080029import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080030import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
31import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
32import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080033import static android.app.ActivityManager.StackId.HOME_STACK_ID;
34import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
35import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080036import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Andrii Kulian4ede3e02017-01-12 11:52:31 -080037import static android.app.ActivityManager.StackId.isDynamicStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
39import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010040import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080041import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080042import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080044import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080045import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
46import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080047import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
48import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
49import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
50import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
51import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080052import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080053import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
54import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
56import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080057import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070058import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080059import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080062import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080063import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
65import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
66import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
71import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
72import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
73import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080074import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -080075import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080077import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080078import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080079import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
Winson Chung74666102017-02-22 17:49:24 -080080import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080081import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080082import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080083import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080084import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080085import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
86import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
87
Todd Kennedye9910222017-02-21 16:00:11 -080088import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080089import android.app.ActivityManager;
90import android.app.ActivityOptions;
91import android.app.AppGlobals;
92import android.app.IActivityContainer;
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.ComponentName;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080098import android.content.IIntentSender;
99import android.content.Intent;
100import android.content.IntentSender;
101import android.content.pm.ActivityInfo;
102import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -0800103import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000104import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800105import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000106import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.content.res.Configuration;
108import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700109import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800111import android.os.Bundle;
112import android.os.IBinder;
113import android.os.RemoteException;
114import android.os.SystemClock;
115import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000116import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800117import android.service.voice.IVoiceInteractionSession;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700118import android.text.TextUtils;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800119import android.util.EventLog;
120import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800121
122import com.android.internal.app.HeavyWeightSwitcherActivity;
123import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800124import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800125import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800126import com.android.server.wm.WindowManagerService;
127
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700128import java.io.PrintWriter;
129import java.text.DateFormat;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800130import java.util.ArrayList;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700131import java.util.Date;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800132
133/**
134 * Controller for interpreting how and then launching activities.
135 *
136 * This class collects all the logic for determining how an intent and flags should be turned into
137 * an activity and associated task and stack.
138 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800139class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800140 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
141 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
142 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
143 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
144 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
145
146 private final ActivityManagerService mService;
147 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000148 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800149 private WindowManagerService mWindowManager;
150
151 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
152
Wale Ogunwale01d66562015-12-29 08:19:19 -0800153 // Share state variable among methods when starting an activity.
154 private ActivityRecord mStartActivity;
155 private Intent mIntent;
156 private int mCallingUid;
157 private ActivityOptions mOptions;
158
159 private boolean mLaunchSingleTop;
160 private boolean mLaunchSingleInstance;
161 private boolean mLaunchSingleTask;
162 private boolean mLaunchTaskBehind;
163 private int mLaunchFlags;
164
165 private Rect mLaunchBounds;
166
167 private ActivityRecord mNotTop;
168 private boolean mDoResume;
169 private int mStartFlags;
170 private ActivityRecord mSourceRecord;
David Stevensc6b91c62017-02-08 14:23:58 -0800171 private int mSourceDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800172
173 private TaskRecord mInTask;
174 private boolean mAddingToTask;
175 private TaskRecord mReuseTask;
176
177 private ActivityInfo mNewTaskInfo;
178 private Intent mNewTaskIntent;
179 private ActivityStack mSourceStack;
180 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700181 // Indicates that we moved other task and are going to put something on top soon, so
182 // we don't want to show it redundantly or accidentally change what's shown below.
183 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800184 private boolean mMovedToFront;
185 private boolean mNoAnimation;
186 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700187 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700188 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800189
190 private IVoiceInteractionSession mVoiceSession;
191 private IVoiceInteractor mVoiceInteractor;
192
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700193 private boolean mUsingVr2dDisplay;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800194
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700195 // Last home activity record we attempted to start
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700196 private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700197 // The result of the last home activity we attempted to start.
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700198 private int mLastHomeActivityStartResult;
199 // Last activity record we attempted to start
200 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
201 // The result of the last activity we attempted to start.
202 private int mLastStartActivityResult;
203 // Time in milli seconds we attempted to start the last activity.
204 private long mLastStartActivityTimeMs;
205 // The reason we were trying to start the last activity
206 private String mLastStartReason;
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700207
Wale Ogunwale01d66562015-12-29 08:19:19 -0800208 private void reset() {
209 mStartActivity = null;
210 mIntent = null;
211 mCallingUid = -1;
212 mOptions = null;
213
214 mLaunchSingleTop = false;
215 mLaunchSingleInstance = false;
216 mLaunchSingleTask = false;
217 mLaunchTaskBehind = false;
218 mLaunchFlags = 0;
219
220 mLaunchBounds = null;
221
222 mNotTop = null;
223 mDoResume = false;
224 mStartFlags = 0;
225 mSourceRecord = null;
David Stevensc6b91c62017-02-08 14:23:58 -0800226 mSourceDisplayId = INVALID_DISPLAY;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800227
228 mInTask = null;
229 mAddingToTask = false;
230 mReuseTask = null;
231
232 mNewTaskInfo = null;
233 mNewTaskIntent = null;
234 mSourceStack = null;
235
236 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700237 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800238 mMovedToFront = false;
239 mNoAnimation = false;
240 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700241 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800242
243 mVoiceSession = null;
244 mVoiceInteractor = null;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800245
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700246 mUsingVr2dDisplay = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800247 }
248
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800249 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
250 mService = service;
251 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000252 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700253 mUsingVr2dDisplay = false;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800254 }
255
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700256 int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
257 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
258 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
259 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
260 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
261 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
262 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
263 TaskRecord inTask, String reason) {
264
265 if (TextUtils.isEmpty(reason)) {
266 throw new IllegalArgumentException("Need to specify a reason.");
267 }
268 mLastStartReason = reason;
269 mLastStartActivityTimeMs = System.currentTimeMillis();
270 mLastStartActivityRecord[0] = null;
271
272 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
273 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
274 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
275 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
276 container, inTask);
277
278 if (outActivity != null) {
279 // mLastStartActivityRecord[0] is set in the call to startActivity above.
280 outActivity[0] = mLastStartActivityRecord[0];
281 }
282 return mLastStartActivityResult;
283 }
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,
292 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
293 TaskRecord inTask) {
294 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700295 // Pull the optional Ephemeral Installer-only bundle out of the options early.
296 final Bundle verificationBundle
297 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800298
299 ProcessRecord callerApp = null;
300 if (caller != null) {
301 callerApp = mService.getRecordForAppLocked(caller);
302 if (callerApp != null) {
303 callingPid = callerApp.pid;
304 callingUid = callerApp.info.uid;
305 } else {
306 Slog.w(TAG, "Unable to find app for caller " + caller
307 + " (pid=" + callingPid + ") when starting: "
308 + intent.toString());
309 err = ActivityManager.START_PERMISSION_DENIED;
310 }
311 }
312
313 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
314
315 if (err == ActivityManager.START_SUCCESS) {
316 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800317 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800318 }
319
320 ActivityRecord sourceRecord = null;
321 ActivityRecord resultRecord = null;
322 if (resultTo != null) {
323 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
324 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
325 "Will send result to " + resultTo + " " + sourceRecord);
326 if (sourceRecord != null) {
327 if (requestCode >= 0 && !sourceRecord.finishing) {
328 resultRecord = sourceRecord;
329 }
330 }
331 }
332
333 final int launchFlags = intent.getFlags();
334
335 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
336 // Transfer the result target from the source activity to the new
337 // one being started, including any failures.
338 if (requestCode >= 0) {
339 ActivityOptions.abort(options);
340 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
341 }
342 resultRecord = sourceRecord.resultTo;
343 if (resultRecord != null && !resultRecord.isInStackLocked()) {
344 resultRecord = null;
345 }
346 resultWho = sourceRecord.resultWho;
347 requestCode = sourceRecord.requestCode;
348 sourceRecord.resultTo = null;
349 if (resultRecord != null) {
350 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
351 }
352 if (sourceRecord.launchedFromUid == callingUid) {
353 // The new activity is being launched from the same uid as the previous
354 // activity in the flow, and asking to forward its result back to the
355 // previous. In this case the activity is serving as a trampoline between
356 // the two, so we also want to update its launchedFromPackage to be the
357 // same as the previous activity. Note that this is safe, since we know
358 // these two packages come from the same uid; the caller could just as
359 // well have supplied that same package name itself. This specifially
360 // deals with the case of an intent picker/chooser being launched in the app
361 // flow to redirect to an activity picked by the user, where we want the final
362 // activity to consider it to have been launched by the previous app activity.
363 callingPackage = sourceRecord.launchedFromPackage;
364 }
365 }
366
367 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
368 // We couldn't find a class that can handle the given Intent.
369 // That's the end of that!
370 err = ActivityManager.START_INTENT_NOT_RESOLVED;
371 }
372
373 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
374 // We couldn't find the specific class specified in the Intent.
375 // Also the end of the line.
376 err = ActivityManager.START_CLASS_NOT_FOUND;
377 }
378
379 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700380 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800381 // If this activity is being launched as part of a voice session, we need
382 // to ensure that it is safe to do so. If the upcoming activity will also
383 // be part of the voice session, we can only launch it if it has explicitly
384 // said it supports the VOICE category, or it is a part of the calling app.
385 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
386 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
387 try {
388 intent.addCategory(Intent.CATEGORY_VOICE);
389 if (!AppGlobals.getPackageManager().activitySupportsIntent(
390 intent.getComponent(), intent, resolvedType)) {
391 Slog.w(TAG,
392 "Activity being started in current voice task does not support voice: "
393 + intent);
394 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
395 }
396 } catch (RemoteException e) {
397 Slog.w(TAG, "Failure checking voice capabilities", e);
398 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
399 }
400 }
401 }
402
403 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
404 // If the caller is starting a new voice session, just make sure the target
405 // is actually allowing it to run this way.
406 try {
407 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
408 intent, resolvedType)) {
409 Slog.w(TAG,
410 "Activity being started in new voice task does not support: "
411 + intent);
412 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
413 }
414 } catch (RemoteException e) {
415 Slog.w(TAG, "Failure checking voice capabilities", e);
416 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
417 }
418 }
419
Andrii Kulian02b7a832016-10-06 23:11:56 -0700420 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800421
Wale Ogunwale01d66562015-12-29 08:19:19 -0800422 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800423 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800424 resultStack.sendActivityResultLocked(
425 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800426 }
427 ActivityOptions.abort(options);
428 return err;
429 }
430
431 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
432 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100433 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800434 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
435 callingPid, resolvedType, aInfo.applicationInfo);
436
437 if (mService.mController != null) {
438 try {
439 // The Intent we give to the watcher has the extra data
440 // stripped off, since it can contain private information.
441 Intent watchIntent = intent.cloneFilter();
442 abort |= !mService.mController.activityStarting(watchIntent,
443 aInfo.applicationInfo.packageName);
444 } catch (RemoteException e) {
445 mService.mController = null;
446 }
447 }
448
Rubin Xu58d25992016-01-21 17:47:13 +0000449 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100450 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
451 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000452 intent = mInterceptor.mIntent;
453 rInfo = mInterceptor.mRInfo;
454 aInfo = mInterceptor.mAInfo;
455 resolvedType = mInterceptor.mResolvedType;
456 inTask = mInterceptor.mInTask;
457 callingPid = mInterceptor.mCallingPid;
458 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100459 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800460 if (abort) {
461 if (resultRecord != null) {
462 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800463 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800464 }
465 // We pretend to the caller that it was really started, but
466 // they will just get a cancel result.
467 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800468 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800469 }
470
471 // If permissions need a review before any of the app components can run, we
472 // launch the review activity and pass a pending intent to start the activity
473 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700474 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800475 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
476 aInfo.packageName, userId)) {
477 IIntentSender target = mService.getIntentSenderLocked(
478 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
479 callingUid, userId, null, null, 0, new Intent[]{intent},
480 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
481 | PendingIntent.FLAG_ONE_SHOT, null);
482
483 final int flags = intent.getFlags();
484 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
485 newIntent.setFlags(flags
486 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
487 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
488 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
489 if (resultRecord != null) {
490 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
491 }
492 intent = newIntent;
493
494 resolvedType = null;
495 callingUid = realCallingUid;
496 callingPid = realCallingPid;
497
498 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
499 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
500 null /*profilerInfo*/);
501
502 if (DEBUG_PERMISSIONS_REVIEW) {
503 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
504 true, false) + "} from uid " + callingUid + " on display "
505 + (container == null ? (mSupervisor.mFocusedStack == null ?
David Stevensc6b91c62017-02-08 14:23:58 -0800506 DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
507 (container.mActivityDisplay == null ? DEFAULT_DISPLAY :
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800508 container.mActivityDisplay.mDisplayId)));
509 }
510 }
511 }
512
513 // If we have an ephemeral app, abort the process of launching the resolved intent.
514 // Instead, launch the ephemeral installer. Once the installer is finished, it
515 // starts either the intent we resolved here [on install error] or the ephemeral
516 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800517 if (rInfo != null && rInfo.auxiliaryInfo != null) {
518 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700519 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800520 resolvedType = null;
521 callingUid = realCallingUid;
522 callingPid = realCallingPid;
523
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800524 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
525 }
526
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800527 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
528 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
529 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
530 mSupervisor, container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800531 if (outActivity != null) {
532 outActivity[0] = r;
533 }
534
535 if (r.appTimeTracker == null && sourceRecord != null) {
536 // If the caller didn't specify an explicit time tracker, we want to continue
537 // tracking under any it has.
538 r.appTimeTracker = sourceRecord.appTimeTracker;
539 }
540
541 final ActivityStack stack = mSupervisor.mFocusedStack;
542 if (voiceSession == null && (stack.mResumedActivity == null
543 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
544 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
545 realCallingPid, realCallingUid, "Activity start")) {
546 PendingActivityLaunch pal = new PendingActivityLaunch(r,
547 sourceRecord, startFlags, stack, callerApp);
548 mPendingActivityLaunches.add(pal);
549 ActivityOptions.abort(options);
550 return ActivityManager.START_SWITCHES_CANCELED;
551 }
552 }
553
554 if (mService.mDidAppSwitch) {
555 // This is the second allowed switch since we stopped switches,
556 // so now just generally allow switches. Use case: user presses
557 // home (switches disabled, switch to home, mDidAppSwitch now true);
558 // user taps a home icon (coming from home so allowed, we hit here
559 // and now allow anyone to switch again).
560 mService.mAppSwitchesAllowedTime = 0;
561 } else {
562 mService.mDidAppSwitch = true;
563 }
564
565 doPendingActivityLaunchesLocked(false);
566
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800567 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
Bryce Lee4a194382017-04-04 14:32:48 -0700568 options, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800569 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800570
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800571 /**
572 * Creates a launch intent for the given auxiliary resolution data.
573 */
Todd Kennedye9910222017-02-21 16:00:11 -0800574 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700575 Intent originalIntent, String callingPackage, Bundle verificationBundle,
576 String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800577 if (auxiliaryResponse.needsPhaseTwo) {
578 // request phase two resolution
579 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700580 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
581 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800582 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700583 return InstantAppResolver.buildEphemeralInstallerIntent(
584 Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
585 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
586 resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
587 auxiliaryResponse.versionCode, auxiliaryResponse.token,
588 auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800589 }
590
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800591 void postStartActivityProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700592 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
593 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800594
Bryce Lee7f936862017-05-09 15:33:18 -0700595 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800596 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800597 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800598
Chong Zhang5022da32016-06-21 16:31:37 -0700599 // We're waiting for an activity launch to finish, but that activity simply
600 // brought another activity to front. Let startActivityMayWait() know about
601 // this, so it waits for the new activity to become visible instead.
602 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
603 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
604 }
605
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800606 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700607 final ActivityStack currentStack = r.getStack();
608 if (currentStack != null) {
609 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800610 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700611 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800612 }
613
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700614 if (startedActivityStackId == DOCKED_STACK_ID) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100615 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700616 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
617 if (homeStackVisible) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100618 // We launch an activity while being in home stack, which means either launcher or
619 // recents into docked stack. We don't want the launched activity to be alone in a
620 // docked stack, so we want to immediately launch recents too.
621 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700622 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100623 }
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700624 return;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800625 }
626
Winson Chunge6385a22017-05-02 18:15:16 -0700627 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
Winson Chunge0c3d5d2017-05-04 18:25:21 -0700628 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
Winson Chunge6385a22017-05-02 18:15:16 -0700629 if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
630 || result == START_DELIVERED_TO_TOP || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800631 // The activity was already running in the pinned stack so it wasn't started, but either
632 // brought to the front or the new intent was delivered to it since it was already in
633 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700634 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
635 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800636 return;
637 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800638 }
639
640 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800641 mSupervisor.moveHomeStackTaskToTop(reason);
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700642 mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
643 null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
644 null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
645 null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
646 null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
647 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
648 false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700649 null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800650 if (mSupervisor.inResumeTopActivity) {
651 // If we are in resume section already, home activity will be initialized, but not
652 // resumed (to avoid recursive resume) and will stay that way until something pokes it
653 // again. We need to schedule another resume.
654 mSupervisor.scheduleResumeTopActivities();
655 }
656 }
657
Robin Lee5d592422017-01-18 13:48:15 +0000658 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100659 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
660 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
661 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000662 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
663 : ActivityOptions.makeBasic());
Bryce Leeaf691c02017-03-20 14:20:22 -0700664 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000665 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100666 }
Tony Mak853304c2016-04-18 15:17:41 +0100667
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800668 final int startActivityMayWait(IApplicationThread caller, int callingUid,
669 String callingPackage, Intent intent, String resolvedType,
670 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
671 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700672 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700673 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700674 IActivityContainer iContainer, TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800675 // Refuse possible leaked file descriptors
676 if (intent != null && intent.hasFileDescriptors()) {
677 throw new IllegalArgumentException("File descriptors passed in Intent");
678 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500679 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800680 boolean componentSpecified = intent.getComponent() != null;
681
682 // Save a copy in case ephemeral needs it
683 final Intent ephemeralIntent = new Intent(intent);
684 // Don't modify the client's object!
685 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700686 if (componentSpecified
687 && intent.getData() != null
688 && Intent.ACTION_VIEW.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700689 && mService.getPackageManagerInternalLocked()
690 .isInstantAppInstallerComponent(intent.getComponent())) {
691 // intercept intents targeted directly to the ephemeral installer the
692 // ephemeral installer should never be started with a raw URL; instead
693 // adjust the intent so it looks like a "normal" instant app launch
694 intent.setComponent(null /*component*/);
695 componentSpecified = false;
696 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800697
698 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000699 if (rInfo == null) {
700 UserInfo userInfo = mSupervisor.getUserInfo(userId);
701 if (userInfo != null && userInfo.isManagedProfile()) {
702 // Special case for managed profiles, if attempting to launch non-cryto aware
703 // app in a locked managed profile from an unlocked parent allow it to resolve
704 // as user will be sent via confirm credentials to unlock the profile.
705 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700706 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000707 long token = Binder.clearCallingIdentity();
708 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700709 UserInfo parent = userManager.getProfileParent(userId);
710 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
711 && userManager.isUserUnlockingOrUnlocked(parent.id)
712 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000713 } finally {
714 Binder.restoreCallingIdentity(token);
715 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700716 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000717 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600718 PackageManager.MATCH_DIRECT_BOOT_AWARE
719 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000720 }
721 }
722 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800723 // Collect information about the target of the Intent.
724 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
725
726 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
727 ActivityStackSupervisor.ActivityContainer container =
728 (ActivityStackSupervisor.ActivityContainer)iContainer;
729 synchronized (mService) {
730 if (container != null && container.mParentActivity != null &&
731 container.mParentActivity.state != RESUMED) {
732 // Cannot start a child activity if the parent is not resumed.
733 return ActivityManager.START_CANCELED;
734 }
735 final int realCallingPid = Binder.getCallingPid();
736 final int realCallingUid = Binder.getCallingUid();
737 int callingPid;
738 if (callingUid >= 0) {
739 callingPid = -1;
740 } else if (caller == null) {
741 callingPid = realCallingPid;
742 callingUid = realCallingUid;
743 } else {
744 callingPid = callingUid = -1;
745 }
746
747 final ActivityStack stack;
748 if (container == null || container.mStack.isOnHomeDisplay()) {
749 stack = mSupervisor.mFocusedStack;
750 } else {
751 stack = container.mStack;
752 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700753 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700754 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800755 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
756 "Starting activity when config will change = " + stack.mConfigWillChange);
757
758 final long origId = Binder.clearCallingIdentity();
759
760 if (aInfo != null &&
761 (aInfo.applicationInfo.privateFlags
762 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
763 // This may be a heavy-weight process! Check to see if we already
764 // have another, different heavy-weight process running.
765 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
766 final ProcessRecord heavy = mService.mHeavyWeightProcess;
767 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
768 || !heavy.processName.equals(aInfo.processName))) {
769 int appCallingUid = callingUid;
770 if (caller != null) {
771 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
772 if (callerApp != null) {
773 appCallingUid = callerApp.info.uid;
774 } else {
775 Slog.w(TAG, "Unable to find app for caller " + caller
776 + " (pid=" + callingPid + ") when starting: "
777 + intent.toString());
778 ActivityOptions.abort(options);
779 return ActivityManager.START_PERMISSION_DENIED;
780 }
781 }
782
783 IIntentSender target = mService.getIntentSenderLocked(
784 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
785 appCallingUid, userId, null, null, 0, new Intent[] { intent },
786 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
787 | PendingIntent.FLAG_ONE_SHOT, null);
788
789 Intent newIntent = new Intent();
790 if (requestCode >= 0) {
791 // Caller is requesting a result.
792 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
793 }
794 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
795 new IntentSender(target));
796 if (heavy.activities.size() > 0) {
797 ActivityRecord hist = heavy.activities.get(0);
798 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
799 hist.packageName);
800 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -0700801 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800802 }
803 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
804 aInfo.packageName);
805 newIntent.setFlags(intent.getFlags());
806 newIntent.setClassName("android",
807 HeavyWeightSwitcherActivity.class.getName());
808 intent = newIntent;
809 resolvedType = null;
810 caller = null;
811 callingUid = Binder.getCallingUid();
812 callingPid = Binder.getCallingPid();
813 componentSpecified = true;
814 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
815 aInfo = rInfo != null ? rInfo.activityInfo : null;
816 if (aInfo != null) {
817 aInfo = mService.getActivityInfoForUser(aInfo, userId);
818 }
819 }
820 }
821 }
822
Jorim Jaggi275561a2016-02-23 10:11:02 -0500823 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800824 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
825 aInfo, rInfo, voiceSession, voiceInteractor,
826 resultTo, resultWho, requestCode, callingPid,
827 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500828 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700829 inTask, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800830
831 Binder.restoreCallingIdentity(origId);
832
833 if (stack.mConfigWillChange) {
834 // If the caller also wants to switch to a new configuration,
835 // do so now. This allows a clean switch, as we are waiting
836 // for the current activity to pause (so we will not destroy
837 // it), and have not yet started the next activity.
838 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
839 "updateConfiguration()");
840 stack.mConfigWillChange = false;
841 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
842 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700843 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800844 }
845
846 if (outResult != null) {
847 outResult.result = res;
848 if (res == ActivityManager.START_SUCCESS) {
849 mSupervisor.mWaitingActivityLaunched.add(outResult);
850 do {
851 try {
852 mService.wait();
853 } catch (InterruptedException e) {
854 }
Chong Zhang5022da32016-06-21 16:31:37 -0700855 } while (outResult.result != START_TASK_TO_FRONT
856 && !outResult.timeout && outResult.who == null);
857 if (outResult.result == START_TASK_TO_FRONT) {
858 res = START_TASK_TO_FRONT;
859 }
860 }
861 if (res == START_TASK_TO_FRONT) {
Bryce Lee4a194382017-04-04 14:32:48 -0700862 final ActivityRecord r = outRecord[0];
863
864 // ActivityRecord may represent a different activity, but it should not be in
865 // the resumed state.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800866 if (r.nowVisible && r.state == RESUMED) {
867 outResult.timeout = false;
Bryce Lee4a194382017-04-04 14:32:48 -0700868 outResult.who = r.realActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800869 outResult.totalTime = 0;
870 outResult.thisTime = 0;
871 } else {
872 outResult.thisTime = SystemClock.uptimeMillis();
Bryce Lee4a194382017-04-04 14:32:48 -0700873 mSupervisor.waitActivityVisible(r.realActivity, outResult);
874 // Note: the timeout variable is not currently not ever set.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800875 do {
876 try {
877 mService.wait();
878 } catch (InterruptedException e) {
879 }
880 } while (!outResult.timeout && outResult.who == null);
881 }
882 }
883 }
884
Bryce Lee4a194382017-04-04 14:32:48 -0700885 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800886 return res;
887 }
888 }
889
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800890 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
891 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700892 Bundle bOptions, int userId, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800893 if (intents == null) {
894 throw new NullPointerException("intents is null");
895 }
896 if (resolvedTypes == null) {
897 throw new NullPointerException("resolvedTypes is null");
898 }
899 if (intents.length != resolvedTypes.length) {
900 throw new IllegalArgumentException("intents are length different than resolvedTypes");
901 }
902
Makoto Onukid67b1872016-07-21 16:26:36 -0700903 final int realCallingPid = Binder.getCallingPid();
904 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800905
906 int callingPid;
907 if (callingUid >= 0) {
908 callingPid = -1;
909 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700910 callingPid = realCallingPid;
911 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800912 } else {
913 callingPid = callingUid = -1;
914 }
915 final long origId = Binder.clearCallingIdentity();
916 try {
917 synchronized (mService) {
918 ActivityRecord[] outActivity = new ActivityRecord[1];
919 for (int i=0; i<intents.length; i++) {
920 Intent intent = intents[i];
921 if (intent == null) {
922 continue;
923 }
924
925 // Refuse possible leaked file descriptors
926 if (intent != null && intent.hasFileDescriptors()) {
927 throw new IllegalArgumentException("File descriptors passed in Intent");
928 }
929
930 boolean componentSpecified = intent.getComponent() != null;
931
932 // Don't modify the client's object!
933 intent = new Intent(intent);
934
935 // Collect information about the target of the Intent.
936 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
937 null, userId);
938 // TODO: New, check if this is correct
939 aInfo = mService.getActivityInfoForUser(aInfo, userId);
940
941 if (aInfo != null &&
942 (aInfo.applicationInfo.privateFlags
943 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
944 throw new IllegalArgumentException(
945 "FLAG_CANT_SAVE_STATE not supported here");
946 }
947
948 ActivityOptions options = ActivityOptions.fromBundle(
949 i == intents.length - 1 ? bOptions : null);
950 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
951 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700952 callingPid, callingUid, callingPackage,
953 realCallingPid, realCallingUid, 0,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700954 options, false, componentSpecified, outActivity, null, null, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800955 if (res < 0) {
956 return res;
957 }
958
959 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
960 }
961 }
962 } finally {
963 Binder.restoreCallingIdentity(origId);
964 }
965
Wale Ogunwale01d66562015-12-29 08:19:19 -0800966 return START_SUCCESS;
967 }
968
Wei Wang65c7a152016-06-02 18:51:22 -0700969 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
Bryce Lee834abec2017-01-09 16:18:14 -0800970 boolean sendHint = forceSend;
971
972 if (!sendHint) {
973 // If not forced, send power hint when the activity's process is different than the
974 // current resumed activity.
975 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
976 sendHint = resumedActivity == null
977 || resumedActivity.app == null
978 || !resumedActivity.app.equals(mStartActivity.app);
979 }
980
981 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700982 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700983 mPowerHintSent = true;
984 }
985 }
986
Wei Wang65c7a152016-06-02 18:51:22 -0700987 void sendPowerHintForLaunchEndIfNeeded() {
988 // Trigger launch power hint if activity is launched
989 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700990 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700991 mPowerHintSent = false;
992 }
993 }
994
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800995 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
996 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700997 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
998 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800999 int result = START_CANCELED;
1000 try {
1001 mService.mWindowManager.deferSurfaceLayout();
1002 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001003 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001004 } finally {
1005 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1006 // activity in an incomplete state can lead to issues, such as performing operations
1007 // without a window container.
Bryce Leea3b0e3f02017-05-17 16:45:36 -07001008 if (!ActivityManager.isStartResultSuccessful(result)
Bryce Lee7f936862017-05-09 15:33:18 -07001009 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001010 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001011 }
1012 mService.mWindowManager.continueSurfaceLayout();
1013 }
1014
Matthew Ng0e205602017-03-22 14:23:25 -07001015 postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001016 mTargetStack);
1017
1018 return result;
1019 }
1020
1021 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001022 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1023 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001024 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1025 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001026
1027 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1028 voiceInteractor);
1029
1030 computeLaunchingTaskFlags();
1031
1032 computeSourceStack();
1033
1034 mIntent.setFlags(mLaunchFlags);
1035
Bryce Lee4a194382017-04-04 14:32:48 -07001036 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001037
Jorim Jaggi2adba072016-03-03 13:43:39 +01001038 final int preferredLaunchStackId =
1039 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001040 final int preferredLaunchDisplayId =
1041 (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001042
Bryce Lee4a194382017-04-04 14:32:48 -07001043 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001044 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1045 // still needs to be a lock task mode violation since the task gets cleared out and
1046 // the device would otherwise leave the locked task.
Bryce Lee4a194382017-04-04 14:32:48 -07001047 if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001048 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1049 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1050 mSupervisor.showLockTaskToast();
1051 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1052 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1053 }
1054
Bryce Leeaf691c02017-03-20 14:20:22 -07001055 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001056 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001057 }
Bryce Lee4a194382017-04-04 14:32:48 -07001058 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001059 // This task was started because of movement of the activity based on affinity...
1060 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001061 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001062 }
1063
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001064 // This code path leads to delivering a new intent, we want to make sure we schedule it
1065 // as the first operation, in case the activity will be resumed as a result of later
1066 // operations.
1067 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001068 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001069 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Lee4a194382017-04-04 14:32:48 -07001070 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001071
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001072 // In this situation we want to remove all activities from the task up to the one
1073 // being started. In most cases this means we are resetting the task to its initial
1074 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001075 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1076 mLaunchFlags);
1077
Bryce Lee4a194382017-04-04 14:32:48 -07001078 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001079 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1080 // task reference is needed in the call below to
1081 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001082 if (reusedActivity.getTask() == null) {
1083 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001084 }
1085
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001086 if (top != null) {
1087 if (top.frontOfTask) {
1088 // Activity aliases may mean we use different intents for the top activity,
1089 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001090 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001091 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001092 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001093 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1094 mStartActivity.launchedFromPackage);
1095 }
1096 }
1097
Wei Wang65c7a152016-06-02 18:51:22 -07001098 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001099
Bryce Lee4a194382017-04-04 14:32:48 -07001100 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001101
Bryce Lee89cd19a2017-05-17 15:18:35 -07001102 final ActivityRecord outResult =
1103 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1104
1105 // When there is a reused activity and the current result is a trampoline activity,
1106 // set the reused activity as the result.
1107 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1108 outActivity[0] = reusedActivity;
1109 }
1110
Wale Ogunwale01d66562015-12-29 08:19:19 -08001111 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1112 // We don't need to start a new activity, and the client said not to do anything
1113 // if that is the case, so this is it! And for paranoia, make sure we have
1114 // correctly resumed the top activity.
1115 resumeTargetStackIfNeeded();
1116 return START_RETURN_INTENT_TO_CALLER;
1117 }
Bryce Lee4a194382017-04-04 14:32:48 -07001118 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001119
1120 if (!mAddingToTask && mReuseTask == null) {
1121 // We didn't do anything... but it was needed (a.k.a., client don't use that
1122 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1123 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001124 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001125 outActivity[0] = reusedActivity;
1126 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001127 return START_TASK_TO_FRONT;
1128 }
1129 }
1130
1131 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001132 final ActivityStack sourceStack = mStartActivity.resultTo != null
1133 ? mStartActivity.resultTo.getStack() : null;
1134 if (sourceStack != null) {
1135 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1136 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1137 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001138 }
1139 ActivityOptions.abort(mOptions);
1140 return START_CLASS_NOT_FOUND;
1141 }
1142
1143 // If the activity being launched is the same as the one currently at the top, then
1144 // we need to check if it should only be launched once.
1145 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001146 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001147 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1148 final boolean dontStart = top != null && mStartActivity.resultTo == null
1149 && top.realActivity.equals(mStartActivity.realActivity)
1150 && top.userId == mStartActivity.userId
1151 && top.app != null && top.app.thread != null
1152 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1153 || mLaunchSingleTop || mLaunchSingleTask);
1154 if (dontStart) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001155 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001156 // For paranoia, make sure we have correctly resumed the top activity.
1157 topStack.mLastPausedActivity = null;
1158 if (mDoResume) {
1159 mSupervisor.resumeFocusedStackTopActivityLocked();
1160 }
1161 ActivityOptions.abort(mOptions);
1162 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1163 // We don't need to start a new activity, and the client said not to do
1164 // anything if that is the case, so this is it!
1165 return START_RETURN_INTENT_TO_CALLER;
1166 }
1167 top.deliverNewIntentLocked(
1168 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001169
1170 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1171 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001172 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1173 preferredLaunchDisplayId, topStack.mStackId);
Chong Zhangd44063c2016-04-08 11:52:30 -07001174
Wale Ogunwale01d66562015-12-29 08:19:19 -08001175 return START_DELIVERED_TO_TOP;
1176 }
1177
1178 boolean newTask = false;
1179 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001180 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001181
1182 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001183 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001184 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1185 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1186 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001187 result = setTaskFromReuseOrCreateNewTask(
1188 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001189 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001190 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001191 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001192 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001193 } else {
1194 // This not being started from an existing activity, and not part of a new task...
1195 // just put it in the top task, though these days this case should never happen.
1196 setTaskToCurrentTopOrCreateNewTask();
1197 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001198 if (result != START_SUCCESS) {
1199 return result;
1200 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001201
1202 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1203 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001204 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1205 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001206 if (mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001207 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001208 }
1209 if (newTask) {
1210 EventLog.writeEvent(
Bryce Leeaf691c02017-03-20 14:20:22 -07001211 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1212 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001213 }
1214 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001215 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001216 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001217
Wei Wang65c7a152016-06-02 18:51:22 -07001218 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001219
Winson Chungb5c41b72016-12-07 15:00:47 -08001220 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1221 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001222 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001223 final ActivityRecord topTaskActivity =
1224 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001225 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001226 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1227 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001228 // If the activity is not focusable, we can't resume it, but still would like to
1229 // make sure it becomes visible as it starts (this will also trigger entry
1230 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001231 // Also, we don't want to resume activities in a task that currently has an overlay
1232 // as the starting activity just needs to be in the visible paused state until the
1233 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001234 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001235 // Go ahead and tell window manager to execute app transition for this activity
1236 // since the app transition will not be triggered through the resume channel.
1237 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001238 } else {
Winson Chung32066032016-11-04 11:55:21 -07001239 // If the target stack was not previously focusable (previous top running activity
1240 // on that stack was not visible) then any prior calls to move the stack to the
1241 // will not update the focused stack. If starting the new activity now allows the
1242 // task stack to be focusable, then ensure that we now update the focused stack
1243 // accordingly.
1244 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1245 mTargetStack.moveToFront("startActivityUnchecked");
1246 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001247 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1248 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001249 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001250 } else {
1251 mTargetStack.addRecentActivityLocked(mStartActivity);
1252 }
1253 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1254
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001255 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1256 preferredLaunchDisplayId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001257
1258 return START_SUCCESS;
1259 }
1260
1261 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1262 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1263 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1264 reset();
1265
1266 mStartActivity = r;
1267 mIntent = r.intent;
1268 mOptions = options;
1269 mCallingUid = r.launchedFromUid;
1270 mSourceRecord = sourceRecord;
1271 mVoiceSession = voiceSession;
1272 mVoiceInteractor = voiceInteractor;
1273
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001274 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
David Stevensc6b91c62017-02-08 14:23:58 -08001275
Wale Ogunwale01d66562015-12-29 08:19:19 -08001276 mLaunchBounds = getOverrideBounds(r, options, inTask);
1277
1278 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1279 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1280 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1281 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1282 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1283 mLaunchTaskBehind = r.mLaunchTaskBehind
1284 && !mLaunchSingleTask && !mLaunchSingleInstance
1285 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1286
1287 sendNewTaskResultRequestIfNeeded();
1288
1289 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1290 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1291 }
1292
1293 // If we are actually going to launch in to a new task, there are some cases where
1294 // we further want to do multiple task.
1295 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1296 if (mLaunchTaskBehind
1297 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1298 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1299 }
1300 }
1301
1302 // We'll invoke onUserLeaving before onPause only if the launching
1303 // activity did not explicitly state that this is an automated launch.
1304 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1305 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1306 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1307
1308 // If the caller has asked not to resume at this point, we make note
1309 // of this in the record so that we can skip it when trying to find
1310 // the top running activity.
1311 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001312 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001313 r.delayedResume = true;
1314 mDoResume = false;
1315 }
1316
Winson Chungcbcadc92017-01-12 15:54:12 -08001317 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1318 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001319 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001320 if (!mOptions.canTaskOverlayResume()) {
1321 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1322 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1323 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001324
Winson Chungcbcadc92017-01-12 15:54:12 -08001325 // The caller specifies that we'd like to be avoided to be moved to the front,
1326 // so be it!
1327 mDoResume = false;
1328 mAvoidMoveToFront = true;
1329 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001330 }
1331 }
1332
Wale Ogunwale01d66562015-12-29 08:19:19 -08001333 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1334
1335 mInTask = inTask;
1336 // In some flows in to this function, we retrieve the task record and hold on to it
1337 // without a lock before calling back in to here... so the task at this point may
1338 // not actually be in recents. Check for that, and if it isn't in recents just
1339 // consider it invalid.
1340 if (inTask != null && !inTask.inRecents) {
1341 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1342 mInTask = null;
1343 }
1344
1345 mStartFlags = startFlags;
1346 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1347 // is the same as the one making the call... or, as a special case, if we do not know
1348 // the caller then we count the current top activity as the caller.
1349 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1350 ActivityRecord checkedCaller = sourceRecord;
1351 if (checkedCaller == null) {
1352 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1353 mNotTop);
1354 }
1355 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1356 // Caller is not the same as launcher, so always needed.
1357 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1358 }
1359 }
1360
1361 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1362 }
1363
1364 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001365 final ActivityStack sourceStack = mStartActivity.resultTo != null
1366 ? mStartActivity.resultTo.getStack() : null;
1367 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001368 // For whatever reason this activity is being launched into a new task...
1369 // yet the caller has requested a result back. Well, that is pretty messed up,
1370 // so instead immediately send back a cancel and let the new task continue launched
1371 // as normal without a dependency on its originator.
1372 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001373 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1374 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1375 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001376 mStartActivity.resultTo = null;
1377 }
1378 }
1379
1380 private void computeLaunchingTaskFlags() {
1381 // If the caller is not coming from another activity, but has given us an explicit task into
1382 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001383 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001384 final Intent baseIntent = mInTask.getBaseIntent();
1385 final ActivityRecord root = mInTask.getRootActivity();
1386 if (baseIntent == null) {
1387 ActivityOptions.abort(mOptions);
1388 throw new IllegalArgumentException("Launching into task without base intent: "
1389 + mInTask);
1390 }
1391
1392 // If this task is empty, then we are adding the first activity -- it
1393 // determines the root, and must be launching as a NEW_TASK.
1394 if (mLaunchSingleInstance || mLaunchSingleTask) {
1395 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1396 ActivityOptions.abort(mOptions);
1397 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1398 + mStartActivity + " into different task " + mInTask);
1399 }
1400 if (root != null) {
1401 ActivityOptions.abort(mOptions);
1402 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1403 + " has root " + root + " but target is singleInstance/Task");
1404 }
1405 }
1406
1407 // If task is empty, then adopt the interesting intent launch flags in to the
1408 // activity being started.
1409 if (root == null) {
1410 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1411 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1412 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1413 | (baseIntent.getFlags() & flagsOfInterest);
1414 mIntent.setFlags(mLaunchFlags);
1415 mInTask.setIntent(mStartActivity);
1416 mAddingToTask = true;
1417
1418 // If the task is not empty and the caller is asking to start it as the root of
1419 // a new task, then we don't actually want to start this on the task. We will
1420 // bring the task to the front, and possibly give it a new intent.
1421 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1422 mAddingToTask = false;
1423
1424 } else {
1425 mAddingToTask = true;
1426 }
1427
1428 mReuseTask = mInTask;
1429 } else {
1430 mInTask = null;
1431 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1432 // when in freeform workspace.
1433 // Also put noDisplay activities in the source task. These by itself can be placed
1434 // in any task/stack, however it could launch other activities like ResolverActivity,
1435 // and we want those to stay in the original task.
1436 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1437 && mSourceRecord.isFreeform()) {
1438 mAddingToTask = true;
1439 }
1440 }
1441
1442 if (mInTask == null) {
1443 if (mSourceRecord == null) {
1444 // This activity is not being started from another... in this
1445 // case we -always- start a new task.
1446 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1447 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1448 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1449 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1450 }
1451 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1452 // The original activity who is starting us is running as a single
1453 // instance... this new activity it is starting must go on its
1454 // own task.
1455 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1456 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1457 // The activity being started is a single instance... it always
1458 // gets launched into its own task.
1459 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1460 }
1461 }
1462 }
1463
1464 private void computeSourceStack() {
1465 if (mSourceRecord == null) {
1466 mSourceStack = null;
1467 return;
1468 }
1469 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001470 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001471 return;
1472 }
1473
1474 // If the source is finishing, we can't further count it as our source. This is because the
1475 // task it is associated with may now be empty and on its way out, so we don't want to
1476 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1477 // a task for it. But save the task information so it can be used when creating the new task.
1478 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1479 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1480 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1481 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1482 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001483
1484 // It is not guaranteed that the source record will have a task associated with it. For,
1485 // example, if this method is being called for processing a pending activity launch, it
1486 // is possible that the activity has been removed from the task after the launch was
1487 // enqueued.
1488 final TaskRecord sourceTask = mSourceRecord.getTask();
1489 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001490 }
1491 mSourceRecord = null;
1492 mSourceStack = null;
1493 }
1494
1495 /**
1496 * Decide whether the new activity should be inserted into an existing task. Returns null
1497 * if not or an ActivityRecord with the task into which the new activity should be added.
1498 */
1499 private ActivityRecord getReusableIntentActivity() {
1500 // We may want to try to place the new activity in to an existing task. We always
1501 // do this if the target activity is singleTask or singleInstance; we will also do
1502 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1503 // us to still place it in a new task: multi task, always doc mode, or being asked to
1504 // launch this as a new task behind the current one.
1505 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1506 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1507 || mLaunchSingleInstance || mLaunchSingleTask;
1508 // If bring to front is requested, and no result is requested and we have not been given
1509 // an explicit task to launch in to, and we can find a task that was started with this
1510 // same component, then instead of launching bring that one to the front.
1511 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1512 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001513 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1514 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1515 intentActivity = task != null ? task.getTopActivity() : null;
1516 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001517 if (mLaunchSingleInstance) {
1518 // There can be one and only one instance of single instance activity in the
1519 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001520 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001521 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1522 // For the launch adjacent case we only want to put the activity in an existing
1523 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001524 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1525 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001526 } else {
1527 // Otherwise find the best task to put the activity in.
David Stevensc6b91c62017-02-08 14:23:58 -08001528 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001529 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001530 }
1531 return intentActivity;
1532 }
1533
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001534 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001535 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1536 * then return the Vr mode's virtual display ID. If not, if the source activity has
1537 * a explicit display ID set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001538 */
1539 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001540 // Check if the Activity is a VR activity. If so, the activity should be launched in
1541 // main display.
1542 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1543 return DEFAULT_DISPLAY;
1544 }
1545
1546 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001547 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001548 if (displayId != INVALID_DISPLAY) {
1549 if (DEBUG_STACK) {
1550 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1551 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001552 mUsingVr2dDisplay = true;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001553 return displayId;
1554 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001555
1556 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1557 // If the activity has a displayId set explicitly, launch it on the same displayId.
1558 if (displayId != INVALID_DISPLAY) {
1559 return displayId;
1560 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001561 return DEFAULT_DISPLAY;
1562 }
1563
1564 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001565 * Figure out which task and activity to bring to front when we have found an existing matching
1566 * activity record in history. May also clear the task if needed.
1567 * @param intentActivity Existing matching activity.
1568 * @return {@link ActivityRecord} brought to front.
1569 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001570 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001571 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001572 mTargetStack.mLastPausedActivity = null;
1573 // If the target task is not in the front, then we need to bring it to the front...
1574 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1575 // the same behavior as if a new instance was being started, which means not bringing it
1576 // to the front if the caller is not itself in the front.
1577 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1578 ActivityRecord curTop = (focusStack == null)
1579 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1580
Bryce Leeaf691c02017-03-20 14:20:22 -07001581 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1582 if (topTask != null
1583 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001584 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001585 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1586 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
Bryce Leeaf691c02017-03-20 14:20:22 -07001587 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001588 // We really do want to push this one into the user's face, right now.
1589 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001590 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001591 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001592 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001593
1594 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1595 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1596 // So no point resuming any of the activities here, it just wastes one extra
1597 // resuming, plus enter AND exit transitions.
1598 // Here we only want to bring the target stack forward. Transition will be applied
1599 // to the new activity that's started after the old ones are gone.
1600 final boolean willClearTask =
1601 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1602 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1603 if (!willClearTask) {
1604 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001605 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1606 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001607 if (launchStack == null || launchStack == mTargetStack) {
1608 // We only want to move to the front, if we aren't going to launch on a
1609 // different stack. If we launch on a different stack, we will put the
1610 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001611 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001612 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1613 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001614 } else if (launchStack.mStackId == DOCKED_STACK_ID
1615 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1616 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1617 // If we want to launch adjacent and mTargetStack is not the computed
1618 // launch stack - move task to top of computed stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001619 intentTask.reparent(launchStack.mStackId, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001620 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1621 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001622 } else {
1623 // TODO: This should be reevaluated in MW v2.
1624 // We choose to move task to front instead of launching it adjacent
1625 // when specific stack was requested explicitly and it appeared to be
1626 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001627 mTargetStack.moveTaskToFrontLocked(intentTask,
1628 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001629 "bringToFrontInsteadOfAdjacentLaunch");
1630 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001631 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001632 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1633 // Target and computed stacks are on different displays and we've
1634 // found a matching task - move the existing instance to that display and
1635 // move it to front.
Bryce Leeaf691c02017-03-20 14:20:22 -07001636 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001637 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1638 "reparentToDisplay");
1639 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001640 }
1641 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001642
1643 // We are moving a task to the front, use starting window to hide initial drawn
1644 // delay.
1645 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1646 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001647 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001648 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001649 }
1650 }
1651 if (!mMovedToFront && mDoResume) {
1652 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1653 + " from " + intentActivity);
1654 mTargetStack.moveToFront("intentActivityFound");
1655 }
1656
Bryce Leeaf691c02017-03-20 14:20:22 -07001657 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001658 DEFAULT_DISPLAY, mTargetStack.mStackId);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001659
Wale Ogunwale01d66562015-12-29 08:19:19 -08001660 // If the caller has requested that the target task be reset, then do so.
1661 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1662 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1663 }
1664 return intentActivity;
1665 }
1666
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001667 private void updateTaskReturnToType(
1668 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001669 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001670 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1671 // Caller wants to appear on home activity.
1672 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1673 return;
Winson Chung83471632016-12-13 11:02:12 -08001674 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001675 // Task will be launched over the home stack, so return home.
1676 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1677 return;
Winson Chung83471632016-12-13 11:02:12 -08001678 } else if (focusedStack != null && focusedStack != task.getStack() &&
1679 focusedStack.isAssistantStack()) {
1680 // Task was launched over the assistant stack, so return there
1681 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1682 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001683 }
1684
1685 // Else we are coming from an application stack so return to an application.
1686 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1687 }
1688
Wale Ogunwale01d66562015-12-29 08:19:19 -08001689 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1690 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1691 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1692 // The caller has requested to completely replace any existing task with its new
1693 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001694 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1695 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001696 // of history or if it is finished immediately), thus disassociating the task. Also note
1697 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1698 // launching another activity.
1699 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1700 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001701 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001702 task.performClearTaskLocked();
1703 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001704 mReuseTask.setIntent(mStartActivity);
1705
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001706 // When we clear the task - focus will be adjusted, which will bring another task
1707 // to top before we launch the activity we need. This will temporary swap their
1708 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1709 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001710 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1711 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001712 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001713 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001714 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001715 // A special case: we need to start the activity because it is not currently
1716 // running, and the caller has asked to clear the current task to have this
1717 // activity at the top.
1718 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001719
1720 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001721 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001722 // Now pretend like this activity is being started by the top of its task, so it
1723 // is put in the right place.
1724 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001725 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001726 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001727 // Target stack got cleared when we all activities were removed above.
1728 // Go ahead and reset it.
1729 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1730 null /* bounds */, mLaunchFlags, mOptions);
1731 mTargetStack.addTask(task,
1732 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1733 }
1734 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001735 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001736 // In this case the top activity on the task is the same as the one being launched,
1737 // so we take that as a request to bring the task to the foreground. If the top
1738 // activity in the task is the root activity, deliver this new intent to it if it
1739 // desires.
1740 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1741 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001742 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Bryce Leeaf691c02017-03-20 14:20:22 -07001743 intentActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001744 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001745 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001746 }
1747 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1748 mStartActivity.launchedFromPackage);
Bryce Leeaf691c02017-03-20 14:20:22 -07001749 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001750 // In this case we are launching the root activity of the task, but with a
1751 // different intent. We should start a new instance on top.
1752 mAddingToTask = true;
1753 mSourceRecord = intentActivity;
1754 }
1755 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1756 // In this case an activity is being launched in to an existing task, without
1757 // resetting that task. This is typically the situation of launching an activity
1758 // from a notification or shortcut. We want to place the new activity on top of the
1759 // current task.
1760 mAddingToTask = true;
1761 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001762 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001763 // In this case we are launching into an existing task that has not yet been started
1764 // from its front door. The current task has been brought to the front. Ideally,
1765 // we'd probably like to place this new task at the bottom of its stack, but that's
1766 // a little hard to do with the current organization of the code so for now we'll
1767 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001768 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001769 }
1770 }
1771
1772 private void resumeTargetStackIfNeeded() {
1773 if (mDoResume) {
1774 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001775 } else {
1776 ActivityOptions.abort(mOptions);
1777 }
1778 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1779 }
1780
Chong Zhang6cda19c2016-06-14 19:07:56 -07001781 private int setTaskFromReuseOrCreateNewTask(
1782 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1783 mTargetStack = computeStackFocus(
1784 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1785
1786 // Do no move the target stack to front yet, as we might bail if
1787 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001788
1789 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001790 final TaskRecord task = mTargetStack.createTaskRecord(
1791 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001792 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001793 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1794 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001795 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001796 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001797 final int stackId = mTargetStack.mStackId;
1798 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001799 mService.resizeStack(
1800 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001801 } else {
Bryce Leeaf691c02017-03-20 14:20:22 -07001802 mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001803 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001804 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001805 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001806 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001807 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001808 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1809 }
1810
1811 if (taskToAffiliate != null) {
1812 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001813 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001814
Bryce Leeaf691c02017-03-20 14:20:22 -07001815 if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001816 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1817 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1818 }
1819
1820 if (!mMovedOtherTask) {
1821 // If stack id is specified in activity options, usually it means that activity is
1822 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1823 // that case we check the target stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001824 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
Chong Zhang6cda19c2016-06-14 19:07:56 -07001825 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1826 }
1827 if (mDoResume) {
1828 mTargetStack.moveToFront("reuseOrNewTask");
1829 }
1830 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001831 }
1832
1833 private int setTaskFromSourceRecord() {
Bryce Leeaf691c02017-03-20 14:20:22 -07001834 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001835 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1836 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1837 }
1838
Bryce Leeaf691c02017-03-20 14:20:22 -07001839 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001840 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001841 // We only want to allow changing stack if the target task is not the top one,
1842 // otherwise we would move the launching task to the other side, rather than show
1843 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001844 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001845 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001846 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001847 mOptions);
1848 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001849
1850 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001851 mTargetStack = sourceStack;
1852 } else if (mTargetStack != sourceStack) {
Winson Chung74666102017-02-22 17:49:24 -08001853 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1854 !ANIMATE, DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001855 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001856
Wale Ogunwale01d66562015-12-29 08:19:19 -08001857 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001858 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001859 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1860 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001861 } else if (mDoResume) {
1862 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001863 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001864
Wale Ogunwale01d66562015-12-29 08:19:19 -08001865 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1866 // In this case, we are adding the activity to an existing task, but the caller has
1867 // asked to clear that task if the activity is already running.
1868 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1869 mKeepCurTransition = true;
1870 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001871 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001872 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1873 // For paranoia, make sure we have correctly resumed the top activity.
1874 mTargetStack.mLastPausedActivity = null;
1875 if (mDoResume) {
1876 mSupervisor.resumeFocusedStackTopActivityLocked();
1877 }
1878 ActivityOptions.abort(mOptions);
1879 return START_DELIVERED_TO_TOP;
1880 }
1881 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1882 // In this case, we are launching an activity in our own task that may already be
1883 // running somewhere in the history, and we want to shuffle it to the front of the
1884 // stack if so.
1885 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1886 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001887 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001888 task.moveActivityToFrontLocked(top);
1889 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001890 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001891 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1892 mTargetStack.mLastPausedActivity = null;
1893 if (mDoResume) {
1894 mSupervisor.resumeFocusedStackTopActivityLocked();
1895 }
1896 return START_DELIVERED_TO_TOP;
1897 }
1898 }
1899
1900 // An existing activity is starting this new activity, so we want to keep the new one in
1901 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001902 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001903 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001904 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001905 return START_SUCCESS;
1906 }
1907
1908 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001909 // The caller is asking that the new activity be started in an explicit
1910 // task it has provided to us.
1911 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1912 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1913 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1914 }
1915
Andrii Kulian02b7a832016-10-06 23:11:56 -07001916 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001917
1918 // Check whether we should actually launch the new activity in to the task,
1919 // or just reuse the current activity on top.
1920 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001921 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1922 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001923 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1924 || mLaunchSingleTop || mLaunchSingleTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001925 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1926 mStartActivity.appTimeTracker, "inTaskToFront");
Bryce Leeaf691c02017-03-20 14:20:22 -07001927 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001928 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1929 // We don't need to start a new activity, and the client said not to do
1930 // anything if that is the case, so this is it!
1931 return START_RETURN_INTENT_TO_CALLER;
1932 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001933 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1934 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001935 return START_DELIVERED_TO_TOP;
1936 }
1937 }
1938
1939 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001940 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1941 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001942 // We don't actually want to have this activity added to the task, so just
1943 // stop here but still tell the caller that we consumed the intent.
1944 ActivityOptions.abort(mOptions);
1945 return START_TASK_TO_FRONT;
1946 }
1947
Yorke Lee64512522017-03-24 13:09:35 -07001948 if (mLaunchBounds != null) {
1949 mInTask.updateOverrideConfiguration(mLaunchBounds);
1950 int stackId = mInTask.getLaunchStackId();
1951 if (stackId != mInTask.getStackId()) {
1952 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1953 DEFER_RESUME, "inTaskToFront");
1954 stackId = mInTask.getStackId();
1955 mTargetStack = mInTask.getStack();
1956 }
1957 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1958 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1959 }
1960 }
1961
1962 mTargetStack.moveTaskToFrontLocked(
1963 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1964
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001965 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1966 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001967 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001968
1969 return START_SUCCESS;
1970 }
1971
1972 private void setTaskToCurrentTopOrCreateNewTask() {
1973 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1974 mOptions);
1975 if (mDoResume) {
1976 mTargetStack.moveToFront("addingToTopTask");
1977 }
1978 final ActivityRecord prev = mTargetStack.topActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07001979 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001980 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1981 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001982 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1983 mTargetStack.positionChildWindowContainerAtTop(task);
1984 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001985 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001986 }
1987
1988 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001989 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001990 parent.addActivityToTop(mStartActivity);
1991 } else {
1992 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1993 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001994 }
1995
1996 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1997 boolean launchSingleTask, int launchFlags) {
1998 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1999 (launchSingleInstance || launchSingleTask)) {
2000 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2001 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2002 "\"singleInstance\" or \"singleTask\"");
2003 launchFlags &=
2004 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2005 } else {
2006 switch (r.info.documentLaunchMode) {
2007 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2008 break;
2009 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2010 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2011 break;
2012 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2013 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2014 break;
2015 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2016 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2017 break;
2018 }
2019 }
2020 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002021 }
2022
2023 final void doPendingActivityLaunchesLocked(boolean doResume) {
2024 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08002025 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2026 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002027 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08002028 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
Bryce Lee4a194382017-04-04 14:32:48 -07002029 null, null /*outRecords*/);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002030 } catch (Exception e) {
2031 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2032 pal.sendErrorResult(e.getMessage());
2033 }
2034 }
2035 }
2036
2037 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08002038 int launchFlags, ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002039 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002040 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002041 if (stack != null) {
2042 return stack;
2043 }
2044
Andrii Kulian02b7a832016-10-06 23:11:56 -07002045 final ActivityStack currentStack = task != null ? task.getStack() : null;
2046 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002047 if (mSupervisor.mFocusedStack != currentStack) {
2048 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2049 "computeStackFocus: Setting " + "focused stack to r=" + r
2050 + " task=" + task);
2051 } else {
2052 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2053 "computeStackFocus: Focused stack already="
2054 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002055 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002056 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002057 }
2058
2059 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
2060 if (container != null) {
2061 // The first time put it on the desired stack, after this put on task stack.
2062 r.mInitialActivityContainer = null;
2063 return container.mStack;
2064 }
2065
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002066 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002067 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2068 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2069 return mSupervisor.mFocusedStack;
2070 }
2071
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002072 if (mSourceDisplayId != DEFAULT_DISPLAY) {
2073 // Try to put the activity in a stack on a secondary display.
2074 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2075 if (stack == null) {
2076 // If source display is not suitable - look for topmost valid stack in the system.
2077 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2078 "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
2079 + ", looking on all displays.");
2080 stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
2081 }
2082 }
2083 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002084 // We first try to put the task in the first dynamic stack on home display.
2085 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2086 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2087 stack = homeDisplayStacks.get(stackNdx);
2088 if (isDynamicStack(stack.mStackId)) {
2089 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2090 "computeStackFocus: Setting focused stack=" + stack);
2091 return stack;
2092 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002093 }
David Stevensc6b91c62017-02-08 14:23:58 -08002094 // If there is no suitable dynamic stack then we figure out which static stack to use.
2095 final int stackId = task != null ? task.getLaunchStackId() :
2096 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2097 FULLSCREEN_WORKSPACE_STACK_ID;
2098 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002099 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002100 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2101 + r + " stackId=" + stack.mStackId);
2102 return stack;
2103 }
2104
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002105 /** Check if provided activity record can launch in currently focused stack. */
2106 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002107 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2108 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2109 final boolean canUseFocusedStack;
2110 switch (focusedStackId) {
2111 case FULLSCREEN_WORKSPACE_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002112 // The fullscreen stack can contain any task regardless of if the task is resizeable
2113 // 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 -08002114 canUseFocusedStack = true;
2115 break;
Winson Chung83471632016-12-13 11:02:12 -08002116 case ASSISTANT_STACK_ID:
2117 canUseFocusedStack = r.isAssistantActivity();
2118 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002119 case DOCKED_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002120 // Any activity which supports split screen can go in the docked stack.
Winson Chungd3395382016-12-13 11:49:09 -08002121 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002122 break;
2123 case FREEFORM_WORKSPACE_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002124 // Any activity which supports freeform can go in the freeform stack.
Winson Chungd3395382016-12-13 11:49:09 -08002125 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002126 break;
2127 default:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002128 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2129 // resizeable task.
2130 // TODO: Check ActivityView after fixing b/35349678.
2131 canUseFocusedStack = isDynamicStack(focusedStackId)
2132 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002133 }
2134
2135 return canUseFocusedStack
David Stevensc6b91c62017-02-08 14:23:58 -08002136 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks())
2137 // We strongly prefer to launch activities on the same display as their source.
2138 && (mSourceDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002139 }
2140
Wale Ogunwale854809c2015-12-27 16:18:19 -08002141 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002142 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002143 // We are reusing a task, keep the stack!
2144 if (mReuseTask != null) {
2145 return mReuseTask.getStack();
2146 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002147
Winson Chung83471632016-12-13 11:02:12 -08002148 // If the activity is of a specific type, return the associated stack, creating it if
2149 // necessary
2150 if (r.isHomeActivity()) {
2151 return mSupervisor.mHomeStack;
2152 }
2153 if (r.isRecentsActivity()) {
2154 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2155 }
2156 if (r.isAssistantActivity()) {
2157 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2158 }
2159
Andrii Kulian16802aa2016-11-02 12:21:33 -07002160 final int launchDisplayId =
2161 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2162
Wale Ogunwale854809c2015-12-27 16:18:19 -08002163 final int launchStackId =
2164 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2165
Andrii Kulian16802aa2016-11-02 12:21:33 -07002166 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2167 throw new IllegalArgumentException(
2168 "Stack and display id can't be set at the same time.");
2169 }
2170
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002171 if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002172 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07002173 }
2174 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08002175 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2176 // for this activity, so we put the activity in the fullscreen stack.
2177 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08002178 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07002179 if (launchDisplayId != INVALID_DISPLAY) {
2180 // Stack id has higher priority than display id.
2181 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2182 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002183
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07002184 // If we are using Vr2d display, find the virtual display stack.
2185 if (mUsingVr2dDisplay) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002186 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2187 if (DEBUG_STACK) {
2188 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2189 ", on virtual display stack:" + as.toString());
2190 }
2191 return as;
2192 }
2193
2194 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2195 || mSourceDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002196 return null;
2197 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002198 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002199
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002200 // The parent activity doesn't want to launch the activity on top of itself, but
2201 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002202 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002203 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2204 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002205
2206 if (parentStack != mSupervisor.mFocusedStack) {
2207 // If task's parent stack is not focused - use it during adjacent launch.
2208 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002209 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002210 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2211 // If task is already on top of focused stack - use it. We don't want to move the
2212 // existing focused task to adjacent stack, just deliver new intent in this case.
2213 return mSupervisor.mFocusedStack;
2214 }
2215
Winson Chung83471632016-12-13 11:02:12 -08002216 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002217 // If parent was in docked stack, the natural place to launch another activity
2218 // will be fullscreen, so it can appear alongside the docked window.
2219 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2220 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002221 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002222 // If the parent is not in the docked stack, we check if there is docked window
2223 // and if yes, we will launch into that stack. If not, we just put the new
2224 // activity into parent's stack, because we can't find a better place.
2225 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2226 if (dockedStack != null
Wale Ogunwalecd501ec2017-04-07 08:53:41 -07002227 && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002228 // There is a docked stack, but it isn't visible, so we can't launch into that.
2229 return null;
2230 } else {
2231 return dockedStack;
2232 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002233 }
2234 }
2235 }
2236
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002237 boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002238 switch (stackId) {
2239 case INVALID_STACK_ID:
2240 case HOME_STACK_ID:
2241 return false;
2242 case FULLSCREEN_WORKSPACE_STACK_ID:
2243 return true;
2244 case FREEFORM_WORKSPACE_STACK_ID:
2245 return r.supportsFreeform();
2246 case DOCKED_STACK_ID:
2247 return r.supportsSplitScreen();
2248 case PINNED_STACK_ID:
2249 return r.supportsPictureInPicture();
2250 case RECENTS_STACK_ID:
2251 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002252 case ASSISTANT_STACK_ID:
2253 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002254 default:
Andrii Kulianeafd9db2017-04-05 22:01:35 -07002255 // TODO: Check ActivityView after fixing b/35349678.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002256 if (StackId.isDynamicStack(stackId)) {
2257 return r.canBeLaunchedOnDisplay(displayId);
Andrii Kulian4acfd852017-01-26 19:43:13 -08002258 }
Winson Chungd3395382016-12-13 11:49:09 -08002259 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2260 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002261 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002262 }
2263
Wale Ogunwale854809c2015-12-27 16:18:19 -08002264 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2265 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002266 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002267 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2268 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002269 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002270 }
2271 }
2272 return newBounds;
2273 }
2274
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002275 void setWindowManager(WindowManagerService wm) {
2276 mWindowManager = wm;
2277 }
2278
2279 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2280 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2281 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2282 if (pal.stack == stack) {
2283 mPendingActivityLaunches.remove(palNdx);
2284 }
2285 }
2286 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002287
2288 static boolean isDocumentLaunchesIntoExisting(int flags) {
2289 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2290 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2291 }
liulvpingcfa825f2016-09-26 20:00:15 +08002292
2293 boolean clearPendingActivityLaunchesLocked(String packageName) {
2294 boolean didSomething = false;
2295
2296 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2297 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2298 ActivityRecord r = pal.r;
2299 if (r != null && r.packageName.equals(packageName)) {
2300 mPendingActivityLaunches.remove(palNdx);
2301 didSomething = true;
2302 }
2303 }
2304 return didSomething;
2305 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002306
2307 void dump(PrintWriter pw, String prefix) {
2308 pw.println(prefix + "ActivityStarter:");
2309 prefix = prefix + " ";
2310
Wale Ogunwale454117f2017-06-22 16:43:53 -07002311 pw.println(prefix + "mCurrentUser=" + mSupervisor.mCurrentUser);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002312 pw.println(prefix + "mLastStartReason=" + mLastStartReason);
2313 pw.println(prefix + "mLastStartActivityTimeMs="
2314 + DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2315 pw.println(prefix + "mLastStartActivityResult=" + mLastStartActivityResult);
2316 ActivityRecord r = mLastStartActivityRecord[0];
2317 if (r != null) {
2318 pw.println(prefix + "mLastStartActivityRecord:");
2319 r.dump(pw, prefix + " ");
2320 }
2321 pw.println(prefix + "mLastHomeActivityStartResult=" + mLastHomeActivityStartResult);
2322 r = mLastHomeActivityStartRecord[0];
2323 if (r != null) {
2324 pw.println(prefix + "mLastHomeActivityStartRecord:");
2325 r.dump(pw, prefix + " ");
2326 }
2327 if (mStartActivity != null) {
2328 pw.println(prefix + "mStartActivity:");
2329 mStartActivity.dump(pw, prefix + " ");
2330 }
2331 if (mIntent != null) {
2332 pw.println(prefix + "mIntent=" + mIntent);
2333 }
2334 if (mOptions != null) {
2335 pw.println(prefix + "mOptions=" + mOptions);
2336 }
2337 pw.println(prefix + "mLaunchSingleTop=" + mLaunchSingleTop
2338 + " mLaunchSingleInstance=" + mLaunchSingleInstance
2339 + " mLaunchSingleTask=" + mLaunchSingleTask
2340 + " mLaunchFlags=0x" + Integer.toHexString(mLaunchFlags)
2341 + " mDoResume=" + mDoResume + " mAddingToTask=" + mAddingToTask);
2342 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002343}