blob: 9b8cbc1043a5770d6c040deb7f543be1a9ddf9fb [file] [log] [blame]
Kenny Guyb1b30262016-02-09 16:02:35 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080017package com.android.server.am;
18
Wale Ogunwale01d66562015-12-29 08:19:19 -080019import static android.app.Activity.RESULT_CANCELED;
Bryce Leef9d49542017-06-26 16:27:32 -070020import static android.app.ActivityManager.START_ABORTED;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080021import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080022import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27import static android.app.ActivityManager.START_SUCCESS;
28import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale68278562017-09-23 17:13:55 -070029import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070031import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
32import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale0568aed2017-09-08 13:29:37 -070033import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080034import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
35import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010036import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080037import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080039import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080040import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080041import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
42import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
44import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
45import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
46import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
47import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080048import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080049import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
50import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
52import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080053import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070054import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080055import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
56import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080058import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080059import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
62import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
66import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
67import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
68import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
69import static com.android.server.am.ActivityManagerService.ANIMATE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080070import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Winson Chung74666102017-02-22 17:49:24 -080071import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080072import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080073import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080074import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080075import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080076import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
77import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
78
Todd Kennedye9910222017-02-21 16:00:11 -080079import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080080import android.app.ActivityManager;
81import android.app.ActivityOptions;
82import android.app.AppGlobals;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080083import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080084import android.app.PendingIntent;
85import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070086import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080087import android.content.IIntentSender;
88import android.content.Intent;
89import android.content.IntentSender;
90import android.content.pm.ActivityInfo;
91import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -080092import android.content.pm.AuxiliaryResolveInfo;
Bryce Lee93e7f792017-10-25 15:54:55 -070093import android.content.pm.IPackageManager;
Kenny Guyb1b30262016-02-09 16:02:35 +000094import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080095import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000096import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.content.res.Configuration;
98import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -070099import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800100import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800101import android.os.Bundle;
102import android.os.IBinder;
103import android.os.RemoteException;
104import android.os.SystemClock;
105import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000106import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.service.voice.IVoiceInteractionSession;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700108import android.text.TextUtils;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800109import android.util.EventLog;
110import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800111
112import com.android.internal.app.HeavyWeightSwitcherActivity;
113import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800114import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800115import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800116
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700117import java.io.PrintWriter;
118import java.text.DateFormat;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800119import java.util.ArrayList;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700120import java.util.Date;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800121
122/**
123 * Controller for interpreting how and then launching activities.
124 *
125 * This class collects all the logic for determining how an intent and flags should be turned into
126 * an activity and associated task and stack.
127 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800128class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800129 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
130 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
131 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
132 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
133 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
Bryce Lee7daee392017-10-12 13:46:18 -0700134 private static final int INVALID_LAUNCH_MODE = -1;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800135
136 private final ActivityManagerService mService;
Bryce Lee93e7f792017-10-25 15:54:55 -0700137 private final IPackageManager mPackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800138 private final ActivityStackSupervisor mSupervisor;
Benjamin Franz563707b2017-06-29 15:06:13 +0100139 private final ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800140
141 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
142
Wale Ogunwale01d66562015-12-29 08:19:19 -0800143 // Share state variable among methods when starting an activity.
144 private ActivityRecord mStartActivity;
145 private Intent mIntent;
146 private int mCallingUid;
147 private ActivityOptions mOptions;
148
Bryce Lee7daee392017-10-12 13:46:18 -0700149 private int mLaunchMode;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800150 private boolean mLaunchTaskBehind;
151 private int mLaunchFlags;
152
Bryce Leedacefc42017-10-10 12:56:02 -0700153 private Rect mLaunchBounds = new Rect();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800154
155 private ActivityRecord mNotTop;
156 private boolean mDoResume;
157 private int mStartFlags;
158 private ActivityRecord mSourceRecord;
Bryce Lee7daee392017-10-12 13:46:18 -0700159
David Stevense5a7b642017-05-22 13:18:23 -0700160 // The display to launch the activity onto, barring any strong reason to do otherwise.
161 private int mPreferredDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800162
163 private TaskRecord mInTask;
164 private boolean mAddingToTask;
165 private TaskRecord mReuseTask;
166
167 private ActivityInfo mNewTaskInfo;
168 private Intent mNewTaskIntent;
169 private ActivityStack mSourceStack;
170 private ActivityStack mTargetStack;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800171 private boolean mMovedToFront;
172 private boolean mNoAnimation;
173 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700174 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700175 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800176
Bryce Lee325e09682017-10-05 17:20:25 -0700177 // We must track when we deliver the new intent since multiple code paths invoke
178 // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
179 // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
180 // delivered at most once.
181 private boolean mIntentDelivered;
182
Wale Ogunwale01d66562015-12-29 08:19:19 -0800183 private IVoiceInteractionSession mVoiceSession;
184 private IVoiceInteractor mVoiceInteractor;
185
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700186 // Last home activity record we attempted to start
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700187 private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700188 // The result of the last home activity we attempted to start.
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700189 private int mLastHomeActivityStartResult;
190 // Last activity record we attempted to start
191 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
192 // The result of the last activity we attempted to start.
193 private int mLastStartActivityResult;
194 // Time in milli seconds we attempted to start the last activity.
195 private long mLastStartActivityTimeMs;
196 // The reason we were trying to start the last activity
197 private String mLastStartReason;
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700198
Wale Ogunwale01d66562015-12-29 08:19:19 -0800199 private void reset() {
200 mStartActivity = null;
201 mIntent = null;
202 mCallingUid = -1;
203 mOptions = null;
204
Wale Ogunwale01d66562015-12-29 08:19:19 -0800205 mLaunchTaskBehind = false;
206 mLaunchFlags = 0;
Bryce Lee7daee392017-10-12 13:46:18 -0700207 mLaunchMode = INVALID_LAUNCH_MODE;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800208
Bryce Leedacefc42017-10-10 12:56:02 -0700209 mLaunchBounds.setEmpty();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800210
211 mNotTop = null;
212 mDoResume = false;
213 mStartFlags = 0;
214 mSourceRecord = null;
David Stevense5a7b642017-05-22 13:18:23 -0700215 mPreferredDisplayId = INVALID_DISPLAY;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800216
217 mInTask = null;
218 mAddingToTask = false;
219 mReuseTask = null;
220
221 mNewTaskInfo = null;
222 mNewTaskIntent = null;
223 mSourceStack = null;
224
225 mTargetStack = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800226 mMovedToFront = false;
227 mNoAnimation = false;
228 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700229 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800230
231 mVoiceSession = null;
232 mVoiceInteractor = null;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800233
Bryce Lee325e09682017-10-05 17:20:25 -0700234 mIntentDelivered = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800235 }
236
Bryce Lee93e7f792017-10-25 15:54:55 -0700237 ActivityStarter(ActivityManagerService service, IPackageManager packageManager) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800238 mService = service;
Bryce Lee93e7f792017-10-25 15:54:55 -0700239 mPackageManager = packageManager;
Bryce Lee7daee392017-10-12 13:46:18 -0700240 mSupervisor = mService.mStackSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000241 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800242 }
243
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700244 int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
245 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
246 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
247 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
248 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
249 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700250 ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700251
252 if (TextUtils.isEmpty(reason)) {
253 throw new IllegalArgumentException("Need to specify a reason.");
254 }
255 mLastStartReason = reason;
256 mLastStartActivityTimeMs = System.currentTimeMillis();
257 mLastStartActivityRecord[0] = null;
258
259 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
260 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
261 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
262 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700263 inTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700264
265 if (outActivity != null) {
266 // mLastStartActivityRecord[0] is set in the call to startActivity above.
267 outActivity[0] = mLastStartActivityRecord[0];
268 }
Bryce Leef9d49542017-06-26 16:27:32 -0700269
Bryce Lee93e7f792017-10-25 15:54:55 -0700270 return getExternalResult(mLastStartActivityResult);
271 }
272
273 public static int getExternalResult(int result) {
Bryce Leef9d49542017-06-26 16:27:32 -0700274 // Aborted results are treated as successes externally, but we must track them internally.
Bryce Lee93e7f792017-10-25 15:54:55 -0700275 return result != START_ABORTED ? result : START_SUCCESS;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700276 }
277
278 /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
279 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800280 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
281 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
282 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
283 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
284 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700285 ActivityRecord[] outActivity, TaskRecord inTask) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800286 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700287 // Pull the optional Ephemeral Installer-only bundle out of the options early.
288 final Bundle verificationBundle
289 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800290
291 ProcessRecord callerApp = null;
292 if (caller != null) {
293 callerApp = mService.getRecordForAppLocked(caller);
294 if (callerApp != null) {
295 callingPid = callerApp.pid;
296 callingUid = callerApp.info.uid;
297 } else {
298 Slog.w(TAG, "Unable to find app for caller " + caller
299 + " (pid=" + callingPid + ") when starting: "
300 + intent.toString());
301 err = ActivityManager.START_PERMISSION_DENIED;
302 }
303 }
304
Bryce Lee93e7f792017-10-25 15:54:55 -0700305 final int userId = aInfo != null && aInfo.applicationInfo != null
306 ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800307
308 if (err == ActivityManager.START_SUCCESS) {
309 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800310 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800311 }
312
313 ActivityRecord sourceRecord = null;
314 ActivityRecord resultRecord = null;
315 if (resultTo != null) {
316 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
317 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
318 "Will send result to " + resultTo + " " + sourceRecord);
319 if (sourceRecord != null) {
320 if (requestCode >= 0 && !sourceRecord.finishing) {
321 resultRecord = sourceRecord;
322 }
323 }
324 }
325
326 final int launchFlags = intent.getFlags();
327
328 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
329 // Transfer the result target from the source activity to the new
330 // one being started, including any failures.
331 if (requestCode >= 0) {
332 ActivityOptions.abort(options);
333 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
334 }
335 resultRecord = sourceRecord.resultTo;
336 if (resultRecord != null && !resultRecord.isInStackLocked()) {
337 resultRecord = null;
338 }
339 resultWho = sourceRecord.resultWho;
340 requestCode = sourceRecord.requestCode;
341 sourceRecord.resultTo = null;
342 if (resultRecord != null) {
343 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
344 }
345 if (sourceRecord.launchedFromUid == callingUid) {
346 // The new activity is being launched from the same uid as the previous
347 // activity in the flow, and asking to forward its result back to the
348 // previous. In this case the activity is serving as a trampoline between
349 // the two, so we also want to update its launchedFromPackage to be the
350 // same as the previous activity. Note that this is safe, since we know
351 // these two packages come from the same uid; the caller could just as
352 // well have supplied that same package name itself. This specifially
353 // deals with the case of an intent picker/chooser being launched in the app
354 // flow to redirect to an activity picked by the user, where we want the final
355 // activity to consider it to have been launched by the previous app activity.
356 callingPackage = sourceRecord.launchedFromPackage;
357 }
358 }
359
360 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
361 // We couldn't find a class that can handle the given Intent.
362 // That's the end of that!
363 err = ActivityManager.START_INTENT_NOT_RESOLVED;
364 }
365
366 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
367 // We couldn't find the specific class specified in the Intent.
368 // Also the end of the line.
369 err = ActivityManager.START_CLASS_NOT_FOUND;
370 }
371
372 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700373 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800374 // If this activity is being launched as part of a voice session, we need
375 // to ensure that it is safe to do so. If the upcoming activity will also
376 // be part of the voice session, we can only launch it if it has explicitly
377 // said it supports the VOICE category, or it is a part of the calling app.
378 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
379 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
380 try {
381 intent.addCategory(Intent.CATEGORY_VOICE);
Bryce Lee93e7f792017-10-25 15:54:55 -0700382 if (!mPackageManager.activitySupportsIntent(
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800383 intent.getComponent(), intent, resolvedType)) {
384 Slog.w(TAG,
385 "Activity being started in current voice task does not support voice: "
386 + intent);
387 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
388 }
389 } catch (RemoteException e) {
390 Slog.w(TAG, "Failure checking voice capabilities", e);
391 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
392 }
393 }
394 }
395
396 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
397 // If the caller is starting a new voice session, just make sure the target
398 // is actually allowing it to run this way.
399 try {
Bryce Lee93e7f792017-10-25 15:54:55 -0700400 if (!mPackageManager.activitySupportsIntent(intent.getComponent(),
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800401 intent, resolvedType)) {
402 Slog.w(TAG,
403 "Activity being started in new voice task does not support: "
404 + intent);
405 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
406 }
407 } catch (RemoteException e) {
408 Slog.w(TAG, "Failure checking voice capabilities", e);
409 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
410 }
411 }
412
Andrii Kulian02b7a832016-10-06 23:11:56 -0700413 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800414
Wale Ogunwale01d66562015-12-29 08:19:19 -0800415 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800416 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800417 resultStack.sendActivityResultLocked(
418 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800419 }
420 ActivityOptions.abort(options);
421 return err;
422 }
423
424 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
425 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100426 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800427 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
428 callingPid, resolvedType, aInfo.applicationInfo);
429
430 if (mService.mController != null) {
431 try {
432 // The Intent we give to the watcher has the extra data
433 // stripped off, since it can contain private information.
434 Intent watchIntent = intent.cloneFilter();
435 abort |= !mService.mController.activityStarting(watchIntent,
436 aInfo.applicationInfo.packageName);
437 } catch (RemoteException e) {
438 mService.mController = null;
439 }
440 }
441
Rubin Xu58d25992016-01-21 17:47:13 +0000442 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Benjamin Franz563707b2017-06-29 15:06:13 +0100443 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
444 callingUid, options)) {
445 // activity start was intercepted, e.g. because the target user is currently in quiet
446 // mode (turn off work) or the target application is suspended
447 intent = mInterceptor.mIntent;
448 rInfo = mInterceptor.mRInfo;
449 aInfo = mInterceptor.mAInfo;
450 resolvedType = mInterceptor.mResolvedType;
451 inTask = mInterceptor.mInTask;
452 callingPid = mInterceptor.mCallingPid;
453 callingUid = mInterceptor.mCallingUid;
454 options = mInterceptor.mActivityOptions;
455 }
456
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800457 if (abort) {
458 if (resultRecord != null) {
459 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800460 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800461 }
462 // We pretend to the caller that it was really started, but
463 // they will just get a cancel result.
464 ActivityOptions.abort(options);
Bryce Leef9d49542017-06-26 16:27:32 -0700465 return START_ABORTED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800466 }
467
468 // If permissions need a review before any of the app components can run, we
469 // launch the review activity and pass a pending intent to start the activity
470 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700471 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800472 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
473 aInfo.packageName, userId)) {
474 IIntentSender target = mService.getIntentSenderLocked(
475 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
476 callingUid, userId, null, null, 0, new Intent[]{intent},
477 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
478 | PendingIntent.FLAG_ONE_SHOT, null);
479
480 final int flags = intent.getFlags();
481 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
482 newIntent.setFlags(flags
483 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
484 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
485 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
486 if (resultRecord != null) {
487 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
488 }
489 intent = newIntent;
490
491 resolvedType = null;
492 callingUid = realCallingUid;
493 callingPid = realCallingPid;
494
495 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
496 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
497 null /*profilerInfo*/);
498
499 if (DEBUG_PERMISSIONS_REVIEW) {
500 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
501 true, false) + "} from uid " + callingUid + " on display "
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700502 + (mSupervisor.mFocusedStack == null
503 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800504 }
505 }
506 }
507
508 // If we have an ephemeral app, abort the process of launching the resolved intent.
509 // Instead, launch the ephemeral installer. Once the installer is finished, it
510 // starts either the intent we resolved here [on install error] or the ephemeral
511 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800512 if (rInfo != null && rInfo.auxiliaryInfo != null) {
513 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700514 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800515 resolvedType = null;
516 callingUid = realCallingUid;
517 callingPid = realCallingPid;
518
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800519 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
520 }
521
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800522 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
523 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
524 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700525 mSupervisor, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800526 if (outActivity != null) {
527 outActivity[0] = r;
528 }
529
530 if (r.appTimeTracker == null && sourceRecord != null) {
531 // If the caller didn't specify an explicit time tracker, we want to continue
532 // tracking under any it has.
533 r.appTimeTracker = sourceRecord.appTimeTracker;
534 }
535
536 final ActivityStack stack = mSupervisor.mFocusedStack;
537 if (voiceSession == null && (stack.mResumedActivity == null
538 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
539 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
540 realCallingPid, realCallingUid, "Activity start")) {
541 PendingActivityLaunch pal = new PendingActivityLaunch(r,
542 sourceRecord, startFlags, stack, callerApp);
543 mPendingActivityLaunches.add(pal);
544 ActivityOptions.abort(options);
545 return ActivityManager.START_SWITCHES_CANCELED;
546 }
547 }
548
549 if (mService.mDidAppSwitch) {
550 // This is the second allowed switch since we stopped switches,
551 // so now just generally allow switches. Use case: user presses
552 // home (switches disabled, switch to home, mDidAppSwitch now true);
553 // user taps a home icon (coming from home so allowed, we hit here
554 // and now allow anyone to switch again).
555 mService.mAppSwitchesAllowedTime = 0;
556 } else {
557 mService.mDidAppSwitch = true;
558 }
559
560 doPendingActivityLaunchesLocked(false);
561
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800562 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
Bryce Lee4a194382017-04-04 14:32:48 -0700563 options, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800564 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800565
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800566 /**
567 * Creates a launch intent for the given auxiliary resolution data.
568 */
Todd Kennedye9910222017-02-21 16:00:11 -0800569 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700570 Intent originalIntent, String callingPackage, Bundle verificationBundle,
571 String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800572 if (auxiliaryResponse.needsPhaseTwo) {
573 // request phase two resolution
574 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700575 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
576 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800577 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700578 return InstantAppResolver.buildEphemeralInstallerIntent(
579 Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
580 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
581 resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
Todd Kennedyd0084f72017-07-28 13:56:14 -0700582 auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
583 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800584 }
585
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700586 void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800587
Bryce Lee7f936862017-05-09 15:33:18 -0700588 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800589 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800590 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800591
Chong Zhang5022da32016-06-21 16:31:37 -0700592 // We're waiting for an activity launch to finish, but that activity simply
593 // brought another activity to front. Let startActivityMayWait() know about
594 // this, so it waits for the new activity to become visible instead.
595 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
596 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
597 }
598
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700599 ActivityStack startedActivityStack = null;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700600 final ActivityStack currentStack = r.getStack();
601 if (currentStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700602 startedActivityStack = currentStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800603 } else if (mTargetStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700604 startedActivityStack = targetStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800605 }
606
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700607 if (startedActivityStack == null) {
608 return;
609 }
610
611 if (startedActivityStack.inSplitScreenPrimaryWindowingMode()) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700612 final ActivityStack homeStack = mSupervisor.mHomeStack;
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700613 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
614 if (homeStackVisible) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100615 // We launch an activity while being in home stack, which means either launcher or
616 // recents into docked stack. We don't want the launched activity to be alone in a
617 // docked stack, so we want to immediately launch recents too.
618 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Bryce Lee7daee392017-10-12 13:46:18 -0700619 mService.mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100620 }
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700621 return;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800622 }
623
Winson Chunge6385a22017-05-02 18:15:16 -0700624 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
Winson Chunge0c3d5d2017-05-04 18:25:21 -0700625 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700626 if (startedActivityStack.inPinnedWindowingMode()
627 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
628 || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800629 // The activity was already running in the pinned stack so it wasn't started, but either
630 // brought to the front or the new intent was delivered to it since it was already in
631 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700632 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
633 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800634 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800635 }
636
637 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800638 mSupervisor.moveHomeStackTaskToTop(reason);
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700639 mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
640 null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
641 null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
642 null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
643 null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
644 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
645 false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700646 null /*inTask*/, "startHomeActivity: " + reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800647 if (mSupervisor.inResumeTopActivity) {
648 // If we are in resume section already, home activity will be initialized, but not
649 // resumed (to avoid recursive resume) and will stay that way until something pokes it
650 // again. We need to schedule another resume.
651 mSupervisor.scheduleResumeTopActivities();
652 }
653 }
654
Robin Lee5d592422017-01-18 13:48:15 +0000655 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100656 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
657 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
658 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000659 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
660 : ActivityOptions.makeBasic());
Bryce Leeaf691c02017-03-20 14:20:22 -0700661 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000662 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100663 }
Tony Mak853304c2016-04-18 15:17:41 +0100664
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800665 final int startActivityMayWait(IApplicationThread caller, int callingUid,
666 String callingPackage, Intent intent, String resolvedType,
667 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
668 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700669 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700670 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700671 TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800672 // Refuse possible leaked file descriptors
673 if (intent != null && intent.hasFileDescriptors()) {
674 throw new IllegalArgumentException("File descriptors passed in Intent");
675 }
Bryce Lee2a3cc462017-10-27 10:57:35 -0700676 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800677 boolean componentSpecified = intent.getComponent() != null;
678
679 // Save a copy in case ephemeral needs it
680 final Intent ephemeralIntent = new Intent(intent);
681 // Don't modify the client's object!
682 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700683 if (componentSpecified
684 && intent.getData() != null
685 && Intent.ACTION_VIEW.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700686 && mService.getPackageManagerInternalLocked()
687 .isInstantAppInstallerComponent(intent.getComponent())) {
688 // intercept intents targeted directly to the ephemeral installer the
689 // ephemeral installer should never be started with a raw URL; instead
690 // adjust the intent so it looks like a "normal" instant app launch
691 intent.setComponent(null /*component*/);
692 componentSpecified = false;
693 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800694
695 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000696 if (rInfo == null) {
697 UserInfo userInfo = mSupervisor.getUserInfo(userId);
698 if (userInfo != null && userInfo.isManagedProfile()) {
699 // Special case for managed profiles, if attempting to launch non-cryto aware
700 // app in a locked managed profile from an unlocked parent allow it to resolve
701 // as user will be sent via confirm credentials to unlock the profile.
702 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700703 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000704 long token = Binder.clearCallingIdentity();
705 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700706 UserInfo parent = userManager.getProfileParent(userId);
707 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
708 && userManager.isUserUnlockingOrUnlocked(parent.id)
709 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000710 } finally {
711 Binder.restoreCallingIdentity(token);
712 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700713 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000714 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600715 PackageManager.MATCH_DIRECT_BOOT_AWARE
716 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000717 }
718 }
719 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800720 // Collect information about the target of the Intent.
721 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
722
723 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800724 synchronized (mService) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800725 final int realCallingPid = Binder.getCallingPid();
726 final int realCallingUid = Binder.getCallingUid();
727 int callingPid;
728 if (callingUid >= 0) {
729 callingPid = -1;
730 } else if (caller == null) {
731 callingPid = realCallingPid;
732 callingUid = realCallingUid;
733 } else {
734 callingPid = callingUid = -1;
735 }
736
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700737 final ActivityStack stack = mSupervisor.mFocusedStack;
Andrii Kulian8072d112016-09-16 11:11:01 -0700738 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700739 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800740 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
741 "Starting activity when config will change = " + stack.mConfigWillChange);
742
743 final long origId = Binder.clearCallingIdentity();
744
745 if (aInfo != null &&
746 (aInfo.applicationInfo.privateFlags
747 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
748 // This may be a heavy-weight process! Check to see if we already
749 // have another, different heavy-weight process running.
750 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
751 final ProcessRecord heavy = mService.mHeavyWeightProcess;
752 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
753 || !heavy.processName.equals(aInfo.processName))) {
754 int appCallingUid = callingUid;
755 if (caller != null) {
756 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
757 if (callerApp != null) {
758 appCallingUid = callerApp.info.uid;
759 } else {
760 Slog.w(TAG, "Unable to find app for caller " + caller
761 + " (pid=" + callingPid + ") when starting: "
762 + intent.toString());
763 ActivityOptions.abort(options);
764 return ActivityManager.START_PERMISSION_DENIED;
765 }
766 }
767
768 IIntentSender target = mService.getIntentSenderLocked(
769 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
770 appCallingUid, userId, null, null, 0, new Intent[] { intent },
771 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
772 | PendingIntent.FLAG_ONE_SHOT, null);
773
774 Intent newIntent = new Intent();
775 if (requestCode >= 0) {
776 // Caller is requesting a result.
777 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
778 }
779 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
780 new IntentSender(target));
781 if (heavy.activities.size() > 0) {
782 ActivityRecord hist = heavy.activities.get(0);
783 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
784 hist.packageName);
785 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -0700786 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800787 }
788 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
789 aInfo.packageName);
790 newIntent.setFlags(intent.getFlags());
791 newIntent.setClassName("android",
792 HeavyWeightSwitcherActivity.class.getName());
793 intent = newIntent;
794 resolvedType = null;
795 caller = null;
796 callingUid = Binder.getCallingUid();
797 callingPid = Binder.getCallingPid();
798 componentSpecified = true;
799 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
800 aInfo = rInfo != null ? rInfo.activityInfo : null;
801 if (aInfo != null) {
802 aInfo = mService.getActivityInfoForUser(aInfo, userId);
803 }
804 }
805 }
806 }
807
Jorim Jaggi275561a2016-02-23 10:11:02 -0500808 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800809 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
810 aInfo, rInfo, voiceSession, voiceInteractor,
811 resultTo, resultWho, requestCode, callingPid,
812 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700813 options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
814 reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800815
816 Binder.restoreCallingIdentity(origId);
817
818 if (stack.mConfigWillChange) {
819 // If the caller also wants to switch to a new configuration,
820 // do so now. This allows a clean switch, as we are waiting
821 // for the current activity to pause (so we will not destroy
822 // it), and have not yet started the next activity.
823 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
824 "updateConfiguration()");
825 stack.mConfigWillChange = false;
826 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
827 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700828 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800829 }
830
831 if (outResult != null) {
832 outResult.result = res;
833 if (res == ActivityManager.START_SUCCESS) {
834 mSupervisor.mWaitingActivityLaunched.add(outResult);
835 do {
836 try {
837 mService.wait();
838 } catch (InterruptedException e) {
839 }
Chong Zhang5022da32016-06-21 16:31:37 -0700840 } while (outResult.result != START_TASK_TO_FRONT
841 && !outResult.timeout && outResult.who == null);
842 if (outResult.result == START_TASK_TO_FRONT) {
843 res = START_TASK_TO_FRONT;
844 }
845 }
846 if (res == START_TASK_TO_FRONT) {
Bryce Lee4a194382017-04-04 14:32:48 -0700847 final ActivityRecord r = outRecord[0];
848
849 // ActivityRecord may represent a different activity, but it should not be in
850 // the resumed state.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800851 if (r.nowVisible && r.state == RESUMED) {
852 outResult.timeout = false;
Bryce Lee4a194382017-04-04 14:32:48 -0700853 outResult.who = r.realActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800854 outResult.totalTime = 0;
855 outResult.thisTime = 0;
856 } else {
857 outResult.thisTime = SystemClock.uptimeMillis();
Bryce Lee4a194382017-04-04 14:32:48 -0700858 mSupervisor.waitActivityVisible(r.realActivity, outResult);
859 // Note: the timeout variable is not currently not ever set.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800860 do {
861 try {
862 mService.wait();
863 } catch (InterruptedException e) {
864 }
865 } while (!outResult.timeout && outResult.who == null);
866 }
867 }
868 }
869
Bryce Lee2a3cc462017-10-27 10:57:35 -0700870 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800871 return res;
872 }
873 }
874
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800875 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
876 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700877 Bundle bOptions, int userId, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800878 if (intents == null) {
879 throw new NullPointerException("intents is null");
880 }
881 if (resolvedTypes == null) {
882 throw new NullPointerException("resolvedTypes is null");
883 }
884 if (intents.length != resolvedTypes.length) {
885 throw new IllegalArgumentException("intents are length different than resolvedTypes");
886 }
887
Makoto Onukid67b1872016-07-21 16:26:36 -0700888 final int realCallingPid = Binder.getCallingPid();
889 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800890
891 int callingPid;
892 if (callingUid >= 0) {
893 callingPid = -1;
894 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700895 callingPid = realCallingPid;
896 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800897 } else {
898 callingPid = callingUid = -1;
899 }
900 final long origId = Binder.clearCallingIdentity();
901 try {
902 synchronized (mService) {
903 ActivityRecord[] outActivity = new ActivityRecord[1];
904 for (int i=0; i<intents.length; i++) {
905 Intent intent = intents[i];
906 if (intent == null) {
907 continue;
908 }
909
910 // Refuse possible leaked file descriptors
911 if (intent != null && intent.hasFileDescriptors()) {
912 throw new IllegalArgumentException("File descriptors passed in Intent");
913 }
914
915 boolean componentSpecified = intent.getComponent() != null;
916
917 // Don't modify the client's object!
918 intent = new Intent(intent);
919
920 // Collect information about the target of the Intent.
921 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
922 null, userId);
923 // TODO: New, check if this is correct
924 aInfo = mService.getActivityInfoForUser(aInfo, userId);
925
926 if (aInfo != null &&
927 (aInfo.applicationInfo.privateFlags
928 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
929 throw new IllegalArgumentException(
930 "FLAG_CANT_SAVE_STATE not supported here");
931 }
932
933 ActivityOptions options = ActivityOptions.fromBundle(
934 i == intents.length - 1 ? bOptions : null);
935 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
936 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700937 callingPid, callingUid, callingPackage,
938 realCallingPid, realCallingUid, 0,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700939 options, false, componentSpecified, outActivity, null, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800940 if (res < 0) {
941 return res;
942 }
943
944 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
945 }
946 }
947 } finally {
948 Binder.restoreCallingIdentity(origId);
949 }
950
Wale Ogunwale01d66562015-12-29 08:19:19 -0800951 return START_SUCCESS;
952 }
953
Bryce Lee28d80422017-07-21 13:25:13 -0700954 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
Bryce Lee834abec2017-01-09 16:18:14 -0800955 boolean sendHint = forceSend;
956
957 if (!sendHint) {
958 // If not forced, send power hint when the activity's process is different than the
959 // current resumed activity.
960 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
961 sendHint = resumedActivity == null
962 || resumedActivity.app == null
Bryce Lee28d80422017-07-21 13:25:13 -0700963 || !resumedActivity.app.equals(targetActivity.app);
Bryce Lee834abec2017-01-09 16:18:14 -0800964 }
965
966 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700967 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700968 mPowerHintSent = true;
969 }
970 }
971
Wei Wang65c7a152016-06-02 18:51:22 -0700972 void sendPowerHintForLaunchEndIfNeeded() {
973 // Trigger launch power hint if activity is launched
974 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700975 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700976 mPowerHintSent = false;
977 }
978 }
979
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800980 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
981 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700982 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
983 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800984 int result = START_CANCELED;
985 try {
986 mService.mWindowManager.deferSurfaceLayout();
987 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700988 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800989 } finally {
990 // If we are not able to proceed, disassociate the activity from the task. Leaving an
991 // activity in an incomplete state can lead to issues, such as performing operations
992 // without a window container.
Bryce Leea3b0e3f02017-05-17 16:45:36 -0700993 if (!ActivityManager.isStartResultSuccessful(result)
Bryce Lee7f936862017-05-09 15:33:18 -0700994 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700995 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800996 }
997 mService.mWindowManager.continueSurfaceLayout();
998 }
999
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001000 postStartActivityProcessing(r, result, mTargetStack);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001001
1002 return result;
1003 }
1004
1005 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001006 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1007 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001008 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1009 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001010
1011 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1012 voiceInteractor);
1013
1014 computeLaunchingTaskFlags();
1015
1016 computeSourceStack();
1017
1018 mIntent.setFlags(mLaunchFlags);
1019
Bryce Lee4a194382017-04-04 14:32:48 -07001020 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001021
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001022 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1023 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1024 if (mOptions != null) {
1025 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1026 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1027 }
Jorim Jaggi2adba072016-03-03 13:43:39 +01001028
Bryce Lee4a194382017-04-04 14:32:48 -07001029 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001030 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1031 // still needs to be a lock task mode violation since the task gets cleared out and
1032 // the device would otherwise leave the locked task.
Benjamin Franza83859f2017-07-03 16:34:14 +01001033 if (mService.mLockTaskController.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001034 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1035 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001036 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1037 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1038 }
1039
Bryce Leeaf691c02017-03-20 14:20:22 -07001040 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001041 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001042 }
Bryce Lee4a194382017-04-04 14:32:48 -07001043 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001044 // This task was started because of movement of the activity based on affinity...
1045 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001046 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001047 }
1048
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001049 // This code path leads to delivering a new intent, we want to make sure we schedule it
1050 // as the first operation, in case the activity will be resumed as a result of later
1051 // operations.
1052 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001053 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Bryce Lee7daee392017-10-12 13:46:18 -07001054 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Lee4a194382017-04-04 14:32:48 -07001055 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001056
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001057 // In this situation we want to remove all activities from the task up to the one
1058 // being started. In most cases this means we are resetting the task to its initial
1059 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001060 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1061 mLaunchFlags);
1062
Bryce Lee4a194382017-04-04 14:32:48 -07001063 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001064 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1065 // task reference is needed in the call below to
1066 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001067 if (reusedActivity.getTask() == null) {
1068 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001069 }
1070
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001071 if (top != null) {
1072 if (top.frontOfTask) {
1073 // Activity aliases may mean we use different intents for the top activity,
1074 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001075 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001076 }
Bryce Lee325e09682017-10-05 17:20:25 -07001077 deliverNewIntent(top);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001078 }
1079 }
1080
Bryce Lee28d80422017-07-21 13:25:13 -07001081 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001082
Bryce Lee4a194382017-04-04 14:32:48 -07001083 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001084
Bryce Lee89cd19a2017-05-17 15:18:35 -07001085 final ActivityRecord outResult =
1086 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1087
1088 // When there is a reused activity and the current result is a trampoline activity,
1089 // set the reused activity as the result.
1090 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1091 outActivity[0] = reusedActivity;
1092 }
1093
Wale Ogunwale01d66562015-12-29 08:19:19 -08001094 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1095 // We don't need to start a new activity, and the client said not to do anything
1096 // if that is the case, so this is it! And for paranoia, make sure we have
1097 // correctly resumed the top activity.
1098 resumeTargetStackIfNeeded();
1099 return START_RETURN_INTENT_TO_CALLER;
1100 }
Bryce Lee4a194382017-04-04 14:32:48 -07001101 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001102
1103 if (!mAddingToTask && mReuseTask == null) {
1104 // We didn't do anything... but it was needed (a.k.a., client don't use that
1105 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1106 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001107 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001108 outActivity[0] = reusedActivity;
1109 }
Bryce Lee28d80422017-07-21 13:25:13 -07001110
Wale Ogunwale01d66562015-12-29 08:19:19 -08001111 return START_TASK_TO_FRONT;
1112 }
1113 }
1114
1115 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001116 final ActivityStack sourceStack = mStartActivity.resultTo != null
1117 ? mStartActivity.resultTo.getStack() : null;
1118 if (sourceStack != null) {
1119 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1120 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1121 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001122 }
1123 ActivityOptions.abort(mOptions);
1124 return START_CLASS_NOT_FOUND;
1125 }
1126
1127 // If the activity being launched is the same as the one currently at the top, then
1128 // we need to check if it should only be launched once.
1129 final ActivityStack topStack = mSupervisor.mFocusedStack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001130 final ActivityRecord topFocused = topStack.getTopActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001131 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1132 final boolean dontStart = top != null && mStartActivity.resultTo == null
1133 && top.realActivity.equals(mStartActivity.realActivity)
1134 && top.userId == mStartActivity.userId
1135 && top.app != null && top.app.thread != null
1136 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001137 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001138 if (dontStart) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001139 // For paranoia, make sure we have correctly resumed the top activity.
1140 topStack.mLastPausedActivity = null;
1141 if (mDoResume) {
1142 mSupervisor.resumeFocusedStackTopActivityLocked();
1143 }
1144 ActivityOptions.abort(mOptions);
1145 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1146 // We don't need to start a new activity, and the client said not to do
1147 // anything if that is the case, so this is it!
1148 return START_RETURN_INTENT_TO_CALLER;
1149 }
Bryce Lee325e09682017-10-05 17:20:25 -07001150
1151 deliverNewIntent(top);
Chong Zhangd44063c2016-04-08 11:52:30 -07001152
1153 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1154 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001155 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001156 preferredLaunchDisplayId, topStack);
Chong Zhangd44063c2016-04-08 11:52:30 -07001157
Wale Ogunwale01d66562015-12-29 08:19:19 -08001158 return START_DELIVERED_TO_TOP;
1159 }
1160
1161 boolean newTask = false;
1162 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001163 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001164
1165 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001166 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001167 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1168 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1169 newTask = true;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001170 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001171 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001172 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001173 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001174 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001175 } else {
1176 // This not being started from an existing activity, and not part of a new task...
1177 // just put it in the top task, though these days this case should never happen.
1178 setTaskToCurrentTopOrCreateNewTask();
1179 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001180 if (result != START_SUCCESS) {
1181 return result;
1182 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001183
1184 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1185 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001186 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1187 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001188 if (newTask) {
Wale Ogunwale66e16852017-10-19 13:35:52 -07001189 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
Bryce Leeaf691c02017-03-20 14:20:22 -07001190 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001191 }
1192 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001193 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001194 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001195
Bryce Lee28d80422017-07-21 13:25:13 -07001196 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001197
Winson Chungb5c41b72016-12-07 15:00:47 -08001198 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1199 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001200 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001201 final ActivityRecord topTaskActivity =
1202 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001203 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001204 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1205 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001206 // If the activity is not focusable, we can't resume it, but still would like to
1207 // make sure it becomes visible as it starts (this will also trigger entry
1208 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001209 // Also, we don't want to resume activities in a task that currently has an overlay
1210 // as the starting activity just needs to be in the visible paused state until the
1211 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001212 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001213 // Go ahead and tell window manager to execute app transition for this activity
1214 // since the app transition will not be triggered through the resume channel.
Bryce Lee7daee392017-10-12 13:46:18 -07001215 mService.mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001216 } else {
Winson Chung32066032016-11-04 11:55:21 -07001217 // If the target stack was not previously focusable (previous top running activity
1218 // on that stack was not visible) then any prior calls to move the stack to the
1219 // will not update the focused stack. If starting the new activity now allows the
1220 // task stack to be focusable, then ensure that we now update the focused stack
1221 // accordingly.
1222 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1223 mTargetStack.moveToFront("startActivityUnchecked");
1224 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001225 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1226 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001227 }
Winson Chung1dbc8112017-09-28 18:05:31 -07001228 } else if (mStartActivity != null) {
1229 mSupervisor.mRecentTasks.add(mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001230 }
1231 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1232
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001233 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001234 preferredLaunchDisplayId, mTargetStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001235
1236 return START_SUCCESS;
1237 }
1238
1239 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1240 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1241 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1242 reset();
1243
1244 mStartActivity = r;
1245 mIntent = r.intent;
1246 mOptions = options;
1247 mCallingUid = r.launchedFromUid;
1248 mSourceRecord = sourceRecord;
1249 mVoiceSession = voiceSession;
1250 mVoiceInteractor = voiceInteractor;
1251
David Stevense5a7b642017-05-22 13:18:23 -07001252 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
David Stevensc6b91c62017-02-08 14:23:58 -08001253
Bryce Leedacefc42017-10-10 12:56:02 -07001254 mLaunchBounds.setEmpty();
1255
1256 mSupervisor.getLaunchingBoundsController().calculateBounds(inTask, null /*layout*/, r,
Bryce Leee4ad7452017-10-26 08:44:04 -07001257 sourceRecord, options, mLaunchBounds);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001258
Bryce Lee7daee392017-10-12 13:46:18 -07001259 mLaunchMode = r.launchMode;
1260
Wale Ogunwale01d66562015-12-29 08:19:19 -08001261 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
Bryce Lee7daee392017-10-12 13:46:18 -07001262 r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1263 LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001264 mLaunchTaskBehind = r.mLaunchTaskBehind
Bryce Lee7daee392017-10-12 13:46:18 -07001265 && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001266 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1267
1268 sendNewTaskResultRequestIfNeeded();
1269
1270 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1271 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1272 }
1273
1274 // If we are actually going to launch in to a new task, there are some cases where
1275 // we further want to do multiple task.
1276 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1277 if (mLaunchTaskBehind
1278 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1279 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1280 }
1281 }
1282
1283 // We'll invoke onUserLeaving before onPause only if the launching
1284 // activity did not explicitly state that this is an automated launch.
1285 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1286 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1287 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1288
1289 // If the caller has asked not to resume at this point, we make note
1290 // of this in the record so that we can skip it when trying to find
1291 // the top running activity.
1292 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001293 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001294 r.delayedResume = true;
1295 mDoResume = false;
1296 }
1297
Winson Chungcbcadc92017-01-12 15:54:12 -08001298 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1299 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001300 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001301 if (!mOptions.canTaskOverlayResume()) {
1302 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1303 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1304 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001305
Winson Chungcbcadc92017-01-12 15:54:12 -08001306 // The caller specifies that we'd like to be avoided to be moved to the front,
1307 // so be it!
1308 mDoResume = false;
1309 mAvoidMoveToFront = true;
1310 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001311 }
1312 }
1313
Wale Ogunwale01d66562015-12-29 08:19:19 -08001314 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1315
1316 mInTask = inTask;
1317 // In some flows in to this function, we retrieve the task record and hold on to it
1318 // without a lock before calling back in to here... so the task at this point may
1319 // not actually be in recents. Check for that, and if it isn't in recents just
1320 // consider it invalid.
1321 if (inTask != null && !inTask.inRecents) {
1322 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1323 mInTask = null;
1324 }
1325
1326 mStartFlags = startFlags;
1327 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1328 // is the same as the one making the call... or, as a special case, if we do not know
1329 // the caller then we count the current top activity as the caller.
1330 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1331 ActivityRecord checkedCaller = sourceRecord;
1332 if (checkedCaller == null) {
1333 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1334 mNotTop);
1335 }
1336 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1337 // Caller is not the same as launcher, so always needed.
1338 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1339 }
1340 }
1341
1342 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1343 }
1344
1345 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001346 final ActivityStack sourceStack = mStartActivity.resultTo != null
1347 ? mStartActivity.resultTo.getStack() : null;
1348 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001349 // For whatever reason this activity is being launched into a new task...
1350 // yet the caller has requested a result back. Well, that is pretty messed up,
1351 // so instead immediately send back a cancel and let the new task continue launched
1352 // as normal without a dependency on its originator.
1353 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001354 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1355 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1356 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001357 mStartActivity.resultTo = null;
1358 }
1359 }
1360
1361 private void computeLaunchingTaskFlags() {
1362 // If the caller is not coming from another activity, but has given us an explicit task into
1363 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001364 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001365 final Intent baseIntent = mInTask.getBaseIntent();
1366 final ActivityRecord root = mInTask.getRootActivity();
1367 if (baseIntent == null) {
1368 ActivityOptions.abort(mOptions);
1369 throw new IllegalArgumentException("Launching into task without base intent: "
1370 + mInTask);
1371 }
1372
1373 // If this task is empty, then we are adding the first activity -- it
1374 // determines the root, and must be launching as a NEW_TASK.
Bryce Lee7daee392017-10-12 13:46:18 -07001375 if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001376 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1377 ActivityOptions.abort(mOptions);
1378 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1379 + mStartActivity + " into different task " + mInTask);
1380 }
1381 if (root != null) {
1382 ActivityOptions.abort(mOptions);
1383 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1384 + " has root " + root + " but target is singleInstance/Task");
1385 }
1386 }
1387
1388 // If task is empty, then adopt the interesting intent launch flags in to the
1389 // activity being started.
1390 if (root == null) {
1391 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1392 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1393 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1394 | (baseIntent.getFlags() & flagsOfInterest);
1395 mIntent.setFlags(mLaunchFlags);
1396 mInTask.setIntent(mStartActivity);
1397 mAddingToTask = true;
1398
1399 // If the task is not empty and the caller is asking to start it as the root of
1400 // a new task, then we don't actually want to start this on the task. We will
1401 // bring the task to the front, and possibly give it a new intent.
1402 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1403 mAddingToTask = false;
1404
1405 } else {
1406 mAddingToTask = true;
1407 }
1408
1409 mReuseTask = mInTask;
1410 } else {
1411 mInTask = null;
1412 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1413 // when in freeform workspace.
1414 // Also put noDisplay activities in the source task. These by itself can be placed
1415 // in any task/stack, however it could launch other activities like ResolverActivity,
1416 // and we want those to stay in the original task.
1417 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001418 && mSourceRecord.inFreeformWindowingMode()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001419 mAddingToTask = true;
1420 }
1421 }
1422
1423 if (mInTask == null) {
1424 if (mSourceRecord == null) {
1425 // This activity is not being started from another... in this
1426 // case we -always- start a new task.
1427 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1428 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1429 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1430 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1431 }
1432 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1433 // The original activity who is starting us is running as a single
1434 // instance... this new activity it is starting must go on its
1435 // own task.
1436 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
Bryce Lee7daee392017-10-12 13:46:18 -07001437 } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001438 // The activity being started is a single instance... it always
1439 // gets launched into its own task.
1440 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1441 }
1442 }
1443 }
1444
1445 private void computeSourceStack() {
1446 if (mSourceRecord == null) {
1447 mSourceStack = null;
1448 return;
1449 }
1450 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001451 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001452 return;
1453 }
1454
1455 // If the source is finishing, we can't further count it as our source. This is because the
1456 // task it is associated with may now be empty and on its way out, so we don't want to
1457 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1458 // a task for it. But save the task information so it can be used when creating the new task.
1459 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1460 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1461 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1462 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1463 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001464
1465 // It is not guaranteed that the source record will have a task associated with it. For,
1466 // example, if this method is being called for processing a pending activity launch, it
1467 // is possible that the activity has been removed from the task after the launch was
1468 // enqueued.
1469 final TaskRecord sourceTask = mSourceRecord.getTask();
1470 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001471 }
1472 mSourceRecord = null;
1473 mSourceStack = null;
1474 }
1475
1476 /**
1477 * Decide whether the new activity should be inserted into an existing task. Returns null
1478 * if not or an ActivityRecord with the task into which the new activity should be added.
1479 */
1480 private ActivityRecord getReusableIntentActivity() {
1481 // We may want to try to place the new activity in to an existing task. We always
1482 // do this if the target activity is singleTask or singleInstance; we will also do
1483 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1484 // us to still place it in a new task: multi task, always doc mode, or being asked to
1485 // launch this as a new task behind the current one.
1486 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1487 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
Bryce Lee7daee392017-10-12 13:46:18 -07001488 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001489 // If bring to front is requested, and no result is requested and we have not been given
1490 // an explicit task to launch in to, and we can find a task that was started with this
1491 // same component, then instead of launching bring that one to the front.
1492 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1493 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001494 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1495 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1496 intentActivity = task != null ? task.getTopActivity() : null;
1497 } else if (putIntoExistingTask) {
Bryce Lee7daee392017-10-12 13:46:18 -07001498 if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001499 // There can be one and only one instance of single instance activity in the
1500 // history, and it is always in its own unique task, so we do a special search.
Bryce Lee28d80422017-07-21 13:25:13 -07001501 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001502 mStartActivity.isActivityTypeHome());
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001503 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1504 // For the launch adjacent case we only want to put the activity in an existing
1505 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001506 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Bryce Lee7daee392017-10-12 13:46:18 -07001507 !(LAUNCH_SINGLE_TASK == mLaunchMode));
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001508 } else {
1509 // Otherwise find the best task to put the activity in.
David Stevense5a7b642017-05-22 13:18:23 -07001510 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001511 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001512 }
1513 return intentActivity;
1514 }
1515
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001516 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001517 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
David Stevense5a7b642017-05-22 13:18:23 -07001518 * then return the Vr mode's virtual display ID. If not, if the activity was started with
1519 * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1520 * set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001521 */
David Stevense5a7b642017-05-22 13:18:23 -07001522 private int getPreferedDisplayId(
1523 ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001524 // Check if the Activity is a VR activity. If so, the activity should be launched in
1525 // main display.
1526 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1527 return DEFAULT_DISPLAY;
1528 }
1529
1530 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001531 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001532 if (displayId != INVALID_DISPLAY) {
1533 if (DEBUG_STACK) {
1534 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1535 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001536 return displayId;
1537 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001538
David Stevense5a7b642017-05-22 13:18:23 -07001539 // If the caller requested a display, prefer that display.
1540 final int launchDisplayId =
1541 (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1542 if (launchDisplayId != INVALID_DISPLAY) {
1543 return launchDisplayId;
1544 }
1545
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001546 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1547 // If the activity has a displayId set explicitly, launch it on the same displayId.
1548 if (displayId != INVALID_DISPLAY) {
1549 return displayId;
1550 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001551 return DEFAULT_DISPLAY;
1552 }
1553
1554 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001555 * Figure out which task and activity to bring to front when we have found an existing matching
1556 * activity record in history. May also clear the task if needed.
1557 * @param intentActivity Existing matching activity.
1558 * @return {@link ActivityRecord} brought to front.
1559 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001560 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001561 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001562 mTargetStack.mLastPausedActivity = null;
1563 // If the target task is not in the front, then we need to bring it to the front...
1564 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1565 // the same behavior as if a new instance was being started, which means not bringing it
1566 // to the front if the caller is not itself in the front.
1567 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1568 ActivityRecord curTop = (focusStack == null)
1569 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1570
Bryce Leeaf691c02017-03-20 14:20:22 -07001571 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1572 if (topTask != null
1573 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001574 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001575 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001576 if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1577 mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001578 // We really do want to push this one into the user's face, right now.
1579 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001580 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001581 }
Chong Zhangdea4bd92016-03-15 12:50:03 -07001582
1583 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1584 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1585 // So no point resuming any of the activities here, it just wastes one extra
1586 // resuming, plus enter AND exit transitions.
1587 // Here we only want to bring the target stack forward. Transition will be applied
1588 // to the new activity that's started after the old ones are gone.
1589 final boolean willClearTask =
1590 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1591 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1592 if (!willClearTask) {
1593 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001594 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1595 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001596 if (launchStack == null || launchStack == mTargetStack) {
1597 // We only want to move to the front, if we aren't going to launch on a
1598 // different stack. If we launch on a different stack, we will put the
1599 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001600 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001601 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1602 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001603 } else if (launchStack.inSplitScreenWindowingMode()) {
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001604 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1605 // If we want to launch adjacent and mTargetStack is not the computed
1606 // launch stack - move task to top of computed stack.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001607 intentTask.reparent(launchStack, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001608 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1609 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001610 } else {
1611 // TODO: This should be reevaluated in MW v2.
1612 // We choose to move task to front instead of launching it adjacent
1613 // when specific stack was requested explicitly and it appeared to be
1614 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001615 mTargetStack.moveTaskToFrontLocked(intentTask,
1616 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001617 "bringToFrontInsteadOfAdjacentLaunch");
1618 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001619 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001620 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1621 // Target and computed stacks are on different displays and we've
1622 // found a matching task - move the existing instance to that display and
1623 // move it to front.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001624 intentActivity.getTask().reparent(launchStack, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001625 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1626 "reparentToDisplay");
1627 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001628 } else if (launchStack.isActivityTypeHome()
1629 && !mTargetStack.isActivityTypeHome()) {
Bryce Lee4ff7da92017-07-17 10:39:24 -07001630 // It is possible for the home activity to be in another stack initially.
1631 // For example, the activity may have been initially started with an intent
1632 // which placed it in the fullscreen stack. To ensure the proper handling of
1633 // the activity based on home stack assumptions, we must move it over.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001634 intentActivity.getTask().reparent(launchStack, ON_TOP,
Bryce Lee4ff7da92017-07-17 10:39:24 -07001635 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1636 "reparentingHome");
1637 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001638 }
1639 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001640
1641 // We are moving a task to the front, use starting window to hide initial drawn
1642 // delay.
1643 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1644 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001645 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001646 }
1647 }
1648 if (!mMovedToFront && mDoResume) {
1649 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1650 + " from " + intentActivity);
1651 mTargetStack.moveToFront("intentActivityFound");
1652 }
1653
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001654 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001655 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001656
Wale Ogunwale01d66562015-12-29 08:19:19 -08001657 // If the caller has requested that the target task be reset, then do so.
1658 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1659 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1660 }
1661 return intentActivity;
1662 }
1663
1664 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1665 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1666 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1667 // The caller has requested to completely replace any existing task with its new
1668 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001669 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1670 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001671 // of history or if it is finished immediately), thus disassociating the task. Also note
1672 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1673 // launching another activity.
1674 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1675 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001676 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001677 task.performClearTaskLocked();
1678 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001679 mReuseTask.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001680 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001681 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001682 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001683 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001684 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001685 // A special case: we need to start the activity because it is not currently
1686 // running, and the caller has asked to clear the current task to have this
1687 // activity at the top.
1688 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001689
1690 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001691 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001692 // Now pretend like this activity is being started by the top of its task, so it
1693 // is put in the right place.
1694 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001695 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001696 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001697 // Target stack got cleared when we all activities were removed above.
1698 // Go ahead and reset it.
1699 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
Bryce Leedacefc42017-10-10 12:56:02 -07001700 mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001701 mTargetStack.addTask(task,
1702 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1703 }
1704 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001705 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001706 // In this case the top activity on the task is the same as the one being launched,
1707 // so we take that as a request to bring the task to the foreground. If the top
1708 // activity in the task is the root activity, deliver this new intent to it if it
1709 // desires.
Bryce Lee7daee392017-10-12 13:46:18 -07001710 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1711 || LAUNCH_SINGLE_TOP == mLaunchMode)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001712 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001713 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001714 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001715 }
Bryce Lee325e09682017-10-05 17:20:25 -07001716 deliverNewIntent(intentActivity);
Bryce Leeaf691c02017-03-20 14:20:22 -07001717 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001718 // In this case we are launching the root activity of the task, but with a
1719 // different intent. We should start a new instance on top.
1720 mAddingToTask = true;
1721 mSourceRecord = intentActivity;
1722 }
1723 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1724 // In this case an activity is being launched in to an existing task, without
1725 // resetting that task. This is typically the situation of launching an activity
1726 // from a notification or shortcut. We want to place the new activity on top of the
1727 // current task.
1728 mAddingToTask = true;
1729 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001730 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001731 // In this case we are launching into an existing task that has not yet been started
1732 // from its front door. The current task has been brought to the front. Ideally,
1733 // we'd probably like to place this new task at the bottom of its stack, but that's
1734 // a little hard to do with the current organization of the code so for now we'll
1735 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001736 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001737 }
1738 }
1739
1740 private void resumeTargetStackIfNeeded() {
1741 if (mDoResume) {
1742 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001743 } else {
1744 ActivityOptions.abort(mOptions);
1745 }
1746 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1747 }
1748
Chong Zhang6cda19c2016-06-14 19:07:56 -07001749 private int setTaskFromReuseOrCreateNewTask(
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001750 TaskRecord taskToAffiliate, ActivityStack topStack) {
Bryce Leedacefc42017-10-10 12:56:02 -07001751 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
Chong Zhang6cda19c2016-06-14 19:07:56 -07001752
1753 // Do no move the target stack to front yet, as we might bail if
1754 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001755
1756 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001757 final TaskRecord task = mTargetStack.createTaskRecord(
1758 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001759 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001760 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001761 mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001762 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001763 updateBounds(mStartActivity.getTask(), mLaunchBounds);
1764
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001765 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001766 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001767 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001768 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1769 }
1770
1771 if (taskToAffiliate != null) {
1772 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001773 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001774
Benjamin Franza83859f2017-07-03 16:34:14 +01001775 if (mService.mLockTaskController.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001776 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1777 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1778 }
1779
Chong Zhang6cda19c2016-06-14 19:07:56 -07001780 if (mDoResume) {
1781 mTargetStack.moveToFront("reuseOrNewTask");
1782 }
1783 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001784 }
1785
Bryce Lee325e09682017-10-05 17:20:25 -07001786 private void deliverNewIntent(ActivityRecord activity) {
1787 if (mIntentDelivered) {
1788 return;
1789 }
1790
1791 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
1792 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1793 mStartActivity.launchedFromPackage);
1794 mIntentDelivered = true;
1795 }
1796
Wale Ogunwale01d66562015-12-29 08:19:19 -08001797 private int setTaskFromSourceRecord() {
Benjamin Franza83859f2017-07-03 16:34:14 +01001798 if (mService.mLockTaskController.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001799 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1800 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1801 }
1802
Bryce Leeaf691c02017-03-20 14:20:22 -07001803 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001804 final ActivityStack sourceStack = mSourceRecord.getStack();
Andrii Kulian02689a72017-07-06 14:28:59 -07001805 // We only want to allow changing stack in two cases:
1806 // 1. If the target task is not the top one. Otherwise we would move the launching task to
1807 // the other side, rather than show two side by side.
1808 // 2. If activity is not allowed on target display.
1809 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
1810 : sourceStack.mDisplayId;
1811 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
1812 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001813 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001814 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001815 mOptions);
Andrii Kulian02689a72017-07-06 14:28:59 -07001816 // If target stack is not found now - we can't just rely on the source stack, as it may
1817 // be not suitable. Let's check other displays.
1818 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
1819 // Can't use target display, lets find a stack on the source display.
1820 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
1821 sourceStack.mDisplayId, mStartActivity);
1822 }
1823 if (mTargetStack == null) {
1824 // There are no suitable stacks on the target and source display(s). Look on all
1825 // displays.
1826 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
1827 mStartActivity, -1 /* currentFocus */);
1828 }
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001829 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001830
1831 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001832 mTargetStack = sourceStack;
1833 } else if (mTargetStack != sourceStack) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001834 sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
1835 DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001836 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001837
Wale Ogunwale01d66562015-12-29 08:19:19 -08001838 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001839 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001840 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1841 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001842 } else if (mDoResume) {
1843 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001844 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001845
Wale Ogunwale01d66562015-12-29 08:19:19 -08001846 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1847 // In this case, we are adding the activity to an existing task, but the caller has
1848 // asked to clear that task if the activity is already running.
1849 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1850 mKeepCurTransition = true;
1851 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001852 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Bryce Lee325e09682017-10-05 17:20:25 -07001853 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001854 // For paranoia, make sure we have correctly resumed the top activity.
1855 mTargetStack.mLastPausedActivity = null;
1856 if (mDoResume) {
1857 mSupervisor.resumeFocusedStackTopActivityLocked();
1858 }
1859 ActivityOptions.abort(mOptions);
1860 return START_DELIVERED_TO_TOP;
1861 }
1862 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1863 // In this case, we are launching an activity in our own task that may already be
1864 // running somewhere in the history, and we want to shuffle it to the front of the
1865 // stack if so.
1866 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1867 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001868 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001869 task.moveActivityToFrontLocked(top);
1870 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001871 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Bryce Lee325e09682017-10-05 17:20:25 -07001872 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001873 mTargetStack.mLastPausedActivity = null;
1874 if (mDoResume) {
1875 mSupervisor.resumeFocusedStackTopActivityLocked();
1876 }
1877 return START_DELIVERED_TO_TOP;
1878 }
1879 }
1880
1881 // An existing activity is starting this new activity, so we want to keep the new one in
1882 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001883 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001884 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001885 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001886 return START_SUCCESS;
1887 }
1888
1889 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001890 // The caller is asking that the new activity be started in an explicit
1891 // task it has provided to us.
Benjamin Franza83859f2017-07-03 16:34:14 +01001892 if (mService.mLockTaskController.isLockTaskModeViolation(mInTask)) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001893 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1894 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1895 }
1896
Andrii Kulian02b7a832016-10-06 23:11:56 -07001897 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001898
1899 // Check whether we should actually launch the new activity in to the task,
1900 // or just reuse the current activity on top.
1901 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001902 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1903 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001904 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001905 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
Yorke Lee64512522017-03-24 13:09:35 -07001906 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1907 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001908 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1909 // We don't need to start a new activity, and the client said not to do
1910 // anything if that is the case, so this is it!
1911 return START_RETURN_INTENT_TO_CALLER;
1912 }
Bryce Lee325e09682017-10-05 17:20:25 -07001913 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001914 return START_DELIVERED_TO_TOP;
1915 }
1916 }
1917
1918 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001919 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1920 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001921 // We don't actually want to have this activity added to the task, so just
1922 // stop here but still tell the caller that we consumed the intent.
1923 ActivityOptions.abort(mOptions);
1924 return START_TASK_TO_FRONT;
1925 }
1926
Bryce Leedacefc42017-10-10 12:56:02 -07001927 if (!mLaunchBounds.isEmpty()) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001928 // TODO: Shouldn't we already know what stack to use by the time we get here?
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001929 ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
1930 if (stack != mInTask.getStack()) {
1931 mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
Yorke Lee64512522017-03-24 13:09:35 -07001932 DEFER_RESUME, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07001933 mTargetStack = mInTask.getStack();
1934 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001935
1936 updateBounds(mInTask, mLaunchBounds);
Yorke Lee64512522017-03-24 13:09:35 -07001937 }
1938
1939 mTargetStack.moveTaskToFrontLocked(
1940 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1941
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001942 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1943 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001944 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001945
1946 return START_SUCCESS;
1947 }
1948
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001949 void updateBounds(TaskRecord task, Rect bounds) {
Bryce Leedacefc42017-10-10 12:56:02 -07001950 if (bounds.isEmpty()) {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001951 return;
1952 }
1953
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001954 final ActivityStack stack = task.getStack();
1955 if (stack != null && stack.resizeStackWithLaunchBounds()) {
1956 mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001957 } else {
1958 task.updateOverrideConfiguration(bounds);
1959 }
1960 }
1961
Wale Ogunwale01d66562015-12-29 08:19:19 -08001962 private void setTaskToCurrentTopOrCreateNewTask() {
Bryce Leedacefc42017-10-10 12:56:02 -07001963 mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001964 if (mDoResume) {
1965 mTargetStack.moveToFront("addingToTopTask");
1966 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001967 final ActivityRecord prev = mTargetStack.getTopActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07001968 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001969 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001970 mIntent, null, null, true);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001971 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1972 mTargetStack.positionChildWindowContainerAtTop(task);
1973 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001974 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001975 }
1976
1977 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001978 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001979 parent.addActivityToTop(mStartActivity);
1980 } else {
1981 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1982 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001983 }
1984
1985 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1986 boolean launchSingleTask, int launchFlags) {
1987 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1988 (launchSingleInstance || launchSingleTask)) {
1989 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1990 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1991 "\"singleInstance\" or \"singleTask\"");
1992 launchFlags &=
1993 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1994 } else {
1995 switch (r.info.documentLaunchMode) {
1996 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1997 break;
1998 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1999 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2000 break;
2001 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2002 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2003 break;
2004 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2005 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2006 break;
2007 }
2008 }
2009 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002010 }
2011
2012 final void doPendingActivityLaunchesLocked(boolean doResume) {
2013 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08002014 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2015 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002016 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08002017 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
Bryce Lee4a194382017-04-04 14:32:48 -07002018 null, null /*outRecords*/);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002019 } catch (Exception e) {
2020 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2021 pal.sendErrorResult(e.getMessage());
2022 }
2023 }
2024 }
2025
Bryce Leedacefc42017-10-10 12:56:02 -07002026 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
2027 ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002028 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002029 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002030 if (stack != null) {
2031 return stack;
2032 }
2033
Andrii Kulian02b7a832016-10-06 23:11:56 -07002034 final ActivityStack currentStack = task != null ? task.getStack() : null;
2035 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002036 if (mSupervisor.mFocusedStack != currentStack) {
2037 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2038 "computeStackFocus: Setting " + "focused stack to r=" + r
2039 + " task=" + task);
2040 } else {
2041 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2042 "computeStackFocus: Focused stack already="
2043 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002044 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002045 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002046 }
2047
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002048 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002049 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2050 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2051 return mSupervisor.mFocusedStack;
2052 }
2053
David Stevense5a7b642017-05-22 13:18:23 -07002054 if (mPreferredDisplayId != DEFAULT_DISPLAY) {
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002055 // Try to put the activity in a stack on a secondary display.
David Stevense5a7b642017-05-22 13:18:23 -07002056 stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002057 if (stack == null) {
2058 // If source display is not suitable - look for topmost valid stack in the system.
2059 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
David Stevense5a7b642017-05-22 13:18:23 -07002060 "computeStackFocus: Can't launch on mPreferredDisplayId="
2061 + mPreferredDisplayId + ", looking on all displays.");
2062 stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002063 }
2064 }
2065 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002066 // We first try to put the task in the first dynamic stack on home display.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002067 final ActivityDisplay display = mSupervisor.getDefaultDisplay();
2068 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2069 stack = display.getChildAt(stackNdx);
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002070 if (!stack.isOnHomeDisplay()) {
David Stevensc6b91c62017-02-08 14:23:58 -08002071 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2072 "computeStackFocus: Setting focused stack=" + stack);
2073 return stack;
2074 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002075 }
David Stevensc6b91c62017-02-08 14:23:58 -08002076 // If there is no suitable dynamic stack then we figure out which static stack to use.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002077 stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002078 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002079 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2080 + r + " stackId=" + stack.mStackId);
2081 return stack;
2082 }
2083
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002084 /** Check if provided activity record can launch in currently focused stack. */
Wale Ogunwale68278562017-09-23 17:13:55 -07002085 // TODO: This method can probably be consolidated into getLaunchStack() below.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002086 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002087 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002088 final boolean canUseFocusedStack;
Wale Ogunwale68278562017-09-23 17:13:55 -07002089 if (focusedStack.isActivityTypeAssistant()) {
2090 canUseFocusedStack = r.isActivityTypeAssistant();
2091 } else {
2092 switch (focusedStack.getWindowingMode()) {
2093 case WINDOWING_MODE_FULLSCREEN:
2094 // The fullscreen stack can contain any task regardless of if the task is
2095 // resizeable or not. So, we let the task go in the fullscreen task if it is the
2096 // focus stack.
2097 canUseFocusedStack = true;
2098 break;
2099 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2100 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2101 // Any activity which supports split screen can go in the docked stack.
2102 canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2103 break;
2104 case WINDOWING_MODE_FREEFORM:
2105 // Any activity which supports freeform can go in the freeform stack.
2106 canUseFocusedStack = r.supportsFreeform();
2107 break;
2108 default:
2109 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2110 // resizeable task.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002111 canUseFocusedStack = !focusedStack.isOnHomeDisplay()
Wale Ogunwale68278562017-09-23 17:13:55 -07002112 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2113 }
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002114 }
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002115 return canUseFocusedStack && !newTask
Wale Ogunwale68278562017-09-23 17:13:55 -07002116 // Using the focus stack isn't important enough to override the preferred display.
David Stevense5a7b642017-05-22 13:18:23 -07002117 && (mPreferredDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002118 }
2119
Wale Ogunwale854809c2015-12-27 16:18:19 -08002120 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002121 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002122 // We are reusing a task, keep the stack!
2123 if (mReuseTask != null) {
2124 return mReuseTask.getStack();
2125 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002126
Bryce Lee7daee392017-10-12 13:46:18 -07002127 final int vrDisplayId = mPreferredDisplayId == mService.mVr2dDisplayId
2128 ? mPreferredDisplayId : INVALID_DISPLAY;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002129 final ActivityStack launchStack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
2130 vrDisplayId);
Winson Chung83471632016-12-13 11:02:12 -08002131
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002132 if (launchStack != null) {
2133 return launchStack;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002134 }
2135
2136 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
David Stevense5a7b642017-05-22 13:18:23 -07002137 || mPreferredDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002138 return null;
2139 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002140 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002141
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002142 // The parent activity doesn't want to launch the activity on top of itself, but
2143 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002144 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002145
2146 if (parentStack != mSupervisor.mFocusedStack) {
2147 // If task's parent stack is not focused - use it during adjacent launch.
2148 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002149 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002150 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2151 // If task is already on top of focused stack - use it. We don't want to move the
2152 // existing focused task to adjacent stack, just deliver new intent in this case.
2153 return mSupervisor.mFocusedStack;
2154 }
2155
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002156 if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002157 // If parent was in docked stack, the natural place to launch another activity
2158 // will be fullscreen, so it can appear alongside the docked window.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002159 final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2160 return parentStack.getDisplay().getOrCreateStack(
2161 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002162 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002163 // If the parent is not in the docked stack, we check if there is docked window
2164 // and if yes, we will launch into that stack. If not, we just put the new
2165 // activity into parent's stack, because we can't find a better place.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002166 final ActivityStack dockedStack =
2167 mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07002168 if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002169 // There is a docked stack, but it isn't visible, so we can't launch into that.
2170 return null;
2171 } else {
2172 return dockedStack;
2173 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002174 }
2175 }
2176 }
2177
Bryce Lee7daee392017-10-12 13:46:18 -07002178 private boolean isLaunchModeOneOf(int mode1, int mode2) {
2179 return mode1 == mLaunchMode || mode2 == mLaunchMode;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002180 }
2181
Daichi Hirono15a02992016-04-27 18:47:01 +09002182 static boolean isDocumentLaunchesIntoExisting(int flags) {
2183 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2184 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2185 }
liulvpingcfa825f2016-09-26 20:00:15 +08002186
2187 boolean clearPendingActivityLaunchesLocked(String packageName) {
2188 boolean didSomething = false;
2189
2190 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2191 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2192 ActivityRecord r = pal.r;
2193 if (r != null && r.packageName.equals(packageName)) {
2194 mPendingActivityLaunches.remove(palNdx);
2195 didSomething = true;
2196 }
2197 }
2198 return didSomething;
2199 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002200
Dianne Hackborne676ec72017-07-25 10:55:08 -07002201 void dump(PrintWriter pw, String prefix, String dumpPackage) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002202 prefix = prefix + " ";
2203
Dianne Hackborne676ec72017-07-25 10:55:08 -07002204 if (dumpPackage != null) {
2205 if ((mLastStartActivityRecord[0] == null ||
2206 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2207 (mLastHomeActivityStartRecord[0] == null ||
2208 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2209 (mStartActivity == null || !dumpPackage.equals(mStartActivity.packageName))) {
2210 pw.print(prefix);
2211 pw.println("(nothing)");
2212 return;
2213 }
2214 }
2215
2216 pw.print(prefix);
2217 pw.print("mCurrentUser=");
2218 pw.println(mSupervisor.mCurrentUser);
2219 pw.print(prefix);
2220 pw.print("mLastStartReason=");
2221 pw.println(mLastStartReason);
2222 pw.print(prefix);
2223 pw.print("mLastStartActivityTimeMs=");
2224 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2225 pw.print(prefix);
2226 pw.print("mLastStartActivityResult=");
2227 pw.println(mLastStartActivityResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002228 ActivityRecord r = mLastStartActivityRecord[0];
2229 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002230 pw.print(prefix);
2231 pw.println("mLastStartActivityRecord:");
2232 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002233 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002234 pw.print(prefix);
2235 pw.print("mLastHomeActivityStartResult=");
2236 pw.println(mLastHomeActivityStartResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002237 r = mLastHomeActivityStartRecord[0];
2238 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002239 pw.print(prefix);
2240 pw.println("mLastHomeActivityStartRecord:");
2241 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002242 }
2243 if (mStartActivity != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002244 pw.print(prefix);
2245 pw.println("mStartActivity:");
2246 mStartActivity.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002247 }
2248 if (mIntent != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002249 pw.print(prefix);
2250 pw.print("mIntent=");
2251 pw.println(mIntent);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002252 }
2253 if (mOptions != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002254 pw.print(prefix);
2255 pw.print("mOptions=");
2256 pw.println(mOptions);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002257 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002258 pw.print(prefix);
2259 pw.print("mLaunchSingleTop=");
Bryce Lee7daee392017-10-12 13:46:18 -07002260 pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002261 pw.print(" mLaunchSingleInstance=");
Bryce Lee7daee392017-10-12 13:46:18 -07002262 pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002263 pw.print(" mLaunchSingleTask=");
Bryce Lee7daee392017-10-12 13:46:18 -07002264 pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002265 pw.print(prefix);
2266 pw.print("mLaunchFlags=0x");
2267 pw.print(Integer.toHexString(mLaunchFlags));
2268 pw.print(" mDoResume=");
2269 pw.print(mDoResume);
2270 pw.print(" mAddingToTask=");
2271 pw.println(mAddingToTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002272 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002273}