blob: 50d5f962e86779fbcaaf9ad0f3ea59049223c92b [file] [log] [blame]
Kenny Guyb1b30262016-02-09 16:02:35 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080017package com.android.server.am;
18
Wale Ogunwale01d66562015-12-29 08:19:19 -080019import static android.app.Activity.RESULT_CANCELED;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080020import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080021import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
22import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
23import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
24import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
25import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
26import static android.app.ActivityManager.START_SUCCESS;
27import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale854809c2015-12-27 16:18:19 -080028import static android.app.ActivityManager.StackId;
Winson Chung83471632016-12-13 11:02:12 -080029import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080030import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
31import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
32import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080033import static android.app.ActivityManager.StackId.HOME_STACK_ID;
34import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
35import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080036import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Andrii Kulian4ede3e02017-01-12 11:52:31 -080037import static android.app.ActivityManager.StackId.isDynamicStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
39import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010040import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080041import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080042import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080044import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080045import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
46import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080047import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
48import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
49import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
50import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
51import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080052import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080053import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
54import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
56import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080057import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070058import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080059import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080062import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080063import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
65import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
66import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
71import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
72import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
73import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080074import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -080075import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080077import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080078import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080079import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
Winson Chung74666102017-02-22 17:49:24 -080080import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080081import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080082import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080083import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080084import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080085import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
86import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
87
Todd Kennedye9910222017-02-21 16:00:11 -080088import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080089import android.app.ActivityManager;
90import android.app.ActivityOptions;
91import android.app.AppGlobals;
92import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080093import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.app.PendingIntent;
95import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070096import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.content.ComponentName;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080098import android.content.IIntentSender;
99import android.content.Intent;
100import android.content.IntentSender;
101import android.content.pm.ActivityInfo;
102import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -0800103import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000104import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800105import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000106import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.content.res.Configuration;
108import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700109import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800111import android.os.Bundle;
112import android.os.IBinder;
113import android.os.RemoteException;
114import android.os.SystemClock;
115import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000116import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800117import android.service.voice.IVoiceInteractionSession;
118import android.util.EventLog;
119import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800120
121import com.android.internal.app.HeavyWeightSwitcherActivity;
122import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800123import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800124import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800125import com.android.server.wm.WindowManagerService;
126
127import java.util.ArrayList;
128
129/**
130 * Controller for interpreting how and then launching activities.
131 *
132 * This class collects all the logic for determining how an intent and flags should be turned into
133 * an activity and associated task and stack.
134 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800135class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800136 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
137 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
138 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
139 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
140 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
141
142 private final ActivityManagerService mService;
143 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000144 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800145 private WindowManagerService mWindowManager;
146
147 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
148
Wale Ogunwale01d66562015-12-29 08:19:19 -0800149 // Share state variable among methods when starting an activity.
150 private ActivityRecord mStartActivity;
151 private Intent mIntent;
152 private int mCallingUid;
153 private ActivityOptions mOptions;
154
155 private boolean mLaunchSingleTop;
156 private boolean mLaunchSingleInstance;
157 private boolean mLaunchSingleTask;
158 private boolean mLaunchTaskBehind;
159 private int mLaunchFlags;
160
161 private Rect mLaunchBounds;
162
163 private ActivityRecord mNotTop;
164 private boolean mDoResume;
165 private int mStartFlags;
166 private ActivityRecord mSourceRecord;
David Stevensc6b91c62017-02-08 14:23:58 -0800167 private int mSourceDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800168
169 private TaskRecord mInTask;
170 private boolean mAddingToTask;
171 private TaskRecord mReuseTask;
172
173 private ActivityInfo mNewTaskInfo;
174 private Intent mNewTaskIntent;
175 private ActivityStack mSourceStack;
176 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700177 // Indicates that we moved other task and are going to put something on top soon, so
178 // we don't want to show it redundantly or accidentally change what's shown below.
179 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800180 private boolean mMovedToFront;
181 private boolean mNoAnimation;
182 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700183 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700184 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800185
186 private IVoiceInteractionSession mVoiceSession;
187 private IVoiceInteractor mVoiceInteractor;
188
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700189 private boolean mUsingVr2dDisplay;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800190
Wale Ogunwale01d66562015-12-29 08:19:19 -0800191 private void reset() {
192 mStartActivity = null;
193 mIntent = null;
194 mCallingUid = -1;
195 mOptions = null;
196
197 mLaunchSingleTop = false;
198 mLaunchSingleInstance = false;
199 mLaunchSingleTask = false;
200 mLaunchTaskBehind = false;
201 mLaunchFlags = 0;
202
203 mLaunchBounds = null;
204
205 mNotTop = null;
206 mDoResume = false;
207 mStartFlags = 0;
208 mSourceRecord = null;
David Stevensc6b91c62017-02-08 14:23:58 -0800209 mSourceDisplayId = INVALID_DISPLAY;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800210
211 mInTask = null;
212 mAddingToTask = false;
213 mReuseTask = null;
214
215 mNewTaskInfo = null;
216 mNewTaskIntent = null;
217 mSourceStack = null;
218
219 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700220 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800221 mMovedToFront = false;
222 mNoAnimation = false;
223 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700224 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800225
226 mVoiceSession = null;
227 mVoiceInteractor = null;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800228
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700229 mUsingVr2dDisplay = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800230 }
231
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800232 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
233 mService = service;
234 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000235 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700236 mUsingVr2dDisplay = false;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800237 }
238
239 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
240 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
241 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
242 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
243 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
244 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
245 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
246 TaskRecord inTask) {
247 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700248 // Pull the optional Ephemeral Installer-only bundle out of the options early.
249 final Bundle verificationBundle
250 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800251
252 ProcessRecord callerApp = null;
253 if (caller != null) {
254 callerApp = mService.getRecordForAppLocked(caller);
255 if (callerApp != null) {
256 callingPid = callerApp.pid;
257 callingUid = callerApp.info.uid;
258 } else {
259 Slog.w(TAG, "Unable to find app for caller " + caller
260 + " (pid=" + callingPid + ") when starting: "
261 + intent.toString());
262 err = ActivityManager.START_PERMISSION_DENIED;
263 }
264 }
265
266 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
267
268 if (err == ActivityManager.START_SUCCESS) {
269 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800270 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800271 }
272
273 ActivityRecord sourceRecord = null;
274 ActivityRecord resultRecord = null;
275 if (resultTo != null) {
276 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
277 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
278 "Will send result to " + resultTo + " " + sourceRecord);
279 if (sourceRecord != null) {
280 if (requestCode >= 0 && !sourceRecord.finishing) {
281 resultRecord = sourceRecord;
282 }
283 }
284 }
285
286 final int launchFlags = intent.getFlags();
287
288 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
289 // Transfer the result target from the source activity to the new
290 // one being started, including any failures.
291 if (requestCode >= 0) {
292 ActivityOptions.abort(options);
293 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
294 }
295 resultRecord = sourceRecord.resultTo;
296 if (resultRecord != null && !resultRecord.isInStackLocked()) {
297 resultRecord = null;
298 }
299 resultWho = sourceRecord.resultWho;
300 requestCode = sourceRecord.requestCode;
301 sourceRecord.resultTo = null;
302 if (resultRecord != null) {
303 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
304 }
305 if (sourceRecord.launchedFromUid == callingUid) {
306 // The new activity is being launched from the same uid as the previous
307 // activity in the flow, and asking to forward its result back to the
308 // previous. In this case the activity is serving as a trampoline between
309 // the two, so we also want to update its launchedFromPackage to be the
310 // same as the previous activity. Note that this is safe, since we know
311 // these two packages come from the same uid; the caller could just as
312 // well have supplied that same package name itself. This specifially
313 // deals with the case of an intent picker/chooser being launched in the app
314 // flow to redirect to an activity picked by the user, where we want the final
315 // activity to consider it to have been launched by the previous app activity.
316 callingPackage = sourceRecord.launchedFromPackage;
317 }
318 }
319
320 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
321 // We couldn't find a class that can handle the given Intent.
322 // That's the end of that!
323 err = ActivityManager.START_INTENT_NOT_RESOLVED;
324 }
325
326 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
327 // We couldn't find the specific class specified in the Intent.
328 // Also the end of the line.
329 err = ActivityManager.START_CLASS_NOT_FOUND;
330 }
331
332 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700333 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800334 // If this activity is being launched as part of a voice session, we need
335 // to ensure that it is safe to do so. If the upcoming activity will also
336 // be part of the voice session, we can only launch it if it has explicitly
337 // said it supports the VOICE category, or it is a part of the calling app.
338 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
339 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
340 try {
341 intent.addCategory(Intent.CATEGORY_VOICE);
342 if (!AppGlobals.getPackageManager().activitySupportsIntent(
343 intent.getComponent(), intent, resolvedType)) {
344 Slog.w(TAG,
345 "Activity being started in current voice task does not support voice: "
346 + intent);
347 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
348 }
349 } catch (RemoteException e) {
350 Slog.w(TAG, "Failure checking voice capabilities", e);
351 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
352 }
353 }
354 }
355
356 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
357 // If the caller is starting a new voice session, just make sure the target
358 // is actually allowing it to run this way.
359 try {
360 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
361 intent, resolvedType)) {
362 Slog.w(TAG,
363 "Activity being started in new voice task does not support: "
364 + intent);
365 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
366 }
367 } catch (RemoteException e) {
368 Slog.w(TAG, "Failure checking voice capabilities", e);
369 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
370 }
371 }
372
Andrii Kulian02b7a832016-10-06 23:11:56 -0700373 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800374
Wale Ogunwale01d66562015-12-29 08:19:19 -0800375 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800376 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800377 resultStack.sendActivityResultLocked(
378 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800379 }
380 ActivityOptions.abort(options);
381 return err;
382 }
383
384 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
385 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100386 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800387 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
388 callingPid, resolvedType, aInfo.applicationInfo);
389
390 if (mService.mController != null) {
391 try {
392 // The Intent we give to the watcher has the extra data
393 // stripped off, since it can contain private information.
394 Intent watchIntent = intent.cloneFilter();
395 abort |= !mService.mController.activityStarting(watchIntent,
396 aInfo.applicationInfo.packageName);
397 } catch (RemoteException e) {
398 mService.mController = null;
399 }
400 }
401
Rubin Xu58d25992016-01-21 17:47:13 +0000402 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100403 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
404 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000405 intent = mInterceptor.mIntent;
406 rInfo = mInterceptor.mRInfo;
407 aInfo = mInterceptor.mAInfo;
408 resolvedType = mInterceptor.mResolvedType;
409 inTask = mInterceptor.mInTask;
410 callingPid = mInterceptor.mCallingPid;
411 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100412 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800413 if (abort) {
414 if (resultRecord != null) {
415 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800416 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800417 }
418 // We pretend to the caller that it was really started, but
419 // they will just get a cancel result.
420 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800421 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800422 }
423
424 // If permissions need a review before any of the app components can run, we
425 // launch the review activity and pass a pending intent to start the activity
426 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700427 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800428 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
429 aInfo.packageName, userId)) {
430 IIntentSender target = mService.getIntentSenderLocked(
431 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
432 callingUid, userId, null, null, 0, new Intent[]{intent},
433 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
434 | PendingIntent.FLAG_ONE_SHOT, null);
435
436 final int flags = intent.getFlags();
437 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
438 newIntent.setFlags(flags
439 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
440 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
441 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
442 if (resultRecord != null) {
443 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
444 }
445 intent = newIntent;
446
447 resolvedType = null;
448 callingUid = realCallingUid;
449 callingPid = realCallingPid;
450
451 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
452 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
453 null /*profilerInfo*/);
454
455 if (DEBUG_PERMISSIONS_REVIEW) {
456 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
457 true, false) + "} from uid " + callingUid + " on display "
458 + (container == null ? (mSupervisor.mFocusedStack == null ?
David Stevensc6b91c62017-02-08 14:23:58 -0800459 DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
460 (container.mActivityDisplay == null ? DEFAULT_DISPLAY :
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800461 container.mActivityDisplay.mDisplayId)));
462 }
463 }
464 }
465
466 // If we have an ephemeral app, abort the process of launching the resolved intent.
467 // Instead, launch the ephemeral installer. Once the installer is finished, it
468 // starts either the intent we resolved here [on install error] or the ephemeral
469 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800470 if (rInfo != null && rInfo.auxiliaryInfo != null) {
471 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700472 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800473 resolvedType = null;
474 callingUid = realCallingUid;
475 callingPid = realCallingPid;
476
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800477 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
478 }
479
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800480 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
481 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
482 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
483 mSupervisor, container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800484 if (outActivity != null) {
485 outActivity[0] = r;
486 }
487
488 if (r.appTimeTracker == null && sourceRecord != null) {
489 // If the caller didn't specify an explicit time tracker, we want to continue
490 // tracking under any it has.
491 r.appTimeTracker = sourceRecord.appTimeTracker;
492 }
493
494 final ActivityStack stack = mSupervisor.mFocusedStack;
495 if (voiceSession == null && (stack.mResumedActivity == null
496 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
497 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
498 realCallingPid, realCallingUid, "Activity start")) {
499 PendingActivityLaunch pal = new PendingActivityLaunch(r,
500 sourceRecord, startFlags, stack, callerApp);
501 mPendingActivityLaunches.add(pal);
502 ActivityOptions.abort(options);
503 return ActivityManager.START_SWITCHES_CANCELED;
504 }
505 }
506
507 if (mService.mDidAppSwitch) {
508 // This is the second allowed switch since we stopped switches,
509 // so now just generally allow switches. Use case: user presses
510 // home (switches disabled, switch to home, mDidAppSwitch now true);
511 // user taps a home icon (coming from home so allowed, we hit here
512 // and now allow anyone to switch again).
513 mService.mAppSwitchesAllowedTime = 0;
514 } else {
515 mService.mDidAppSwitch = true;
516 }
517
518 doPendingActivityLaunchesLocked(false);
519
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800520 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
Bryce Lee4a194382017-04-04 14:32:48 -0700521 options, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800522 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800523
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800524 /**
525 * Creates a launch intent for the given auxiliary resolution data.
526 */
Todd Kennedye9910222017-02-21 16:00:11 -0800527 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700528 Intent originalIntent, String callingPackage, Bundle verificationBundle,
529 String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800530 if (auxiliaryResponse.needsPhaseTwo) {
531 // request phase two resolution
532 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700533 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
534 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800535 }
Todd Kennedy1fb34042017-03-01 13:56:58 -0800536 return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
Todd Kennedy7dd99e32017-05-03 16:12:49 -0700537 auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
538 resolvedType, userId, auxiliaryResponse.packageName,
Todd Kennedy1fb34042017-03-01 13:56:58 -0800539 auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
540 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800541 }
542
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800543 void postStartActivityProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700544 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
545 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800546
Bryce Lee7f936862017-05-09 15:33:18 -0700547 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800548 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800549 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800550
Chong Zhang5022da32016-06-21 16:31:37 -0700551 // We're waiting for an activity launch to finish, but that activity simply
552 // brought another activity to front. Let startActivityMayWait() know about
553 // this, so it waits for the new activity to become visible instead.
554 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
555 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
556 }
557
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800558 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700559 final ActivityStack currentStack = r.getStack();
560 if (currentStack != null) {
561 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800562 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700563 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800564 }
565
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700566 if (startedActivityStackId == DOCKED_STACK_ID) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100567 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700568 final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
569 if (homeStackVisible) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100570 // We launch an activity while being in home stack, which means either launcher or
571 // recents into docked stack. We don't want the launched activity to be alone in a
572 // docked stack, so we want to immediately launch recents too.
573 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700574 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100575 }
Wale Ogunwalecd501ec2017-04-07 08:53:41 -0700576 return;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800577 }
578
Winson Chunge6385a22017-05-02 18:15:16 -0700579 boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
Winson Chunge0c3d5d2017-05-04 18:25:21 -0700580 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
Winson Chunge6385a22017-05-02 18:15:16 -0700581 if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
582 || result == START_DELIVERED_TO_TOP || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800583 // The activity was already running in the pinned stack so it wasn't started, but either
584 // brought to the front or the new intent was delivered to it since it was already in
585 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700586 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
587 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800588 return;
589 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800590 }
591
592 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800593 mSupervisor.moveHomeStackTaskToTop(reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800594 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
595 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
596 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
597 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
598 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700599 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800600 null /*container*/, null /*inTask*/);
601 if (mSupervisor.inResumeTopActivity) {
602 // If we are in resume section already, home activity will be initialized, but not
603 // resumed (to avoid recursive resume) and will stay that way until something pokes it
604 // again. We need to schedule another resume.
605 mSupervisor.scheduleResumeTopActivities();
606 }
607 }
608
Robin Lee5d592422017-01-18 13:48:15 +0000609 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100610 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
611 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
612 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000613 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
614 : ActivityOptions.makeBasic());
Bryce Leeaf691c02017-03-20 14:20:22 -0700615 options.setLaunchTaskId(mSupervisor.getHomeActivity().getTask().taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000616 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100617 }
Tony Mak853304c2016-04-18 15:17:41 +0100618
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800619 final int startActivityMayWait(IApplicationThread caller, int callingUid,
620 String callingPackage, Intent intent, String resolvedType,
621 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
622 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700623 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700624 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800625 IActivityContainer iContainer, TaskRecord inTask) {
626 // Refuse possible leaked file descriptors
627 if (intent != null && intent.hasFileDescriptors()) {
628 throw new IllegalArgumentException("File descriptors passed in Intent");
629 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500630 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800631 boolean componentSpecified = intent.getComponent() != null;
632
633 // Save a copy in case ephemeral needs it
634 final Intent ephemeralIntent = new Intent(intent);
635 // Don't modify the client's object!
636 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700637 if (componentSpecified
638 && intent.getData() != null
639 && Intent.ACTION_VIEW.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700640 && mService.getPackageManagerInternalLocked()
641 .isInstantAppInstallerComponent(intent.getComponent())) {
642 // intercept intents targeted directly to the ephemeral installer the
643 // ephemeral installer should never be started with a raw URL; instead
644 // adjust the intent so it looks like a "normal" instant app launch
645 intent.setComponent(null /*component*/);
646 componentSpecified = false;
647 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800648
649 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000650 if (rInfo == null) {
651 UserInfo userInfo = mSupervisor.getUserInfo(userId);
652 if (userInfo != null && userInfo.isManagedProfile()) {
653 // Special case for managed profiles, if attempting to launch non-cryto aware
654 // app in a locked managed profile from an unlocked parent allow it to resolve
655 // as user will be sent via confirm credentials to unlock the profile.
656 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700657 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000658 long token = Binder.clearCallingIdentity();
659 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700660 UserInfo parent = userManager.getProfileParent(userId);
661 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
662 && userManager.isUserUnlockingOrUnlocked(parent.id)
663 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000664 } finally {
665 Binder.restoreCallingIdentity(token);
666 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700667 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000668 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600669 PackageManager.MATCH_DIRECT_BOOT_AWARE
670 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000671 }
672 }
673 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800674 // Collect information about the target of the Intent.
675 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
676
677 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
678 ActivityStackSupervisor.ActivityContainer container =
679 (ActivityStackSupervisor.ActivityContainer)iContainer;
680 synchronized (mService) {
681 if (container != null && container.mParentActivity != null &&
682 container.mParentActivity.state != RESUMED) {
683 // Cannot start a child activity if the parent is not resumed.
684 return ActivityManager.START_CANCELED;
685 }
686 final int realCallingPid = Binder.getCallingPid();
687 final int realCallingUid = Binder.getCallingUid();
688 int callingPid;
689 if (callingUid >= 0) {
690 callingPid = -1;
691 } else if (caller == null) {
692 callingPid = realCallingPid;
693 callingUid = realCallingUid;
694 } else {
695 callingPid = callingUid = -1;
696 }
697
698 final ActivityStack stack;
699 if (container == null || container.mStack.isOnHomeDisplay()) {
700 stack = mSupervisor.mFocusedStack;
701 } else {
702 stack = container.mStack;
703 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700704 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700705 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800706 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
707 "Starting activity when config will change = " + stack.mConfigWillChange);
708
709 final long origId = Binder.clearCallingIdentity();
710
711 if (aInfo != null &&
712 (aInfo.applicationInfo.privateFlags
713 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
714 // This may be a heavy-weight process! Check to see if we already
715 // have another, different heavy-weight process running.
716 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
717 final ProcessRecord heavy = mService.mHeavyWeightProcess;
718 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
719 || !heavy.processName.equals(aInfo.processName))) {
720 int appCallingUid = callingUid;
721 if (caller != null) {
722 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
723 if (callerApp != null) {
724 appCallingUid = callerApp.info.uid;
725 } else {
726 Slog.w(TAG, "Unable to find app for caller " + caller
727 + " (pid=" + callingPid + ") when starting: "
728 + intent.toString());
729 ActivityOptions.abort(options);
730 return ActivityManager.START_PERMISSION_DENIED;
731 }
732 }
733
734 IIntentSender target = mService.getIntentSenderLocked(
735 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
736 appCallingUid, userId, null, null, 0, new Intent[] { intent },
737 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
738 | PendingIntent.FLAG_ONE_SHOT, null);
739
740 Intent newIntent = new Intent();
741 if (requestCode >= 0) {
742 // Caller is requesting a result.
743 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
744 }
745 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
746 new IntentSender(target));
747 if (heavy.activities.size() > 0) {
748 ActivityRecord hist = heavy.activities.get(0);
749 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
750 hist.packageName);
751 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -0700752 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800753 }
754 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
755 aInfo.packageName);
756 newIntent.setFlags(intent.getFlags());
757 newIntent.setClassName("android",
758 HeavyWeightSwitcherActivity.class.getName());
759 intent = newIntent;
760 resolvedType = null;
761 caller = null;
762 callingUid = Binder.getCallingUid();
763 callingPid = Binder.getCallingPid();
764 componentSpecified = true;
765 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
766 aInfo = rInfo != null ? rInfo.activityInfo : null;
767 if (aInfo != null) {
768 aInfo = mService.getActivityInfoForUser(aInfo, userId);
769 }
770 }
771 }
772 }
773
Jorim Jaggi275561a2016-02-23 10:11:02 -0500774 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800775 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
776 aInfo, rInfo, voiceSession, voiceInteractor,
777 resultTo, resultWho, requestCode, callingPid,
778 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500779 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
780 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800781
782 Binder.restoreCallingIdentity(origId);
783
784 if (stack.mConfigWillChange) {
785 // If the caller also wants to switch to a new configuration,
786 // do so now. This allows a clean switch, as we are waiting
787 // for the current activity to pause (so we will not destroy
788 // it), and have not yet started the next activity.
789 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
790 "updateConfiguration()");
791 stack.mConfigWillChange = false;
792 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
793 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700794 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800795 }
796
797 if (outResult != null) {
798 outResult.result = res;
799 if (res == ActivityManager.START_SUCCESS) {
800 mSupervisor.mWaitingActivityLaunched.add(outResult);
801 do {
802 try {
803 mService.wait();
804 } catch (InterruptedException e) {
805 }
Chong Zhang5022da32016-06-21 16:31:37 -0700806 } while (outResult.result != START_TASK_TO_FRONT
807 && !outResult.timeout && outResult.who == null);
808 if (outResult.result == START_TASK_TO_FRONT) {
809 res = START_TASK_TO_FRONT;
810 }
811 }
812 if (res == START_TASK_TO_FRONT) {
Bryce Lee4a194382017-04-04 14:32:48 -0700813 final ActivityRecord r = outRecord[0];
814
815 // ActivityRecord may represent a different activity, but it should not be in
816 // the resumed state.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800817 if (r.nowVisible && r.state == RESUMED) {
818 outResult.timeout = false;
Bryce Lee4a194382017-04-04 14:32:48 -0700819 outResult.who = r.realActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800820 outResult.totalTime = 0;
821 outResult.thisTime = 0;
822 } else {
823 outResult.thisTime = SystemClock.uptimeMillis();
Bryce Lee4a194382017-04-04 14:32:48 -0700824 mSupervisor.waitActivityVisible(r.realActivity, outResult);
825 // Note: the timeout variable is not currently not ever set.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800826 do {
827 try {
828 mService.wait();
829 } catch (InterruptedException e) {
830 }
831 } while (!outResult.timeout && outResult.who == null);
832 }
833 }
834 }
835
Bryce Lee4a194382017-04-04 14:32:48 -0700836 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800837 return res;
838 }
839 }
840
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800841 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
842 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
843 Bundle bOptions, int userId) {
844 if (intents == null) {
845 throw new NullPointerException("intents is null");
846 }
847 if (resolvedTypes == null) {
848 throw new NullPointerException("resolvedTypes is null");
849 }
850 if (intents.length != resolvedTypes.length) {
851 throw new IllegalArgumentException("intents are length different than resolvedTypes");
852 }
853
Makoto Onukid67b1872016-07-21 16:26:36 -0700854 final int realCallingPid = Binder.getCallingPid();
855 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800856
857 int callingPid;
858 if (callingUid >= 0) {
859 callingPid = -1;
860 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700861 callingPid = realCallingPid;
862 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800863 } else {
864 callingPid = callingUid = -1;
865 }
866 final long origId = Binder.clearCallingIdentity();
867 try {
868 synchronized (mService) {
869 ActivityRecord[] outActivity = new ActivityRecord[1];
870 for (int i=0; i<intents.length; i++) {
871 Intent intent = intents[i];
872 if (intent == null) {
873 continue;
874 }
875
876 // Refuse possible leaked file descriptors
877 if (intent != null && intent.hasFileDescriptors()) {
878 throw new IllegalArgumentException("File descriptors passed in Intent");
879 }
880
881 boolean componentSpecified = intent.getComponent() != null;
882
883 // Don't modify the client's object!
884 intent = new Intent(intent);
885
886 // Collect information about the target of the Intent.
887 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
888 null, userId);
889 // TODO: New, check if this is correct
890 aInfo = mService.getActivityInfoForUser(aInfo, userId);
891
892 if (aInfo != null &&
893 (aInfo.applicationInfo.privateFlags
894 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
895 throw new IllegalArgumentException(
896 "FLAG_CANT_SAVE_STATE not supported here");
897 }
898
899 ActivityOptions options = ActivityOptions.fromBundle(
900 i == intents.length - 1 ? bOptions : null);
901 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
902 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700903 callingPid, callingUid, callingPackage,
904 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800905 options, false, componentSpecified, outActivity, null, null);
906 if (res < 0) {
907 return res;
908 }
909
910 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
911 }
912 }
913 } finally {
914 Binder.restoreCallingIdentity(origId);
915 }
916
Wale Ogunwale01d66562015-12-29 08:19:19 -0800917 return START_SUCCESS;
918 }
919
Wei Wang65c7a152016-06-02 18:51:22 -0700920 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
Bryce Lee834abec2017-01-09 16:18:14 -0800921 boolean sendHint = forceSend;
922
923 if (!sendHint) {
924 // If not forced, send power hint when the activity's process is different than the
925 // current resumed activity.
926 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
927 sendHint = resumedActivity == null
928 || resumedActivity.app == null
929 || !resumedActivity.app.equals(mStartActivity.app);
930 }
931
932 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700933 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700934 mPowerHintSent = true;
935 }
936 }
937
Wei Wang65c7a152016-06-02 18:51:22 -0700938 void sendPowerHintForLaunchEndIfNeeded() {
939 // Trigger launch power hint if activity is launched
940 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700941 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700942 mPowerHintSent = false;
943 }
944 }
945
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800946 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
947 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700948 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
949 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800950 int result = START_CANCELED;
951 try {
952 mService.mWindowManager.deferSurfaceLayout();
953 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700954 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800955 } finally {
956 // If we are not able to proceed, disassociate the activity from the task. Leaving an
957 // activity in an incomplete state can lead to issues, such as performing operations
958 // without a window container.
Bryce Lee7f936862017-05-09 15:33:18 -0700959 if (ActivityManager.isStartResultFatalError(result)
960 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700961 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800962 }
963 mService.mWindowManager.continueSurfaceLayout();
964 }
965
Matthew Ng0e205602017-03-22 14:23:25 -0700966 postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800967 mTargetStack);
968
969 return result;
970 }
971
972 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -0800973 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
974 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700975 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
976 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800977
978 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
979 voiceInteractor);
980
981 computeLaunchingTaskFlags();
982
983 computeSourceStack();
984
985 mIntent.setFlags(mLaunchFlags);
986
Bryce Lee4a194382017-04-04 14:32:48 -0700987 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800988
Jorim Jaggi2adba072016-03-03 13:43:39 +0100989 final int preferredLaunchStackId =
990 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700991 final int preferredLaunchDisplayId =
992 (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
Jorim Jaggi2adba072016-03-03 13:43:39 +0100993
Bryce Lee4a194382017-04-04 14:32:48 -0700994 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800995 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
996 // still needs to be a lock task mode violation since the task gets cleared out and
997 // the device would otherwise leave the locked task.
Bryce Lee4a194382017-04-04 14:32:48 -0700998 if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -0800999 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1000 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1001 mSupervisor.showLockTaskToast();
1002 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1003 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1004 }
1005
Bryce Leeaf691c02017-03-20 14:20:22 -07001006 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001007 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001008 }
Bryce Lee4a194382017-04-04 14:32:48 -07001009 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001010 // This task was started because of movement of the activity based on affinity...
1011 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001012 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001013 }
1014
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001015 // This code path leads to delivering a new intent, we want to make sure we schedule it
1016 // as the first operation, in case the activity will be resumed as a result of later
1017 // operations.
1018 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001019 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001020 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Lee4a194382017-04-04 14:32:48 -07001021 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001022
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001023 // In this situation we want to remove all activities from the task up to the one
1024 // being started. In most cases this means we are resetting the task to its initial
1025 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001026 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1027 mLaunchFlags);
1028
Bryce Lee4a194382017-04-04 14:32:48 -07001029 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001030 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1031 // task reference is needed in the call below to
1032 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001033 if (reusedActivity.getTask() == null) {
1034 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001035 }
1036
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001037 if (top != null) {
1038 if (top.frontOfTask) {
1039 // Activity aliases may mean we use different intents for the top activity,
1040 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001041 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001042 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001043 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001044 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1045 mStartActivity.launchedFromPackage);
1046 }
1047 }
1048
Wei Wang65c7a152016-06-02 18:51:22 -07001049 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001050
Bryce Lee4a194382017-04-04 14:32:48 -07001051 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001052
Bryce Lee89cd19a2017-05-17 15:18:35 -07001053 final ActivityRecord outResult =
1054 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1055
1056 // When there is a reused activity and the current result is a trampoline activity,
1057 // set the reused activity as the result.
1058 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1059 outActivity[0] = reusedActivity;
1060 }
1061
Wale Ogunwale01d66562015-12-29 08:19:19 -08001062 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1063 // We don't need to start a new activity, and the client said not to do anything
1064 // if that is the case, so this is it! And for paranoia, make sure we have
1065 // correctly resumed the top activity.
1066 resumeTargetStackIfNeeded();
1067 return START_RETURN_INTENT_TO_CALLER;
1068 }
Bryce Lee4a194382017-04-04 14:32:48 -07001069 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001070
1071 if (!mAddingToTask && mReuseTask == null) {
1072 // We didn't do anything... but it was needed (a.k.a., client don't use that
1073 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1074 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001075 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001076 outActivity[0] = reusedActivity;
1077 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001078 return START_TASK_TO_FRONT;
1079 }
1080 }
1081
1082 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001083 final ActivityStack sourceStack = mStartActivity.resultTo != null
1084 ? mStartActivity.resultTo.getStack() : null;
1085 if (sourceStack != null) {
1086 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1087 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1088 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001089 }
1090 ActivityOptions.abort(mOptions);
1091 return START_CLASS_NOT_FOUND;
1092 }
1093
1094 // If the activity being launched is the same as the one currently at the top, then
1095 // we need to check if it should only be launched once.
1096 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001097 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001098 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1099 final boolean dontStart = top != null && mStartActivity.resultTo == null
1100 && top.realActivity.equals(mStartActivity.realActivity)
1101 && top.userId == mStartActivity.userId
1102 && top.app != null && top.app.thread != null
1103 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1104 || mLaunchSingleTop || mLaunchSingleTask);
1105 if (dontStart) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001106 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001107 // For paranoia, make sure we have correctly resumed the top activity.
1108 topStack.mLastPausedActivity = null;
1109 if (mDoResume) {
1110 mSupervisor.resumeFocusedStackTopActivityLocked();
1111 }
1112 ActivityOptions.abort(mOptions);
1113 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1114 // We don't need to start a new activity, and the client said not to do
1115 // anything if that is the case, so this is it!
1116 return START_RETURN_INTENT_TO_CALLER;
1117 }
1118 top.deliverNewIntentLocked(
1119 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001120
1121 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1122 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001123 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1124 preferredLaunchDisplayId, topStack.mStackId);
Chong Zhangd44063c2016-04-08 11:52:30 -07001125
Wale Ogunwale01d66562015-12-29 08:19:19 -08001126 return START_DELIVERED_TO_TOP;
1127 }
1128
1129 boolean newTask = false;
1130 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001131 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001132
1133 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001134 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001135 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1136 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1137 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001138 result = setTaskFromReuseOrCreateNewTask(
1139 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001140 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001141 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001142 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001143 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001144 } else {
1145 // This not being started from an existing activity, and not part of a new task...
1146 // just put it in the top task, though these days this case should never happen.
1147 setTaskToCurrentTopOrCreateNewTask();
1148 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001149 if (result != START_SUCCESS) {
1150 return result;
1151 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001152
1153 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1154 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001155 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1156 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001157 if (mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001158 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001159 }
1160 if (newTask) {
1161 EventLog.writeEvent(
Bryce Leeaf691c02017-03-20 14:20:22 -07001162 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1163 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001164 }
1165 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001166 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001167 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001168
Wei Wang65c7a152016-06-02 18:51:22 -07001169 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001170
Winson Chungb5c41b72016-12-07 15:00:47 -08001171 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1172 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001173 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001174 final ActivityRecord topTaskActivity =
1175 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001176 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001177 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1178 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001179 // If the activity is not focusable, we can't resume it, but still would like to
1180 // make sure it becomes visible as it starts (this will also trigger entry
1181 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001182 // Also, we don't want to resume activities in a task that currently has an overlay
1183 // as the starting activity just needs to be in the visible paused state until the
1184 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001185 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001186 // Go ahead and tell window manager to execute app transition for this activity
1187 // since the app transition will not be triggered through the resume channel.
1188 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001189 } else {
Winson Chung32066032016-11-04 11:55:21 -07001190 // If the target stack was not previously focusable (previous top running activity
1191 // on that stack was not visible) then any prior calls to move the stack to the
1192 // will not update the focused stack. If starting the new activity now allows the
1193 // task stack to be focusable, then ensure that we now update the focused stack
1194 // accordingly.
1195 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1196 mTargetStack.moveToFront("startActivityUnchecked");
1197 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001198 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1199 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001200 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001201 } else {
1202 mTargetStack.addRecentActivityLocked(mStartActivity);
1203 }
1204 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1205
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001206 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1207 preferredLaunchDisplayId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001208
1209 return START_SUCCESS;
1210 }
1211
1212 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1213 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1214 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1215 reset();
1216
1217 mStartActivity = r;
1218 mIntent = r.intent;
1219 mOptions = options;
1220 mCallingUid = r.launchedFromUid;
1221 mSourceRecord = sourceRecord;
1222 mVoiceSession = voiceSession;
1223 mVoiceInteractor = voiceInteractor;
1224
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001225 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
David Stevensc6b91c62017-02-08 14:23:58 -08001226
Wale Ogunwale01d66562015-12-29 08:19:19 -08001227 mLaunchBounds = getOverrideBounds(r, options, inTask);
1228
1229 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1230 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1231 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1232 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1233 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1234 mLaunchTaskBehind = r.mLaunchTaskBehind
1235 && !mLaunchSingleTask && !mLaunchSingleInstance
1236 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1237
1238 sendNewTaskResultRequestIfNeeded();
1239
1240 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1241 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1242 }
1243
1244 // If we are actually going to launch in to a new task, there are some cases where
1245 // we further want to do multiple task.
1246 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1247 if (mLaunchTaskBehind
1248 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1249 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1250 }
1251 }
1252
1253 // We'll invoke onUserLeaving before onPause only if the launching
1254 // activity did not explicitly state that this is an automated launch.
1255 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1256 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1257 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1258
1259 // If the caller has asked not to resume at this point, we make note
1260 // of this in the record so that we can skip it when trying to find
1261 // the top running activity.
1262 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001263 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001264 r.delayedResume = true;
1265 mDoResume = false;
1266 }
1267
Winson Chungcbcadc92017-01-12 15:54:12 -08001268 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1269 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001270 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001271 if (!mOptions.canTaskOverlayResume()) {
1272 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1273 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1274 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001275
Winson Chungcbcadc92017-01-12 15:54:12 -08001276 // The caller specifies that we'd like to be avoided to be moved to the front,
1277 // so be it!
1278 mDoResume = false;
1279 mAvoidMoveToFront = true;
1280 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001281 }
1282 }
1283
Wale Ogunwale01d66562015-12-29 08:19:19 -08001284 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1285
1286 mInTask = inTask;
1287 // In some flows in to this function, we retrieve the task record and hold on to it
1288 // without a lock before calling back in to here... so the task at this point may
1289 // not actually be in recents. Check for that, and if it isn't in recents just
1290 // consider it invalid.
1291 if (inTask != null && !inTask.inRecents) {
1292 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1293 mInTask = null;
1294 }
1295
1296 mStartFlags = startFlags;
1297 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1298 // is the same as the one making the call... or, as a special case, if we do not know
1299 // the caller then we count the current top activity as the caller.
1300 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1301 ActivityRecord checkedCaller = sourceRecord;
1302 if (checkedCaller == null) {
1303 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1304 mNotTop);
1305 }
1306 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1307 // Caller is not the same as launcher, so always needed.
1308 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1309 }
1310 }
1311
1312 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1313 }
1314
1315 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001316 final ActivityStack sourceStack = mStartActivity.resultTo != null
1317 ? mStartActivity.resultTo.getStack() : null;
1318 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001319 // For whatever reason this activity is being launched into a new task...
1320 // yet the caller has requested a result back. Well, that is pretty messed up,
1321 // so instead immediately send back a cancel and let the new task continue launched
1322 // as normal without a dependency on its originator.
1323 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001324 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1325 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1326 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001327 mStartActivity.resultTo = null;
1328 }
1329 }
1330
1331 private void computeLaunchingTaskFlags() {
1332 // If the caller is not coming from another activity, but has given us an explicit task into
1333 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001334 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001335 final Intent baseIntent = mInTask.getBaseIntent();
1336 final ActivityRecord root = mInTask.getRootActivity();
1337 if (baseIntent == null) {
1338 ActivityOptions.abort(mOptions);
1339 throw new IllegalArgumentException("Launching into task without base intent: "
1340 + mInTask);
1341 }
1342
1343 // If this task is empty, then we are adding the first activity -- it
1344 // determines the root, and must be launching as a NEW_TASK.
1345 if (mLaunchSingleInstance || mLaunchSingleTask) {
1346 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1347 ActivityOptions.abort(mOptions);
1348 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1349 + mStartActivity + " into different task " + mInTask);
1350 }
1351 if (root != null) {
1352 ActivityOptions.abort(mOptions);
1353 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1354 + " has root " + root + " but target is singleInstance/Task");
1355 }
1356 }
1357
1358 // If task is empty, then adopt the interesting intent launch flags in to the
1359 // activity being started.
1360 if (root == null) {
1361 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1362 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1363 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1364 | (baseIntent.getFlags() & flagsOfInterest);
1365 mIntent.setFlags(mLaunchFlags);
1366 mInTask.setIntent(mStartActivity);
1367 mAddingToTask = true;
1368
1369 // If the task is not empty and the caller is asking to start it as the root of
1370 // a new task, then we don't actually want to start this on the task. We will
1371 // bring the task to the front, and possibly give it a new intent.
1372 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1373 mAddingToTask = false;
1374
1375 } else {
1376 mAddingToTask = true;
1377 }
1378
1379 mReuseTask = mInTask;
1380 } else {
1381 mInTask = null;
1382 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1383 // when in freeform workspace.
1384 // Also put noDisplay activities in the source task. These by itself can be placed
1385 // in any task/stack, however it could launch other activities like ResolverActivity,
1386 // and we want those to stay in the original task.
1387 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1388 && mSourceRecord.isFreeform()) {
1389 mAddingToTask = true;
1390 }
1391 }
1392
1393 if (mInTask == null) {
1394 if (mSourceRecord == null) {
1395 // This activity is not being started from another... in this
1396 // case we -always- start a new task.
1397 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1398 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1399 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1400 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1401 }
1402 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1403 // The original activity who is starting us is running as a single
1404 // instance... this new activity it is starting must go on its
1405 // own task.
1406 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1407 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1408 // The activity being started is a single instance... it always
1409 // gets launched into its own task.
1410 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1411 }
1412 }
1413 }
1414
1415 private void computeSourceStack() {
1416 if (mSourceRecord == null) {
1417 mSourceStack = null;
1418 return;
1419 }
1420 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001421 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001422 return;
1423 }
1424
1425 // If the source is finishing, we can't further count it as our source. This is because the
1426 // task it is associated with may now be empty and on its way out, so we don't want to
1427 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1428 // a task for it. But save the task information so it can be used when creating the new task.
1429 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1430 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1431 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1432 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1433 mNewTaskInfo = mSourceRecord.info;
Bryce Leeaf691c02017-03-20 14:20:22 -07001434 mNewTaskIntent = mSourceRecord.getTask().intent;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001435 }
1436 mSourceRecord = null;
1437 mSourceStack = null;
1438 }
1439
1440 /**
1441 * Decide whether the new activity should be inserted into an existing task. Returns null
1442 * if not or an ActivityRecord with the task into which the new activity should be added.
1443 */
1444 private ActivityRecord getReusableIntentActivity() {
1445 // We may want to try to place the new activity in to an existing task. We always
1446 // do this if the target activity is singleTask or singleInstance; we will also do
1447 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1448 // us to still place it in a new task: multi task, always doc mode, or being asked to
1449 // launch this as a new task behind the current one.
1450 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1451 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1452 || mLaunchSingleInstance || mLaunchSingleTask;
1453 // If bring to front is requested, and no result is requested and we have not been given
1454 // an explicit task to launch in to, and we can find a task that was started with this
1455 // same component, then instead of launching bring that one to the front.
1456 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1457 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001458 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1459 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1460 intentActivity = task != null ? task.getTopActivity() : null;
1461 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001462 if (mLaunchSingleInstance) {
1463 // There can be one and only one instance of single instance activity in the
1464 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001465 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001466 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1467 // For the launch adjacent case we only want to put the activity in an existing
1468 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001469 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1470 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001471 } else {
1472 // Otherwise find the best task to put the activity in.
David Stevensc6b91c62017-02-08 14:23:58 -08001473 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001474 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001475 }
1476 return intentActivity;
1477 }
1478
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001479 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001480 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1481 * then return the Vr mode's virtual display ID. If not, if the source activity has
1482 * a explicit display ID set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001483 */
1484 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001485 // Check if the Activity is a VR activity. If so, the activity should be launched in
1486 // main display.
1487 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1488 return DEFAULT_DISPLAY;
1489 }
1490
1491 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001492 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001493 if (displayId != INVALID_DISPLAY) {
1494 if (DEBUG_STACK) {
1495 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1496 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001497 mUsingVr2dDisplay = true;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001498 return displayId;
1499 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001500
1501 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1502 // If the activity has a displayId set explicitly, launch it on the same displayId.
1503 if (displayId != INVALID_DISPLAY) {
1504 return displayId;
1505 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001506 return DEFAULT_DISPLAY;
1507 }
1508
1509 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001510 * Figure out which task and activity to bring to front when we have found an existing matching
1511 * activity record in history. May also clear the task if needed.
1512 * @param intentActivity Existing matching activity.
1513 * @return {@link ActivityRecord} brought to front.
1514 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001515 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001516 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001517 mTargetStack.mLastPausedActivity = null;
1518 // If the target task is not in the front, then we need to bring it to the front...
1519 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1520 // the same behavior as if a new instance was being started, which means not bringing it
1521 // to the front if the caller is not itself in the front.
1522 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1523 ActivityRecord curTop = (focusStack == null)
1524 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1525
Bryce Leeaf691c02017-03-20 14:20:22 -07001526 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1527 if (topTask != null
1528 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001529 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001530 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1531 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
Bryce Leeaf691c02017-03-20 14:20:22 -07001532 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001533 // We really do want to push this one into the user's face, right now.
1534 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001535 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001536 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001537 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001538
1539 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1540 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1541 // So no point resuming any of the activities here, it just wastes one extra
1542 // resuming, plus enter AND exit transitions.
1543 // Here we only want to bring the target stack forward. Transition will be applied
1544 // to the new activity that's started after the old ones are gone.
1545 final boolean willClearTask =
1546 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1547 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1548 if (!willClearTask) {
1549 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001550 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1551 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001552 if (launchStack == null || launchStack == mTargetStack) {
1553 // We only want to move to the front, if we aren't going to launch on a
1554 // different stack. If we launch on a different stack, we will put the
1555 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001556 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001557 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1558 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001559 } else if (launchStack.mStackId == DOCKED_STACK_ID
1560 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1561 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1562 // If we want to launch adjacent and mTargetStack is not the computed
1563 // launch stack - move task to top of computed stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001564 intentTask.reparent(launchStack.mStackId, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001565 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1566 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001567 } else {
1568 // TODO: This should be reevaluated in MW v2.
1569 // We choose to move task to front instead of launching it adjacent
1570 // when specific stack was requested explicitly and it appeared to be
1571 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001572 mTargetStack.moveTaskToFrontLocked(intentTask,
1573 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001574 "bringToFrontInsteadOfAdjacentLaunch");
1575 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001576 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001577 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1578 // Target and computed stacks are on different displays and we've
1579 // found a matching task - move the existing instance to that display and
1580 // move it to front.
Bryce Leeaf691c02017-03-20 14:20:22 -07001581 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001582 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1583 "reparentToDisplay");
1584 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001585 }
1586 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001587
1588 // We are moving a task to the front, use starting window to hide initial drawn
1589 // delay.
1590 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1591 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001592 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001593 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001594 }
1595 }
1596 if (!mMovedToFront && mDoResume) {
1597 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1598 + " from " + intentActivity);
1599 mTargetStack.moveToFront("intentActivityFound");
1600 }
1601
Bryce Leeaf691c02017-03-20 14:20:22 -07001602 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001603 DEFAULT_DISPLAY, mTargetStack.mStackId);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001604
Wale Ogunwale01d66562015-12-29 08:19:19 -08001605 // If the caller has requested that the target task be reset, then do so.
1606 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1607 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1608 }
1609 return intentActivity;
1610 }
1611
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001612 private void updateTaskReturnToType(
1613 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001614 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001615 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1616 // Caller wants to appear on home activity.
1617 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1618 return;
Winson Chung83471632016-12-13 11:02:12 -08001619 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001620 // Task will be launched over the home stack, so return home.
1621 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1622 return;
Winson Chung83471632016-12-13 11:02:12 -08001623 } else if (focusedStack != null && focusedStack != task.getStack() &&
1624 focusedStack.isAssistantStack()) {
1625 // Task was launched over the assistant stack, so return there
1626 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1627 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001628 }
1629
1630 // Else we are coming from an application stack so return to an application.
1631 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1632 }
1633
Wale Ogunwale01d66562015-12-29 08:19:19 -08001634 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1635 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1636 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1637 // The caller has requested to completely replace any existing task with its new
1638 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001639 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1640 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001641 // of history or if it is finished immediately), thus disassociating the task. Also note
1642 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1643 // launching another activity.
1644 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1645 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001646 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001647 task.performClearTaskLocked();
1648 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001649 mReuseTask.setIntent(mStartActivity);
1650
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001651 // When we clear the task - focus will be adjusted, which will bring another task
1652 // to top before we launch the activity we need. This will temporary swap their
1653 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1654 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001655 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1656 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001657 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001658 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001659 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001660 // A special case: we need to start the activity because it is not currently
1661 // running, and the caller has asked to clear the current task to have this
1662 // activity at the top.
1663 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001664
1665 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001666 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001667 // Now pretend like this activity is being started by the top of its task, so it
1668 // is put in the right place.
1669 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001670 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001671 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001672 // Target stack got cleared when we all activities were removed above.
1673 // Go ahead and reset it.
1674 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1675 null /* bounds */, mLaunchFlags, mOptions);
1676 mTargetStack.addTask(task,
1677 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1678 }
1679 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001680 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001681 // In this case the top activity on the task is the same as the one being launched,
1682 // so we take that as a request to bring the task to the foreground. If the top
1683 // activity in the task is the root activity, deliver this new intent to it if it
1684 // desires.
1685 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1686 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001687 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Bryce Leeaf691c02017-03-20 14:20:22 -07001688 intentActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001689 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001690 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001691 }
1692 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1693 mStartActivity.launchedFromPackage);
Bryce Leeaf691c02017-03-20 14:20:22 -07001694 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001695 // In this case we are launching the root activity of the task, but with a
1696 // different intent. We should start a new instance on top.
1697 mAddingToTask = true;
1698 mSourceRecord = intentActivity;
1699 }
1700 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1701 // In this case an activity is being launched in to an existing task, without
1702 // resetting that task. This is typically the situation of launching an activity
1703 // from a notification or shortcut. We want to place the new activity on top of the
1704 // current task.
1705 mAddingToTask = true;
1706 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001707 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001708 // In this case we are launching into an existing task that has not yet been started
1709 // from its front door. The current task has been brought to the front. Ideally,
1710 // we'd probably like to place this new task at the bottom of its stack, but that's
1711 // a little hard to do with the current organization of the code so for now we'll
1712 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001713 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001714 }
1715 }
1716
1717 private void resumeTargetStackIfNeeded() {
1718 if (mDoResume) {
1719 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001720 } else {
1721 ActivityOptions.abort(mOptions);
1722 }
1723 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1724 }
1725
Chong Zhang6cda19c2016-06-14 19:07:56 -07001726 private int setTaskFromReuseOrCreateNewTask(
1727 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1728 mTargetStack = computeStackFocus(
1729 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1730
1731 // Do no move the target stack to front yet, as we might bail if
1732 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001733
1734 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001735 final TaskRecord task = mTargetStack.createTaskRecord(
1736 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001737 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001738 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1739 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001740 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001741 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001742 final int stackId = mTargetStack.mStackId;
1743 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001744 mService.resizeStack(
1745 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001746 } else {
Bryce Leeaf691c02017-03-20 14:20:22 -07001747 mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001748 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001749 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001750 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001751 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001752 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001753 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1754 }
1755
1756 if (taskToAffiliate != null) {
1757 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001758 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001759
Bryce Leeaf691c02017-03-20 14:20:22 -07001760 if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001761 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1762 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1763 }
1764
1765 if (!mMovedOtherTask) {
1766 // If stack id is specified in activity options, usually it means that activity is
1767 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1768 // that case we check the target stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001769 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
Chong Zhang6cda19c2016-06-14 19:07:56 -07001770 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1771 }
1772 if (mDoResume) {
1773 mTargetStack.moveToFront("reuseOrNewTask");
1774 }
1775 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001776 }
1777
1778 private int setTaskFromSourceRecord() {
Bryce Leeaf691c02017-03-20 14:20:22 -07001779 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001780 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1781 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1782 }
1783
Bryce Leeaf691c02017-03-20 14:20:22 -07001784 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001785 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001786 // We only want to allow changing stack if the target task is not the top one,
1787 // otherwise we would move the launching task to the other side, rather than show
1788 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001789 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001790 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001791 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001792 mOptions);
1793 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001794
1795 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001796 mTargetStack = sourceStack;
1797 } else if (mTargetStack != sourceStack) {
Winson Chung74666102017-02-22 17:49:24 -08001798 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1799 !ANIMATE, DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001800 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001801
Wale Ogunwale01d66562015-12-29 08:19:19 -08001802 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001803 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001804 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1805 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001806 } else if (mDoResume) {
1807 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001808 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001809
Wale Ogunwale01d66562015-12-29 08:19:19 -08001810 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1811 // In this case, we are adding the activity to an existing task, but the caller has
1812 // asked to clear that task if the activity is already running.
1813 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1814 mKeepCurTransition = true;
1815 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001816 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001817 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1818 // For paranoia, make sure we have correctly resumed the top activity.
1819 mTargetStack.mLastPausedActivity = null;
1820 if (mDoResume) {
1821 mSupervisor.resumeFocusedStackTopActivityLocked();
1822 }
1823 ActivityOptions.abort(mOptions);
1824 return START_DELIVERED_TO_TOP;
1825 }
1826 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1827 // In this case, we are launching an activity in our own task that may already be
1828 // running somewhere in the history, and we want to shuffle it to the front of the
1829 // stack if so.
1830 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1831 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001832 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001833 task.moveActivityToFrontLocked(top);
1834 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001835 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001836 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1837 mTargetStack.mLastPausedActivity = null;
1838 if (mDoResume) {
1839 mSupervisor.resumeFocusedStackTopActivityLocked();
1840 }
1841 return START_DELIVERED_TO_TOP;
1842 }
1843 }
1844
1845 // An existing activity is starting this new activity, so we want to keep the new one in
1846 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001847 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001848 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001849 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001850 return START_SUCCESS;
1851 }
1852
1853 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001854 // The caller is asking that the new activity be started in an explicit
1855 // task it has provided to us.
1856 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1857 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1858 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1859 }
1860
Andrii Kulian02b7a832016-10-06 23:11:56 -07001861 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001862
1863 // Check whether we should actually launch the new activity in to the task,
1864 // or just reuse the current activity on top.
1865 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001866 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1867 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001868 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1869 || mLaunchSingleTop || mLaunchSingleTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001870 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1871 mStartActivity.appTimeTracker, "inTaskToFront");
Bryce Leeaf691c02017-03-20 14:20:22 -07001872 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001873 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1874 // We don't need to start a new activity, and the client said not to do
1875 // anything if that is the case, so this is it!
1876 return START_RETURN_INTENT_TO_CALLER;
1877 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001878 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1879 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001880 return START_DELIVERED_TO_TOP;
1881 }
1882 }
1883
1884 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001885 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1886 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001887 // We don't actually want to have this activity added to the task, so just
1888 // stop here but still tell the caller that we consumed the intent.
1889 ActivityOptions.abort(mOptions);
1890 return START_TASK_TO_FRONT;
1891 }
1892
Yorke Lee64512522017-03-24 13:09:35 -07001893 if (mLaunchBounds != null) {
1894 mInTask.updateOverrideConfiguration(mLaunchBounds);
1895 int stackId = mInTask.getLaunchStackId();
1896 if (stackId != mInTask.getStackId()) {
1897 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1898 DEFER_RESUME, "inTaskToFront");
1899 stackId = mInTask.getStackId();
1900 mTargetStack = mInTask.getStack();
1901 }
1902 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1903 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1904 }
1905 }
1906
1907 mTargetStack.moveTaskToFrontLocked(
1908 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1909
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001910 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1911 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001912 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001913
1914 return START_SUCCESS;
1915 }
1916
1917 private void setTaskToCurrentTopOrCreateNewTask() {
1918 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1919 mOptions);
1920 if (mDoResume) {
1921 mTargetStack.moveToFront("addingToTopTask");
1922 }
1923 final ActivityRecord prev = mTargetStack.topActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07001924 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001925 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1926 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001927 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1928 mTargetStack.positionChildWindowContainerAtTop(task);
1929 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001930 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001931 }
1932
1933 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001934 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001935 parent.addActivityToTop(mStartActivity);
1936 } else {
1937 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1938 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001939 }
1940
1941 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1942 boolean launchSingleTask, int launchFlags) {
1943 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1944 (launchSingleInstance || launchSingleTask)) {
1945 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1946 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1947 "\"singleInstance\" or \"singleTask\"");
1948 launchFlags &=
1949 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1950 } else {
1951 switch (r.info.documentLaunchMode) {
1952 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1953 break;
1954 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1955 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1956 break;
1957 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1958 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1959 break;
1960 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1961 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1962 break;
1963 }
1964 }
1965 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001966 }
1967
1968 final void doPendingActivityLaunchesLocked(boolean doResume) {
1969 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001970 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1971 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001972 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001973 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
Bryce Lee4a194382017-04-04 14:32:48 -07001974 null, null /*outRecords*/);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001975 } catch (Exception e) {
1976 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1977 pal.sendErrorResult(e.getMessage());
1978 }
1979 }
1980 }
1981
1982 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001983 int launchFlags, ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001984 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001985 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001986 if (stack != null) {
1987 return stack;
1988 }
1989
Andrii Kulian02b7a832016-10-06 23:11:56 -07001990 final ActivityStack currentStack = task != null ? task.getStack() : null;
1991 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001992 if (mSupervisor.mFocusedStack != currentStack) {
1993 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1994 "computeStackFocus: Setting " + "focused stack to r=" + r
1995 + " task=" + task);
1996 } else {
1997 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1998 "computeStackFocus: Focused stack already="
1999 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002000 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002001 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002002 }
2003
2004 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
2005 if (container != null) {
2006 // The first time put it on the desired stack, after this put on task stack.
2007 r.mInitialActivityContainer = null;
2008 return container.mStack;
2009 }
2010
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002011 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002012 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2013 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2014 return mSupervisor.mFocusedStack;
2015 }
2016
David Stevensc6b91c62017-02-08 14:23:58 -08002017 if (mSourceDisplayId == DEFAULT_DISPLAY) {
2018 // We first try to put the task in the first dynamic stack on home display.
2019 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2020 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2021 stack = homeDisplayStacks.get(stackNdx);
2022 if (isDynamicStack(stack.mStackId)) {
2023 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2024 "computeStackFocus: Setting focused stack=" + stack);
2025 return stack;
2026 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002027 }
David Stevensc6b91c62017-02-08 14:23:58 -08002028 // If there is no suitable dynamic stack then we figure out which static stack to use.
2029 final int stackId = task != null ? task.getLaunchStackId() :
2030 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2031 FULLSCREEN_WORKSPACE_STACK_ID;
2032 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2033 } else {
2034 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002035 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002036 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2037 + r + " stackId=" + stack.mStackId);
2038 return stack;
2039 }
2040
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002041 /** Check if provided activity record can launch in currently focused stack. */
2042 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002043 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2044 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2045 final boolean canUseFocusedStack;
2046 switch (focusedStackId) {
2047 case FULLSCREEN_WORKSPACE_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002048 // The fullscreen stack can contain any task regardless of if the task is resizeable
2049 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002050 canUseFocusedStack = true;
2051 break;
Winson Chung83471632016-12-13 11:02:12 -08002052 case ASSISTANT_STACK_ID:
2053 canUseFocusedStack = r.isAssistantActivity();
2054 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002055 case DOCKED_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002056 // Any activity which supports split screen can go in the docked stack.
Winson Chungd3395382016-12-13 11:49:09 -08002057 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002058 break;
2059 case FREEFORM_WORKSPACE_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002060 // Any activity which supports freeform can go in the freeform stack.
Winson Chungd3395382016-12-13 11:49:09 -08002061 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002062 break;
2063 default:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002064 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2065 // resizeable task.
2066 // TODO: Check ActivityView after fixing b/35349678.
2067 canUseFocusedStack = isDynamicStack(focusedStackId)
2068 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002069 }
2070
2071 return canUseFocusedStack
David Stevensc6b91c62017-02-08 14:23:58 -08002072 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks())
2073 // We strongly prefer to launch activities on the same display as their source.
2074 && (mSourceDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002075 }
2076
Wale Ogunwale854809c2015-12-27 16:18:19 -08002077 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002078 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07002079
Winson Chung83471632016-12-13 11:02:12 -08002080 // If the activity is of a specific type, return the associated stack, creating it if
2081 // necessary
2082 if (r.isHomeActivity()) {
2083 return mSupervisor.mHomeStack;
2084 }
2085 if (r.isRecentsActivity()) {
2086 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2087 }
2088 if (r.isAssistantActivity()) {
2089 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2090 }
2091
Jorim Jaggib8c58762016-04-20 17:58:29 -07002092 // We are reusing a task, keep the stack!
2093 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002094 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07002095 }
2096
Andrii Kulian16802aa2016-11-02 12:21:33 -07002097 final int launchDisplayId =
2098 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2099
Wale Ogunwale854809c2015-12-27 16:18:19 -08002100 final int launchStackId =
2101 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2102
Andrii Kulian16802aa2016-11-02 12:21:33 -07002103 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2104 throw new IllegalArgumentException(
2105 "Stack and display id can't be set at the same time.");
2106 }
2107
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002108 if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002109 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07002110 }
2111 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08002112 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2113 // for this activity, so we put the activity in the fullscreen stack.
2114 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08002115 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07002116 if (launchDisplayId != INVALID_DISPLAY) {
2117 // Stack id has higher priority than display id.
2118 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2119 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002120
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07002121 // If we are using Vr2d display, find the virtual display stack.
2122 if (mUsingVr2dDisplay) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002123 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2124 if (DEBUG_STACK) {
2125 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2126 ", on virtual display stack:" + as.toString());
2127 }
2128 return as;
2129 }
2130
2131 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2132 || mSourceDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002133 return null;
2134 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002135 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002136
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002137 // The parent activity doesn't want to launch the activity on top of itself, but
2138 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002139 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002140 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2141 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002142
2143 if (parentStack != mSupervisor.mFocusedStack) {
2144 // If task's parent stack is not focused - use it during adjacent launch.
2145 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002146 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002147 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2148 // If task is already on top of focused stack - use it. We don't want to move the
2149 // existing focused task to adjacent stack, just deliver new intent in this case.
2150 return mSupervisor.mFocusedStack;
2151 }
2152
Winson Chung83471632016-12-13 11:02:12 -08002153 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002154 // If parent was in docked stack, the natural place to launch another activity
2155 // will be fullscreen, so it can appear alongside the docked window.
2156 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2157 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002158 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002159 // If the parent is not in the docked stack, we check if there is docked window
2160 // and if yes, we will launch into that stack. If not, we just put the new
2161 // activity into parent's stack, because we can't find a better place.
2162 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2163 if (dockedStack != null
Wale Ogunwalecd501ec2017-04-07 08:53:41 -07002164 && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002165 // There is a docked stack, but it isn't visible, so we can't launch into that.
2166 return null;
2167 } else {
2168 return dockedStack;
2169 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002170 }
2171 }
2172 }
2173
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002174 boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002175 switch (stackId) {
2176 case INVALID_STACK_ID:
2177 case HOME_STACK_ID:
2178 return false;
2179 case FULLSCREEN_WORKSPACE_STACK_ID:
2180 return true;
2181 case FREEFORM_WORKSPACE_STACK_ID:
2182 return r.supportsFreeform();
2183 case DOCKED_STACK_ID:
2184 return r.supportsSplitScreen();
2185 case PINNED_STACK_ID:
2186 return r.supportsPictureInPicture();
2187 case RECENTS_STACK_ID:
2188 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002189 case ASSISTANT_STACK_ID:
2190 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002191 default:
Andrii Kulianeafd9db2017-04-05 22:01:35 -07002192 // TODO: Check ActivityView after fixing b/35349678.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002193 if (StackId.isDynamicStack(stackId)) {
2194 return r.canBeLaunchedOnDisplay(displayId);
Andrii Kulian4acfd852017-01-26 19:43:13 -08002195 }
Winson Chungd3395382016-12-13 11:49:09 -08002196 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2197 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002198 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002199 }
2200
Wale Ogunwale854809c2015-12-27 16:18:19 -08002201 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2202 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002203 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002204 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2205 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002206 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002207 }
2208 }
2209 return newBounds;
2210 }
2211
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002212 void setWindowManager(WindowManagerService wm) {
2213 mWindowManager = wm;
2214 }
2215
2216 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2217 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2218 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2219 if (pal.stack == stack) {
2220 mPendingActivityLaunches.remove(palNdx);
2221 }
2222 }
2223 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002224
2225 static boolean isDocumentLaunchesIntoExisting(int flags) {
2226 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2227 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2228 }
liulvpingcfa825f2016-09-26 20:00:15 +08002229
2230 boolean clearPendingActivityLaunchesLocked(String packageName) {
2231 boolean didSomething = false;
2232
2233 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2234 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2235 ActivityRecord r = pal.r;
2236 if (r != null && r.packageName.equals(packageName)) {
2237 mPendingActivityLaunches.remove(palNdx);
2238 didSomething = true;
2239 }
2240 }
2241 return didSomething;
2242 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002243}