blob: 830008395ad545d68cce27a4dd88d5975085743a [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 Ogunwale6fbde9f2017-08-24 07:24:12 -070029import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
30import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
31import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070032import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale68278562017-09-23 17:13:55 -070033import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
34import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070035import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
36import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale0568aed2017-09-08 13:29:37 -070037import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
39import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010040import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080041import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080042import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080044import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080045import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
46import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080047import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
48import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
49import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
50import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
51import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080052import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080053import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
54import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
56import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080057import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070058import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080059import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080062import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080063import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
65import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
66import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
71import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
72import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
73import static com.android.server.am.ActivityManagerService.ANIMATE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080074import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Winson Chung74666102017-02-22 17:49:24 -080075import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080077import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080078import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080079import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080080import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
81import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
82
Todd Kennedye9910222017-02-21 16:00:11 -080083import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080084import android.app.ActivityManager;
85import android.app.ActivityOptions;
86import android.app.AppGlobals;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080087import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080088import android.app.PendingIntent;
89import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070090import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080091import android.content.IIntentSender;
92import android.content.Intent;
93import android.content.IntentSender;
94import android.content.pm.ActivityInfo;
95import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -080096import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000097import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080098import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000099import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800100import android.content.res.Configuration;
101import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700102import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800103import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800104import android.os.Bundle;
105import android.os.IBinder;
106import android.os.RemoteException;
107import android.os.SystemClock;
108import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000109import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import android.service.voice.IVoiceInteractionSession;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700111import android.text.TextUtils;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800112import android.util.EventLog;
113import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800114
115import com.android.internal.app.HeavyWeightSwitcherActivity;
116import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800117import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800118import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800119import com.android.server.wm.WindowManagerService;
120
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700121import java.io.PrintWriter;
122import java.text.DateFormat;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800123import java.util.ArrayList;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700124import java.util.Date;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800125
126/**
127 * Controller for interpreting how and then launching activities.
128 *
129 * This class collects all the logic for determining how an intent and flags should be turned into
130 * an activity and associated task and stack.
131 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800132class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800133 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
134 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
135 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
136 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
137 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
138
139 private final ActivityManagerService mService;
140 private final ActivityStackSupervisor mSupervisor;
Benjamin Franz563707b2017-06-29 15:06:13 +0100141 private final ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800142 private WindowManagerService mWindowManager;
143
144 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
145
Wale Ogunwale01d66562015-12-29 08:19:19 -0800146 // Share state variable among methods when starting an activity.
147 private ActivityRecord mStartActivity;
148 private Intent mIntent;
149 private int mCallingUid;
150 private ActivityOptions mOptions;
151
152 private boolean mLaunchSingleTop;
153 private boolean mLaunchSingleInstance;
154 private boolean mLaunchSingleTask;
155 private boolean mLaunchTaskBehind;
156 private int mLaunchFlags;
157
158 private Rect mLaunchBounds;
159
160 private ActivityRecord mNotTop;
161 private boolean mDoResume;
162 private int mStartFlags;
163 private ActivityRecord mSourceRecord;
David Stevense5a7b642017-05-22 13:18:23 -0700164 // The display to launch the activity onto, barring any strong reason to do otherwise.
165 private int mPreferredDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800166
167 private TaskRecord mInTask;
168 private boolean mAddingToTask;
169 private TaskRecord mReuseTask;
170
171 private ActivityInfo mNewTaskInfo;
172 private Intent mNewTaskIntent;
173 private ActivityStack mSourceStack;
174 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700175 // Indicates that we moved other task and are going to put something on top soon, so
176 // we don't want to show it redundantly or accidentally change what's shown below.
177 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800178 private boolean mMovedToFront;
179 private boolean mNoAnimation;
180 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700181 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700182 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800183
Bryce Lee325e09682017-10-05 17:20:25 -0700184 // We must track when we deliver the new intent since multiple code paths invoke
185 // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
186 // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
187 // delivered at most once.
188 private boolean mIntentDelivered;
189
Wale Ogunwale01d66562015-12-29 08:19:19 -0800190 private IVoiceInteractionSession mVoiceSession;
191 private IVoiceInteractor mVoiceInteractor;
192
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700193 private boolean mUsingVr2dDisplay;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800194
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700195 // Last home activity record we attempted to start
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700196 private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700197 // The result of the last home activity we attempted to start.
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700198 private int mLastHomeActivityStartResult;
199 // Last activity record we attempted to start
200 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
201 // The result of the last activity we attempted to start.
202 private int mLastStartActivityResult;
203 // Time in milli seconds we attempted to start the last activity.
204 private long mLastStartActivityTimeMs;
205 // The reason we were trying to start the last activity
206 private String mLastStartReason;
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700207
Wale Ogunwale01d66562015-12-29 08:19:19 -0800208 private void reset() {
209 mStartActivity = null;
210 mIntent = null;
211 mCallingUid = -1;
212 mOptions = null;
213
214 mLaunchSingleTop = false;
215 mLaunchSingleInstance = false;
216 mLaunchSingleTask = false;
217 mLaunchTaskBehind = false;
218 mLaunchFlags = 0;
219
220 mLaunchBounds = null;
221
222 mNotTop = null;
223 mDoResume = false;
224 mStartFlags = 0;
225 mSourceRecord = null;
David Stevense5a7b642017-05-22 13:18:23 -0700226 mPreferredDisplayId = INVALID_DISPLAY;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800227
228 mInTask = null;
229 mAddingToTask = false;
230 mReuseTask = null;
231
232 mNewTaskInfo = null;
233 mNewTaskIntent = null;
234 mSourceStack = null;
235
236 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700237 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800238 mMovedToFront = false;
239 mNoAnimation = false;
240 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700241 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800242
243 mVoiceSession = null;
244 mVoiceInteractor = null;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800245
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700246 mUsingVr2dDisplay = false;
Bryce Lee325e09682017-10-05 17:20:25 -0700247
248 mIntentDelivered = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800249 }
250
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800251 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
252 mService = service;
253 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000254 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700255 mUsingVr2dDisplay = false;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800256 }
257
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700258 int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
259 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
260 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
261 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
262 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
263 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700264 ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700265
266 if (TextUtils.isEmpty(reason)) {
267 throw new IllegalArgumentException("Need to specify a reason.");
268 }
269 mLastStartReason = reason;
270 mLastStartActivityTimeMs = System.currentTimeMillis();
271 mLastStartActivityRecord[0] = null;
272
273 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
274 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
275 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
276 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700277 inTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700278
279 if (outActivity != null) {
280 // mLastStartActivityRecord[0] is set in the call to startActivity above.
281 outActivity[0] = mLastStartActivityRecord[0];
282 }
Bryce Leef9d49542017-06-26 16:27:32 -0700283
284 // Aborted results are treated as successes externally, but we must track them internally.
285 return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700286 }
287
288 /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
289 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800290 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
291 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
292 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
293 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
294 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700295 ActivityRecord[] outActivity, TaskRecord inTask) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800296 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700297 // Pull the optional Ephemeral Installer-only bundle out of the options early.
298 final Bundle verificationBundle
299 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800300
301 ProcessRecord callerApp = null;
302 if (caller != null) {
303 callerApp = mService.getRecordForAppLocked(caller);
304 if (callerApp != null) {
305 callingPid = callerApp.pid;
306 callingUid = callerApp.info.uid;
307 } else {
308 Slog.w(TAG, "Unable to find app for caller " + caller
309 + " (pid=" + callingPid + ") when starting: "
310 + intent.toString());
311 err = ActivityManager.START_PERMISSION_DENIED;
312 }
313 }
314
315 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
316
317 if (err == ActivityManager.START_SUCCESS) {
318 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800319 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800320 }
321
322 ActivityRecord sourceRecord = null;
323 ActivityRecord resultRecord = null;
324 if (resultTo != null) {
325 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
326 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
327 "Will send result to " + resultTo + " " + sourceRecord);
328 if (sourceRecord != null) {
329 if (requestCode >= 0 && !sourceRecord.finishing) {
330 resultRecord = sourceRecord;
331 }
332 }
333 }
334
335 final int launchFlags = intent.getFlags();
336
337 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
338 // Transfer the result target from the source activity to the new
339 // one being started, including any failures.
340 if (requestCode >= 0) {
341 ActivityOptions.abort(options);
342 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
343 }
344 resultRecord = sourceRecord.resultTo;
345 if (resultRecord != null && !resultRecord.isInStackLocked()) {
346 resultRecord = null;
347 }
348 resultWho = sourceRecord.resultWho;
349 requestCode = sourceRecord.requestCode;
350 sourceRecord.resultTo = null;
351 if (resultRecord != null) {
352 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
353 }
354 if (sourceRecord.launchedFromUid == callingUid) {
355 // The new activity is being launched from the same uid as the previous
356 // activity in the flow, and asking to forward its result back to the
357 // previous. In this case the activity is serving as a trampoline between
358 // the two, so we also want to update its launchedFromPackage to be the
359 // same as the previous activity. Note that this is safe, since we know
360 // these two packages come from the same uid; the caller could just as
361 // well have supplied that same package name itself. This specifially
362 // deals with the case of an intent picker/chooser being launched in the app
363 // flow to redirect to an activity picked by the user, where we want the final
364 // activity to consider it to have been launched by the previous app activity.
365 callingPackage = sourceRecord.launchedFromPackage;
366 }
367 }
368
369 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
370 // We couldn't find a class that can handle the given Intent.
371 // That's the end of that!
372 err = ActivityManager.START_INTENT_NOT_RESOLVED;
373 }
374
375 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
376 // We couldn't find the specific class specified in the Intent.
377 // Also the end of the line.
378 err = ActivityManager.START_CLASS_NOT_FOUND;
379 }
380
381 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700382 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800383 // If this activity is being launched as part of a voice session, we need
384 // to ensure that it is safe to do so. If the upcoming activity will also
385 // be part of the voice session, we can only launch it if it has explicitly
386 // said it supports the VOICE category, or it is a part of the calling app.
387 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
388 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
389 try {
390 intent.addCategory(Intent.CATEGORY_VOICE);
391 if (!AppGlobals.getPackageManager().activitySupportsIntent(
392 intent.getComponent(), intent, resolvedType)) {
393 Slog.w(TAG,
394 "Activity being started in current voice task does not support voice: "
395 + intent);
396 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
397 }
398 } catch (RemoteException e) {
399 Slog.w(TAG, "Failure checking voice capabilities", e);
400 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
401 }
402 }
403 }
404
405 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
406 // If the caller is starting a new voice session, just make sure the target
407 // is actually allowing it to run this way.
408 try {
409 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
410 intent, resolvedType)) {
411 Slog.w(TAG,
412 "Activity being started in new voice task does not support: "
413 + intent);
414 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
415 }
416 } catch (RemoteException e) {
417 Slog.w(TAG, "Failure checking voice capabilities", e);
418 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
419 }
420 }
421
Andrii Kulian02b7a832016-10-06 23:11:56 -0700422 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800423
Wale Ogunwale01d66562015-12-29 08:19:19 -0800424 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800425 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800426 resultStack.sendActivityResultLocked(
427 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800428 }
429 ActivityOptions.abort(options);
430 return err;
431 }
432
433 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
434 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100435 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800436 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
437 callingPid, resolvedType, aInfo.applicationInfo);
438
439 if (mService.mController != null) {
440 try {
441 // The Intent we give to the watcher has the extra data
442 // stripped off, since it can contain private information.
443 Intent watchIntent = intent.cloneFilter();
444 abort |= !mService.mController.activityStarting(watchIntent,
445 aInfo.applicationInfo.packageName);
446 } catch (RemoteException e) {
447 mService.mController = null;
448 }
449 }
450
Rubin Xu58d25992016-01-21 17:47:13 +0000451 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Benjamin Franz563707b2017-06-29 15:06:13 +0100452 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
453 callingUid, options)) {
454 // activity start was intercepted, e.g. because the target user is currently in quiet
455 // mode (turn off work) or the target application is suspended
456 intent = mInterceptor.mIntent;
457 rInfo = mInterceptor.mRInfo;
458 aInfo = mInterceptor.mAInfo;
459 resolvedType = mInterceptor.mResolvedType;
460 inTask = mInterceptor.mInTask;
461 callingPid = mInterceptor.mCallingPid;
462 callingUid = mInterceptor.mCallingUid;
463 options = mInterceptor.mActivityOptions;
464 }
465
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800466 if (abort) {
467 if (resultRecord != null) {
468 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800469 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800470 }
471 // We pretend to the caller that it was really started, but
472 // they will just get a cancel result.
473 ActivityOptions.abort(options);
Bryce Leef9d49542017-06-26 16:27:32 -0700474 return START_ABORTED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800475 }
476
477 // If permissions need a review before any of the app components can run, we
478 // launch the review activity and pass a pending intent to start the activity
479 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700480 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800481 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
482 aInfo.packageName, userId)) {
483 IIntentSender target = mService.getIntentSenderLocked(
484 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
485 callingUid, userId, null, null, 0, new Intent[]{intent},
486 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
487 | PendingIntent.FLAG_ONE_SHOT, null);
488
489 final int flags = intent.getFlags();
490 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
491 newIntent.setFlags(flags
492 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
493 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
494 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
495 if (resultRecord != null) {
496 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
497 }
498 intent = newIntent;
499
500 resolvedType = null;
501 callingUid = realCallingUid;
502 callingPid = realCallingPid;
503
504 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
505 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
506 null /*profilerInfo*/);
507
508 if (DEBUG_PERMISSIONS_REVIEW) {
509 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
510 true, false) + "} from uid " + callingUid + " on display "
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700511 + (mSupervisor.mFocusedStack == null
512 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800513 }
514 }
515 }
516
517 // If we have an ephemeral app, abort the process of launching the resolved intent.
518 // Instead, launch the ephemeral installer. Once the installer is finished, it
519 // starts either the intent we resolved here [on install error] or the ephemeral
520 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800521 if (rInfo != null && rInfo.auxiliaryInfo != null) {
522 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700523 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800524 resolvedType = null;
525 callingUid = realCallingUid;
526 callingPid = realCallingPid;
527
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800528 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
529 }
530
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800531 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
532 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
533 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700534 mSupervisor, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800535 if (outActivity != null) {
536 outActivity[0] = r;
537 }
538
539 if (r.appTimeTracker == null && sourceRecord != null) {
540 // If the caller didn't specify an explicit time tracker, we want to continue
541 // tracking under any it has.
542 r.appTimeTracker = sourceRecord.appTimeTracker;
543 }
544
545 final ActivityStack stack = mSupervisor.mFocusedStack;
546 if (voiceSession == null && (stack.mResumedActivity == null
547 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
548 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
549 realCallingPid, realCallingUid, "Activity start")) {
550 PendingActivityLaunch pal = new PendingActivityLaunch(r,
551 sourceRecord, startFlags, stack, callerApp);
552 mPendingActivityLaunches.add(pal);
553 ActivityOptions.abort(options);
554 return ActivityManager.START_SWITCHES_CANCELED;
555 }
556 }
557
558 if (mService.mDidAppSwitch) {
559 // This is the second allowed switch since we stopped switches,
560 // so now just generally allow switches. Use case: user presses
561 // home (switches disabled, switch to home, mDidAppSwitch now true);
562 // user taps a home icon (coming from home so allowed, we hit here
563 // and now allow anyone to switch again).
564 mService.mAppSwitchesAllowedTime = 0;
565 } else {
566 mService.mDidAppSwitch = true;
567 }
568
569 doPendingActivityLaunchesLocked(false);
570
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800571 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
Bryce Lee4a194382017-04-04 14:32:48 -0700572 options, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800573 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800574
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800575 /**
576 * Creates a launch intent for the given auxiliary resolution data.
577 */
Todd Kennedye9910222017-02-21 16:00:11 -0800578 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700579 Intent originalIntent, String callingPackage, Bundle verificationBundle,
580 String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800581 if (auxiliaryResponse.needsPhaseTwo) {
582 // request phase two resolution
583 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700584 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
585 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800586 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700587 return InstantAppResolver.buildEphemeralInstallerIntent(
588 Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
589 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
590 resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
Todd Kennedyd0084f72017-07-28 13:56:14 -0700591 auxiliaryResponse.installFailureActivity, auxiliaryResponse.versionCode,
592 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800593 }
594
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700595 void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800596
Bryce Lee7f936862017-05-09 15:33:18 -0700597 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800598 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800599 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800600
Chong Zhang5022da32016-06-21 16:31:37 -0700601 // We're waiting for an activity launch to finish, but that activity simply
602 // brought another activity to front. Let startActivityMayWait() know about
603 // this, so it waits for the new activity to become visible instead.
604 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
605 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
606 }
607
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700608 ActivityStack startedActivityStack = null;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700609 final ActivityStack currentStack = r.getStack();
610 if (currentStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700611 startedActivityStack = currentStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800612 } else if (mTargetStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700613 startedActivityStack = targetStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800614 }
615
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700616 if (startedActivityStack == null) {
617 return;
618 }
619
620 if (startedActivityStack.inSplitScreenPrimaryWindowingMode()) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700621 final ActivityStack homeStack = mSupervisor.getDefaultDisplay().getStack(
622 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700623 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
624 if (homeStackVisible) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100625 // We launch an activity while being in home stack, which means either launcher or
626 // recents into docked stack. We don't want the launched activity to be alone in a
627 // docked stack, so we want to immediately launch recents too.
628 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700629 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100630 }
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700631 return;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800632 }
633
Winson Chunge6385a22017-05-02 18:15:16 -0700634 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
Winson Chunge0c3d5d2017-05-04 18:25:21 -0700635 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700636 if (startedActivityStack.inPinnedWindowingMode()
637 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
638 || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800639 // The activity was already running in the pinned stack so it wasn't started, but either
640 // brought to the front or the new intent was delivered to it since it was already in
641 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700642 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
643 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800644 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800645 }
646
647 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800648 mSupervisor.moveHomeStackTaskToTop(reason);
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700649 mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
650 null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
651 null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
652 null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
653 null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
654 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
655 false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700656 null /*inTask*/, "startHomeActivity: " + reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800657 if (mSupervisor.inResumeTopActivity) {
658 // If we are in resume section already, home activity will be initialized, but not
659 // resumed (to avoid recursive resume) and will stay that way until something pokes it
660 // again. We need to schedule another resume.
661 mSupervisor.scheduleResumeTopActivities();
662 }
663 }
664
Robin Lee5d592422017-01-18 13:48:15 +0000665 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100666 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
667 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
668 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000669 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
670 : ActivityOptions.makeBasic());
Bryce Leeaf691c02017-03-20 14:20:22 -0700671 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000672 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100673 }
Tony Mak853304c2016-04-18 15:17:41 +0100674
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800675 final int startActivityMayWait(IApplicationThread caller, int callingUid,
676 String callingPackage, Intent intent, String resolvedType,
677 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
678 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700679 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700680 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700681 TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800682 // Refuse possible leaked file descriptors
683 if (intent != null && intent.hasFileDescriptors()) {
684 throw new IllegalArgumentException("File descriptors passed in Intent");
685 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500686 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800687 boolean componentSpecified = intent.getComponent() != null;
688
689 // Save a copy in case ephemeral needs it
690 final Intent ephemeralIntent = new Intent(intent);
691 // Don't modify the client's object!
692 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700693 if (componentSpecified
694 && intent.getData() != null
695 && Intent.ACTION_VIEW.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700696 && mService.getPackageManagerInternalLocked()
697 .isInstantAppInstallerComponent(intent.getComponent())) {
698 // intercept intents targeted directly to the ephemeral installer the
699 // ephemeral installer should never be started with a raw URL; instead
700 // adjust the intent so it looks like a "normal" instant app launch
701 intent.setComponent(null /*component*/);
702 componentSpecified = false;
703 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800704
705 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000706 if (rInfo == null) {
707 UserInfo userInfo = mSupervisor.getUserInfo(userId);
708 if (userInfo != null && userInfo.isManagedProfile()) {
709 // Special case for managed profiles, if attempting to launch non-cryto aware
710 // app in a locked managed profile from an unlocked parent allow it to resolve
711 // as user will be sent via confirm credentials to unlock the profile.
712 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700713 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000714 long token = Binder.clearCallingIdentity();
715 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700716 UserInfo parent = userManager.getProfileParent(userId);
717 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
718 && userManager.isUserUnlockingOrUnlocked(parent.id)
719 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000720 } finally {
721 Binder.restoreCallingIdentity(token);
722 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700723 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000724 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600725 PackageManager.MATCH_DIRECT_BOOT_AWARE
726 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000727 }
728 }
729 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800730 // Collect information about the target of the Intent.
731 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
732
733 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800734 synchronized (mService) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800735 final int realCallingPid = Binder.getCallingPid();
736 final int realCallingUid = Binder.getCallingUid();
737 int callingPid;
738 if (callingUid >= 0) {
739 callingPid = -1;
740 } else if (caller == null) {
741 callingPid = realCallingPid;
742 callingUid = realCallingUid;
743 } else {
744 callingPid = callingUid = -1;
745 }
746
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700747 final ActivityStack stack = mSupervisor.mFocusedStack;
Andrii Kulian8072d112016-09-16 11:11:01 -0700748 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700749 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800750 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
751 "Starting activity when config will change = " + stack.mConfigWillChange);
752
753 final long origId = Binder.clearCallingIdentity();
754
755 if (aInfo != null &&
756 (aInfo.applicationInfo.privateFlags
757 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
758 // This may be a heavy-weight process! Check to see if we already
759 // have another, different heavy-weight process running.
760 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
761 final ProcessRecord heavy = mService.mHeavyWeightProcess;
762 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
763 || !heavy.processName.equals(aInfo.processName))) {
764 int appCallingUid = callingUid;
765 if (caller != null) {
766 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
767 if (callerApp != null) {
768 appCallingUid = callerApp.info.uid;
769 } else {
770 Slog.w(TAG, "Unable to find app for caller " + caller
771 + " (pid=" + callingPid + ") when starting: "
772 + intent.toString());
773 ActivityOptions.abort(options);
774 return ActivityManager.START_PERMISSION_DENIED;
775 }
776 }
777
778 IIntentSender target = mService.getIntentSenderLocked(
779 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
780 appCallingUid, userId, null, null, 0, new Intent[] { intent },
781 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
782 | PendingIntent.FLAG_ONE_SHOT, null);
783
784 Intent newIntent = new Intent();
785 if (requestCode >= 0) {
786 // Caller is requesting a result.
787 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
788 }
789 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
790 new IntentSender(target));
791 if (heavy.activities.size() > 0) {
792 ActivityRecord hist = heavy.activities.get(0);
793 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
794 hist.packageName);
795 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -0700796 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800797 }
798 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
799 aInfo.packageName);
800 newIntent.setFlags(intent.getFlags());
801 newIntent.setClassName("android",
802 HeavyWeightSwitcherActivity.class.getName());
803 intent = newIntent;
804 resolvedType = null;
805 caller = null;
806 callingUid = Binder.getCallingUid();
807 callingPid = Binder.getCallingPid();
808 componentSpecified = true;
809 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
810 aInfo = rInfo != null ? rInfo.activityInfo : null;
811 if (aInfo != null) {
812 aInfo = mService.getActivityInfoForUser(aInfo, userId);
813 }
814 }
815 }
816 }
817
Jorim Jaggi275561a2016-02-23 10:11:02 -0500818 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800819 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
820 aInfo, rInfo, voiceSession, voiceInteractor,
821 resultTo, resultWho, requestCode, callingPid,
822 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700823 options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
824 reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800825
826 Binder.restoreCallingIdentity(origId);
827
828 if (stack.mConfigWillChange) {
829 // If the caller also wants to switch to a new configuration,
830 // do so now. This allows a clean switch, as we are waiting
831 // for the current activity to pause (so we will not destroy
832 // it), and have not yet started the next activity.
833 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
834 "updateConfiguration()");
835 stack.mConfigWillChange = false;
836 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
837 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700838 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800839 }
840
841 if (outResult != null) {
842 outResult.result = res;
843 if (res == ActivityManager.START_SUCCESS) {
844 mSupervisor.mWaitingActivityLaunched.add(outResult);
845 do {
846 try {
847 mService.wait();
848 } catch (InterruptedException e) {
849 }
Chong Zhang5022da32016-06-21 16:31:37 -0700850 } while (outResult.result != START_TASK_TO_FRONT
851 && !outResult.timeout && outResult.who == null);
852 if (outResult.result == START_TASK_TO_FRONT) {
853 res = START_TASK_TO_FRONT;
854 }
855 }
856 if (res == START_TASK_TO_FRONT) {
Bryce Lee4a194382017-04-04 14:32:48 -0700857 final ActivityRecord r = outRecord[0];
858
859 // ActivityRecord may represent a different activity, but it should not be in
860 // the resumed state.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800861 if (r.nowVisible && r.state == RESUMED) {
862 outResult.timeout = false;
Bryce Lee4a194382017-04-04 14:32:48 -0700863 outResult.who = r.realActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800864 outResult.totalTime = 0;
865 outResult.thisTime = 0;
866 } else {
867 outResult.thisTime = SystemClock.uptimeMillis();
Bryce Lee4a194382017-04-04 14:32:48 -0700868 mSupervisor.waitActivityVisible(r.realActivity, outResult);
869 // Note: the timeout variable is not currently not ever set.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800870 do {
871 try {
872 mService.wait();
873 } catch (InterruptedException e) {
874 }
875 } while (!outResult.timeout && outResult.who == null);
876 }
877 }
878 }
879
Bryce Lee4a194382017-04-04 14:32:48 -0700880 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800881 return res;
882 }
883 }
884
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800885 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
886 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700887 Bundle bOptions, int userId, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800888 if (intents == null) {
889 throw new NullPointerException("intents is null");
890 }
891 if (resolvedTypes == null) {
892 throw new NullPointerException("resolvedTypes is null");
893 }
894 if (intents.length != resolvedTypes.length) {
895 throw new IllegalArgumentException("intents are length different than resolvedTypes");
896 }
897
Makoto Onukid67b1872016-07-21 16:26:36 -0700898 final int realCallingPid = Binder.getCallingPid();
899 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800900
901 int callingPid;
902 if (callingUid >= 0) {
903 callingPid = -1;
904 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700905 callingPid = realCallingPid;
906 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800907 } else {
908 callingPid = callingUid = -1;
909 }
910 final long origId = Binder.clearCallingIdentity();
911 try {
912 synchronized (mService) {
913 ActivityRecord[] outActivity = new ActivityRecord[1];
914 for (int i=0; i<intents.length; i++) {
915 Intent intent = intents[i];
916 if (intent == null) {
917 continue;
918 }
919
920 // Refuse possible leaked file descriptors
921 if (intent != null && intent.hasFileDescriptors()) {
922 throw new IllegalArgumentException("File descriptors passed in Intent");
923 }
924
925 boolean componentSpecified = intent.getComponent() != null;
926
927 // Don't modify the client's object!
928 intent = new Intent(intent);
929
930 // Collect information about the target of the Intent.
931 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
932 null, userId);
933 // TODO: New, check if this is correct
934 aInfo = mService.getActivityInfoForUser(aInfo, userId);
935
936 if (aInfo != null &&
937 (aInfo.applicationInfo.privateFlags
938 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
939 throw new IllegalArgumentException(
940 "FLAG_CANT_SAVE_STATE not supported here");
941 }
942
943 ActivityOptions options = ActivityOptions.fromBundle(
944 i == intents.length - 1 ? bOptions : null);
945 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
946 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700947 callingPid, callingUid, callingPackage,
948 realCallingPid, realCallingUid, 0,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700949 options, false, componentSpecified, outActivity, null, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800950 if (res < 0) {
951 return res;
952 }
953
954 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
955 }
956 }
957 } finally {
958 Binder.restoreCallingIdentity(origId);
959 }
960
Wale Ogunwale01d66562015-12-29 08:19:19 -0800961 return START_SUCCESS;
962 }
963
Bryce Lee28d80422017-07-21 13:25:13 -0700964 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
Bryce Lee834abec2017-01-09 16:18:14 -0800965 boolean sendHint = forceSend;
966
967 if (!sendHint) {
968 // If not forced, send power hint when the activity's process is different than the
969 // current resumed activity.
970 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
971 sendHint = resumedActivity == null
972 || resumedActivity.app == null
Bryce Lee28d80422017-07-21 13:25:13 -0700973 || !resumedActivity.app.equals(targetActivity.app);
Bryce Lee834abec2017-01-09 16:18:14 -0800974 }
975
976 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700977 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700978 mPowerHintSent = true;
979 }
980 }
981
Wei Wang65c7a152016-06-02 18:51:22 -0700982 void sendPowerHintForLaunchEndIfNeeded() {
983 // Trigger launch power hint if activity is launched
984 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700985 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700986 mPowerHintSent = false;
987 }
988 }
989
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800990 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
991 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700992 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
993 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800994 int result = START_CANCELED;
995 try {
996 mService.mWindowManager.deferSurfaceLayout();
997 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700998 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800999 } finally {
1000 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1001 // activity in an incomplete state can lead to issues, such as performing operations
1002 // without a window container.
Bryce Leea3b0e3f02017-05-17 16:45:36 -07001003 if (!ActivityManager.isStartResultSuccessful(result)
Bryce Lee7f936862017-05-09 15:33:18 -07001004 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001005 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001006 }
1007 mService.mWindowManager.continueSurfaceLayout();
1008 }
1009
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001010 postStartActivityProcessing(r, result, mTargetStack);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001011
1012 return result;
1013 }
1014
1015 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001016 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1017 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001018 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1019 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001020
1021 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1022 voiceInteractor);
1023
1024 computeLaunchingTaskFlags();
1025
1026 computeSourceStack();
1027
1028 mIntent.setFlags(mLaunchFlags);
1029
Bryce Lee4a194382017-04-04 14:32:48 -07001030 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001031
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001032 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1033 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1034 if (mOptions != null) {
1035 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1036 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1037 }
Jorim Jaggi2adba072016-03-03 13:43:39 +01001038
Bryce Lee4a194382017-04-04 14:32:48 -07001039 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001040 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1041 // still needs to be a lock task mode violation since the task gets cleared out and
1042 // the device would otherwise leave the locked task.
Benjamin Franza83859f2017-07-03 16:34:14 +01001043 if (mService.mLockTaskController.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001044 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1045 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001046 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1047 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1048 }
1049
Bryce Leeaf691c02017-03-20 14:20:22 -07001050 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001051 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001052 }
Bryce Lee4a194382017-04-04 14:32:48 -07001053 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001054 // This task was started because of movement of the activity based on affinity...
1055 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001056 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001057 }
1058
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001059 // This code path leads to delivering a new intent, we want to make sure we schedule it
1060 // as the first operation, in case the activity will be resumed as a result of later
1061 // operations.
1062 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001063 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001064 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Lee4a194382017-04-04 14:32:48 -07001065 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001066
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001067 // In this situation we want to remove all activities from the task up to the one
1068 // being started. In most cases this means we are resetting the task to its initial
1069 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001070 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1071 mLaunchFlags);
1072
Bryce Lee4a194382017-04-04 14:32:48 -07001073 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001074 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1075 // task reference is needed in the call below to
1076 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001077 if (reusedActivity.getTask() == null) {
1078 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001079 }
1080
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001081 if (top != null) {
1082 if (top.frontOfTask) {
1083 // Activity aliases may mean we use different intents for the top activity,
1084 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001085 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001086 }
Bryce Lee325e09682017-10-05 17:20:25 -07001087 deliverNewIntent(top);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001088 }
1089 }
1090
Bryce Lee28d80422017-07-21 13:25:13 -07001091 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001092
Bryce Lee4a194382017-04-04 14:32:48 -07001093 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001094
Bryce Lee89cd19a2017-05-17 15:18:35 -07001095 final ActivityRecord outResult =
1096 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1097
1098 // When there is a reused activity and the current result is a trampoline activity,
1099 // set the reused activity as the result.
1100 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1101 outActivity[0] = reusedActivity;
1102 }
1103
Wale Ogunwale01d66562015-12-29 08:19:19 -08001104 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1105 // We don't need to start a new activity, and the client said not to do anything
1106 // if that is the case, so this is it! And for paranoia, make sure we have
1107 // correctly resumed the top activity.
1108 resumeTargetStackIfNeeded();
1109 return START_RETURN_INTENT_TO_CALLER;
1110 }
Bryce Lee4a194382017-04-04 14:32:48 -07001111 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001112
1113 if (!mAddingToTask && mReuseTask == null) {
1114 // We didn't do anything... but it was needed (a.k.a., client don't use that
1115 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1116 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001117 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001118 outActivity[0] = reusedActivity;
1119 }
Bryce Lee28d80422017-07-21 13:25:13 -07001120
Wale Ogunwale01d66562015-12-29 08:19:19 -08001121 return START_TASK_TO_FRONT;
1122 }
1123 }
1124
1125 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001126 final ActivityStack sourceStack = mStartActivity.resultTo != null
1127 ? mStartActivity.resultTo.getStack() : null;
1128 if (sourceStack != null) {
1129 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1130 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1131 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001132 }
1133 ActivityOptions.abort(mOptions);
1134 return START_CLASS_NOT_FOUND;
1135 }
1136
1137 // If the activity being launched is the same as the one currently at the top, then
1138 // we need to check if it should only be launched once.
1139 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001140 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001141 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1142 final boolean dontStart = top != null && mStartActivity.resultTo == null
1143 && top.realActivity.equals(mStartActivity.realActivity)
1144 && top.userId == mStartActivity.userId
1145 && top.app != null && top.app.thread != null
1146 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1147 || mLaunchSingleTop || mLaunchSingleTask);
1148 if (dontStart) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001149 // For paranoia, make sure we have correctly resumed the top activity.
1150 topStack.mLastPausedActivity = null;
1151 if (mDoResume) {
1152 mSupervisor.resumeFocusedStackTopActivityLocked();
1153 }
1154 ActivityOptions.abort(mOptions);
1155 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1156 // We don't need to start a new activity, and the client said not to do
1157 // anything if that is the case, so this is it!
1158 return START_RETURN_INTENT_TO_CALLER;
1159 }
Bryce Lee325e09682017-10-05 17:20:25 -07001160
1161 deliverNewIntent(top);
Chong Zhangd44063c2016-04-08 11:52:30 -07001162
1163 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1164 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001165 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001166 preferredLaunchDisplayId, topStack.mStackId);
Chong Zhangd44063c2016-04-08 11:52:30 -07001167
Wale Ogunwale01d66562015-12-29 08:19:19 -08001168 return START_DELIVERED_TO_TOP;
1169 }
1170
1171 boolean newTask = false;
1172 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001173 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001174
1175 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001176 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001177 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1178 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1179 newTask = true;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001180 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001181 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001182 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001183 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001184 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001185 } else {
1186 // This not being started from an existing activity, and not part of a new task...
1187 // just put it in the top task, though these days this case should never happen.
1188 setTaskToCurrentTopOrCreateNewTask();
1189 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001190 if (result != START_SUCCESS) {
1191 return result;
1192 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001193
1194 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1195 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001196 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1197 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001198 if (mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001199 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001200 }
1201 if (newTask) {
1202 EventLog.writeEvent(
Bryce Leeaf691c02017-03-20 14:20:22 -07001203 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1204 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001205 }
1206 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001207 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001208 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001209
Bryce Lee28d80422017-07-21 13:25:13 -07001210 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001211
Winson Chungb5c41b72016-12-07 15:00:47 -08001212 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1213 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001214 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001215 final ActivityRecord topTaskActivity =
1216 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001217 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001218 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1219 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001220 // If the activity is not focusable, we can't resume it, but still would like to
1221 // make sure it becomes visible as it starts (this will also trigger entry
1222 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001223 // Also, we don't want to resume activities in a task that currently has an overlay
1224 // as the starting activity just needs to be in the visible paused state until the
1225 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001226 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001227 // Go ahead and tell window manager to execute app transition for this activity
1228 // since the app transition will not be triggered through the resume channel.
1229 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001230 } else {
Winson Chung32066032016-11-04 11:55:21 -07001231 // If the target stack was not previously focusable (previous top running activity
1232 // on that stack was not visible) then any prior calls to move the stack to the
1233 // will not update the focused stack. If starting the new activity now allows the
1234 // task stack to be focusable, then ensure that we now update the focused stack
1235 // accordingly.
1236 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1237 mTargetStack.moveToFront("startActivityUnchecked");
1238 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001239 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1240 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001241 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001242 } else {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001243 mSupervisor.addRecentActivity(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001244 }
1245 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1246
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001247 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001248 preferredLaunchDisplayId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001249
1250 return START_SUCCESS;
1251 }
1252
1253 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1254 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1255 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1256 reset();
1257
1258 mStartActivity = r;
1259 mIntent = r.intent;
1260 mOptions = options;
1261 mCallingUid = r.launchedFromUid;
1262 mSourceRecord = sourceRecord;
1263 mVoiceSession = voiceSession;
1264 mVoiceInteractor = voiceInteractor;
1265
David Stevense5a7b642017-05-22 13:18:23 -07001266 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
David Stevensc6b91c62017-02-08 14:23:58 -08001267
Wale Ogunwale01d66562015-12-29 08:19:19 -08001268 mLaunchBounds = getOverrideBounds(r, options, inTask);
1269
1270 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1271 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1272 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1273 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1274 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1275 mLaunchTaskBehind = r.mLaunchTaskBehind
1276 && !mLaunchSingleTask && !mLaunchSingleInstance
1277 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1278
1279 sendNewTaskResultRequestIfNeeded();
1280
1281 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1282 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1283 }
1284
1285 // If we are actually going to launch in to a new task, there are some cases where
1286 // we further want to do multiple task.
1287 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1288 if (mLaunchTaskBehind
1289 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1290 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1291 }
1292 }
1293
1294 // We'll invoke onUserLeaving before onPause only if the launching
1295 // activity did not explicitly state that this is an automated launch.
1296 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1297 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1298 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1299
1300 // If the caller has asked not to resume at this point, we make note
1301 // of this in the record so that we can skip it when trying to find
1302 // the top running activity.
1303 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001304 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001305 r.delayedResume = true;
1306 mDoResume = false;
1307 }
1308
Winson Chungcbcadc92017-01-12 15:54:12 -08001309 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1310 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001311 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001312 if (!mOptions.canTaskOverlayResume()) {
1313 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1314 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1315 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001316
Winson Chungcbcadc92017-01-12 15:54:12 -08001317 // The caller specifies that we'd like to be avoided to be moved to the front,
1318 // so be it!
1319 mDoResume = false;
1320 mAvoidMoveToFront = true;
1321 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001322 }
1323 }
1324
Wale Ogunwale01d66562015-12-29 08:19:19 -08001325 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1326
1327 mInTask = inTask;
1328 // In some flows in to this function, we retrieve the task record and hold on to it
1329 // without a lock before calling back in to here... so the task at this point may
1330 // not actually be in recents. Check for that, and if it isn't in recents just
1331 // consider it invalid.
1332 if (inTask != null && !inTask.inRecents) {
1333 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1334 mInTask = null;
1335 }
1336
1337 mStartFlags = startFlags;
1338 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1339 // is the same as the one making the call... or, as a special case, if we do not know
1340 // the caller then we count the current top activity as the caller.
1341 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1342 ActivityRecord checkedCaller = sourceRecord;
1343 if (checkedCaller == null) {
1344 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1345 mNotTop);
1346 }
1347 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1348 // Caller is not the same as launcher, so always needed.
1349 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1350 }
1351 }
1352
1353 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1354 }
1355
1356 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001357 final ActivityStack sourceStack = mStartActivity.resultTo != null
1358 ? mStartActivity.resultTo.getStack() : null;
1359 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001360 // For whatever reason this activity is being launched into a new task...
1361 // yet the caller has requested a result back. Well, that is pretty messed up,
1362 // so instead immediately send back a cancel and let the new task continue launched
1363 // as normal without a dependency on its originator.
1364 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001365 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1366 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1367 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001368 mStartActivity.resultTo = null;
1369 }
1370 }
1371
1372 private void computeLaunchingTaskFlags() {
1373 // If the caller is not coming from another activity, but has given us an explicit task into
1374 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001375 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001376 final Intent baseIntent = mInTask.getBaseIntent();
1377 final ActivityRecord root = mInTask.getRootActivity();
1378 if (baseIntent == null) {
1379 ActivityOptions.abort(mOptions);
1380 throw new IllegalArgumentException("Launching into task without base intent: "
1381 + mInTask);
1382 }
1383
1384 // If this task is empty, then we are adding the first activity -- it
1385 // determines the root, and must be launching as a NEW_TASK.
1386 if (mLaunchSingleInstance || mLaunchSingleTask) {
1387 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1388 ActivityOptions.abort(mOptions);
1389 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1390 + mStartActivity + " into different task " + mInTask);
1391 }
1392 if (root != null) {
1393 ActivityOptions.abort(mOptions);
1394 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1395 + " has root " + root + " but target is singleInstance/Task");
1396 }
1397 }
1398
1399 // If task is empty, then adopt the interesting intent launch flags in to the
1400 // activity being started.
1401 if (root == null) {
1402 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1403 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1404 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1405 | (baseIntent.getFlags() & flagsOfInterest);
1406 mIntent.setFlags(mLaunchFlags);
1407 mInTask.setIntent(mStartActivity);
1408 mAddingToTask = true;
1409
1410 // If the task is not empty and the caller is asking to start it as the root of
1411 // a new task, then we don't actually want to start this on the task. We will
1412 // bring the task to the front, and possibly give it a new intent.
1413 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1414 mAddingToTask = false;
1415
1416 } else {
1417 mAddingToTask = true;
1418 }
1419
1420 mReuseTask = mInTask;
1421 } else {
1422 mInTask = null;
1423 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1424 // when in freeform workspace.
1425 // Also put noDisplay activities in the source task. These by itself can be placed
1426 // in any task/stack, however it could launch other activities like ResolverActivity,
1427 // and we want those to stay in the original task.
1428 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001429 && mSourceRecord.inFreeformWindowingMode()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001430 mAddingToTask = true;
1431 }
1432 }
1433
1434 if (mInTask == null) {
1435 if (mSourceRecord == null) {
1436 // This activity is not being started from another... in this
1437 // case we -always- start a new task.
1438 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1439 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1440 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1441 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1442 }
1443 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1444 // The original activity who is starting us is running as a single
1445 // instance... this new activity it is starting must go on its
1446 // own task.
1447 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1448 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1449 // The activity being started is a single instance... it always
1450 // gets launched into its own task.
1451 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1452 }
1453 }
1454 }
1455
1456 private void computeSourceStack() {
1457 if (mSourceRecord == null) {
1458 mSourceStack = null;
1459 return;
1460 }
1461 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001462 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001463 return;
1464 }
1465
1466 // If the source is finishing, we can't further count it as our source. This is because the
1467 // task it is associated with may now be empty and on its way out, so we don't want to
1468 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1469 // a task for it. But save the task information so it can be used when creating the new task.
1470 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1471 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1472 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1473 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1474 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001475
1476 // It is not guaranteed that the source record will have a task associated with it. For,
1477 // example, if this method is being called for processing a pending activity launch, it
1478 // is possible that the activity has been removed from the task after the launch was
1479 // enqueued.
1480 final TaskRecord sourceTask = mSourceRecord.getTask();
1481 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001482 }
1483 mSourceRecord = null;
1484 mSourceStack = null;
1485 }
1486
1487 /**
1488 * Decide whether the new activity should be inserted into an existing task. Returns null
1489 * if not or an ActivityRecord with the task into which the new activity should be added.
1490 */
1491 private ActivityRecord getReusableIntentActivity() {
1492 // We may want to try to place the new activity in to an existing task. We always
1493 // do this if the target activity is singleTask or singleInstance; we will also do
1494 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1495 // us to still place it in a new task: multi task, always doc mode, or being asked to
1496 // launch this as a new task behind the current one.
1497 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1498 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1499 || mLaunchSingleInstance || mLaunchSingleTask;
1500 // If bring to front is requested, and no result is requested and we have not been given
1501 // an explicit task to launch in to, and we can find a task that was started with this
1502 // same component, then instead of launching bring that one to the front.
1503 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1504 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001505 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1506 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1507 intentActivity = task != null ? task.getTopActivity() : null;
1508 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001509 if (mLaunchSingleInstance) {
1510 // There can be one and only one instance of single instance activity in the
1511 // history, and it is always in its own unique task, so we do a special search.
Bryce Lee28d80422017-07-21 13:25:13 -07001512 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001513 mStartActivity.isActivityTypeHome());
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001514 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1515 // For the launch adjacent case we only want to put the activity in an existing
1516 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001517 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1518 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001519 } else {
1520 // Otherwise find the best task to put the activity in.
David Stevense5a7b642017-05-22 13:18:23 -07001521 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001522 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001523 }
1524 return intentActivity;
1525 }
1526
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001527 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001528 * 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 -07001529 * then return the Vr mode's virtual display ID. If not, if the activity was started with
1530 * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1531 * set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001532 */
David Stevense5a7b642017-05-22 13:18:23 -07001533 private int getPreferedDisplayId(
1534 ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001535 // Check if the Activity is a VR activity. If so, the activity should be launched in
1536 // main display.
1537 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1538 return DEFAULT_DISPLAY;
1539 }
1540
1541 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001542 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001543 if (displayId != INVALID_DISPLAY) {
1544 if (DEBUG_STACK) {
1545 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1546 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001547 mUsingVr2dDisplay = true;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001548 return displayId;
1549 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001550
David Stevense5a7b642017-05-22 13:18:23 -07001551 // If the caller requested a display, prefer that display.
1552 final int launchDisplayId =
1553 (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1554 if (launchDisplayId != INVALID_DISPLAY) {
1555 return launchDisplayId;
1556 }
1557
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001558 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1559 // If the activity has a displayId set explicitly, launch it on the same displayId.
1560 if (displayId != INVALID_DISPLAY) {
1561 return displayId;
1562 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001563 return DEFAULT_DISPLAY;
1564 }
1565
1566 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001567 * Figure out which task and activity to bring to front when we have found an existing matching
1568 * activity record in history. May also clear the task if needed.
1569 * @param intentActivity Existing matching activity.
1570 * @return {@link ActivityRecord} brought to front.
1571 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001572 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001573 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001574 mTargetStack.mLastPausedActivity = null;
1575 // If the target task is not in the front, then we need to bring it to the front...
1576 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1577 // the same behavior as if a new instance was being started, which means not bringing it
1578 // to the front if the caller is not itself in the front.
1579 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1580 ActivityRecord curTop = (focusStack == null)
1581 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1582
Bryce Leeaf691c02017-03-20 14:20:22 -07001583 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1584 if (topTask != null
1585 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001586 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001587 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1588 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
Bryce Leeaf691c02017-03-20 14:20:22 -07001589 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001590 // We really do want to push this one into the user's face, right now.
1591 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001592 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001593 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001594 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001595
1596 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1597 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1598 // So no point resuming any of the activities here, it just wastes one extra
1599 // resuming, plus enter AND exit transitions.
1600 // Here we only want to bring the target stack forward. Transition will be applied
1601 // to the new activity that's started after the old ones are gone.
1602 final boolean willClearTask =
1603 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1604 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1605 if (!willClearTask) {
1606 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001607 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1608 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001609 if (launchStack == null || launchStack == mTargetStack) {
1610 // We only want to move to the front, if we aren't going to launch on a
1611 // different stack. If we launch on a different stack, we will put the
1612 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001613 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001614 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1615 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001616 } else if (launchStack.inSplitScreenWindowingMode()) {
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001617 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1618 // If we want to launch adjacent and mTargetStack is not the computed
1619 // launch stack - move task to top of computed stack.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001620 intentTask.reparent(launchStack, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001621 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1622 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001623 } else {
1624 // TODO: This should be reevaluated in MW v2.
1625 // We choose to move task to front instead of launching it adjacent
1626 // when specific stack was requested explicitly and it appeared to be
1627 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001628 mTargetStack.moveTaskToFrontLocked(intentTask,
1629 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001630 "bringToFrontInsteadOfAdjacentLaunch");
1631 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001632 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001633 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1634 // Target and computed stacks are on different displays and we've
1635 // found a matching task - move the existing instance to that display and
1636 // move it to front.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001637 intentActivity.getTask().reparent(launchStack, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001638 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1639 "reparentToDisplay");
1640 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001641 } else if (launchStack.isActivityTypeHome()
1642 && !mTargetStack.isActivityTypeHome()) {
Bryce Lee4ff7da92017-07-17 10:39:24 -07001643 // It is possible for the home activity to be in another stack initially.
1644 // For example, the activity may have been initially started with an intent
1645 // which placed it in the fullscreen stack. To ensure the proper handling of
1646 // the activity based on home stack assumptions, we must move it over.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001647 intentActivity.getTask().reparent(launchStack, ON_TOP,
Bryce Lee4ff7da92017-07-17 10:39:24 -07001648 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1649 "reparentingHome");
1650 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001651 }
1652 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001653
1654 // We are moving a task to the front, use starting window to hide initial drawn
1655 // delay.
1656 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1657 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001658 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001659 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001660 }
1661 }
1662 if (!mMovedToFront && mDoResume) {
1663 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1664 + " from " + intentActivity);
1665 mTargetStack.moveToFront("intentActivityFound");
1666 }
1667
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001668 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
1669 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001670
Wale Ogunwale01d66562015-12-29 08:19:19 -08001671 // If the caller has requested that the target task be reset, then do so.
1672 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1673 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1674 }
1675 return intentActivity;
1676 }
1677
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001678 private void updateTaskReturnToType(
1679 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001680 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001681 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1682 // Caller wants to appear on home activity.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001683 task.setTaskToReturnTo(ACTIVITY_TYPE_HOME);
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001684 return;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001685 } else if (focusedStack == null || focusedStack.isActivityTypeHome()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001686 // Task will be launched over the home stack, so return home.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001687 task.setTaskToReturnTo(ACTIVITY_TYPE_HOME);
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001688 return;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001689 } else if (focusedStack != task.getStack() && focusedStack.isActivityTypeAssistant()) {
Winson Chung83471632016-12-13 11:02:12 -08001690 // Task was launched over the assistant stack, so return there
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001691 task.setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT);
Winson Chung83471632016-12-13 11:02:12 -08001692 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001693 }
1694
1695 // Else we are coming from an application stack so return to an application.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001696 task.setTaskToReturnTo(ACTIVITY_TYPE_STANDARD);
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001697 }
1698
Wale Ogunwale01d66562015-12-29 08:19:19 -08001699 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1700 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1701 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1702 // The caller has requested to completely replace any existing task with its new
1703 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001704 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1705 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001706 // of history or if it is finished immediately), thus disassociating the task. Also note
1707 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1708 // launching another activity.
1709 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1710 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001711 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001712 task.performClearTaskLocked();
1713 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001714 mReuseTask.setIntent(mStartActivity);
1715
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001716 // When we clear the task - focus will be adjusted, which will bring another task
1717 // to top before we launch the activity we need. This will temporary swap their
1718 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1719 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001720 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1721 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001722 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001723 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001724 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001725 // A special case: we need to start the activity because it is not currently
1726 // running, and the caller has asked to clear the current task to have this
1727 // activity at the top.
1728 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001729
1730 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001731 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001732 // Now pretend like this activity is being started by the top of its task, so it
1733 // is put in the right place.
1734 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001735 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001736 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001737 // Target stack got cleared when we all activities were removed above.
1738 // Go ahead and reset it.
1739 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1740 null /* bounds */, mLaunchFlags, mOptions);
1741 mTargetStack.addTask(task,
1742 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1743 }
1744 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001745 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001746 // In this case the top activity on the task is the same as the one being launched,
1747 // so we take that as a request to bring the task to the foreground. If the top
1748 // activity in the task is the root activity, deliver this new intent to it if it
1749 // desires.
1750 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1751 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001752 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001753 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001754 }
Bryce Lee325e09682017-10-05 17:20:25 -07001755 deliverNewIntent(intentActivity);
Bryce Leeaf691c02017-03-20 14:20:22 -07001756 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001757 // In this case we are launching the root activity of the task, but with a
1758 // different intent. We should start a new instance on top.
1759 mAddingToTask = true;
1760 mSourceRecord = intentActivity;
1761 }
1762 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1763 // In this case an activity is being launched in to an existing task, without
1764 // resetting that task. This is typically the situation of launching an activity
1765 // from a notification or shortcut. We want to place the new activity on top of the
1766 // current task.
1767 mAddingToTask = true;
1768 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001769 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001770 // In this case we are launching into an existing task that has not yet been started
1771 // from its front door. The current task has been brought to the front. Ideally,
1772 // we'd probably like to place this new task at the bottom of its stack, but that's
1773 // a little hard to do with the current organization of the code so for now we'll
1774 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001775 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001776 }
1777 }
1778
1779 private void resumeTargetStackIfNeeded() {
1780 if (mDoResume) {
1781 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001782 } else {
1783 ActivityOptions.abort(mOptions);
1784 }
1785 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1786 }
1787
Chong Zhang6cda19c2016-06-14 19:07:56 -07001788 private int setTaskFromReuseOrCreateNewTask(
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001789 TaskRecord taskToAffiliate, ActivityStack topStack) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001790 mTargetStack = computeStackFocus(
1791 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1792
1793 // Do no move the target stack to front yet, as we might bail if
1794 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001795
1796 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001797 final TaskRecord task = mTargetStack.createTaskRecord(
1798 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001799 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001800 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001801 mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001802 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001803 updateBounds(mStartActivity.getTask(), mLaunchBounds);
1804
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001805 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001806 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001807 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001808 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1809 }
1810
1811 if (taskToAffiliate != null) {
1812 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001813 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001814
Benjamin Franza83859f2017-07-03 16:34:14 +01001815 if (mService.mLockTaskController.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001816 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1817 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1818 }
1819
1820 if (!mMovedOtherTask) {
1821 // If stack id is specified in activity options, usually it means that activity is
1822 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1823 // that case we check the target stack.
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001824 // TODO: Not sure I understand the value or use of the commented out code and the
1825 // comment above. See if this causes any issues and why...
Bryce Leeaf691c02017-03-20 14:20:22 -07001826 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001827 /*preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : */topStack);
Chong Zhang6cda19c2016-06-14 19:07:56 -07001828 }
1829 if (mDoResume) {
1830 mTargetStack.moveToFront("reuseOrNewTask");
1831 }
1832 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001833 }
1834
Bryce Lee325e09682017-10-05 17:20:25 -07001835 private void deliverNewIntent(ActivityRecord activity) {
1836 if (mIntentDelivered) {
1837 return;
1838 }
1839
1840 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
1841 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1842 mStartActivity.launchedFromPackage);
1843 mIntentDelivered = true;
1844 }
1845
Wale Ogunwale01d66562015-12-29 08:19:19 -08001846 private int setTaskFromSourceRecord() {
Benjamin Franza83859f2017-07-03 16:34:14 +01001847 if (mService.mLockTaskController.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001848 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1849 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1850 }
1851
Bryce Leeaf691c02017-03-20 14:20:22 -07001852 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001853 final ActivityStack sourceStack = mSourceRecord.getStack();
Andrii Kulian02689a72017-07-06 14:28:59 -07001854 // We only want to allow changing stack in two cases:
1855 // 1. If the target task is not the top one. Otherwise we would move the launching task to
1856 // the other side, rather than show two side by side.
1857 // 2. If activity is not allowed on target display.
1858 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
1859 : sourceStack.mDisplayId;
1860 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
1861 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001862 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001863 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001864 mOptions);
Andrii Kulian02689a72017-07-06 14:28:59 -07001865 // If target stack is not found now - we can't just rely on the source stack, as it may
1866 // be not suitable. Let's check other displays.
1867 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
1868 // Can't use target display, lets find a stack on the source display.
1869 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
1870 sourceStack.mDisplayId, mStartActivity);
1871 }
1872 if (mTargetStack == null) {
1873 // There are no suitable stacks on the target and source display(s). Look on all
1874 // displays.
1875 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
1876 mStartActivity, -1 /* currentFocus */);
1877 }
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001878 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001879
1880 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001881 mTargetStack = sourceStack;
1882 } else if (mTargetStack != sourceStack) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001883 sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
1884 DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001885 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001886
Wale Ogunwale01d66562015-12-29 08:19:19 -08001887 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001888 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001889 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1890 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001891 } else if (mDoResume) {
1892 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001893 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001894
Wale Ogunwale01d66562015-12-29 08:19:19 -08001895 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1896 // In this case, we are adding the activity to an existing task, but the caller has
1897 // asked to clear that task if the activity is already running.
1898 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1899 mKeepCurTransition = true;
1900 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001901 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Bryce Lee325e09682017-10-05 17:20:25 -07001902 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001903 // For paranoia, make sure we have correctly resumed the top activity.
1904 mTargetStack.mLastPausedActivity = null;
1905 if (mDoResume) {
1906 mSupervisor.resumeFocusedStackTopActivityLocked();
1907 }
1908 ActivityOptions.abort(mOptions);
1909 return START_DELIVERED_TO_TOP;
1910 }
1911 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1912 // In this case, we are launching an activity in our own task that may already be
1913 // running somewhere in the history, and we want to shuffle it to the front of the
1914 // stack if so.
1915 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1916 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001917 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001918 task.moveActivityToFrontLocked(top);
1919 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001920 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Bryce Lee325e09682017-10-05 17:20:25 -07001921 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001922 mTargetStack.mLastPausedActivity = null;
1923 if (mDoResume) {
1924 mSupervisor.resumeFocusedStackTopActivityLocked();
1925 }
1926 return START_DELIVERED_TO_TOP;
1927 }
1928 }
1929
1930 // An existing activity is starting this new activity, so we want to keep the new one in
1931 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001932 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001933 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001934 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001935 return START_SUCCESS;
1936 }
1937
1938 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001939 // The caller is asking that the new activity be started in an explicit
1940 // task it has provided to us.
Benjamin Franza83859f2017-07-03 16:34:14 +01001941 if (mService.mLockTaskController.isLockTaskModeViolation(mInTask)) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001942 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1943 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1944 }
1945
Andrii Kulian02b7a832016-10-06 23:11:56 -07001946 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001947
1948 // Check whether we should actually launch the new activity in to the task,
1949 // or just reuse the current activity on top.
1950 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001951 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1952 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001953 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1954 || mLaunchSingleTop || mLaunchSingleTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001955 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1956 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001957 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1958 // We don't need to start a new activity, and the client said not to do
1959 // anything if that is the case, so this is it!
1960 return START_RETURN_INTENT_TO_CALLER;
1961 }
Bryce Lee325e09682017-10-05 17:20:25 -07001962 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001963 return START_DELIVERED_TO_TOP;
1964 }
1965 }
1966
1967 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001968 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1969 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001970 // We don't actually want to have this activity added to the task, so just
1971 // stop here but still tell the caller that we consumed the intent.
1972 ActivityOptions.abort(mOptions);
1973 return START_TASK_TO_FRONT;
1974 }
1975
Yorke Lee64512522017-03-24 13:09:35 -07001976 if (mLaunchBounds != null) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001977 // TODO: Shouldn't we already know what stack to use by the time we get here?
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001978 ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
1979 if (stack != mInTask.getStack()) {
1980 mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
Yorke Lee64512522017-03-24 13:09:35 -07001981 DEFER_RESUME, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07001982 mTargetStack = mInTask.getStack();
1983 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001984
1985 updateBounds(mInTask, mLaunchBounds);
Yorke Lee64512522017-03-24 13:09:35 -07001986 }
1987
1988 mTargetStack.moveTaskToFrontLocked(
1989 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1990
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001991 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1992 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001993 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001994
1995 return START_SUCCESS;
1996 }
1997
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001998 void updateBounds(TaskRecord task, Rect bounds) {
1999 if (bounds == null) {
2000 return;
2001 }
2002
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002003 final ActivityStack stack = task.getStack();
2004 if (stack != null && stack.resizeStackWithLaunchBounds()) {
2005 mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002006 } else {
2007 task.updateOverrideConfiguration(bounds);
2008 }
2009 }
2010
Wale Ogunwale01d66562015-12-29 08:19:19 -08002011 private void setTaskToCurrentTopOrCreateNewTask() {
2012 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
2013 mOptions);
2014 if (mDoResume) {
2015 mTargetStack.moveToFront("addingToTopTask");
2016 }
2017 final ActivityRecord prev = mTargetStack.topActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07002018 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08002019 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07002020 mIntent, null, null, true);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002021 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2022 mTargetStack.positionChildWindowContainerAtTop(task);
2023 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002024 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002025 }
2026
2027 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002028 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002029 parent.addActivityToTop(mStartActivity);
2030 } else {
2031 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2032 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002033 }
2034
2035 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2036 boolean launchSingleTask, int launchFlags) {
2037 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2038 (launchSingleInstance || launchSingleTask)) {
2039 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2040 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2041 "\"singleInstance\" or \"singleTask\"");
2042 launchFlags &=
2043 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2044 } else {
2045 switch (r.info.documentLaunchMode) {
2046 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2047 break;
2048 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2049 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2050 break;
2051 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2052 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2053 break;
2054 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2055 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2056 break;
2057 }
2058 }
2059 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002060 }
2061
2062 final void doPendingActivityLaunchesLocked(boolean doResume) {
2063 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08002064 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
2065 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002066 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08002067 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
Bryce Lee4a194382017-04-04 14:32:48 -07002068 null, null /*outRecords*/);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002069 } catch (Exception e) {
2070 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
2071 pal.sendErrorResult(e.getMessage());
2072 }
2073 }
2074 }
2075
2076 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08002077 int launchFlags, ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002078 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002079 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002080 if (stack != null) {
2081 return stack;
2082 }
2083
Andrii Kulian02b7a832016-10-06 23:11:56 -07002084 final ActivityStack currentStack = task != null ? task.getStack() : null;
2085 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002086 if (mSupervisor.mFocusedStack != currentStack) {
2087 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2088 "computeStackFocus: Setting " + "focused stack to r=" + r
2089 + " task=" + task);
2090 } else {
2091 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2092 "computeStackFocus: Focused stack already="
2093 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002094 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002095 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002096 }
2097
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002098 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002099 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2100 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2101 return mSupervisor.mFocusedStack;
2102 }
2103
David Stevense5a7b642017-05-22 13:18:23 -07002104 if (mPreferredDisplayId != DEFAULT_DISPLAY) {
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002105 // Try to put the activity in a stack on a secondary display.
David Stevense5a7b642017-05-22 13:18:23 -07002106 stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002107 if (stack == null) {
2108 // If source display is not suitable - look for topmost valid stack in the system.
2109 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
David Stevense5a7b642017-05-22 13:18:23 -07002110 "computeStackFocus: Can't launch on mPreferredDisplayId="
2111 + mPreferredDisplayId + ", looking on all displays.");
2112 stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002113 }
2114 }
2115 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002116 // We first try to put the task in the first dynamic stack on home display.
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07002117 final ArrayList<ActivityStack> homeDisplayStacks =
2118 mSupervisor.getStacksOnDefaultDisplay();
David Stevensc6b91c62017-02-08 14:23:58 -08002119 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2120 stack = homeDisplayStacks.get(stackNdx);
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002121 if (!stack.isOnHomeDisplay()) {
David Stevensc6b91c62017-02-08 14:23:58 -08002122 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2123 "computeStackFocus: Setting focused stack=" + stack);
2124 return stack;
2125 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002126 }
David Stevensc6b91c62017-02-08 14:23:58 -08002127 // If there is no suitable dynamic stack then we figure out which static stack to use.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002128 stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002129 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002130 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2131 + r + " stackId=" + stack.mStackId);
2132 return stack;
2133 }
2134
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002135 /** Check if provided activity record can launch in currently focused stack. */
Wale Ogunwale68278562017-09-23 17:13:55 -07002136 // TODO: This method can probably be consolidated into getLaunchStack() below.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002137 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002138 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002139 final boolean canUseFocusedStack;
Wale Ogunwale68278562017-09-23 17:13:55 -07002140 if (focusedStack.isActivityTypeAssistant()) {
2141 canUseFocusedStack = r.isActivityTypeAssistant();
2142 } else {
2143 switch (focusedStack.getWindowingMode()) {
2144 case WINDOWING_MODE_FULLSCREEN:
2145 // The fullscreen stack can contain any task regardless of if the task is
2146 // resizeable or not. So, we let the task go in the fullscreen task if it is the
2147 // focus stack.
2148 canUseFocusedStack = true;
2149 break;
2150 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2151 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2152 // Any activity which supports split screen can go in the docked stack.
2153 canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2154 break;
2155 case WINDOWING_MODE_FREEFORM:
2156 // Any activity which supports freeform can go in the freeform stack.
2157 canUseFocusedStack = r.supportsFreeform();
2158 break;
2159 default:
2160 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2161 // resizeable task.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002162 canUseFocusedStack = !focusedStack.isOnHomeDisplay()
Wale Ogunwale68278562017-09-23 17:13:55 -07002163 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2164 }
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002165 }
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002166 return canUseFocusedStack && !newTask
Wale Ogunwale68278562017-09-23 17:13:55 -07002167 // Using the focus stack isn't important enough to override the preferred display.
David Stevense5a7b642017-05-22 13:18:23 -07002168 && (mPreferredDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002169 }
2170
Wale Ogunwale854809c2015-12-27 16:18:19 -08002171 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002172 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002173 // We are reusing a task, keep the stack!
2174 if (mReuseTask != null) {
2175 return mReuseTask.getStack();
2176 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002177
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002178 final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY;
2179 final ActivityStack launchStack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
2180 vrDisplayId);
Winson Chung83471632016-12-13 11:02:12 -08002181
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002182 if (launchStack != null) {
2183 return launchStack;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002184 }
2185
2186 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
David Stevense5a7b642017-05-22 13:18:23 -07002187 || mPreferredDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002188 return null;
2189 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002190 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002191
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002192 // The parent activity doesn't want to launch the activity on top of itself, but
2193 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002194 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002195
2196 if (parentStack != mSupervisor.mFocusedStack) {
2197 // If task's parent stack is not focused - use it during adjacent launch.
2198 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002199 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002200 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2201 // If task is already on top of focused stack - use it. We don't want to move the
2202 // existing focused task to adjacent stack, just deliver new intent in this case.
2203 return mSupervisor.mFocusedStack;
2204 }
2205
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002206 if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002207 // If parent was in docked stack, the natural place to launch another activity
2208 // will be fullscreen, so it can appear alongside the docked window.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002209 final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2210 return parentStack.getDisplay().getOrCreateStack(
2211 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002212 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002213 // If the parent is not in the docked stack, we check if there is docked window
2214 // and if yes, we will launch into that stack. If not, we just put the new
2215 // activity into parent's stack, because we can't find a better place.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002216 final ActivityStack dockedStack = mSupervisor.getDefaultDisplay().getStack(
2217 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07002218 if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002219 // There is a docked stack, but it isn't visible, so we can't launch into that.
2220 return null;
2221 } else {
2222 return dockedStack;
2223 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002224 }
2225 }
2226 }
2227
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002228 private Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002229 Rect newBounds = null;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002230 if (mSupervisor.canUseActivityOptionsLaunchBounds(options)
2231 && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
2232 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002233 }
2234 return newBounds;
2235 }
2236
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002237 void setWindowManager(WindowManagerService wm) {
2238 mWindowManager = wm;
2239 }
2240
Daichi Hirono15a02992016-04-27 18:47:01 +09002241 static boolean isDocumentLaunchesIntoExisting(int flags) {
2242 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2243 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2244 }
liulvpingcfa825f2016-09-26 20:00:15 +08002245
2246 boolean clearPendingActivityLaunchesLocked(String packageName) {
2247 boolean didSomething = false;
2248
2249 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2250 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2251 ActivityRecord r = pal.r;
2252 if (r != null && r.packageName.equals(packageName)) {
2253 mPendingActivityLaunches.remove(palNdx);
2254 didSomething = true;
2255 }
2256 }
2257 return didSomething;
2258 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002259
Dianne Hackborne676ec72017-07-25 10:55:08 -07002260 void dump(PrintWriter pw, String prefix, String dumpPackage) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002261 prefix = prefix + " ";
2262
Dianne Hackborne676ec72017-07-25 10:55:08 -07002263 if (dumpPackage != null) {
2264 if ((mLastStartActivityRecord[0] == null ||
2265 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2266 (mLastHomeActivityStartRecord[0] == null ||
2267 !dumpPackage.equals(mLastHomeActivityStartRecord[0].packageName)) &&
2268 (mStartActivity == null || !dumpPackage.equals(mStartActivity.packageName))) {
2269 pw.print(prefix);
2270 pw.println("(nothing)");
2271 return;
2272 }
2273 }
2274
2275 pw.print(prefix);
2276 pw.print("mCurrentUser=");
2277 pw.println(mSupervisor.mCurrentUser);
2278 pw.print(prefix);
2279 pw.print("mLastStartReason=");
2280 pw.println(mLastStartReason);
2281 pw.print(prefix);
2282 pw.print("mLastStartActivityTimeMs=");
2283 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2284 pw.print(prefix);
2285 pw.print("mLastStartActivityResult=");
2286 pw.println(mLastStartActivityResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002287 ActivityRecord r = mLastStartActivityRecord[0];
2288 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002289 pw.print(prefix);
2290 pw.println("mLastStartActivityRecord:");
2291 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002292 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002293 pw.print(prefix);
2294 pw.print("mLastHomeActivityStartResult=");
2295 pw.println(mLastHomeActivityStartResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002296 r = mLastHomeActivityStartRecord[0];
2297 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002298 pw.print(prefix);
2299 pw.println("mLastHomeActivityStartRecord:");
2300 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002301 }
2302 if (mStartActivity != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002303 pw.print(prefix);
2304 pw.println("mStartActivity:");
2305 mStartActivity.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002306 }
2307 if (mIntent != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002308 pw.print(prefix);
2309 pw.print("mIntent=");
2310 pw.println(mIntent);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002311 }
2312 if (mOptions != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002313 pw.print(prefix);
2314 pw.print("mOptions=");
2315 pw.println(mOptions);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002316 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002317 pw.print(prefix);
2318 pw.print("mLaunchSingleTop=");
2319 pw.print(mLaunchSingleTop);
2320 pw.print(" mLaunchSingleInstance=");
2321 pw.print(mLaunchSingleInstance);
2322 pw.print(" mLaunchSingleTask=");
2323 pw.println(mLaunchSingleTask);
2324 pw.print(prefix);
2325 pw.print("mLaunchFlags=0x");
2326 pw.print(Integer.toHexString(mLaunchFlags));
2327 pw.print(" mDoResume=");
2328 pw.print(mDoResume);
2329 pw.print(" mAddingToTask=");
2330 pw.println(mAddingToTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002331 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002332}