blob: 6d4eb5b03d89e5f3467f4df9c85ba1193403d55c [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
547 if (result < START_SUCCESS) {
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.
Winson Chung27ed7d42017-05-02 14:40:33 -0700959 if (result < START_SUCCESS && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -0700960 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800961 }
962 mService.mWindowManager.continueSurfaceLayout();
963 }
964
Matthew Ng0e205602017-03-22 14:23:25 -0700965 postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800966 mTargetStack);
967
968 return result;
969 }
970
971 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -0800972 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
973 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -0700974 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
975 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800976
977 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
978 voiceInteractor);
979
980 computeLaunchingTaskFlags();
981
982 computeSourceStack();
983
984 mIntent.setFlags(mLaunchFlags);
985
Bryce Lee4a194382017-04-04 14:32:48 -0700986 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800987
Jorim Jaggi2adba072016-03-03 13:43:39 +0100988 final int preferredLaunchStackId =
989 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700990 final int preferredLaunchDisplayId =
991 (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
Jorim Jaggi2adba072016-03-03 13:43:39 +0100992
Bryce Lee4a194382017-04-04 14:32:48 -0700993 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800994 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
995 // still needs to be a lock task mode violation since the task gets cleared out and
996 // the device would otherwise leave the locked task.
Bryce Lee4a194382017-04-04 14:32:48 -0700997 if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -0800998 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
999 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1000 mSupervisor.showLockTaskToast();
1001 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1002 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1003 }
1004
Bryce Leeaf691c02017-03-20 14:20:22 -07001005 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001006 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001007 }
Bryce Lee4a194382017-04-04 14:32:48 -07001008 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001009 // This task was started because of movement of the activity based on affinity...
1010 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001011 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001012 }
1013
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001014 // This code path leads to delivering a new intent, we want to make sure we schedule it
1015 // as the first operation, in case the activity will be resumed as a result of later
1016 // operations.
1017 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001018 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001019 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Lee4a194382017-04-04 14:32:48 -07001020 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001021
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001022 // In this situation we want to remove all activities from the task up to the one
1023 // being started. In most cases this means we are resetting the task to its initial
1024 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001025 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1026 mLaunchFlags);
1027
Bryce Lee4a194382017-04-04 14:32:48 -07001028 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001029 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1030 // task reference is needed in the call below to
1031 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001032 if (reusedActivity.getTask() == null) {
1033 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001034 }
1035
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001036 if (top != null) {
1037 if (top.frontOfTask) {
1038 // Activity aliases may mean we use different intents for the top activity,
1039 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001040 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001041 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001042 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001043 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1044 mStartActivity.launchedFromPackage);
1045 }
1046 }
1047
Wei Wang65c7a152016-06-02 18:51:22 -07001048 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001049
Bryce Lee4a194382017-04-04 14:32:48 -07001050 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001051
1052 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1053 // We don't need to start a new activity, and the client said not to do anything
1054 // if that is the case, so this is it! And for paranoia, make sure we have
1055 // correctly resumed the top activity.
1056 resumeTargetStackIfNeeded();
1057 return START_RETURN_INTENT_TO_CALLER;
1058 }
Bryce Lee4a194382017-04-04 14:32:48 -07001059 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001060
1061 if (!mAddingToTask && mReuseTask == null) {
1062 // We didn't do anything... but it was needed (a.k.a., client don't use that
1063 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1064 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001065 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001066 outActivity[0] = reusedActivity;
1067 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001068 return START_TASK_TO_FRONT;
1069 }
1070 }
1071
1072 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001073 final ActivityStack sourceStack = mStartActivity.resultTo != null
1074 ? mStartActivity.resultTo.getStack() : null;
1075 if (sourceStack != null) {
1076 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1077 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1078 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001079 }
1080 ActivityOptions.abort(mOptions);
1081 return START_CLASS_NOT_FOUND;
1082 }
1083
1084 // If the activity being launched is the same as the one currently at the top, then
1085 // we need to check if it should only be launched once.
1086 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001087 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001088 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1089 final boolean dontStart = top != null && mStartActivity.resultTo == null
1090 && top.realActivity.equals(mStartActivity.realActivity)
1091 && top.userId == mStartActivity.userId
1092 && top.app != null && top.app.thread != null
1093 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1094 || mLaunchSingleTop || mLaunchSingleTask);
1095 if (dontStart) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001096 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001097 // For paranoia, make sure we have correctly resumed the top activity.
1098 topStack.mLastPausedActivity = null;
1099 if (mDoResume) {
1100 mSupervisor.resumeFocusedStackTopActivityLocked();
1101 }
1102 ActivityOptions.abort(mOptions);
1103 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1104 // We don't need to start a new activity, and the client said not to do
1105 // anything if that is the case, so this is it!
1106 return START_RETURN_INTENT_TO_CALLER;
1107 }
1108 top.deliverNewIntentLocked(
1109 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001110
1111 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1112 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001113 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
1114 preferredLaunchDisplayId, topStack.mStackId);
Chong Zhangd44063c2016-04-08 11:52:30 -07001115
Wale Ogunwale01d66562015-12-29 08:19:19 -08001116 return START_DELIVERED_TO_TOP;
1117 }
1118
1119 boolean newTask = false;
1120 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001121 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001122
1123 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001124 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001125 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1126 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1127 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001128 result = setTaskFromReuseOrCreateNewTask(
1129 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001130 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001131 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001132 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001133 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001134 } else {
1135 // This not being started from an existing activity, and not part of a new task...
1136 // just put it in the top task, though these days this case should never happen.
1137 setTaskToCurrentTopOrCreateNewTask();
1138 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001139 if (result != START_SUCCESS) {
1140 return result;
1141 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001142
1143 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1144 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001145 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1146 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001147 if (mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001148 mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001149 }
1150 if (newTask) {
1151 EventLog.writeEvent(
Bryce Leeaf691c02017-03-20 14:20:22 -07001152 EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1153 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001154 }
1155 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001156 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001157 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001158
Wei Wang65c7a152016-06-02 18:51:22 -07001159 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001160
Winson Chungb5c41b72016-12-07 15:00:47 -08001161 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1162 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001163 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001164 final ActivityRecord topTaskActivity =
1165 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001166 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001167 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1168 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001169 // If the activity is not focusable, we can't resume it, but still would like to
1170 // make sure it becomes visible as it starts (this will also trigger entry
1171 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001172 // Also, we don't want to resume activities in a task that currently has an overlay
1173 // as the starting activity just needs to be in the visible paused state until the
1174 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001175 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001176 // Go ahead and tell window manager to execute app transition for this activity
1177 // since the app transition will not be triggered through the resume channel.
1178 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001179 } else {
Winson Chung32066032016-11-04 11:55:21 -07001180 // If the target stack was not previously focusable (previous top running activity
1181 // on that stack was not visible) then any prior calls to move the stack to the
1182 // will not update the focused stack. If starting the new activity now allows the
1183 // task stack to be focusable, then ensure that we now update the focused stack
1184 // accordingly.
1185 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1186 mTargetStack.moveToFront("startActivityUnchecked");
1187 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001188 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1189 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001190 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001191 } else {
1192 mTargetStack.addRecentActivityLocked(mStartActivity);
1193 }
1194 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1195
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001196 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
1197 preferredLaunchDisplayId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001198
1199 return START_SUCCESS;
1200 }
1201
1202 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1203 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1204 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1205 reset();
1206
1207 mStartActivity = r;
1208 mIntent = r.intent;
1209 mOptions = options;
1210 mCallingUid = r.launchedFromUid;
1211 mSourceRecord = sourceRecord;
1212 mVoiceSession = voiceSession;
1213 mVoiceInteractor = voiceInteractor;
1214
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001215 mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity);
David Stevensc6b91c62017-02-08 14:23:58 -08001216
Wale Ogunwale01d66562015-12-29 08:19:19 -08001217 mLaunchBounds = getOverrideBounds(r, options, inTask);
1218
1219 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1220 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1221 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1222 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1223 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1224 mLaunchTaskBehind = r.mLaunchTaskBehind
1225 && !mLaunchSingleTask && !mLaunchSingleInstance
1226 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1227
1228 sendNewTaskResultRequestIfNeeded();
1229
1230 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1231 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1232 }
1233
1234 // If we are actually going to launch in to a new task, there are some cases where
1235 // we further want to do multiple task.
1236 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1237 if (mLaunchTaskBehind
1238 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1239 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1240 }
1241 }
1242
1243 // We'll invoke onUserLeaving before onPause only if the launching
1244 // activity did not explicitly state that this is an automated launch.
1245 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1246 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1247 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1248
1249 // If the caller has asked not to resume at this point, we make note
1250 // of this in the record so that we can skip it when trying to find
1251 // the top running activity.
1252 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001253 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001254 r.delayedResume = true;
1255 mDoResume = false;
1256 }
1257
Winson Chungcbcadc92017-01-12 15:54:12 -08001258 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1259 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001260 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001261 if (!mOptions.canTaskOverlayResume()) {
1262 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1263 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1264 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001265
Winson Chungcbcadc92017-01-12 15:54:12 -08001266 // The caller specifies that we'd like to be avoided to be moved to the front,
1267 // so be it!
1268 mDoResume = false;
1269 mAvoidMoveToFront = true;
1270 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001271 }
1272 }
1273
Wale Ogunwale01d66562015-12-29 08:19:19 -08001274 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1275
1276 mInTask = inTask;
1277 // In some flows in to this function, we retrieve the task record and hold on to it
1278 // without a lock before calling back in to here... so the task at this point may
1279 // not actually be in recents. Check for that, and if it isn't in recents just
1280 // consider it invalid.
1281 if (inTask != null && !inTask.inRecents) {
1282 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1283 mInTask = null;
1284 }
1285
1286 mStartFlags = startFlags;
1287 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1288 // is the same as the one making the call... or, as a special case, if we do not know
1289 // the caller then we count the current top activity as the caller.
1290 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1291 ActivityRecord checkedCaller = sourceRecord;
1292 if (checkedCaller == null) {
1293 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1294 mNotTop);
1295 }
1296 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1297 // Caller is not the same as launcher, so always needed.
1298 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1299 }
1300 }
1301
1302 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1303 }
1304
1305 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001306 final ActivityStack sourceStack = mStartActivity.resultTo != null
1307 ? mStartActivity.resultTo.getStack() : null;
1308 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001309 // For whatever reason this activity is being launched into a new task...
1310 // yet the caller has requested a result back. Well, that is pretty messed up,
1311 // so instead immediately send back a cancel and let the new task continue launched
1312 // as normal without a dependency on its originator.
1313 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001314 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1315 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1316 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001317 mStartActivity.resultTo = null;
1318 }
1319 }
1320
1321 private void computeLaunchingTaskFlags() {
1322 // If the caller is not coming from another activity, but has given us an explicit task into
1323 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001324 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001325 final Intent baseIntent = mInTask.getBaseIntent();
1326 final ActivityRecord root = mInTask.getRootActivity();
1327 if (baseIntent == null) {
1328 ActivityOptions.abort(mOptions);
1329 throw new IllegalArgumentException("Launching into task without base intent: "
1330 + mInTask);
1331 }
1332
1333 // If this task is empty, then we are adding the first activity -- it
1334 // determines the root, and must be launching as a NEW_TASK.
1335 if (mLaunchSingleInstance || mLaunchSingleTask) {
1336 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1337 ActivityOptions.abort(mOptions);
1338 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1339 + mStartActivity + " into different task " + mInTask);
1340 }
1341 if (root != null) {
1342 ActivityOptions.abort(mOptions);
1343 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1344 + " has root " + root + " but target is singleInstance/Task");
1345 }
1346 }
1347
1348 // If task is empty, then adopt the interesting intent launch flags in to the
1349 // activity being started.
1350 if (root == null) {
1351 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1352 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1353 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1354 | (baseIntent.getFlags() & flagsOfInterest);
1355 mIntent.setFlags(mLaunchFlags);
1356 mInTask.setIntent(mStartActivity);
1357 mAddingToTask = true;
1358
1359 // If the task is not empty and the caller is asking to start it as the root of
1360 // a new task, then we don't actually want to start this on the task. We will
1361 // bring the task to the front, and possibly give it a new intent.
1362 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1363 mAddingToTask = false;
1364
1365 } else {
1366 mAddingToTask = true;
1367 }
1368
1369 mReuseTask = mInTask;
1370 } else {
1371 mInTask = null;
1372 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1373 // when in freeform workspace.
1374 // Also put noDisplay activities in the source task. These by itself can be placed
1375 // in any task/stack, however it could launch other activities like ResolverActivity,
1376 // and we want those to stay in the original task.
1377 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1378 && mSourceRecord.isFreeform()) {
1379 mAddingToTask = true;
1380 }
1381 }
1382
1383 if (mInTask == null) {
1384 if (mSourceRecord == null) {
1385 // This activity is not being started from another... in this
1386 // case we -always- start a new task.
1387 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1388 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1389 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1390 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1391 }
1392 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1393 // The original activity who is starting us is running as a single
1394 // instance... this new activity it is starting must go on its
1395 // own task.
1396 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1397 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1398 // The activity being started is a single instance... it always
1399 // gets launched into its own task.
1400 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1401 }
1402 }
1403 }
1404
1405 private void computeSourceStack() {
1406 if (mSourceRecord == null) {
1407 mSourceStack = null;
1408 return;
1409 }
1410 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001411 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001412 return;
1413 }
1414
1415 // If the source is finishing, we can't further count it as our source. This is because the
1416 // task it is associated with may now be empty and on its way out, so we don't want to
1417 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1418 // a task for it. But save the task information so it can be used when creating the new task.
1419 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1420 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1421 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1422 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1423 mNewTaskInfo = mSourceRecord.info;
Bryce Leeaf691c02017-03-20 14:20:22 -07001424 mNewTaskIntent = mSourceRecord.getTask().intent;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001425 }
1426 mSourceRecord = null;
1427 mSourceStack = null;
1428 }
1429
1430 /**
1431 * Decide whether the new activity should be inserted into an existing task. Returns null
1432 * if not or an ActivityRecord with the task into which the new activity should be added.
1433 */
1434 private ActivityRecord getReusableIntentActivity() {
1435 // We may want to try to place the new activity in to an existing task. We always
1436 // do this if the target activity is singleTask or singleInstance; we will also do
1437 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1438 // us to still place it in a new task: multi task, always doc mode, or being asked to
1439 // launch this as a new task behind the current one.
1440 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1441 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1442 || mLaunchSingleInstance || mLaunchSingleTask;
1443 // If bring to front is requested, and no result is requested and we have not been given
1444 // an explicit task to launch in to, and we can find a task that was started with this
1445 // same component, then instead of launching bring that one to the front.
1446 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1447 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001448 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1449 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1450 intentActivity = task != null ? task.getTopActivity() : null;
1451 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001452 if (mLaunchSingleInstance) {
1453 // There can be one and only one instance of single instance activity in the
1454 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001455 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001456 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1457 // For the launch adjacent case we only want to put the activity in an existing
1458 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001459 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1460 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001461 } else {
1462 // Otherwise find the best task to put the activity in.
David Stevensc6b91c62017-02-08 14:23:58 -08001463 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001464 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001465 }
1466 return intentActivity;
1467 }
1468
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001469 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001470 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
1471 * then return the Vr mode's virtual display ID. If not, if the source activity has
1472 * a explicit display ID set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001473 */
1474 private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001475 // Check if the Activity is a VR activity. If so, the activity should be launched in
1476 // main display.
1477 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1478 return DEFAULT_DISPLAY;
1479 }
1480
1481 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001482 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001483 if (displayId != INVALID_DISPLAY) {
1484 if (DEBUG_STACK) {
1485 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1486 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001487 mUsingVr2dDisplay = true;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001488 return displayId;
1489 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001490
1491 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1492 // If the activity has a displayId set explicitly, launch it on the same displayId.
1493 if (displayId != INVALID_DISPLAY) {
1494 return displayId;
1495 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001496 return DEFAULT_DISPLAY;
1497 }
1498
1499 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001500 * Figure out which task and activity to bring to front when we have found an existing matching
1501 * activity record in history. May also clear the task if needed.
1502 * @param intentActivity Existing matching activity.
1503 * @return {@link ActivityRecord} brought to front.
1504 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001505 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001506 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001507 mTargetStack.mLastPausedActivity = null;
1508 // If the target task is not in the front, then we need to bring it to the front...
1509 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1510 // the same behavior as if a new instance was being started, which means not bringing it
1511 // to the front if the caller is not itself in the front.
1512 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1513 ActivityRecord curTop = (focusStack == null)
1514 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1515
Bryce Leeaf691c02017-03-20 14:20:22 -07001516 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1517 if (topTask != null
1518 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001519 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001520 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1521 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
Bryce Leeaf691c02017-03-20 14:20:22 -07001522 mSourceStack.topActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001523 // We really do want to push this one into the user's face, right now.
1524 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001525 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001526 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001527 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001528
1529 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1530 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1531 // So no point resuming any of the activities here, it just wastes one extra
1532 // resuming, plus enter AND exit transitions.
1533 // Here we only want to bring the target stack forward. Transition will be applied
1534 // to the new activity that's started after the old ones are gone.
1535 final boolean willClearTask =
1536 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1537 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1538 if (!willClearTask) {
1539 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001540 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1541 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001542 if (launchStack == null || launchStack == mTargetStack) {
1543 // We only want to move to the front, if we aren't going to launch on a
1544 // different stack. If we launch on a different stack, we will put the
1545 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001546 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001547 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1548 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001549 } else if (launchStack.mStackId == DOCKED_STACK_ID
1550 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1551 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1552 // If we want to launch adjacent and mTargetStack is not the computed
1553 // launch stack - move task to top of computed stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001554 intentTask.reparent(launchStack.mStackId, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001555 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1556 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001557 } else {
1558 // TODO: This should be reevaluated in MW v2.
1559 // We choose to move task to front instead of launching it adjacent
1560 // when specific stack was requested explicitly and it appeared to be
1561 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001562 mTargetStack.moveTaskToFrontLocked(intentTask,
1563 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001564 "bringToFrontInsteadOfAdjacentLaunch");
1565 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001566 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001567 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1568 // Target and computed stacks are on different displays and we've
1569 // found a matching task - move the existing instance to that display and
1570 // move it to front.
Bryce Leeaf691c02017-03-20 14:20:22 -07001571 intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001572 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1573 "reparentToDisplay");
1574 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001575 }
1576 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001577
1578 // We are moving a task to the front, use starting window to hide initial drawn
1579 // delay.
1580 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1581 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001582 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001583 updateTaskReturnToType(intentActivity.getTask(), mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001584 }
1585 }
1586 if (!mMovedToFront && mDoResume) {
1587 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1588 + " from " + intentActivity);
1589 mTargetStack.moveToFront("intentActivityFound");
1590 }
1591
Bryce Leeaf691c02017-03-20 14:20:22 -07001592 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001593 DEFAULT_DISPLAY, mTargetStack.mStackId);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001594
Wale Ogunwale01d66562015-12-29 08:19:19 -08001595 // If the caller has requested that the target task be reset, then do so.
1596 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1597 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1598 }
1599 return intentActivity;
1600 }
1601
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001602 private void updateTaskReturnToType(
1603 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001604 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001605 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1606 // Caller wants to appear on home activity.
1607 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1608 return;
Winson Chung83471632016-12-13 11:02:12 -08001609 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001610 // Task will be launched over the home stack, so return home.
1611 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1612 return;
Winson Chung83471632016-12-13 11:02:12 -08001613 } else if (focusedStack != null && focusedStack != task.getStack() &&
1614 focusedStack.isAssistantStack()) {
1615 // Task was launched over the assistant stack, so return there
1616 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1617 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001618 }
1619
1620 // Else we are coming from an application stack so return to an application.
1621 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1622 }
1623
Wale Ogunwale01d66562015-12-29 08:19:19 -08001624 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1625 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1626 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1627 // The caller has requested to completely replace any existing task with its new
1628 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001629 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1630 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001631 // of history or if it is finished immediately), thus disassociating the task. Also note
1632 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1633 // launching another activity.
1634 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1635 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001636 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001637 task.performClearTaskLocked();
1638 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001639 mReuseTask.setIntent(mStartActivity);
1640
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001641 // When we clear the task - focus will be adjusted, which will bring another task
1642 // to top before we launch the activity we need. This will temporary swap their
1643 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1644 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001645 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1646 || mLaunchSingleInstance || mLaunchSingleTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001647 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001648 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001649 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001650 // A special case: we need to start the activity because it is not currently
1651 // running, and the caller has asked to clear the current task to have this
1652 // activity at the top.
1653 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001654
1655 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001656 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001657 // Now pretend like this activity is being started by the top of its task, so it
1658 // is put in the right place.
1659 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001660 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001661 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001662 // Target stack got cleared when we all activities were removed above.
1663 // Go ahead and reset it.
1664 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1665 null /* bounds */, mLaunchFlags, mOptions);
1666 mTargetStack.addTask(task,
1667 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1668 }
1669 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001670 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001671 // In this case the top activity on the task is the same as the one being launched,
1672 // so we take that as a request to bring the task to the foreground. If the top
1673 // activity in the task is the root activity, deliver this new intent to it if it
1674 // desires.
1675 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1676 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001677 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Bryce Leeaf691c02017-03-20 14:20:22 -07001678 intentActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001679 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001680 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001681 }
1682 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1683 mStartActivity.launchedFromPackage);
Bryce Leeaf691c02017-03-20 14:20:22 -07001684 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001685 // In this case we are launching the root activity of the task, but with a
1686 // different intent. We should start a new instance on top.
1687 mAddingToTask = true;
1688 mSourceRecord = intentActivity;
1689 }
1690 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1691 // In this case an activity is being launched in to an existing task, without
1692 // resetting that task. This is typically the situation of launching an activity
1693 // from a notification or shortcut. We want to place the new activity on top of the
1694 // current task.
1695 mAddingToTask = true;
1696 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001697 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001698 // In this case we are launching into an existing task that has not yet been started
1699 // from its front door. The current task has been brought to the front. Ideally,
1700 // we'd probably like to place this new task at the bottom of its stack, but that's
1701 // a little hard to do with the current organization of the code so for now we'll
1702 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001703 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001704 }
1705 }
1706
1707 private void resumeTargetStackIfNeeded() {
1708 if (mDoResume) {
1709 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001710 } else {
1711 ActivityOptions.abort(mOptions);
1712 }
1713 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1714 }
1715
Chong Zhang6cda19c2016-06-14 19:07:56 -07001716 private int setTaskFromReuseOrCreateNewTask(
1717 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1718 mTargetStack = computeStackFocus(
1719 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1720
1721 // Do no move the target stack to front yet, as we might bail if
1722 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001723
1724 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001725 final TaskRecord task = mTargetStack.createTaskRecord(
1726 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001727 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001728 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1729 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001730 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001731 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001732 final int stackId = mTargetStack.mStackId;
1733 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001734 mService.resizeStack(
1735 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001736 } else {
Bryce Leeaf691c02017-03-20 14:20:22 -07001737 mStartActivity.getTask().updateOverrideConfiguration(mLaunchBounds);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001738 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001739 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001740 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001741 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001742 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001743 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1744 }
1745
1746 if (taskToAffiliate != null) {
1747 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001748 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001749
Bryce Leeaf691c02017-03-20 14:20:22 -07001750 if (mSupervisor.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001751 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1752 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1753 }
1754
1755 if (!mMovedOtherTask) {
1756 // If stack id is specified in activity options, usually it means that activity is
1757 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1758 // that case we check the target stack.
Bryce Leeaf691c02017-03-20 14:20:22 -07001759 updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
Chong Zhang6cda19c2016-06-14 19:07:56 -07001760 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1761 }
1762 if (mDoResume) {
1763 mTargetStack.moveToFront("reuseOrNewTask");
1764 }
1765 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001766 }
1767
1768 private int setTaskFromSourceRecord() {
Bryce Leeaf691c02017-03-20 14:20:22 -07001769 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001770 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1771 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1772 }
1773
Bryce Leeaf691c02017-03-20 14:20:22 -07001774 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001775 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001776 // We only want to allow changing stack if the target task is not the top one,
1777 // otherwise we would move the launching task to the other side, rather than show
1778 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001779 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001780 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001781 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001782 mOptions);
1783 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001784
1785 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001786 mTargetStack = sourceStack;
1787 } else if (mTargetStack != sourceStack) {
Winson Chung74666102017-02-22 17:49:24 -08001788 sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
1789 !ANIMATE, DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001790 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001791
Wale Ogunwale01d66562015-12-29 08:19:19 -08001792 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001793 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001794 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1795 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001796 } else if (mDoResume) {
1797 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001798 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001799
Wale Ogunwale01d66562015-12-29 08:19:19 -08001800 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1801 // In this case, we are adding the activity to an existing task, but the caller has
1802 // asked to clear that task if the activity is already running.
1803 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1804 mKeepCurTransition = true;
1805 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001806 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001807 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1808 // For paranoia, make sure we have correctly resumed the top activity.
1809 mTargetStack.mLastPausedActivity = null;
1810 if (mDoResume) {
1811 mSupervisor.resumeFocusedStackTopActivityLocked();
1812 }
1813 ActivityOptions.abort(mOptions);
1814 return START_DELIVERED_TO_TOP;
1815 }
1816 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1817 // In this case, we are launching an activity in our own task that may already be
1818 // running somewhere in the history, and we want to shuffle it to the front of the
1819 // stack if so.
1820 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1821 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001822 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001823 task.moveActivityToFrontLocked(top);
1824 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001825 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001826 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1827 mTargetStack.mLastPausedActivity = null;
1828 if (mDoResume) {
1829 mSupervisor.resumeFocusedStackTopActivityLocked();
1830 }
1831 return START_DELIVERED_TO_TOP;
1832 }
1833 }
1834
1835 // An existing activity is starting this new activity, so we want to keep the new one in
1836 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001837 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001838 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001839 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001840 return START_SUCCESS;
1841 }
1842
1843 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001844 // The caller is asking that the new activity be started in an explicit
1845 // task it has provided to us.
1846 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1847 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1848 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1849 }
1850
Andrii Kulian02b7a832016-10-06 23:11:56 -07001851 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001852
1853 // Check whether we should actually launch the new activity in to the task,
1854 // or just reuse the current activity on top.
1855 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001856 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1857 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001858 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1859 || mLaunchSingleTop || mLaunchSingleTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001860 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1861 mStartActivity.appTimeTracker, "inTaskToFront");
Bryce Leeaf691c02017-03-20 14:20:22 -07001862 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001863 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1864 // We don't need to start a new activity, and the client said not to do
1865 // anything if that is the case, so this is it!
1866 return START_RETURN_INTENT_TO_CALLER;
1867 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001868 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1869 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001870 return START_DELIVERED_TO_TOP;
1871 }
1872 }
1873
1874 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07001875 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
1876 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001877 // We don't actually want to have this activity added to the task, so just
1878 // stop here but still tell the caller that we consumed the intent.
1879 ActivityOptions.abort(mOptions);
1880 return START_TASK_TO_FRONT;
1881 }
1882
Yorke Lee64512522017-03-24 13:09:35 -07001883 if (mLaunchBounds != null) {
1884 mInTask.updateOverrideConfiguration(mLaunchBounds);
1885 int stackId = mInTask.getLaunchStackId();
1886 if (stackId != mInTask.getStackId()) {
1887 mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
1888 DEFER_RESUME, "inTaskToFront");
1889 stackId = mInTask.getStackId();
1890 mTargetStack = mInTask.getStack();
1891 }
1892 if (StackId.resizeStackWithLaunchBounds(stackId)) {
1893 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
1894 }
1895 }
1896
1897 mTargetStack.moveTaskToFrontLocked(
1898 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1899
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001900 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1901 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001902 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001903
1904 return START_SUCCESS;
1905 }
1906
1907 private void setTaskToCurrentTopOrCreateNewTask() {
1908 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1909 mOptions);
1910 if (mDoResume) {
1911 mTargetStack.moveToFront("addingToTopTask");
1912 }
1913 final ActivityRecord prev = mTargetStack.topActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07001914 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001915 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1916 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001917 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1918 mTargetStack.positionChildWindowContainerAtTop(task);
1919 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001920 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001921 }
1922
1923 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001924 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001925 parent.addActivityToTop(mStartActivity);
1926 } else {
1927 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1928 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001929 }
1930
1931 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1932 boolean launchSingleTask, int launchFlags) {
1933 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1934 (launchSingleInstance || launchSingleTask)) {
1935 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1936 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1937 "\"singleInstance\" or \"singleTask\"");
1938 launchFlags &=
1939 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1940 } else {
1941 switch (r.info.documentLaunchMode) {
1942 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1943 break;
1944 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1945 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1946 break;
1947 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1948 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1949 break;
1950 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1951 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1952 break;
1953 }
1954 }
1955 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001956 }
1957
1958 final void doPendingActivityLaunchesLocked(boolean doResume) {
1959 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001960 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1961 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001962 try {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001963 startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
Bryce Lee4a194382017-04-04 14:32:48 -07001964 null, null /*outRecords*/);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001965 } catch (Exception e) {
1966 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1967 pal.sendErrorResult(e.getMessage());
1968 }
1969 }
1970 }
1971
1972 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001973 int launchFlags, ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001974 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001975 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001976 if (stack != null) {
1977 return stack;
1978 }
1979
Andrii Kulian02b7a832016-10-06 23:11:56 -07001980 final ActivityStack currentStack = task != null ? task.getStack() : null;
1981 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001982 if (mSupervisor.mFocusedStack != currentStack) {
1983 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1984 "computeStackFocus: Setting " + "focused stack to r=" + r
1985 + " task=" + task);
1986 } else {
1987 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1988 "computeStackFocus: Focused stack already="
1989 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001990 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001991 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001992 }
1993
1994 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1995 if (container != null) {
1996 // The first time put it on the desired stack, after this put on task stack.
1997 r.mInitialActivityContainer = null;
1998 return container.mStack;
1999 }
2000
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002001 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002002 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2003 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2004 return mSupervisor.mFocusedStack;
2005 }
2006
David Stevensc6b91c62017-02-08 14:23:58 -08002007 if (mSourceDisplayId == DEFAULT_DISPLAY) {
2008 // We first try to put the task in the first dynamic stack on home display.
2009 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
2010 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2011 stack = homeDisplayStacks.get(stackNdx);
2012 if (isDynamicStack(stack.mStackId)) {
2013 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2014 "computeStackFocus: Setting focused stack=" + stack);
2015 return stack;
2016 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002017 }
David Stevensc6b91c62017-02-08 14:23:58 -08002018 // If there is no suitable dynamic stack then we figure out which static stack to use.
2019 final int stackId = task != null ? task.getLaunchStackId() :
2020 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
2021 FULLSCREEN_WORKSPACE_STACK_ID;
2022 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
2023 } else {
2024 stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002025 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002026 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2027 + r + " stackId=" + stack.mStackId);
2028 return stack;
2029 }
2030
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002031 /** Check if provided activity record can launch in currently focused stack. */
2032 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002033 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
2034 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
2035 final boolean canUseFocusedStack;
2036 switch (focusedStackId) {
2037 case FULLSCREEN_WORKSPACE_STACK_ID:
David Stevensc6b91c62017-02-08 14:23:58 -08002038 // The fullscreen stack can contain any task regardless of if the task is resizeable
2039 // 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 -08002040 canUseFocusedStack = true;
2041 break;
Winson Chung83471632016-12-13 11:02:12 -08002042 case ASSISTANT_STACK_ID:
2043 canUseFocusedStack = r.isAssistantActivity();
2044 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002045 case DOCKED_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002046 // Any activity which supports split screen can go in the docked stack.
Winson Chungd3395382016-12-13 11:49:09 -08002047 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002048 break;
2049 case FREEFORM_WORKSPACE_STACK_ID:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002050 // Any activity which supports freeform can go in the freeform stack.
Winson Chungd3395382016-12-13 11:49:09 -08002051 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002052 break;
2053 default:
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002054 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2055 // resizeable task.
2056 // TODO: Check ActivityView after fixing b/35349678.
2057 canUseFocusedStack = isDynamicStack(focusedStackId)
2058 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002059 }
2060
2061 return canUseFocusedStack
David Stevensc6b91c62017-02-08 14:23:58 -08002062 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks())
2063 // We strongly prefer to launch activities on the same display as their source.
2064 && (mSourceDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002065 }
2066
Wale Ogunwale854809c2015-12-27 16:18:19 -08002067 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002068 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07002069
Winson Chung83471632016-12-13 11:02:12 -08002070 // If the activity is of a specific type, return the associated stack, creating it if
2071 // necessary
2072 if (r.isHomeActivity()) {
2073 return mSupervisor.mHomeStack;
2074 }
2075 if (r.isRecentsActivity()) {
2076 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2077 }
2078 if (r.isAssistantActivity()) {
2079 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
2080 }
2081
Jorim Jaggib8c58762016-04-20 17:58:29 -07002082 // We are reusing a task, keep the stack!
2083 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002084 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07002085 }
2086
Andrii Kulian16802aa2016-11-02 12:21:33 -07002087 final int launchDisplayId =
2088 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
2089
Wale Ogunwale854809c2015-12-27 16:18:19 -08002090 final int launchStackId =
2091 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
2092
Andrii Kulian16802aa2016-11-02 12:21:33 -07002093 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
2094 throw new IllegalArgumentException(
2095 "Stack and display id can't be set at the same time.");
2096 }
2097
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002098 if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002099 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07002100 }
2101 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08002102 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2103 // for this activity, so we put the activity in the fullscreen stack.
2104 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08002105 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07002106 if (launchDisplayId != INVALID_DISPLAY) {
2107 // Stack id has higher priority than display id.
2108 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
2109 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002110
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07002111 // If we are using Vr2d display, find the virtual display stack.
2112 if (mUsingVr2dDisplay) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002113 ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
2114 if (DEBUG_STACK) {
2115 Slog.v(TAG, "Launch stack for app: " + r.toString() +
2116 ", on virtual display stack:" + as.toString());
2117 }
2118 return as;
2119 }
2120
2121 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
2122 || mSourceDisplayId != DEFAULT_DISPLAY) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002123 return null;
2124 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002125 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002126
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002127 // The parent activity doesn't want to launch the activity on top of itself, but
2128 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002129 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002130 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2131 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002132
2133 if (parentStack != mSupervisor.mFocusedStack) {
2134 // If task's parent stack is not focused - use it during adjacent launch.
2135 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002136 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002137 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2138 // If task is already on top of focused stack - use it. We don't want to move the
2139 // existing focused task to adjacent stack, just deliver new intent in this case.
2140 return mSupervisor.mFocusedStack;
2141 }
2142
Winson Chung83471632016-12-13 11:02:12 -08002143 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002144 // If parent was in docked stack, the natural place to launch another activity
2145 // will be fullscreen, so it can appear alongside the docked window.
2146 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2147 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002148 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002149 // If the parent is not in the docked stack, we check if there is docked window
2150 // and if yes, we will launch into that stack. If not, we just put the new
2151 // activity into parent's stack, because we can't find a better place.
2152 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2153 if (dockedStack != null
Wale Ogunwalecd501ec2017-04-07 08:53:41 -07002154 && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002155 // There is a docked stack, but it isn't visible, so we can't launch into that.
2156 return null;
2157 } else {
2158 return dockedStack;
2159 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002160 }
2161 }
2162 }
2163
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002164 boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002165 switch (stackId) {
2166 case INVALID_STACK_ID:
2167 case HOME_STACK_ID:
2168 return false;
2169 case FULLSCREEN_WORKSPACE_STACK_ID:
2170 return true;
2171 case FREEFORM_WORKSPACE_STACK_ID:
2172 return r.supportsFreeform();
2173 case DOCKED_STACK_ID:
2174 return r.supportsSplitScreen();
2175 case PINNED_STACK_ID:
2176 return r.supportsPictureInPicture();
2177 case RECENTS_STACK_ID:
2178 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002179 case ASSISTANT_STACK_ID:
2180 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002181 default:
Andrii Kulianeafd9db2017-04-05 22:01:35 -07002182 // TODO: Check ActivityView after fixing b/35349678.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07002183 if (StackId.isDynamicStack(stackId)) {
2184 return r.canBeLaunchedOnDisplay(displayId);
Andrii Kulian4acfd852017-01-26 19:43:13 -08002185 }
Winson Chungd3395382016-12-13 11:49:09 -08002186 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2187 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002188 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002189 }
2190
Wale Ogunwale854809c2015-12-27 16:18:19 -08002191 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2192 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002193 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002194 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2195 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002196 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002197 }
2198 }
2199 return newBounds;
2200 }
2201
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002202 void setWindowManager(WindowManagerService wm) {
2203 mWindowManager = wm;
2204 }
2205
2206 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2207 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2208 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2209 if (pal.stack == stack) {
2210 mPendingActivityLaunches.remove(palNdx);
2211 }
2212 }
2213 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002214
2215 static boolean isDocumentLaunchesIntoExisting(int flags) {
2216 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2217 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2218 }
liulvpingcfa825f2016-09-26 20:00:15 +08002219
2220 boolean clearPendingActivityLaunchesLocked(String packageName) {
2221 boolean didSomething = false;
2222
2223 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2224 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2225 ActivityRecord r = pal.r;
2226 if (r != null && r.packageName.equals(packageName)) {
2227 mPendingActivityLaunches.remove(palNdx);
2228 didSomething = true;
2229 }
2230 }
2231 return didSomething;
2232 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002233}