blob: 47a7f5d8d8f23d0992ee90150fa00fbf4307f874 [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;
20import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
21import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
22import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
23import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
24import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
25import static android.app.ActivityManager.START_SUCCESS;
26import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale854809c2015-12-27 16:18:19 -080027import static android.app.ActivityManager.StackId;
Winson Chung83471632016-12-13 11:02:12 -080028import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080029import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
30import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
31import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080032import static android.app.ActivityManager.StackId.HOME_STACK_ID;
33import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
34import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080035import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Andrii Kulian4ede3e02017-01-12 11:52:31 -080036import static android.app.ActivityManager.StackId.isDynamicStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080037import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
38import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010039import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080040import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080041import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080042import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080043import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080044import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
45import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080046import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
47import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
48import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
49import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
50import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080051import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080052import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
53import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
54import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
55import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Andrii Kulian16802aa2016-11-02 12:21:33 -070056import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080057import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080060import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080061import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
62import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
63import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
64import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
66import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
69import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
70import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
71import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080072import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -080073import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080074import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
75import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
76import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080077import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080078import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
79import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
80import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080081import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080082import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080083import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080084
Todd Kennedye9910222017-02-21 16:00:11 -080085import android.annotation.NonNull;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080086import android.app.ActivityManager;
87import android.app.ActivityOptions;
88import android.app.AppGlobals;
89import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080090import android.app.IApplicationThread;
Bryce Lee98689f72017-03-01 23:44:43 +000091import android.app.KeyguardManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080092import android.app.PendingIntent;
93import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070094import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080095import android.content.ComponentName;
Bryce Lee98689f72017-03-01 23:44:43 +000096import android.content.Context;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.content.IIntentSender;
98import android.content.Intent;
99import android.content.IntentSender;
100import android.content.pm.ActivityInfo;
101import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -0800102import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000103import android.content.pm.PackageManager;
Todd Kennedye9910222017-02-21 16:00:11 -0800104import android.content.pm.PackageManagerInternal;
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;
120import android.view.Display;
121
122import com.android.internal.app.HeavyWeightSwitcherActivity;
123import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800124import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800125import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800126import com.android.server.wm.WindowManagerService;
127
128import java.util.ArrayList;
129
130/**
131 * Controller for interpreting how and then launching activities.
132 *
133 * This class collects all the logic for determining how an intent and flags should be turned into
134 * an activity and associated task and stack.
135 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800136class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800137 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
138 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
139 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
140 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
141 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
142
143 private final ActivityManagerService mService;
144 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000145 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800146 private WindowManagerService mWindowManager;
147
148 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
149
Wale Ogunwale01d66562015-12-29 08:19:19 -0800150 // Share state variable among methods when starting an activity.
151 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700152 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800153 private Intent mIntent;
154 private int mCallingUid;
155 private ActivityOptions mOptions;
156
157 private boolean mLaunchSingleTop;
158 private boolean mLaunchSingleInstance;
159 private boolean mLaunchSingleTask;
160 private boolean mLaunchTaskBehind;
161 private int mLaunchFlags;
162
163 private Rect mLaunchBounds;
164
165 private ActivityRecord mNotTop;
166 private boolean mDoResume;
167 private int mStartFlags;
168 private ActivityRecord mSourceRecord;
169
170 private TaskRecord mInTask;
171 private boolean mAddingToTask;
172 private TaskRecord mReuseTask;
173
174 private ActivityInfo mNewTaskInfo;
175 private Intent mNewTaskIntent;
176 private ActivityStack mSourceStack;
177 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700178 // Indicates that we moved other task and are going to put something on top soon, so
179 // we don't want to show it redundantly or accidentally change what's shown below.
180 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800181 private boolean mMovedToFront;
182 private boolean mNoAnimation;
183 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700184 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700185 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800186
187 private IVoiceInteractionSession mVoiceSession;
188 private IVoiceInteractor mVoiceInteractor;
189
190 private void reset() {
191 mStartActivity = null;
192 mIntent = null;
193 mCallingUid = -1;
194 mOptions = null;
195
196 mLaunchSingleTop = false;
197 mLaunchSingleInstance = false;
198 mLaunchSingleTask = false;
199 mLaunchTaskBehind = false;
200 mLaunchFlags = 0;
201
202 mLaunchBounds = null;
203
204 mNotTop = null;
205 mDoResume = false;
206 mStartFlags = 0;
207 mSourceRecord = null;
208
209 mInTask = null;
210 mAddingToTask = false;
211 mReuseTask = null;
212
213 mNewTaskInfo = null;
214 mNewTaskIntent = null;
215 mSourceStack = null;
216
217 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700218 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800219 mMovedToFront = false;
220 mNoAnimation = false;
221 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700222 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800223
224 mVoiceSession = null;
225 mVoiceInteractor = null;
226 }
227
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800228 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
229 mService = service;
230 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000231 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800232 }
233
234 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
235 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
236 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
237 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
238 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
239 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
240 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
241 TaskRecord inTask) {
242 int err = ActivityManager.START_SUCCESS;
243
244 ProcessRecord callerApp = null;
245 if (caller != null) {
246 callerApp = mService.getRecordForAppLocked(caller);
247 if (callerApp != null) {
248 callingPid = callerApp.pid;
249 callingUid = callerApp.info.uid;
250 } else {
251 Slog.w(TAG, "Unable to find app for caller " + caller
252 + " (pid=" + callingPid + ") when starting: "
253 + intent.toString());
254 err = ActivityManager.START_PERMISSION_DENIED;
255 }
256 }
257
258 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
259
260 if (err == ActivityManager.START_SUCCESS) {
261 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800262 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800263 }
264
265 ActivityRecord sourceRecord = null;
266 ActivityRecord resultRecord = null;
267 if (resultTo != null) {
268 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
269 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
270 "Will send result to " + resultTo + " " + sourceRecord);
271 if (sourceRecord != null) {
272 if (requestCode >= 0 && !sourceRecord.finishing) {
273 resultRecord = sourceRecord;
274 }
275 }
276 }
277
278 final int launchFlags = intent.getFlags();
279
280 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
281 // Transfer the result target from the source activity to the new
282 // one being started, including any failures.
283 if (requestCode >= 0) {
284 ActivityOptions.abort(options);
285 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
286 }
287 resultRecord = sourceRecord.resultTo;
288 if (resultRecord != null && !resultRecord.isInStackLocked()) {
289 resultRecord = null;
290 }
291 resultWho = sourceRecord.resultWho;
292 requestCode = sourceRecord.requestCode;
293 sourceRecord.resultTo = null;
294 if (resultRecord != null) {
295 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
296 }
297 if (sourceRecord.launchedFromUid == callingUid) {
298 // The new activity is being launched from the same uid as the previous
299 // activity in the flow, and asking to forward its result back to the
300 // previous. In this case the activity is serving as a trampoline between
301 // the two, so we also want to update its launchedFromPackage to be the
302 // same as the previous activity. Note that this is safe, since we know
303 // these two packages come from the same uid; the caller could just as
304 // well have supplied that same package name itself. This specifially
305 // deals with the case of an intent picker/chooser being launched in the app
306 // flow to redirect to an activity picked by the user, where we want the final
307 // activity to consider it to have been launched by the previous app activity.
308 callingPackage = sourceRecord.launchedFromPackage;
309 }
310 }
311
312 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
313 // We couldn't find a class that can handle the given Intent.
314 // That's the end of that!
315 err = ActivityManager.START_INTENT_NOT_RESOLVED;
316 }
317
318 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
319 // We couldn't find the specific class specified in the Intent.
320 // Also the end of the line.
321 err = ActivityManager.START_CLASS_NOT_FOUND;
322 }
323
324 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
325 && sourceRecord.task.voiceSession != null) {
326 // If this activity is being launched as part of a voice session, we need
327 // to ensure that it is safe to do so. If the upcoming activity will also
328 // be part of the voice session, we can only launch it if it has explicitly
329 // said it supports the VOICE category, or it is a part of the calling app.
330 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
331 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
332 try {
333 intent.addCategory(Intent.CATEGORY_VOICE);
334 if (!AppGlobals.getPackageManager().activitySupportsIntent(
335 intent.getComponent(), intent, resolvedType)) {
336 Slog.w(TAG,
337 "Activity being started in current voice task does not support voice: "
338 + intent);
339 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
340 }
341 } catch (RemoteException e) {
342 Slog.w(TAG, "Failure checking voice capabilities", e);
343 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
344 }
345 }
346 }
347
348 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
349 // If the caller is starting a new voice session, just make sure the target
350 // is actually allowing it to run this way.
351 try {
352 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
353 intent, resolvedType)) {
354 Slog.w(TAG,
355 "Activity being started in new voice task does not support: "
356 + intent);
357 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
358 }
359 } catch (RemoteException e) {
360 Slog.w(TAG, "Failure checking voice capabilities", e);
361 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
362 }
363 }
364
Andrii Kulian02b7a832016-10-06 23:11:56 -0700365 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800366
Wale Ogunwale01d66562015-12-29 08:19:19 -0800367 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800368 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800369 resultStack.sendActivityResultLocked(
370 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800371 }
372 ActivityOptions.abort(options);
373 return err;
374 }
375
376 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
377 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100378 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800379 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
380 callingPid, resolvedType, aInfo.applicationInfo);
381
382 if (mService.mController != null) {
383 try {
384 // The Intent we give to the watcher has the extra data
385 // stripped off, since it can contain private information.
386 Intent watchIntent = intent.cloneFilter();
387 abort |= !mService.mController.activityStarting(watchIntent,
388 aInfo.applicationInfo.packageName);
389 } catch (RemoteException e) {
390 mService.mController = null;
391 }
392 }
393
Rubin Xu58d25992016-01-21 17:47:13 +0000394 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100395 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
396 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000397 intent = mInterceptor.mIntent;
398 rInfo = mInterceptor.mRInfo;
399 aInfo = mInterceptor.mAInfo;
400 resolvedType = mInterceptor.mResolvedType;
401 inTask = mInterceptor.mInTask;
402 callingPid = mInterceptor.mCallingPid;
403 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100404 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800405 if (abort) {
406 if (resultRecord != null) {
407 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800408 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800409 }
410 // We pretend to the caller that it was really started, but
411 // they will just get a cancel result.
412 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800413 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800414 }
415
416 // If permissions need a review before any of the app components can run, we
417 // launch the review activity and pass a pending intent to start the activity
418 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700419 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800420 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
421 aInfo.packageName, userId)) {
422 IIntentSender target = mService.getIntentSenderLocked(
423 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
424 callingUid, userId, null, null, 0, new Intent[]{intent},
425 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
426 | PendingIntent.FLAG_ONE_SHOT, null);
427
428 final int flags = intent.getFlags();
429 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
430 newIntent.setFlags(flags
431 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
432 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
433 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
434 if (resultRecord != null) {
435 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
436 }
437 intent = newIntent;
438
439 resolvedType = null;
440 callingUid = realCallingUid;
441 callingPid = realCallingPid;
442
443 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
444 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
445 null /*profilerInfo*/);
446
447 if (DEBUG_PERMISSIONS_REVIEW) {
448 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
449 true, false) + "} from uid " + callingUid + " on display "
450 + (container == null ? (mSupervisor.mFocusedStack == null ?
451 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
452 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
453 container.mActivityDisplay.mDisplayId)));
454 }
455 }
456 }
457
458 // If we have an ephemeral app, abort the process of launching the resolved intent.
459 // Instead, launch the ephemeral installer. Once the installer is finished, it
460 // starts either the intent we resolved here [on install error] or the ephemeral
461 // app [on install success].
Todd Kennedye9910222017-02-21 16:00:11 -0800462 if (rInfo != null && rInfo.auxiliaryInfo != null) {
463 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
464 callingPackage, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800465 resolvedType = null;
466 callingUid = realCallingUid;
467 callingPid = realCallingPid;
468
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800469 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
470 }
471
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800472 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
473 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
474 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
475 mSupervisor, container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800476 if (outActivity != null) {
477 outActivity[0] = r;
478 }
479
480 if (r.appTimeTracker == null && sourceRecord != null) {
481 // If the caller didn't specify an explicit time tracker, we want to continue
482 // tracking under any it has.
483 r.appTimeTracker = sourceRecord.appTimeTracker;
484 }
485
486 final ActivityStack stack = mSupervisor.mFocusedStack;
487 if (voiceSession == null && (stack.mResumedActivity == null
488 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
489 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
490 realCallingPid, realCallingUid, "Activity start")) {
491 PendingActivityLaunch pal = new PendingActivityLaunch(r,
492 sourceRecord, startFlags, stack, callerApp);
493 mPendingActivityLaunches.add(pal);
494 ActivityOptions.abort(options);
495 return ActivityManager.START_SWITCHES_CANCELED;
496 }
497 }
498
499 if (mService.mDidAppSwitch) {
500 // This is the second allowed switch since we stopped switches,
501 // so now just generally allow switches. Use case: user presses
502 // home (switches disabled, switch to home, mDidAppSwitch now true);
503 // user taps a home icon (coming from home so allowed, we hit here
504 // and now allow anyone to switch again).
505 mService.mAppSwitchesAllowedTime = 0;
506 } else {
507 mService.mDidAppSwitch = true;
508 }
509
510 doPendingActivityLaunchesLocked(false);
511
Bryce Lee98689f72017-03-01 23:44:43 +0000512 try {
513 mService.mWindowManager.deferSurfaceLayout();
514 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
515 true, options, inTask);
516 } finally {
517 mService.mWindowManager.continueSurfaceLayout();
518 }
519 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
520 return err;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800521 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800522
Todd Kennedye9910222017-02-21 16:00:11 -0800523 /** Creates a launch intent for the given auxiliary resolution data. */
524 private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
Bryce Lee98689f72017-03-01 23:44:43 +0000525 Intent originalIntent, String callingPackage,
526 String resolvedType, int userId) {
Todd Kennedye9910222017-02-21 16:00:11 -0800527 if (auxiliaryResponse.needsPhaseTwo) {
528 // request phase two resolution
529 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Bryce Lee98689f72017-03-01 23:44:43 +0000530 auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800531 }
Todd Kennedy1fb34042017-03-01 13:56:58 -0800532 return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
533 callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
534 auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
535 auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
Todd Kennedye9910222017-02-21 16:00:11 -0800536 }
537
Bryce Lee98689f72017-03-01 23:44:43 +0000538 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700539 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
540 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800541
542 if (result < START_SUCCESS) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800543 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800544 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800545
Chong Zhang5022da32016-06-21 16:31:37 -0700546 // We're waiting for an activity launch to finish, but that activity simply
547 // brought another activity to front. Let startActivityMayWait() know about
548 // this, so it waits for the new activity to become visible instead.
549 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
550 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
551 }
552
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800553 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700554 final ActivityStack currentStack = r.getStack();
555 if (currentStack != null) {
556 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800557 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700558 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800559 }
560
Jorim Jaggi352d5842016-05-19 10:20:28 -0700561 // If we launched the activity from a no display activity that was launched from the home
562 // screen, we also need to start recents to un-minimize the docked stack, since the
563 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700564 // Note that some apps have trampoline activities without noDisplay being set. In that case,
565 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
566 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700567 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
568 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700569 final boolean noDisplayActivityOverHome = sourceRecord != null
570 && sourceRecord.noDisplay
571 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700572 if (startedActivityStackId == DOCKED_STACK_ID
573 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100574 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
575 final ActivityRecord topActivityHomeStack = homeStack != null
576 ? homeStack.topRunningActivityLocked() : null;
577 if (topActivityHomeStack == null
578 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
579 // We launch an activity while being in home stack, which means either launcher or
580 // recents into docked stack. We don't want the launched activity to be alone in a
581 // docked stack, so we want to immediately launch recents too.
582 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700583 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100584 return;
585 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800586 }
587
588 if (startedActivityStackId == PINNED_STACK_ID
589 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
590 // The activity was already running in the pinned stack so it wasn't started, but either
591 // brought to the front or the new intent was delivered to it since it was already in
592 // front. Notify anyone interested in this piece of information.
Winson Chung3535df22017-01-17 18:43:39 -0800593 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
Winson Chung49affea2017-02-16 20:41:08 -0800594 sourceRecord.launchedFromPackage);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800595 return;
596 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800597 }
598
599 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800600 mSupervisor.moveHomeStackTaskToTop(reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800601 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
602 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
603 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
604 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
605 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700606 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800607 null /*container*/, null /*inTask*/);
608 if (mSupervisor.inResumeTopActivity) {
609 // If we are in resume section already, home activity will be initialized, but not
610 // resumed (to avoid recursive resume) and will stay that way until something pokes it
611 // again. We need to schedule another resume.
612 mSupervisor.scheduleResumeTopActivities();
613 }
614 }
615
Robin Lee5d592422017-01-18 13:48:15 +0000616 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100617 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
618 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
619 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000620 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
621 : ActivityOptions.makeBasic());
Tony Mak646fe992016-04-21 16:43:08 +0100622 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000623 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100624 }
Tony Mak853304c2016-04-18 15:17:41 +0100625
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800626 final int startActivityMayWait(IApplicationThread caller, int callingUid,
627 String callingPackage, Intent intent, String resolvedType,
628 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
629 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700630 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700631 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800632 IActivityContainer iContainer, TaskRecord inTask) {
633 // Refuse possible leaked file descriptors
634 if (intent != null && intent.hasFileDescriptors()) {
635 throw new IllegalArgumentException("File descriptors passed in Intent");
636 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500637 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800638 boolean componentSpecified = intent.getComponent() != null;
639
640 // Save a copy in case ephemeral needs it
641 final Intent ephemeralIntent = new Intent(intent);
642 // Don't modify the client's object!
643 intent = new Intent(intent);
644
645 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000646 if (rInfo == null) {
647 UserInfo userInfo = mSupervisor.getUserInfo(userId);
648 if (userInfo != null && userInfo.isManagedProfile()) {
649 // Special case for managed profiles, if attempting to launch non-cryto aware
650 // app in a locked managed profile from an unlocked parent allow it to resolve
651 // as user will be sent via confirm credentials to unlock the profile.
652 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700653 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000654 long token = Binder.clearCallingIdentity();
655 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700656 UserInfo parent = userManager.getProfileParent(userId);
657 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
658 && userManager.isUserUnlockingOrUnlocked(parent.id)
659 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000660 } finally {
661 Binder.restoreCallingIdentity(token);
662 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700663 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000664 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600665 PackageManager.MATCH_DIRECT_BOOT_AWARE
666 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000667 }
668 }
669 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800670 // Collect information about the target of the Intent.
671 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
672
673 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
674 ActivityStackSupervisor.ActivityContainer container =
675 (ActivityStackSupervisor.ActivityContainer)iContainer;
676 synchronized (mService) {
677 if (container != null && container.mParentActivity != null &&
678 container.mParentActivity.state != RESUMED) {
679 // Cannot start a child activity if the parent is not resumed.
680 return ActivityManager.START_CANCELED;
681 }
682 final int realCallingPid = Binder.getCallingPid();
683 final int realCallingUid = Binder.getCallingUid();
684 int callingPid;
685 if (callingUid >= 0) {
686 callingPid = -1;
687 } else if (caller == null) {
688 callingPid = realCallingPid;
689 callingUid = realCallingUid;
690 } else {
691 callingPid = callingUid = -1;
692 }
693
694 final ActivityStack stack;
695 if (container == null || container.mStack.isOnHomeDisplay()) {
696 stack = mSupervisor.mFocusedStack;
697 } else {
698 stack = container.mStack;
699 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700700 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700701 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800702 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
703 "Starting activity when config will change = " + stack.mConfigWillChange);
704
705 final long origId = Binder.clearCallingIdentity();
706
707 if (aInfo != null &&
708 (aInfo.applicationInfo.privateFlags
709 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
710 // This may be a heavy-weight process! Check to see if we already
711 // have another, different heavy-weight process running.
712 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
713 final ProcessRecord heavy = mService.mHeavyWeightProcess;
714 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
715 || !heavy.processName.equals(aInfo.processName))) {
716 int appCallingUid = callingUid;
717 if (caller != null) {
718 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
719 if (callerApp != null) {
720 appCallingUid = callerApp.info.uid;
721 } else {
722 Slog.w(TAG, "Unable to find app for caller " + caller
723 + " (pid=" + callingPid + ") when starting: "
724 + intent.toString());
725 ActivityOptions.abort(options);
726 return ActivityManager.START_PERMISSION_DENIED;
727 }
728 }
729
730 IIntentSender target = mService.getIntentSenderLocked(
731 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
732 appCallingUid, userId, null, null, 0, new Intent[] { intent },
733 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
734 | PendingIntent.FLAG_ONE_SHOT, null);
735
736 Intent newIntent = new Intent();
737 if (requestCode >= 0) {
738 // Caller is requesting a result.
739 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
740 }
741 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
742 new IntentSender(target));
743 if (heavy.activities.size() > 0) {
744 ActivityRecord hist = heavy.activities.get(0);
745 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
746 hist.packageName);
747 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
748 hist.task.taskId);
749 }
750 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
751 aInfo.packageName);
752 newIntent.setFlags(intent.getFlags());
753 newIntent.setClassName("android",
754 HeavyWeightSwitcherActivity.class.getName());
755 intent = newIntent;
756 resolvedType = null;
757 caller = null;
758 callingUid = Binder.getCallingUid();
759 callingPid = Binder.getCallingPid();
760 componentSpecified = true;
761 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
762 aInfo = rInfo != null ? rInfo.activityInfo : null;
763 if (aInfo != null) {
764 aInfo = mService.getActivityInfoForUser(aInfo, userId);
765 }
766 }
767 }
768 }
769
Jorim Jaggi275561a2016-02-23 10:11:02 -0500770 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800771 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
772 aInfo, rInfo, voiceSession, voiceInteractor,
773 resultTo, resultWho, requestCode, callingPid,
774 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500775 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
776 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800777
778 Binder.restoreCallingIdentity(origId);
779
780 if (stack.mConfigWillChange) {
781 // If the caller also wants to switch to a new configuration,
782 // do so now. This allows a clean switch, as we are waiting
783 // for the current activity to pause (so we will not destroy
784 // it), and have not yet started the next activity.
785 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
786 "updateConfiguration()");
787 stack.mConfigWillChange = false;
788 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
789 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700790 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800791 }
792
793 if (outResult != null) {
794 outResult.result = res;
795 if (res == ActivityManager.START_SUCCESS) {
796 mSupervisor.mWaitingActivityLaunched.add(outResult);
797 do {
798 try {
799 mService.wait();
800 } catch (InterruptedException e) {
801 }
Chong Zhang5022da32016-06-21 16:31:37 -0700802 } while (outResult.result != START_TASK_TO_FRONT
803 && !outResult.timeout && outResult.who == null);
804 if (outResult.result == START_TASK_TO_FRONT) {
805 res = START_TASK_TO_FRONT;
806 }
807 }
808 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800809 ActivityRecord r = stack.topRunningActivityLocked();
810 if (r.nowVisible && r.state == RESUMED) {
811 outResult.timeout = false;
812 outResult.who = new ComponentName(r.info.packageName, r.info.name);
813 outResult.totalTime = 0;
814 outResult.thisTime = 0;
815 } else {
816 outResult.thisTime = SystemClock.uptimeMillis();
817 mSupervisor.mWaitingActivityVisible.add(outResult);
818 do {
819 try {
820 mService.wait();
821 } catch (InterruptedException e) {
822 }
823 } while (!outResult.timeout && outResult.who == null);
824 }
825 }
826 }
827
Jorim Jaggibe67c902016-04-12 00:53:16 -0700828 final ActivityRecord launchedActivity = mReusedActivity != null
829 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700830 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800831 return res;
832 }
833 }
834
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800835 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
836 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
837 Bundle bOptions, int userId) {
838 if (intents == null) {
839 throw new NullPointerException("intents is null");
840 }
841 if (resolvedTypes == null) {
842 throw new NullPointerException("resolvedTypes is null");
843 }
844 if (intents.length != resolvedTypes.length) {
845 throw new IllegalArgumentException("intents are length different than resolvedTypes");
846 }
847
Makoto Onukid67b1872016-07-21 16:26:36 -0700848 final int realCallingPid = Binder.getCallingPid();
849 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800850
851 int callingPid;
852 if (callingUid >= 0) {
853 callingPid = -1;
854 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700855 callingPid = realCallingPid;
856 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800857 } else {
858 callingPid = callingUid = -1;
859 }
860 final long origId = Binder.clearCallingIdentity();
861 try {
862 synchronized (mService) {
863 ActivityRecord[] outActivity = new ActivityRecord[1];
864 for (int i=0; i<intents.length; i++) {
865 Intent intent = intents[i];
866 if (intent == null) {
867 continue;
868 }
869
870 // Refuse possible leaked file descriptors
871 if (intent != null && intent.hasFileDescriptors()) {
872 throw new IllegalArgumentException("File descriptors passed in Intent");
873 }
874
875 boolean componentSpecified = intent.getComponent() != null;
876
877 // Don't modify the client's object!
878 intent = new Intent(intent);
879
880 // Collect information about the target of the Intent.
881 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
882 null, userId);
883 // TODO: New, check if this is correct
884 aInfo = mService.getActivityInfoForUser(aInfo, userId);
885
886 if (aInfo != null &&
887 (aInfo.applicationInfo.privateFlags
888 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
889 throw new IllegalArgumentException(
890 "FLAG_CANT_SAVE_STATE not supported here");
891 }
892
893 ActivityOptions options = ActivityOptions.fromBundle(
894 i == intents.length - 1 ? bOptions : null);
895 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
896 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700897 callingPid, callingUid, callingPackage,
898 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800899 options, false, componentSpecified, outActivity, null, null);
900 if (res < 0) {
901 return res;
902 }
903
904 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
905 }
906 }
907 } finally {
908 Binder.restoreCallingIdentity(origId);
909 }
910
Wale Ogunwale01d66562015-12-29 08:19:19 -0800911 return START_SUCCESS;
912 }
913
Wei Wang65c7a152016-06-02 18:51:22 -0700914 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
Bryce Lee834abec2017-01-09 16:18:14 -0800915 boolean sendHint = forceSend;
916
917 if (!sendHint) {
918 // If not forced, send power hint when the activity's process is different than the
919 // current resumed activity.
920 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
921 sendHint = resumedActivity == null
922 || resumedActivity.app == null
923 || !resumedActivity.app.equals(mStartActivity.app);
924 }
925
926 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700927 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700928 mPowerHintSent = true;
929 }
930 }
931
Wei Wang65c7a152016-06-02 18:51:22 -0700932 void sendPowerHintForLaunchEndIfNeeded() {
933 // Trigger launch power hint if activity is launched
934 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700935 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700936 mPowerHintSent = false;
937 }
938 }
939
Wale Ogunwale01d66562015-12-29 08:19:19 -0800940 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
941 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
942 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
943
944 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
945 voiceInteractor);
946
947 computeLaunchingTaskFlags();
948
949 computeSourceStack();
950
951 mIntent.setFlags(mLaunchFlags);
952
Jorim Jaggibe67c902016-04-12 00:53:16 -0700953 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800954
Jorim Jaggi2adba072016-03-03 13:43:39 +0100955 final int preferredLaunchStackId =
956 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
957
Jorim Jaggibe67c902016-04-12 00:53:16 -0700958 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800959 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
960 // still needs to be a lock task mode violation since the task gets cleared out and
961 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700962 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800963 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
964 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
965 mSupervisor.showLockTaskToast();
966 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
967 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
968 }
969
970 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -0700971 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800972 }
Jorim Jaggibe67c902016-04-12 00:53:16 -0700973 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800974 // This task was started because of movement of the activity based on affinity...
975 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700976 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800977 }
978
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800979 // This code path leads to delivering a new intent, we want to make sure we schedule it
980 // as the first operation, in case the activity will be resumed as a result of later
981 // operations.
982 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +0900983 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800984 || mLaunchSingleInstance || mLaunchSingleTask) {
985 // In this situation we want to remove all activities from the task up to the one
986 // being started. In most cases this means we are resetting the task to its initial
987 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700988 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800989 mStartActivity, mLaunchFlags);
990 if (top != null) {
991 if (top.frontOfTask) {
992 // Activity aliases may mean we use different intents for the top activity,
993 // so make sure the task now has the identity of the new intent.
994 top.task.setIntent(mStartActivity);
995 }
996 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
997 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
998 mStartActivity.launchedFromPackage);
999 }
1000 }
1001
Wei Wang65c7a152016-06-02 18:51:22 -07001002 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001003
Jorim Jaggibe67c902016-04-12 00:53:16 -07001004 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001005
1006 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1007 // We don't need to start a new activity, and the client said not to do anything
1008 // if that is the case, so this is it! And for paranoia, make sure we have
1009 // correctly resumed the top activity.
1010 resumeTargetStackIfNeeded();
1011 return START_RETURN_INTENT_TO_CALLER;
1012 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001013 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001014
1015 if (!mAddingToTask && mReuseTask == null) {
1016 // We didn't do anything... but it was needed (a.k.a., client don't use that
1017 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1018 resumeTargetStackIfNeeded();
1019 return START_TASK_TO_FRONT;
1020 }
1021 }
1022
1023 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001024 final ActivityStack sourceStack = mStartActivity.resultTo != null
1025 ? mStartActivity.resultTo.getStack() : null;
1026 if (sourceStack != null) {
1027 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1028 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1029 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001030 }
1031 ActivityOptions.abort(mOptions);
1032 return START_CLASS_NOT_FOUND;
1033 }
1034
1035 // If the activity being launched is the same as the one currently at the top, then
1036 // we need to check if it should only be launched once.
1037 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001038 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001039 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1040 final boolean dontStart = top != null && mStartActivity.resultTo == null
1041 && top.realActivity.equals(mStartActivity.realActivity)
1042 && top.userId == mStartActivity.userId
1043 && top.app != null && top.app.thread != null
1044 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1045 || mLaunchSingleTop || mLaunchSingleTask);
1046 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001047 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001048 // For paranoia, make sure we have correctly resumed the top activity.
1049 topStack.mLastPausedActivity = null;
1050 if (mDoResume) {
1051 mSupervisor.resumeFocusedStackTopActivityLocked();
1052 }
1053 ActivityOptions.abort(mOptions);
1054 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1055 // We don't need to start a new activity, and the client said not to do
1056 // anything if that is the case, so this is it!
1057 return START_RETURN_INTENT_TO_CALLER;
1058 }
1059 top.deliverNewIntentLocked(
1060 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001061
1062 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1063 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1064 mSupervisor.handleNonResizableTaskIfNeeded(
1065 top.task, preferredLaunchStackId, topStack.mStackId);
1066
Wale Ogunwale01d66562015-12-29 08:19:19 -08001067 return START_DELIVERED_TO_TOP;
1068 }
1069
1070 boolean newTask = false;
1071 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1072 ? mSourceRecord.task : null;
1073
1074 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001075 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001076 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1077 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1078 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001079 result = setTaskFromReuseOrCreateNewTask(
1080 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001081 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001082 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001083 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001084 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001085 } else {
1086 // This not being started from an existing activity, and not part of a new task...
1087 // just put it in the top task, though these days this case should never happen.
1088 setTaskToCurrentTopOrCreateNewTask();
1089 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001090 if (result != START_SUCCESS) {
1091 return result;
1092 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001093
1094 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1095 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001096 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1097 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001098 if (mSourceRecord != null) {
1099 mStartActivity.task.setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001100 }
1101 if (newTask) {
1102 EventLog.writeEvent(
1103 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1104 }
1105 ActivityStack.logStartActivity(
1106 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1107 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001108
Wei Wang65c7a152016-06-02 18:51:22 -07001109 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001110
Winson Chungb5c41b72016-12-07 15:00:47 -08001111 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1112 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001113 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001114 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1115 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001116 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1117 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001118 // If the activity is not focusable, we can't resume it, but still would like to
1119 // make sure it becomes visible as it starts (this will also trigger entry
1120 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001121 // Also, we don't want to resume activities in a task that currently has an overlay
1122 // as the starting activity just needs to be in the visible paused state until the
1123 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001124 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001125 // Go ahead and tell window manager to execute app transition for this activity
1126 // since the app transition will not be triggered through the resume channel.
1127 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001128 } else {
Winson Chung32066032016-11-04 11:55:21 -07001129 // If the target stack was not previously focusable (previous top running activity
1130 // on that stack was not visible) then any prior calls to move the stack to the
1131 // will not update the focused stack. If starting the new activity now allows the
1132 // task stack to be focusable, then ensure that we now update the focused stack
1133 // accordingly.
1134 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1135 mTargetStack.moveToFront("startActivityUnchecked");
1136 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001137 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1138 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001139 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001140 } else {
1141 mTargetStack.addRecentActivityLocked(mStartActivity);
1142 }
1143 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1144
Jorim Jaggid53f0922016-04-06 22:16:23 -07001145 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001146 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001147
1148 return START_SUCCESS;
1149 }
1150
1151 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1152 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1153 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1154 reset();
1155
1156 mStartActivity = r;
1157 mIntent = r.intent;
1158 mOptions = options;
1159 mCallingUid = r.launchedFromUid;
1160 mSourceRecord = sourceRecord;
1161 mVoiceSession = voiceSession;
1162 mVoiceInteractor = voiceInteractor;
1163
1164 mLaunchBounds = getOverrideBounds(r, options, inTask);
1165
1166 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1167 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1168 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1169 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1170 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1171 mLaunchTaskBehind = r.mLaunchTaskBehind
1172 && !mLaunchSingleTask && !mLaunchSingleInstance
1173 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1174
1175 sendNewTaskResultRequestIfNeeded();
1176
1177 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1178 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1179 }
1180
1181 // If we are actually going to launch in to a new task, there are some cases where
1182 // we further want to do multiple task.
1183 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1184 if (mLaunchTaskBehind
1185 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1186 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1187 }
1188 }
1189
1190 // We'll invoke onUserLeaving before onPause only if the launching
1191 // activity did not explicitly state that this is an automated launch.
1192 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1193 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1194 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1195
1196 // If the caller has asked not to resume at this point, we make note
1197 // of this in the record so that we can skip it when trying to find
1198 // the top running activity.
1199 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001200 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001201 r.delayedResume = true;
1202 mDoResume = false;
1203 }
1204
Winson Chungcbcadc92017-01-12 15:54:12 -08001205 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1206 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001207 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001208 if (!mOptions.canTaskOverlayResume()) {
1209 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1210 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1211 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001212
Winson Chungcbcadc92017-01-12 15:54:12 -08001213 // The caller specifies that we'd like to be avoided to be moved to the front,
1214 // so be it!
1215 mDoResume = false;
1216 mAvoidMoveToFront = true;
1217 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001218 }
1219 }
1220
Wale Ogunwale01d66562015-12-29 08:19:19 -08001221 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1222
1223 mInTask = inTask;
1224 // In some flows in to this function, we retrieve the task record and hold on to it
1225 // without a lock before calling back in to here... so the task at this point may
1226 // not actually be in recents. Check for that, and if it isn't in recents just
1227 // consider it invalid.
1228 if (inTask != null && !inTask.inRecents) {
1229 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1230 mInTask = null;
1231 }
1232
1233 mStartFlags = startFlags;
1234 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1235 // is the same as the one making the call... or, as a special case, if we do not know
1236 // the caller then we count the current top activity as the caller.
1237 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1238 ActivityRecord checkedCaller = sourceRecord;
1239 if (checkedCaller == null) {
1240 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1241 mNotTop);
1242 }
1243 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1244 // Caller is not the same as launcher, so always needed.
1245 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1246 }
1247 }
1248
1249 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1250 }
1251
1252 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001253 final ActivityStack sourceStack = mStartActivity.resultTo != null
1254 ? mStartActivity.resultTo.getStack() : null;
1255 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001256 // For whatever reason this activity is being launched into a new task...
1257 // yet the caller has requested a result back. Well, that is pretty messed up,
1258 // so instead immediately send back a cancel and let the new task continue launched
1259 // as normal without a dependency on its originator.
1260 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001261 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1262 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1263 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001264 mStartActivity.resultTo = null;
1265 }
1266 }
1267
1268 private void computeLaunchingTaskFlags() {
1269 // If the caller is not coming from another activity, but has given us an explicit task into
1270 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001271 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001272 final Intent baseIntent = mInTask.getBaseIntent();
1273 final ActivityRecord root = mInTask.getRootActivity();
1274 if (baseIntent == null) {
1275 ActivityOptions.abort(mOptions);
1276 throw new IllegalArgumentException("Launching into task without base intent: "
1277 + mInTask);
1278 }
1279
1280 // If this task is empty, then we are adding the first activity -- it
1281 // determines the root, and must be launching as a NEW_TASK.
1282 if (mLaunchSingleInstance || mLaunchSingleTask) {
1283 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1284 ActivityOptions.abort(mOptions);
1285 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1286 + mStartActivity + " into different task " + mInTask);
1287 }
1288 if (root != null) {
1289 ActivityOptions.abort(mOptions);
1290 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1291 + " has root " + root + " but target is singleInstance/Task");
1292 }
1293 }
1294
1295 // If task is empty, then adopt the interesting intent launch flags in to the
1296 // activity being started.
1297 if (root == null) {
1298 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1299 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1300 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1301 | (baseIntent.getFlags() & flagsOfInterest);
1302 mIntent.setFlags(mLaunchFlags);
1303 mInTask.setIntent(mStartActivity);
1304 mAddingToTask = true;
1305
1306 // If the task is not empty and the caller is asking to start it as the root of
1307 // a new task, then we don't actually want to start this on the task. We will
1308 // bring the task to the front, and possibly give it a new intent.
1309 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1310 mAddingToTask = false;
1311
1312 } else {
1313 mAddingToTask = true;
1314 }
1315
1316 mReuseTask = mInTask;
1317 } else {
1318 mInTask = null;
1319 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1320 // when in freeform workspace.
1321 // Also put noDisplay activities in the source task. These by itself can be placed
1322 // in any task/stack, however it could launch other activities like ResolverActivity,
1323 // and we want those to stay in the original task.
1324 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1325 && mSourceRecord.isFreeform()) {
1326 mAddingToTask = true;
1327 }
1328 }
1329
1330 if (mInTask == null) {
1331 if (mSourceRecord == null) {
1332 // This activity is not being started from another... in this
1333 // case we -always- start a new task.
1334 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1335 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1336 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1337 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1338 }
1339 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1340 // The original activity who is starting us is running as a single
1341 // instance... this new activity it is starting must go on its
1342 // own task.
1343 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1344 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1345 // The activity being started is a single instance... it always
1346 // gets launched into its own task.
1347 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1348 }
1349 }
1350 }
1351
1352 private void computeSourceStack() {
1353 if (mSourceRecord == null) {
1354 mSourceStack = null;
1355 return;
1356 }
1357 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001358 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001359 return;
1360 }
1361
1362 // If the source is finishing, we can't further count it as our source. This is because the
1363 // task it is associated with may now be empty and on its way out, so we don't want to
1364 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1365 // a task for it. But save the task information so it can be used when creating the new task.
1366 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1367 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1368 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1369 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1370 mNewTaskInfo = mSourceRecord.info;
1371 mNewTaskIntent = mSourceRecord.task.intent;
1372 }
1373 mSourceRecord = null;
1374 mSourceStack = null;
1375 }
1376
1377 /**
1378 * Decide whether the new activity should be inserted into an existing task. Returns null
1379 * if not or an ActivityRecord with the task into which the new activity should be added.
1380 */
1381 private ActivityRecord getReusableIntentActivity() {
1382 // We may want to try to place the new activity in to an existing task. We always
1383 // do this if the target activity is singleTask or singleInstance; we will also do
1384 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1385 // us to still place it in a new task: multi task, always doc mode, or being asked to
1386 // launch this as a new task behind the current one.
1387 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1388 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1389 || mLaunchSingleInstance || mLaunchSingleTask;
1390 // If bring to front is requested, and no result is requested and we have not been given
1391 // an explicit task to launch in to, and we can find a task that was started with this
1392 // same component, then instead of launching bring that one to the front.
1393 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1394 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001395 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1396 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1397 intentActivity = task != null ? task.getTopActivity() : null;
1398 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001399 if (mLaunchSingleInstance) {
1400 // There can be one and only one instance of single instance activity in the
1401 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001402 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001403 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1404 // For the launch adjacent case we only want to put the activity in an existing
1405 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001406 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1407 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001408 } else {
1409 // Otherwise find the best task to put the activity in.
1410 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1411 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001412 }
1413 return intentActivity;
1414 }
1415
1416 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001417 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001418 mTargetStack.mLastPausedActivity = null;
1419 // If the target task is not in the front, then we need to bring it to the front...
1420 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1421 // the same behavior as if a new instance was being started, which means not bringing it
1422 // to the front if the caller is not itself in the front.
1423 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1424 ActivityRecord curTop = (focusStack == null)
1425 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1426
Jorim Jaggic875ae72016-04-26 22:41:06 -07001427 if (curTop != null
1428 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1429 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001430 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1431 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1432 mSourceStack.topActivity().task == mSourceRecord.task)) {
1433 // We really do want to push this one into the user's face, right now.
1434 if (mLaunchTaskBehind && mSourceRecord != null) {
1435 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1436 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001437 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001438
1439 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1440 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1441 // So no point resuming any of the activities here, it just wastes one extra
1442 // resuming, plus enter AND exit transitions.
1443 // Here we only want to bring the target stack forward. Transition will be applied
1444 // to the new activity that's started after the old ones are gone.
1445 final boolean willClearTask =
1446 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1447 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1448 if (!willClearTask) {
1449 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001450 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001451 if (launchStack == null || launchStack == mTargetStack) {
1452 // We only want to move to the front, if we aren't going to launch on a
1453 // different stack. If we launch on a different stack, we will put the
1454 // task on top there.
1455 mTargetStack.moveTaskToFrontLocked(
1456 intentActivity.task, mNoAnimation, mOptions,
1457 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1458 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001459 } else if (launchStack.mStackId == DOCKED_STACK_ID
1460 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1461 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1462 // If we want to launch adjacent and mTargetStack is not the computed
1463 // launch stack - move task to top of computed stack.
1464 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1465 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1466 ANIMATE);
1467 } else {
1468 // TODO: This should be reevaluated in MW v2.
1469 // We choose to move task to front instead of launching it adjacent
1470 // when specific stack was requested explicitly and it appeared to be
1471 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1472 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1473 mOptions, mStartActivity.appTimeTracker,
1474 "bringToFrontInsteadOfAdjacentLaunch");
1475 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001476 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001477 }
1478 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001479
1480 // We are moving a task to the front, use starting window to hide initial drawn
1481 // delay.
1482 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1483 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001484 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001485 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001486 }
1487 }
1488 if (!mMovedToFront && mDoResume) {
1489 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1490 + " from " + intentActivity);
1491 mTargetStack.moveToFront("intentActivityFound");
1492 }
1493
Jorim Jaggid53f0922016-04-06 22:16:23 -07001494 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1495 mTargetStack.mStackId);
1496
Wale Ogunwale01d66562015-12-29 08:19:19 -08001497 // If the caller has requested that the target task be reset, then do so.
1498 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1499 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1500 }
1501 return intentActivity;
1502 }
1503
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001504 private void updateTaskReturnToType(
1505 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001506 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001507 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1508 // Caller wants to appear on home activity.
1509 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1510 return;
Winson Chung83471632016-12-13 11:02:12 -08001511 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001512 // Task will be launched over the home stack, so return home.
1513 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1514 return;
Winson Chung83471632016-12-13 11:02:12 -08001515 } else if (focusedStack != null && focusedStack != task.getStack() &&
1516 focusedStack.isAssistantStack()) {
1517 // Task was launched over the assistant stack, so return there
1518 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1519 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001520 }
1521
1522 // Else we are coming from an application stack so return to an application.
1523 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1524 }
1525
Wale Ogunwale01d66562015-12-29 08:19:19 -08001526 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1527 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1528 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1529 // The caller has requested to completely replace any existing task with its new
1530 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001531 intentActivity.task.performClearTaskLocked();
1532 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001533 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001534 // When we clear the task - focus will be adjusted, which will bring another task
1535 // to top before we launch the activity we need. This will temporary swap their
1536 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1537 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001538 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1539 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001540 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1541 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001542 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001543 // A special case: we need to start the activity because it is not currently
1544 // running, and the caller has asked to clear the current task to have this
1545 // activity at the top.
1546 mAddingToTask = true;
1547 // Now pretend like this activity is being started by the top of its task, so it
1548 // is put in the right place.
1549 mSourceRecord = intentActivity;
1550 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001551 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001552 // Target stack got cleared when we all activities were removed above.
1553 // Go ahead and reset it.
1554 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1555 null /* bounds */, mLaunchFlags, mOptions);
1556 mTargetStack.addTask(task,
1557 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1558 }
1559 }
1560 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1561 // In this case the top activity on the task is the same as the one being launched,
1562 // so we take that as a request to bring the task to the foreground. If the top
1563 // activity in the task is the root activity, deliver this new intent to it if it
1564 // desires.
1565 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1566 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001567 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001568 intentActivity.task);
1569 if (intentActivity.frontOfTask) {
1570 intentActivity.task.setIntent(mStartActivity);
1571 }
1572 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1573 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001574 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001575 // In this case we are launching the root activity of the task, but with a
1576 // different intent. We should start a new instance on top.
1577 mAddingToTask = true;
1578 mSourceRecord = intentActivity;
1579 }
1580 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1581 // In this case an activity is being launched in to an existing task, without
1582 // resetting that task. This is typically the situation of launching an activity
1583 // from a notification or shortcut. We want to place the new activity on top of the
1584 // current task.
1585 mAddingToTask = true;
1586 mSourceRecord = intentActivity;
1587 } else if (!intentActivity.task.rootWasReset) {
1588 // In this case we are launching into an existing task that has not yet been started
1589 // from its front door. The current task has been brought to the front. Ideally,
1590 // we'd probably like to place this new task at the bottom of its stack, but that's
1591 // a little hard to do with the current organization of the code so for now we'll
1592 // just drop it.
1593 intentActivity.task.setIntent(mStartActivity);
1594 }
1595 }
1596
1597 private void resumeTargetStackIfNeeded() {
1598 if (mDoResume) {
1599 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001600 } else {
1601 ActivityOptions.abort(mOptions);
1602 }
1603 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1604 }
1605
Chong Zhang6cda19c2016-06-14 19:07:56 -07001606 private int setTaskFromReuseOrCreateNewTask(
1607 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1608 mTargetStack = computeStackFocus(
1609 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1610
1611 // Do no move the target stack to front yet, as we might bail if
1612 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001613
1614 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001615 final TaskRecord task = mTargetStack.createTaskRecord(
1616 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001617 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001618 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1619 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001620 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001621 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001622 final int stackId = mTargetStack.mStackId;
1623 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001624 mService.resizeStack(
1625 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001626 } else {
1627 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1628 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001629 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001630 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1631 + " in new task " + mStartActivity.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001632 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001633 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1634 }
1635
1636 if (taskToAffiliate != null) {
1637 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001638 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001639
1640 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1641 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1642 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1643 }
1644
1645 if (!mMovedOtherTask) {
1646 // If stack id is specified in activity options, usually it means that activity is
1647 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1648 // that case we check the target stack.
1649 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1650 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1651 }
1652 if (mDoResume) {
1653 mTargetStack.moveToFront("reuseOrNewTask");
1654 }
1655 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001656 }
1657
1658 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001659 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1660 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1661 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1662 }
1663
Wale Ogunwale01d66562015-12-29 08:19:19 -08001664 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001665 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001666 // We only want to allow changing stack if the target task is not the top one,
1667 // otherwise we would move the launching task to the other side, rather than show
1668 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001669 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001670 if (moveStackAllowed) {
1671 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1672 mOptions);
1673 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001674
1675 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001676 mTargetStack = sourceStack;
1677 } else if (mTargetStack != sourceStack) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001678 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1679 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1680 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001681
Wale Ogunwale01d66562015-12-29 08:19:19 -08001682 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001683 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001684 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1685 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001686 } else if (mDoResume) {
1687 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001688 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001689
Wale Ogunwale01d66562015-12-29 08:19:19 -08001690 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1691 // In this case, we are adding the activity to an existing task, but the caller has
1692 // asked to clear that task if the activity is already running.
1693 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1694 mKeepCurTransition = true;
1695 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001696 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001697 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1698 // For paranoia, make sure we have correctly resumed the top activity.
1699 mTargetStack.mLastPausedActivity = null;
1700 if (mDoResume) {
1701 mSupervisor.resumeFocusedStackTopActivityLocked();
1702 }
1703 ActivityOptions.abort(mOptions);
1704 return START_DELIVERED_TO_TOP;
1705 }
1706 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1707 // In this case, we are launching an activity in our own task that may already be
1708 // running somewhere in the history, and we want to shuffle it to the front of the
1709 // stack if so.
1710 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1711 if (top != null) {
1712 final TaskRecord task = top.task;
1713 task.moveActivityToFrontLocked(top);
1714 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001715 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001716 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1717 mTargetStack.mLastPausedActivity = null;
1718 if (mDoResume) {
1719 mSupervisor.resumeFocusedStackTopActivityLocked();
1720 }
1721 return START_DELIVERED_TO_TOP;
1722 }
1723 }
1724
1725 // An existing activity is starting this new activity, so we want to keep the new one in
1726 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001727 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001728 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1729 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1730 return START_SUCCESS;
1731 }
1732
1733 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001734 // The caller is asking that the new activity be started in an explicit
1735 // task it has provided to us.
1736 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1737 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1738 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1739 }
1740
Wale Ogunwale01d66562015-12-29 08:19:19 -08001741 if (mLaunchBounds != null) {
1742 mInTask.updateOverrideConfiguration(mLaunchBounds);
1743 int stackId = mInTask.getLaunchStackId();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001744 if (stackId != mInTask.getStackId()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08001745 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(mInTask,
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08001746 stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001747 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001748 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001749 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001750 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001751 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001752 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001753 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001754 mTargetStack.moveTaskToFrontLocked(
1755 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1756
1757 // Check whether we should actually launch the new activity in to the task,
1758 // or just reuse the current activity on top.
1759 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001760 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1761 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001762 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1763 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001764 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001765 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1766 // We don't need to start a new activity, and the client said not to do
1767 // anything if that is the case, so this is it!
1768 return START_RETURN_INTENT_TO_CALLER;
1769 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001770 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1771 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001772 return START_DELIVERED_TO_TOP;
1773 }
1774 }
1775
1776 if (!mAddingToTask) {
1777 // We don't actually want to have this activity added to the task, so just
1778 // stop here but still tell the caller that we consumed the intent.
1779 ActivityOptions.abort(mOptions);
1780 return START_TASK_TO_FRONT;
1781 }
1782
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001783 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1784 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1785 + " in explicit task " + mStartActivity.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001786
1787 return START_SUCCESS;
1788 }
1789
1790 private void setTaskToCurrentTopOrCreateNewTask() {
1791 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1792 mOptions);
1793 if (mDoResume) {
1794 mTargetStack.moveToFront("addingToTopTask");
1795 }
1796 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001797 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001798 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1799 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001800 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1801 mTargetStack.positionChildWindowContainerAtTop(task);
1802 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1803 + " in new guessed " + mStartActivity.task);
1804 }
1805
1806 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Winson Chungba7db922017-02-02 10:06:09 -08001807 if (mStartActivity.task == null || mStartActivity.task == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001808 parent.addActivityToTop(mStartActivity);
1809 } else {
1810 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1811 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001812 }
1813
1814 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1815 boolean launchSingleTask, int launchFlags) {
1816 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1817 (launchSingleInstance || launchSingleTask)) {
1818 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1819 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1820 "\"singleInstance\" or \"singleTask\"");
1821 launchFlags &=
1822 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1823 } else {
1824 switch (r.info.documentLaunchMode) {
1825 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1826 break;
1827 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1828 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1829 break;
1830 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1831 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1832 break;
1833 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1834 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1835 break;
1836 }
1837 }
1838 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001839 }
1840
1841 final void doPendingActivityLaunchesLocked(boolean doResume) {
1842 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001843 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1844 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001845 try {
Bryce Lee98689f72017-03-01 23:44:43 +00001846 final int result = startActivityUnchecked(
1847 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1848 postStartActivityUncheckedProcessing(
1849 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1850 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001851 } catch (Exception e) {
1852 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1853 pal.sendErrorResult(e.getMessage());
1854 }
1855 }
1856 }
1857
1858 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001859 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001860 final TaskRecord task = r.task;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001861 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001862 if (stack != null) {
1863 return stack;
1864 }
1865
Andrii Kulian02b7a832016-10-06 23:11:56 -07001866 final ActivityStack currentStack = task != null ? task.getStack() : null;
1867 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001868 if (mSupervisor.mFocusedStack != currentStack) {
1869 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1870 "computeStackFocus: Setting " + "focused stack to r=" + r
1871 + " task=" + task);
1872 } else {
1873 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1874 "computeStackFocus: Focused stack already="
1875 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001876 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001877 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001878 }
1879
1880 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1881 if (container != null) {
1882 // The first time put it on the desired stack, after this put on task stack.
1883 r.mInitialActivityContainer = null;
1884 return container.mStack;
1885 }
1886
1887 // The fullscreen stack can contain any task regardless of if the task is resizeable
1888 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
Andrii Kulian16802aa2016-11-02 12:21:33 -07001889 // Same also applies to dynamic stacks, as they behave similar to fullscreen stack.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001890 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1891 // we can also put it in the focused stack.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001892 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001893 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1894 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1895 return mSupervisor.mFocusedStack;
1896 }
1897
Andrii Kulian16802aa2016-11-02 12:21:33 -07001898 // We first try to put the task in the first dynamic stack on home display.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001899 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1900 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1901 stack = homeDisplayStacks.get(stackNdx);
Andrii Kulian4ede3e02017-01-12 11:52:31 -08001902 if (isDynamicStack(stack.mStackId)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001903 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1904 "computeStackFocus: Setting focused stack=" + stack);
1905 return stack;
1906 }
1907 }
1908
1909 // If there is no suitable dynamic stack then we figure out which static stack to use.
1910 final int stackId = task != null ? task.getLaunchStackId() :
1911 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1912 FULLSCREEN_WORKSPACE_STACK_ID;
1913 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1914 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1915 + r + " stackId=" + stack.mStackId);
1916 return stack;
1917 }
1918
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001919 /** Check if provided activity record can launch in currently focused stack. */
1920 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
1921 // The fullscreen stack can contain any task regardless of if the task is resizeable
1922 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1923 // Same also applies to dynamic stacks, as they behave similar to fullscreen stack.
1924 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1925 // we can also put it in the focused stack.
1926 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
1927 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1928 final boolean canUseFocusedStack;
1929 switch (focusedStackId) {
1930 case FULLSCREEN_WORKSPACE_STACK_ID:
1931 canUseFocusedStack = true;
1932 break;
Winson Chung83471632016-12-13 11:02:12 -08001933 case ASSISTANT_STACK_ID:
1934 canUseFocusedStack = r.isAssistantActivity();
1935 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001936 case DOCKED_STACK_ID:
Winson Chungd3395382016-12-13 11:49:09 -08001937 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001938 break;
1939 case FREEFORM_WORKSPACE_STACK_ID:
Winson Chungd3395382016-12-13 11:49:09 -08001940 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001941 break;
1942 default:
1943 canUseFocusedStack = isDynamicStack(focusedStackId)
1944 && mSupervisor.isCallerAllowedToLaunchOnDisplay(r.launchedFromPid,
1945 r.launchedFromUid, focusedStack.mDisplayId);
1946 }
1947
1948 return canUseFocusedStack
1949 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks());
1950 }
1951
Wale Ogunwale854809c2015-12-27 16:18:19 -08001952 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001953 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001954
Winson Chung83471632016-12-13 11:02:12 -08001955 // If the activity is of a specific type, return the associated stack, creating it if
1956 // necessary
1957 if (r.isHomeActivity()) {
1958 return mSupervisor.mHomeStack;
1959 }
1960 if (r.isRecentsActivity()) {
1961 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1962 }
1963 if (r.isAssistantActivity()) {
1964 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1965 }
1966
Jorim Jaggib8c58762016-04-20 17:58:29 -07001967 // We are reusing a task, keep the stack!
1968 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001969 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07001970 }
1971
Andrii Kulian16802aa2016-11-02 12:21:33 -07001972 final int launchDisplayId =
1973 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
1974
Wale Ogunwale854809c2015-12-27 16:18:19 -08001975 final int launchStackId =
1976 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1977
Andrii Kulian16802aa2016-11-02 12:21:33 -07001978 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
1979 throw new IllegalArgumentException(
1980 "Stack and display id can't be set at the same time.");
1981 }
1982
Wale Ogunwale854809c2015-12-27 16:18:19 -08001983 if (isValidLaunchStackId(launchStackId, r)) {
1984 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07001985 }
1986 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001987 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1988 // for this activity, so we put the activity in the fullscreen stack.
1989 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001990 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07001991 if (launchDisplayId != INVALID_DISPLAY) {
1992 // Stack id has higher priority than display id.
1993 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
1994 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001995
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001996 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001997 return null;
1998 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001999 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002000
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002001 // The parent activity doesn't want to launch the activity on top of itself, but
2002 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002003 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002004 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2005 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002006
2007 if (parentStack != mSupervisor.mFocusedStack) {
2008 // If task's parent stack is not focused - use it during adjacent launch.
2009 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002010 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002011 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2012 // If task is already on top of focused stack - use it. We don't want to move the
2013 // existing focused task to adjacent stack, just deliver new intent in this case.
2014 return mSupervisor.mFocusedStack;
2015 }
2016
Winson Chung83471632016-12-13 11:02:12 -08002017 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002018 // If parent was in docked stack, the natural place to launch another activity
2019 // will be fullscreen, so it can appear alongside the docked window.
2020 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2021 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002022 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002023 // If the parent is not in the docked stack, we check if there is docked window
2024 // and if yes, we will launch into that stack. If not, we just put the new
2025 // activity into parent's stack, because we can't find a better place.
2026 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2027 if (dockedStack != null
2028 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2029 // There is a docked stack, but it isn't visible, so we can't launch into that.
2030 return null;
2031 } else {
2032 return dockedStack;
2033 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002034 }
2035 }
2036 }
2037
Andrii Kulian16802aa2016-11-02 12:21:33 -07002038 boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002039 switch (stackId) {
2040 case INVALID_STACK_ID:
2041 case HOME_STACK_ID:
2042 return false;
2043 case FULLSCREEN_WORKSPACE_STACK_ID:
2044 return true;
2045 case FREEFORM_WORKSPACE_STACK_ID:
2046 return r.supportsFreeform();
2047 case DOCKED_STACK_ID:
2048 return r.supportsSplitScreen();
2049 case PINNED_STACK_ID:
2050 return r.supportsPictureInPicture();
2051 case RECENTS_STACK_ID:
2052 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002053 case ASSISTANT_STACK_ID:
2054 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002055 default:
Andrii Kulian4acfd852017-01-26 19:43:13 -08002056 if (StackId.isDynamicStack(stackId)) {
2057 return true;
2058 }
Winson Chungd3395382016-12-13 11:49:09 -08002059 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2060 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002061 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002062 }
2063
Wale Ogunwale854809c2015-12-27 16:18:19 -08002064 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2065 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002066 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002067 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2068 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002069 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002070 }
2071 }
2072 return newBounds;
2073 }
2074
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002075 void setWindowManager(WindowManagerService wm) {
2076 mWindowManager = wm;
2077 }
2078
2079 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2080 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2081 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2082 if (pal.stack == stack) {
2083 mPendingActivityLaunches.remove(palNdx);
2084 }
2085 }
2086 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002087
2088 static boolean isDocumentLaunchesIntoExisting(int flags) {
2089 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2090 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2091 }
liulvpingcfa825f2016-09-26 20:00:15 +08002092
2093 boolean clearPendingActivityLaunchesLocked(String packageName) {
2094 boolean didSomething = false;
2095
2096 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2097 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2098 ActivityRecord r = pal.r;
2099 if (r != null && r.packageName.equals(packageName)) {
2100 mPendingActivityLaunches.remove(palNdx);
2101 didSomething = true;
2102 }
2103 }
2104 return didSomething;
2105 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002106}