blob: 4b07af0d00dc7f26a1e17bb88053d6963fb11968 [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
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080085import android.app.ActivityManager;
86import android.app.ActivityOptions;
87import android.app.AppGlobals;
88import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080089import android.app.IApplicationThread;
Tony Mak853304c2016-04-18 15:17:41 +010090import android.app.KeyguardManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080091import android.app.PendingIntent;
92import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070093import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.content.ComponentName;
Tony Mak853304c2016-04-18 15:17:41 +010095import android.content.Context;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080096import android.content.IIntentSender;
97import android.content.Intent;
98import android.content.IntentSender;
99import android.content.pm.ActivityInfo;
100import android.content.pm.ApplicationInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000101import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800102import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000103import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800104import android.content.res.Configuration;
105import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700106import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800108import android.os.Bundle;
109import android.os.IBinder;
110import android.os.RemoteException;
111import android.os.SystemClock;
112import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000113import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800114import android.service.voice.IVoiceInteractionSession;
115import android.util.EventLog;
116import android.util.Slog;
117import android.view.Display;
118
119import com.android.internal.app.HeavyWeightSwitcherActivity;
120import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800121import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800122import com.android.server.pm.EphemeralResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800123import com.android.server.wm.WindowManagerService;
124
125import java.util.ArrayList;
126
127/**
128 * Controller for interpreting how and then launching activities.
129 *
130 * This class collects all the logic for determining how an intent and flags should be turned into
131 * an activity and associated task and stack.
132 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800133class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800134 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
135 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
136 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
137 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
138 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
139
140 private final ActivityManagerService mService;
141 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000142 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800143 private WindowManagerService mWindowManager;
144
145 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
146
Wale Ogunwale01d66562015-12-29 08:19:19 -0800147 // Share state variable among methods when starting an activity.
148 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700149 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800150 private Intent mIntent;
151 private int mCallingUid;
152 private ActivityOptions mOptions;
153
154 private boolean mLaunchSingleTop;
155 private boolean mLaunchSingleInstance;
156 private boolean mLaunchSingleTask;
157 private boolean mLaunchTaskBehind;
158 private int mLaunchFlags;
159
160 private Rect mLaunchBounds;
161
162 private ActivityRecord mNotTop;
163 private boolean mDoResume;
164 private int mStartFlags;
165 private ActivityRecord mSourceRecord;
166
167 private TaskRecord mInTask;
168 private boolean mAddingToTask;
169 private TaskRecord mReuseTask;
170
171 private ActivityInfo mNewTaskInfo;
172 private Intent mNewTaskIntent;
173 private ActivityStack mSourceStack;
174 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700175 // Indicates that we moved other task and are going to put something on top soon, so
176 // we don't want to show it redundantly or accidentally change what's shown below.
177 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800178 private boolean mMovedToFront;
179 private boolean mNoAnimation;
180 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700181 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700182 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800183
184 private IVoiceInteractionSession mVoiceSession;
185 private IVoiceInteractor mVoiceInteractor;
186
187 private void reset() {
188 mStartActivity = null;
189 mIntent = null;
190 mCallingUid = -1;
191 mOptions = null;
192
193 mLaunchSingleTop = false;
194 mLaunchSingleInstance = false;
195 mLaunchSingleTask = false;
196 mLaunchTaskBehind = false;
197 mLaunchFlags = 0;
198
199 mLaunchBounds = null;
200
201 mNotTop = null;
202 mDoResume = false;
203 mStartFlags = 0;
204 mSourceRecord = null;
205
206 mInTask = null;
207 mAddingToTask = false;
208 mReuseTask = null;
209
210 mNewTaskInfo = null;
211 mNewTaskIntent = null;
212 mSourceStack = null;
213
214 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700215 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800216 mMovedToFront = false;
217 mNoAnimation = false;
218 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700219 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800220
221 mVoiceSession = null;
222 mVoiceInteractor = null;
223 }
224
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800225 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
226 mService = service;
227 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000228 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800229 }
230
231 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
232 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
233 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
234 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
235 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
236 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
237 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
238 TaskRecord inTask) {
239 int err = ActivityManager.START_SUCCESS;
240
241 ProcessRecord callerApp = null;
242 if (caller != null) {
243 callerApp = mService.getRecordForAppLocked(caller);
244 if (callerApp != null) {
245 callingPid = callerApp.pid;
246 callingUid = callerApp.info.uid;
247 } else {
248 Slog.w(TAG, "Unable to find app for caller " + caller
249 + " (pid=" + callingPid + ") when starting: "
250 + intent.toString());
251 err = ActivityManager.START_PERMISSION_DENIED;
252 }
253 }
254
255 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
256
257 if (err == ActivityManager.START_SUCCESS) {
258 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800259 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800260 }
261
262 ActivityRecord sourceRecord = null;
263 ActivityRecord resultRecord = null;
264 if (resultTo != null) {
265 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
266 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
267 "Will send result to " + resultTo + " " + sourceRecord);
268 if (sourceRecord != null) {
269 if (requestCode >= 0 && !sourceRecord.finishing) {
270 resultRecord = sourceRecord;
271 }
272 }
273 }
274
275 final int launchFlags = intent.getFlags();
276
277 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
278 // Transfer the result target from the source activity to the new
279 // one being started, including any failures.
280 if (requestCode >= 0) {
281 ActivityOptions.abort(options);
282 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
283 }
284 resultRecord = sourceRecord.resultTo;
285 if (resultRecord != null && !resultRecord.isInStackLocked()) {
286 resultRecord = null;
287 }
288 resultWho = sourceRecord.resultWho;
289 requestCode = sourceRecord.requestCode;
290 sourceRecord.resultTo = null;
291 if (resultRecord != null) {
292 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
293 }
294 if (sourceRecord.launchedFromUid == callingUid) {
295 // The new activity is being launched from the same uid as the previous
296 // activity in the flow, and asking to forward its result back to the
297 // previous. In this case the activity is serving as a trampoline between
298 // the two, so we also want to update its launchedFromPackage to be the
299 // same as the previous activity. Note that this is safe, since we know
300 // these two packages come from the same uid; the caller could just as
301 // well have supplied that same package name itself. This specifially
302 // deals with the case of an intent picker/chooser being launched in the app
303 // flow to redirect to an activity picked by the user, where we want the final
304 // activity to consider it to have been launched by the previous app activity.
305 callingPackage = sourceRecord.launchedFromPackage;
306 }
307 }
308
309 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
310 // We couldn't find a class that can handle the given Intent.
311 // That's the end of that!
312 err = ActivityManager.START_INTENT_NOT_RESOLVED;
313 }
314
315 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
316 // We couldn't find the specific class specified in the Intent.
317 // Also the end of the line.
318 err = ActivityManager.START_CLASS_NOT_FOUND;
319 }
320
321 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
322 && sourceRecord.task.voiceSession != null) {
323 // If this activity is being launched as part of a voice session, we need
324 // to ensure that it is safe to do so. If the upcoming activity will also
325 // be part of the voice session, we can only launch it if it has explicitly
326 // said it supports the VOICE category, or it is a part of the calling app.
327 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
328 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
329 try {
330 intent.addCategory(Intent.CATEGORY_VOICE);
331 if (!AppGlobals.getPackageManager().activitySupportsIntent(
332 intent.getComponent(), intent, resolvedType)) {
333 Slog.w(TAG,
334 "Activity being started in current voice task does not support voice: "
335 + intent);
336 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
337 }
338 } catch (RemoteException e) {
339 Slog.w(TAG, "Failure checking voice capabilities", e);
340 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
341 }
342 }
343 }
344
345 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
346 // If the caller is starting a new voice session, just make sure the target
347 // is actually allowing it to run this way.
348 try {
349 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
350 intent, resolvedType)) {
351 Slog.w(TAG,
352 "Activity being started in new voice task does not support: "
353 + intent);
354 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
355 }
356 } catch (RemoteException e) {
357 Slog.w(TAG, "Failure checking voice capabilities", e);
358 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
359 }
360 }
361
Andrii Kulian02b7a832016-10-06 23:11:56 -0700362 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800363
Wale Ogunwale01d66562015-12-29 08:19:19 -0800364 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800365 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800366 resultStack.sendActivityResultLocked(
367 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800368 }
369 ActivityOptions.abort(options);
370 return err;
371 }
372
373 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
374 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100375 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800376 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
377 callingPid, resolvedType, aInfo.applicationInfo);
378
379 if (mService.mController != null) {
380 try {
381 // The Intent we give to the watcher has the extra data
382 // stripped off, since it can contain private information.
383 Intent watchIntent = intent.cloneFilter();
384 abort |= !mService.mController.activityStarting(watchIntent,
385 aInfo.applicationInfo.packageName);
386 } catch (RemoteException e) {
387 mService.mController = null;
388 }
389 }
390
Rubin Xu58d25992016-01-21 17:47:13 +0000391 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100392 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
393 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000394 intent = mInterceptor.mIntent;
395 rInfo = mInterceptor.mRInfo;
396 aInfo = mInterceptor.mAInfo;
397 resolvedType = mInterceptor.mResolvedType;
398 inTask = mInterceptor.mInTask;
399 callingPid = mInterceptor.mCallingPid;
400 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100401 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800402 if (abort) {
403 if (resultRecord != null) {
404 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800405 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800406 }
407 // We pretend to the caller that it was really started, but
408 // they will just get a cancel result.
409 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800410 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800411 }
412
413 // If permissions need a review before any of the app components can run, we
414 // launch the review activity and pass a pending intent to start the activity
415 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700416 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800417 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
418 aInfo.packageName, userId)) {
419 IIntentSender target = mService.getIntentSenderLocked(
420 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
421 callingUid, userId, null, null, 0, new Intent[]{intent},
422 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
423 | PendingIntent.FLAG_ONE_SHOT, null);
424
425 final int flags = intent.getFlags();
426 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
427 newIntent.setFlags(flags
428 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
429 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
430 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
431 if (resultRecord != null) {
432 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
433 }
434 intent = newIntent;
435
436 resolvedType = null;
437 callingUid = realCallingUid;
438 callingPid = realCallingPid;
439
440 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
441 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
442 null /*profilerInfo*/);
443
444 if (DEBUG_PERMISSIONS_REVIEW) {
445 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
446 true, false) + "} from uid " + callingUid + " on display "
447 + (container == null ? (mSupervisor.mFocusedStack == null ?
448 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
449 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
450 container.mActivityDisplay.mDisplayId)));
451 }
452 }
453 }
454
455 // If we have an ephemeral app, abort the process of launching the resolved intent.
456 // Instead, launch the ephemeral installer. Once the installer is finished, it
457 // starts either the intent we resolved here [on install error] or the ephemeral
458 // app [on install success].
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800459 if (rInfo != null && rInfo.ephemeralResponse != null) {
Todd Kennedye5195dd2016-10-19 15:29:19 -0700460 final String packageName =
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800461 rInfo.ephemeralResponse.resolveInfo.getPackageName();
462 final String splitName = rInfo.ephemeralResponse.splitName;
463 final boolean needsPhaseTwo = rInfo.ephemeralResponse.needsPhase2;
464 final String token = rInfo.ephemeralResponse.token;
Todd Kennedy316c2f22017-01-23 15:40:07 -0800465 final int versionCode = rInfo.ephemeralResponse.resolveInfo.getVersionCode();
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800466 if (needsPhaseTwo) {
467 // request phase two resolution
468 mService.getPackageManagerInternalLocked().requestEphemeralResolutionPhaseTwo(
469 rInfo.ephemeralResponse, ephemeralIntent, resolvedType, intent,
470 callingPackage, userId);
471 }
472 intent = EphemeralResolver.buildEphemeralInstallerIntent(intent, ephemeralIntent,
Todd Kennedy316c2f22017-01-23 15:40:07 -0800473 callingPackage, resolvedType, userId, packageName, splitName, versionCode,
474 token, needsPhaseTwo);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800475 resolvedType = null;
476 callingUid = realCallingUid;
477 callingPid = realCallingPid;
478
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800479 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
480 }
481
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800482 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
483 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
484 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
485 mSupervisor, container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800486 if (outActivity != null) {
487 outActivity[0] = r;
488 }
489
490 if (r.appTimeTracker == null && sourceRecord != null) {
491 // If the caller didn't specify an explicit time tracker, we want to continue
492 // tracking under any it has.
493 r.appTimeTracker = sourceRecord.appTimeTracker;
494 }
495
496 final ActivityStack stack = mSupervisor.mFocusedStack;
497 if (voiceSession == null && (stack.mResumedActivity == null
498 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
499 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
500 realCallingPid, realCallingUid, "Activity start")) {
501 PendingActivityLaunch pal = new PendingActivityLaunch(r,
502 sourceRecord, startFlags, stack, callerApp);
503 mPendingActivityLaunches.add(pal);
504 ActivityOptions.abort(options);
505 return ActivityManager.START_SWITCHES_CANCELED;
506 }
507 }
508
509 if (mService.mDidAppSwitch) {
510 // This is the second allowed switch since we stopped switches,
511 // so now just generally allow switches. Use case: user presses
512 // home (switches disabled, switch to home, mDidAppSwitch now true);
513 // user taps a home icon (coming from home so allowed, we hit here
514 // and now allow anyone to switch again).
515 mService.mAppSwitchesAllowedTime = 0;
516 } else {
517 mService.mDidAppSwitch = true;
518 }
519
520 doPendingActivityLaunchesLocked(false);
521
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700522 try {
523 mService.mWindowManager.deferSurfaceLayout();
524 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
525 true, options, inTask);
526 } finally {
527 mService.mWindowManager.continueSurfaceLayout();
528 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700529 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800530 return err;
531 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800532
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800533 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700534 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
535 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800536
537 if (result < START_SUCCESS) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800538 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800539 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800540
Chong Zhang5022da32016-06-21 16:31:37 -0700541 // We're waiting for an activity launch to finish, but that activity simply
542 // brought another activity to front. Let startActivityMayWait() know about
543 // this, so it waits for the new activity to become visible instead.
544 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
545 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
546 }
547
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800548 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700549 final ActivityStack currentStack = r.getStack();
550 if (currentStack != null) {
551 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800552 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700553 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800554 }
555
Jorim Jaggi352d5842016-05-19 10:20:28 -0700556 // If we launched the activity from a no display activity that was launched from the home
557 // screen, we also need to start recents to un-minimize the docked stack, since the
558 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700559 // Note that some apps have trampoline activities without noDisplay being set. In that case,
560 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
561 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700562 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
563 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700564 final boolean noDisplayActivityOverHome = sourceRecord != null
565 && sourceRecord.noDisplay
566 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700567 if (startedActivityStackId == DOCKED_STACK_ID
568 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100569 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
570 final ActivityRecord topActivityHomeStack = homeStack != null
571 ? homeStack.topRunningActivityLocked() : null;
572 if (topActivityHomeStack == null
573 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
574 // We launch an activity while being in home stack, which means either launcher or
575 // recents into docked stack. We don't want the launched activity to be alone in a
576 // docked stack, so we want to immediately launch recents too.
577 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700578 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100579 return;
580 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800581 }
582
583 if (startedActivityStackId == PINNED_STACK_ID
584 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
585 // The activity was already running in the pinned stack so it wasn't started, but either
586 // brought to the front or the new intent was delivered to it since it was already in
587 // front. Notify anyone interested in this piece of information.
Winson Chung3535df22017-01-17 18:43:39 -0800588 final ComponentName sourceComponent = sourceRecord == null ? null :
589 sourceRecord.realActivity;
590 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
591 sourceComponent);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800592 return;
593 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800594 }
595
596 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800597 mSupervisor.moveHomeStackTaskToTop(reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800598 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
599 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
600 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
601 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
602 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700603 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800604 null /*container*/, null /*inTask*/);
605 if (mSupervisor.inResumeTopActivity) {
606 // If we are in resume section already, home activity will be initialized, but not
607 // resumed (to avoid recursive resume) and will stay that way until something pokes it
608 // again. We need to schedule another resume.
609 mSupervisor.scheduleResumeTopActivities();
610 }
611 }
612
Robin Lee5d592422017-01-18 13:48:15 +0000613 void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
Tony Mak646fe992016-04-21 16:43:08 +0100614 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
615 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
616 FLAG_ACTIVITY_TASK_ON_HOME);
Robin Lee5d592422017-01-18 13:48:15 +0000617 ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
618 : ActivityOptions.makeBasic());
Tony Mak646fe992016-04-21 16:43:08 +0100619 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
Robin Lee5d592422017-01-18 13:48:15 +0000620 mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
Tony Mak646fe992016-04-21 16:43:08 +0100621 }
Tony Mak853304c2016-04-18 15:17:41 +0100622
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800623 final int startActivityMayWait(IApplicationThread caller, int callingUid,
624 String callingPackage, Intent intent, String resolvedType,
625 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
626 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700627 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700628 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800629 IActivityContainer iContainer, TaskRecord inTask) {
630 // Refuse possible leaked file descriptors
631 if (intent != null && intent.hasFileDescriptors()) {
632 throw new IllegalArgumentException("File descriptors passed in Intent");
633 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500634 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800635 boolean componentSpecified = intent.getComponent() != null;
636
637 // Save a copy in case ephemeral needs it
638 final Intent ephemeralIntent = new Intent(intent);
639 // Don't modify the client's object!
640 intent = new Intent(intent);
641
642 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000643 if (rInfo == null) {
644 UserInfo userInfo = mSupervisor.getUserInfo(userId);
645 if (userInfo != null && userInfo.isManagedProfile()) {
646 // Special case for managed profiles, if attempting to launch non-cryto aware
647 // app in a locked managed profile from an unlocked parent allow it to resolve
648 // as user will be sent via confirm credentials to unlock the profile.
649 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700650 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000651 long token = Binder.clearCallingIdentity();
652 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700653 UserInfo parent = userManager.getProfileParent(userId);
654 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
655 && userManager.isUserUnlockingOrUnlocked(parent.id)
656 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000657 } finally {
658 Binder.restoreCallingIdentity(token);
659 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700660 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000661 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600662 PackageManager.MATCH_DIRECT_BOOT_AWARE
663 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000664 }
665 }
666 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800667 // Collect information about the target of the Intent.
668 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
669
670 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
671 ActivityStackSupervisor.ActivityContainer container =
672 (ActivityStackSupervisor.ActivityContainer)iContainer;
673 synchronized (mService) {
674 if (container != null && container.mParentActivity != null &&
675 container.mParentActivity.state != RESUMED) {
676 // Cannot start a child activity if the parent is not resumed.
677 return ActivityManager.START_CANCELED;
678 }
679 final int realCallingPid = Binder.getCallingPid();
680 final int realCallingUid = Binder.getCallingUid();
681 int callingPid;
682 if (callingUid >= 0) {
683 callingPid = -1;
684 } else if (caller == null) {
685 callingPid = realCallingPid;
686 callingUid = realCallingUid;
687 } else {
688 callingPid = callingUid = -1;
689 }
690
691 final ActivityStack stack;
692 if (container == null || container.mStack.isOnHomeDisplay()) {
693 stack = mSupervisor.mFocusedStack;
694 } else {
695 stack = container.mStack;
696 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700697 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700698 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800699 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
700 "Starting activity when config will change = " + stack.mConfigWillChange);
701
702 final long origId = Binder.clearCallingIdentity();
703
704 if (aInfo != null &&
705 (aInfo.applicationInfo.privateFlags
706 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
707 // This may be a heavy-weight process! Check to see if we already
708 // have another, different heavy-weight process running.
709 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
710 final ProcessRecord heavy = mService.mHeavyWeightProcess;
711 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
712 || !heavy.processName.equals(aInfo.processName))) {
713 int appCallingUid = callingUid;
714 if (caller != null) {
715 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
716 if (callerApp != null) {
717 appCallingUid = callerApp.info.uid;
718 } else {
719 Slog.w(TAG, "Unable to find app for caller " + caller
720 + " (pid=" + callingPid + ") when starting: "
721 + intent.toString());
722 ActivityOptions.abort(options);
723 return ActivityManager.START_PERMISSION_DENIED;
724 }
725 }
726
727 IIntentSender target = mService.getIntentSenderLocked(
728 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
729 appCallingUid, userId, null, null, 0, new Intent[] { intent },
730 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
731 | PendingIntent.FLAG_ONE_SHOT, null);
732
733 Intent newIntent = new Intent();
734 if (requestCode >= 0) {
735 // Caller is requesting a result.
736 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
737 }
738 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
739 new IntentSender(target));
740 if (heavy.activities.size() > 0) {
741 ActivityRecord hist = heavy.activities.get(0);
742 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
743 hist.packageName);
744 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
745 hist.task.taskId);
746 }
747 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
748 aInfo.packageName);
749 newIntent.setFlags(intent.getFlags());
750 newIntent.setClassName("android",
751 HeavyWeightSwitcherActivity.class.getName());
752 intent = newIntent;
753 resolvedType = null;
754 caller = null;
755 callingUid = Binder.getCallingUid();
756 callingPid = Binder.getCallingPid();
757 componentSpecified = true;
758 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
759 aInfo = rInfo != null ? rInfo.activityInfo : null;
760 if (aInfo != null) {
761 aInfo = mService.getActivityInfoForUser(aInfo, userId);
762 }
763 }
764 }
765 }
766
Jorim Jaggi275561a2016-02-23 10:11:02 -0500767 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800768 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
769 aInfo, rInfo, voiceSession, voiceInteractor,
770 resultTo, resultWho, requestCode, callingPid,
771 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500772 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
773 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800774
775 Binder.restoreCallingIdentity(origId);
776
777 if (stack.mConfigWillChange) {
778 // If the caller also wants to switch to a new configuration,
779 // do so now. This allows a clean switch, as we are waiting
780 // for the current activity to pause (so we will not destroy
781 // it), and have not yet started the next activity.
782 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
783 "updateConfiguration()");
784 stack.mConfigWillChange = false;
785 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
786 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700787 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800788 }
789
790 if (outResult != null) {
791 outResult.result = res;
792 if (res == ActivityManager.START_SUCCESS) {
793 mSupervisor.mWaitingActivityLaunched.add(outResult);
794 do {
795 try {
796 mService.wait();
797 } catch (InterruptedException e) {
798 }
Chong Zhang5022da32016-06-21 16:31:37 -0700799 } while (outResult.result != START_TASK_TO_FRONT
800 && !outResult.timeout && outResult.who == null);
801 if (outResult.result == START_TASK_TO_FRONT) {
802 res = START_TASK_TO_FRONT;
803 }
804 }
805 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800806 ActivityRecord r = stack.topRunningActivityLocked();
807 if (r.nowVisible && r.state == RESUMED) {
808 outResult.timeout = false;
809 outResult.who = new ComponentName(r.info.packageName, r.info.name);
810 outResult.totalTime = 0;
811 outResult.thisTime = 0;
812 } else {
813 outResult.thisTime = SystemClock.uptimeMillis();
814 mSupervisor.mWaitingActivityVisible.add(outResult);
815 do {
816 try {
817 mService.wait();
818 } catch (InterruptedException e) {
819 }
820 } while (!outResult.timeout && outResult.who == null);
821 }
822 }
823 }
824
Jorim Jaggibe67c902016-04-12 00:53:16 -0700825 final ActivityRecord launchedActivity = mReusedActivity != null
826 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700827 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800828 return res;
829 }
830 }
831
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800832 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
833 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
834 Bundle bOptions, int userId) {
835 if (intents == null) {
836 throw new NullPointerException("intents is null");
837 }
838 if (resolvedTypes == null) {
839 throw new NullPointerException("resolvedTypes is null");
840 }
841 if (intents.length != resolvedTypes.length) {
842 throw new IllegalArgumentException("intents are length different than resolvedTypes");
843 }
844
Makoto Onukid67b1872016-07-21 16:26:36 -0700845 final int realCallingPid = Binder.getCallingPid();
846 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800847
848 int callingPid;
849 if (callingUid >= 0) {
850 callingPid = -1;
851 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700852 callingPid = realCallingPid;
853 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800854 } else {
855 callingPid = callingUid = -1;
856 }
857 final long origId = Binder.clearCallingIdentity();
858 try {
859 synchronized (mService) {
860 ActivityRecord[] outActivity = new ActivityRecord[1];
861 for (int i=0; i<intents.length; i++) {
862 Intent intent = intents[i];
863 if (intent == null) {
864 continue;
865 }
866
867 // Refuse possible leaked file descriptors
868 if (intent != null && intent.hasFileDescriptors()) {
869 throw new IllegalArgumentException("File descriptors passed in Intent");
870 }
871
872 boolean componentSpecified = intent.getComponent() != null;
873
874 // Don't modify the client's object!
875 intent = new Intent(intent);
876
877 // Collect information about the target of the Intent.
878 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
879 null, userId);
880 // TODO: New, check if this is correct
881 aInfo = mService.getActivityInfoForUser(aInfo, userId);
882
883 if (aInfo != null &&
884 (aInfo.applicationInfo.privateFlags
885 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
886 throw new IllegalArgumentException(
887 "FLAG_CANT_SAVE_STATE not supported here");
888 }
889
890 ActivityOptions options = ActivityOptions.fromBundle(
891 i == intents.length - 1 ? bOptions : null);
892 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
893 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700894 callingPid, callingUid, callingPackage,
895 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800896 options, false, componentSpecified, outActivity, null, null);
897 if (res < 0) {
898 return res;
899 }
900
901 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
902 }
903 }
904 } finally {
905 Binder.restoreCallingIdentity(origId);
906 }
907
Wale Ogunwale01d66562015-12-29 08:19:19 -0800908 return START_SUCCESS;
909 }
910
Wei Wang65c7a152016-06-02 18:51:22 -0700911 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
Bryce Lee834abec2017-01-09 16:18:14 -0800912 boolean sendHint = forceSend;
913
914 if (!sendHint) {
915 // If not forced, send power hint when the activity's process is different than the
916 // current resumed activity.
917 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
918 sendHint = resumedActivity == null
919 || resumedActivity.app == null
920 || !resumedActivity.app.equals(mStartActivity.app);
921 }
922
923 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700924 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700925 mPowerHintSent = true;
926 }
927 }
928
Wei Wang65c7a152016-06-02 18:51:22 -0700929 void sendPowerHintForLaunchEndIfNeeded() {
930 // Trigger launch power hint if activity is launched
931 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700932 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700933 mPowerHintSent = false;
934 }
935 }
936
Wale Ogunwale01d66562015-12-29 08:19:19 -0800937 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
938 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
939 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
940
941 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
942 voiceInteractor);
943
944 computeLaunchingTaskFlags();
945
946 computeSourceStack();
947
948 mIntent.setFlags(mLaunchFlags);
949
Jorim Jaggibe67c902016-04-12 00:53:16 -0700950 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800951
Jorim Jaggi2adba072016-03-03 13:43:39 +0100952 final int preferredLaunchStackId =
953 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
954
Jorim Jaggibe67c902016-04-12 00:53:16 -0700955 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800956 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
957 // still needs to be a lock task mode violation since the task gets cleared out and
958 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700959 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800960 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
961 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
962 mSupervisor.showLockTaskToast();
963 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
964 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
965 }
966
967 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -0700968 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800969 }
Jorim Jaggibe67c902016-04-12 00:53:16 -0700970 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800971 // This task was started because of movement of the activity based on affinity...
972 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700973 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800974 }
975
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800976 // This code path leads to delivering a new intent, we want to make sure we schedule it
977 // as the first operation, in case the activity will be resumed as a result of later
978 // operations.
979 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +0900980 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800981 || mLaunchSingleInstance || mLaunchSingleTask) {
982 // In this situation we want to remove all activities from the task up to the one
983 // being started. In most cases this means we are resetting the task to its initial
984 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700985 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800986 mStartActivity, mLaunchFlags);
987 if (top != null) {
988 if (top.frontOfTask) {
989 // Activity aliases may mean we use different intents for the top activity,
990 // so make sure the task now has the identity of the new intent.
991 top.task.setIntent(mStartActivity);
992 }
993 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
994 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
995 mStartActivity.launchedFromPackage);
996 }
997 }
998
Wei Wang65c7a152016-06-02 18:51:22 -0700999 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001000
Jorim Jaggibe67c902016-04-12 00:53:16 -07001001 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001002
1003 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1004 // We don't need to start a new activity, and the client said not to do anything
1005 // if that is the case, so this is it! And for paranoia, make sure we have
1006 // correctly resumed the top activity.
1007 resumeTargetStackIfNeeded();
1008 return START_RETURN_INTENT_TO_CALLER;
1009 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001010 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001011
1012 if (!mAddingToTask && mReuseTask == null) {
1013 // We didn't do anything... but it was needed (a.k.a., client don't use that
1014 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1015 resumeTargetStackIfNeeded();
1016 return START_TASK_TO_FRONT;
1017 }
1018 }
1019
1020 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001021 final ActivityStack sourceStack = mStartActivity.resultTo != null
1022 ? mStartActivity.resultTo.getStack() : null;
1023 if (sourceStack != null) {
1024 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1025 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1026 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001027 }
1028 ActivityOptions.abort(mOptions);
1029 return START_CLASS_NOT_FOUND;
1030 }
1031
1032 // If the activity being launched is the same as the one currently at the top, then
1033 // we need to check if it should only be launched once.
1034 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001035 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001036 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1037 final boolean dontStart = top != null && mStartActivity.resultTo == null
1038 && top.realActivity.equals(mStartActivity.realActivity)
1039 && top.userId == mStartActivity.userId
1040 && top.app != null && top.app.thread != null
1041 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1042 || mLaunchSingleTop || mLaunchSingleTask);
1043 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001044 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001045 // For paranoia, make sure we have correctly resumed the top activity.
1046 topStack.mLastPausedActivity = null;
1047 if (mDoResume) {
1048 mSupervisor.resumeFocusedStackTopActivityLocked();
1049 }
1050 ActivityOptions.abort(mOptions);
1051 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1052 // We don't need to start a new activity, and the client said not to do
1053 // anything if that is the case, so this is it!
1054 return START_RETURN_INTENT_TO_CALLER;
1055 }
1056 top.deliverNewIntentLocked(
1057 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001058
1059 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1060 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1061 mSupervisor.handleNonResizableTaskIfNeeded(
1062 top.task, preferredLaunchStackId, topStack.mStackId);
1063
Wale Ogunwale01d66562015-12-29 08:19:19 -08001064 return START_DELIVERED_TO_TOP;
1065 }
1066
1067 boolean newTask = false;
1068 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1069 ? mSourceRecord.task : null;
1070
1071 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001072 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001073 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1074 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1075 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001076 result = setTaskFromReuseOrCreateNewTask(
1077 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001078 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001079 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001080 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001081 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001082 } else {
1083 // This not being started from an existing activity, and not part of a new task...
1084 // just put it in the top task, though these days this case should never happen.
1085 setTaskToCurrentTopOrCreateNewTask();
1086 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001087 if (result != START_SUCCESS) {
1088 return result;
1089 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001090
1091 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1092 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001093 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1094 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Winson Chung83471632016-12-13 11:02:12 -08001095 if (mSourceRecord != null) {
1096 mStartActivity.task.setTaskToReturnTo(mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001097 }
1098 if (newTask) {
1099 EventLog.writeEvent(
1100 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1101 }
1102 ActivityStack.logStartActivity(
1103 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1104 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001105
Wei Wang65c7a152016-06-02 18:51:22 -07001106 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001107
Winson Chungb5c41b72016-12-07 15:00:47 -08001108 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1109 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001110 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001111 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1112 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001113 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1114 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001115 // If the activity is not focusable, we can't resume it, but still would like to
1116 // make sure it becomes visible as it starts (this will also trigger entry
1117 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001118 // Also, we don't want to resume activities in a task that currently has an overlay
1119 // as the starting activity just needs to be in the visible paused state until the
1120 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001121 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001122 // Go ahead and tell window manager to execute app transition for this activity
1123 // since the app transition will not be triggered through the resume channel.
1124 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001125 } else {
Winson Chung32066032016-11-04 11:55:21 -07001126 // If the target stack was not previously focusable (previous top running activity
1127 // on that stack was not visible) then any prior calls to move the stack to the
1128 // will not update the focused stack. If starting the new activity now allows the
1129 // task stack to be focusable, then ensure that we now update the focused stack
1130 // accordingly.
1131 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1132 mTargetStack.moveToFront("startActivityUnchecked");
1133 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001134 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1135 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001136 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001137 } else {
1138 mTargetStack.addRecentActivityLocked(mStartActivity);
1139 }
1140 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1141
Jorim Jaggid53f0922016-04-06 22:16:23 -07001142 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001143 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001144
1145 return START_SUCCESS;
1146 }
1147
1148 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1149 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1150 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1151 reset();
1152
1153 mStartActivity = r;
1154 mIntent = r.intent;
1155 mOptions = options;
1156 mCallingUid = r.launchedFromUid;
1157 mSourceRecord = sourceRecord;
1158 mVoiceSession = voiceSession;
1159 mVoiceInteractor = voiceInteractor;
1160
1161 mLaunchBounds = getOverrideBounds(r, options, inTask);
1162
1163 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1164 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1165 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1166 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1167 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1168 mLaunchTaskBehind = r.mLaunchTaskBehind
1169 && !mLaunchSingleTask && !mLaunchSingleInstance
1170 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1171
1172 sendNewTaskResultRequestIfNeeded();
1173
1174 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1175 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1176 }
1177
1178 // If we are actually going to launch in to a new task, there are some cases where
1179 // we further want to do multiple task.
1180 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1181 if (mLaunchTaskBehind
1182 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1183 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1184 }
1185 }
1186
1187 // We'll invoke onUserLeaving before onPause only if the launching
1188 // activity did not explicitly state that this is an automated launch.
1189 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1190 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1191 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1192
1193 // If the caller has asked not to resume at this point, we make note
1194 // of this in the record so that we can skip it when trying to find
1195 // the top running activity.
1196 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001197 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001198 r.delayedResume = true;
1199 mDoResume = false;
1200 }
1201
Winson Chungcbcadc92017-01-12 15:54:12 -08001202 if (mOptions != null && mOptions.getLaunchTaskId() != -1
1203 && mOptions.getTaskOverlay()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001204 r.mTaskOverlay = true;
Winson Chungcbcadc92017-01-12 15:54:12 -08001205 if (!mOptions.canTaskOverlayResume()) {
1206 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1207 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1208 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001209
Winson Chungcbcadc92017-01-12 15:54:12 -08001210 // The caller specifies that we'd like to be avoided to be moved to the front,
1211 // so be it!
1212 mDoResume = false;
1213 mAvoidMoveToFront = true;
1214 }
Jorim Jaggic875ae72016-04-26 22:41:06 -07001215 }
1216 }
1217
Wale Ogunwale01d66562015-12-29 08:19:19 -08001218 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1219
1220 mInTask = inTask;
1221 // In some flows in to this function, we retrieve the task record and hold on to it
1222 // without a lock before calling back in to here... so the task at this point may
1223 // not actually be in recents. Check for that, and if it isn't in recents just
1224 // consider it invalid.
1225 if (inTask != null && !inTask.inRecents) {
1226 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1227 mInTask = null;
1228 }
1229
1230 mStartFlags = startFlags;
1231 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1232 // is the same as the one making the call... or, as a special case, if we do not know
1233 // the caller then we count the current top activity as the caller.
1234 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1235 ActivityRecord checkedCaller = sourceRecord;
1236 if (checkedCaller == null) {
1237 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1238 mNotTop);
1239 }
1240 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1241 // Caller is not the same as launcher, so always needed.
1242 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1243 }
1244 }
1245
1246 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1247 }
1248
1249 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001250 final ActivityStack sourceStack = mStartActivity.resultTo != null
1251 ? mStartActivity.resultTo.getStack() : null;
1252 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001253 // For whatever reason this activity is being launched into a new task...
1254 // yet the caller has requested a result back. Well, that is pretty messed up,
1255 // so instead immediately send back a cancel and let the new task continue launched
1256 // as normal without a dependency on its originator.
1257 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001258 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1259 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1260 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001261 mStartActivity.resultTo = null;
1262 }
1263 }
1264
1265 private void computeLaunchingTaskFlags() {
1266 // If the caller is not coming from another activity, but has given us an explicit task into
1267 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001268 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001269 final Intent baseIntent = mInTask.getBaseIntent();
1270 final ActivityRecord root = mInTask.getRootActivity();
1271 if (baseIntent == null) {
1272 ActivityOptions.abort(mOptions);
1273 throw new IllegalArgumentException("Launching into task without base intent: "
1274 + mInTask);
1275 }
1276
1277 // If this task is empty, then we are adding the first activity -- it
1278 // determines the root, and must be launching as a NEW_TASK.
1279 if (mLaunchSingleInstance || mLaunchSingleTask) {
1280 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1281 ActivityOptions.abort(mOptions);
1282 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1283 + mStartActivity + " into different task " + mInTask);
1284 }
1285 if (root != null) {
1286 ActivityOptions.abort(mOptions);
1287 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1288 + " has root " + root + " but target is singleInstance/Task");
1289 }
1290 }
1291
1292 // If task is empty, then adopt the interesting intent launch flags in to the
1293 // activity being started.
1294 if (root == null) {
1295 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1296 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1297 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1298 | (baseIntent.getFlags() & flagsOfInterest);
1299 mIntent.setFlags(mLaunchFlags);
1300 mInTask.setIntent(mStartActivity);
1301 mAddingToTask = true;
1302
1303 // If the task is not empty and the caller is asking to start it as the root of
1304 // a new task, then we don't actually want to start this on the task. We will
1305 // bring the task to the front, and possibly give it a new intent.
1306 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1307 mAddingToTask = false;
1308
1309 } else {
1310 mAddingToTask = true;
1311 }
1312
1313 mReuseTask = mInTask;
1314 } else {
1315 mInTask = null;
1316 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1317 // when in freeform workspace.
1318 // Also put noDisplay activities in the source task. These by itself can be placed
1319 // in any task/stack, however it could launch other activities like ResolverActivity,
1320 // and we want those to stay in the original task.
1321 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1322 && mSourceRecord.isFreeform()) {
1323 mAddingToTask = true;
1324 }
1325 }
1326
1327 if (mInTask == null) {
1328 if (mSourceRecord == null) {
1329 // This activity is not being started from another... in this
1330 // case we -always- start a new task.
1331 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1332 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1333 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1334 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1335 }
1336 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1337 // The original activity who is starting us is running as a single
1338 // instance... this new activity it is starting must go on its
1339 // own task.
1340 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1341 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1342 // The activity being started is a single instance... it always
1343 // gets launched into its own task.
1344 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1345 }
1346 }
1347 }
1348
1349 private void computeSourceStack() {
1350 if (mSourceRecord == null) {
1351 mSourceStack = null;
1352 return;
1353 }
1354 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001355 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001356 return;
1357 }
1358
1359 // If the source is finishing, we can't further count it as our source. This is because the
1360 // task it is associated with may now be empty and on its way out, so we don't want to
1361 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1362 // a task for it. But save the task information so it can be used when creating the new task.
1363 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1364 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1365 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1366 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1367 mNewTaskInfo = mSourceRecord.info;
1368 mNewTaskIntent = mSourceRecord.task.intent;
1369 }
1370 mSourceRecord = null;
1371 mSourceStack = null;
1372 }
1373
1374 /**
1375 * Decide whether the new activity should be inserted into an existing task. Returns null
1376 * if not or an ActivityRecord with the task into which the new activity should be added.
1377 */
1378 private ActivityRecord getReusableIntentActivity() {
1379 // We may want to try to place the new activity in to an existing task. We always
1380 // do this if the target activity is singleTask or singleInstance; we will also do
1381 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1382 // us to still place it in a new task: multi task, always doc mode, or being asked to
1383 // launch this as a new task behind the current one.
1384 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1385 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1386 || mLaunchSingleInstance || mLaunchSingleTask;
1387 // If bring to front is requested, and no result is requested and we have not been given
1388 // an explicit task to launch in to, and we can find a task that was started with this
1389 // same component, then instead of launching bring that one to the front.
1390 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1391 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001392 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1393 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1394 intentActivity = task != null ? task.getTopActivity() : null;
1395 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001396 if (mLaunchSingleInstance) {
1397 // There can be one and only one instance of single instance activity in the
1398 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001399 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001400 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1401 // For the launch adjacent case we only want to put the activity in an existing
1402 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001403 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1404 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001405 } else {
1406 // Otherwise find the best task to put the activity in.
1407 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1408 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001409 }
1410 return intentActivity;
1411 }
1412
1413 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001414 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001415 mTargetStack.mLastPausedActivity = null;
1416 // If the target task is not in the front, then we need to bring it to the front...
1417 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1418 // the same behavior as if a new instance was being started, which means not bringing it
1419 // to the front if the caller is not itself in the front.
1420 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1421 ActivityRecord curTop = (focusStack == null)
1422 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1423
Jorim Jaggic875ae72016-04-26 22:41:06 -07001424 if (curTop != null
1425 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1426 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001427 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1428 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1429 mSourceStack.topActivity().task == mSourceRecord.task)) {
1430 // We really do want to push this one into the user's face, right now.
1431 if (mLaunchTaskBehind && mSourceRecord != null) {
1432 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1433 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001434 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001435
1436 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1437 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1438 // So no point resuming any of the activities here, it just wastes one extra
1439 // resuming, plus enter AND exit transitions.
1440 // Here we only want to bring the target stack forward. Transition will be applied
1441 // to the new activity that's started after the old ones are gone.
1442 final boolean willClearTask =
1443 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1444 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1445 if (!willClearTask) {
1446 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001447 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001448 if (launchStack == null || launchStack == mTargetStack) {
1449 // We only want to move to the front, if we aren't going to launch on a
1450 // different stack. If we launch on a different stack, we will put the
1451 // task on top there.
1452 mTargetStack.moveTaskToFrontLocked(
1453 intentActivity.task, mNoAnimation, mOptions,
1454 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1455 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001456 } else if (launchStack.mStackId == DOCKED_STACK_ID
1457 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1458 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1459 // If we want to launch adjacent and mTargetStack is not the computed
1460 // launch stack - move task to top of computed stack.
1461 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1462 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1463 ANIMATE);
1464 } else {
1465 // TODO: This should be reevaluated in MW v2.
1466 // We choose to move task to front instead of launching it adjacent
1467 // when specific stack was requested explicitly and it appeared to be
1468 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1469 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1470 mOptions, mStartActivity.appTimeTracker,
1471 "bringToFrontInsteadOfAdjacentLaunch");
1472 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001473 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001474 }
1475 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001476
1477 // We are moving a task to the front, use starting window to hide initial drawn
1478 // delay.
1479 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1480 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001481 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001482 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001483 }
1484 }
1485 if (!mMovedToFront && mDoResume) {
1486 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1487 + " from " + intentActivity);
1488 mTargetStack.moveToFront("intentActivityFound");
1489 }
1490
Jorim Jaggid53f0922016-04-06 22:16:23 -07001491 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1492 mTargetStack.mStackId);
1493
Wale Ogunwale01d66562015-12-29 08:19:19 -08001494 // If the caller has requested that the target task be reset, then do so.
1495 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1496 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1497 }
1498 return intentActivity;
1499 }
1500
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001501 private void updateTaskReturnToType(
1502 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001503 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001504 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1505 // Caller wants to appear on home activity.
1506 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1507 return;
Winson Chung83471632016-12-13 11:02:12 -08001508 } else if (focusedStack == null || focusedStack.isHomeStack()) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001509 // Task will be launched over the home stack, so return home.
1510 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1511 return;
Winson Chung83471632016-12-13 11:02:12 -08001512 } else if (focusedStack != null && focusedStack != task.getStack() &&
1513 focusedStack.isAssistantStack()) {
1514 // Task was launched over the assistant stack, so return there
1515 task.setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
1516 return;
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001517 }
1518
1519 // Else we are coming from an application stack so return to an application.
1520 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1521 }
1522
Wale Ogunwale01d66562015-12-29 08:19:19 -08001523 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1524 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1525 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1526 // The caller has requested to completely replace any existing task with its new
1527 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001528 intentActivity.task.performClearTaskLocked();
1529 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001530 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001531 // When we clear the task - focus will be adjusted, which will bring another task
1532 // to top before we launch the activity we need. This will temporary swap their
1533 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1534 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001535 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1536 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001537 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1538 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001539 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001540 // A special case: we need to start the activity because it is not currently
1541 // running, and the caller has asked to clear the current task to have this
1542 // activity at the top.
1543 mAddingToTask = true;
1544 // Now pretend like this activity is being started by the top of its task, so it
1545 // is put in the right place.
1546 mSourceRecord = intentActivity;
1547 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001548 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001549 // Target stack got cleared when we all activities were removed above.
1550 // Go ahead and reset it.
1551 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1552 null /* bounds */, mLaunchFlags, mOptions);
1553 mTargetStack.addTask(task,
1554 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1555 }
1556 }
1557 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1558 // In this case the top activity on the task is the same as the one being launched,
1559 // so we take that as a request to bring the task to the foreground. If the top
1560 // activity in the task is the root activity, deliver this new intent to it if it
1561 // desires.
1562 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1563 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001564 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001565 intentActivity.task);
1566 if (intentActivity.frontOfTask) {
1567 intentActivity.task.setIntent(mStartActivity);
1568 }
1569 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1570 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001571 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001572 // In this case we are launching the root activity of the task, but with a
1573 // different intent. We should start a new instance on top.
1574 mAddingToTask = true;
1575 mSourceRecord = intentActivity;
1576 }
1577 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1578 // In this case an activity is being launched in to an existing task, without
1579 // resetting that task. This is typically the situation of launching an activity
1580 // from a notification or shortcut. We want to place the new activity on top of the
1581 // current task.
1582 mAddingToTask = true;
1583 mSourceRecord = intentActivity;
1584 } else if (!intentActivity.task.rootWasReset) {
1585 // In this case we are launching into an existing task that has not yet been started
1586 // from its front door. The current task has been brought to the front. Ideally,
1587 // we'd probably like to place this new task at the bottom of its stack, but that's
1588 // a little hard to do with the current organization of the code so for now we'll
1589 // just drop it.
1590 intentActivity.task.setIntent(mStartActivity);
1591 }
1592 }
1593
1594 private void resumeTargetStackIfNeeded() {
1595 if (mDoResume) {
1596 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001597 } else {
1598 ActivityOptions.abort(mOptions);
1599 }
1600 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1601 }
1602
Chong Zhang6cda19c2016-06-14 19:07:56 -07001603 private int setTaskFromReuseOrCreateNewTask(
1604 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1605 mTargetStack = computeStackFocus(
1606 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1607
1608 // Do no move the target stack to front yet, as we might bail if
1609 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001610
1611 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001612 final TaskRecord task = mTargetStack.createTaskRecord(
1613 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001614 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001615 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1616 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001617 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001618 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001619 final int stackId = mTargetStack.mStackId;
1620 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001621 mService.resizeStack(
1622 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001623 } else {
1624 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1625 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001626 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001627 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1628 + " in new task " + mStartActivity.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001629 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001630 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1631 }
1632
1633 if (taskToAffiliate != null) {
1634 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001635 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001636
1637 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1638 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1639 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1640 }
1641
1642 if (!mMovedOtherTask) {
1643 // If stack id is specified in activity options, usually it means that activity is
1644 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1645 // that case we check the target stack.
1646 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1647 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1648 }
1649 if (mDoResume) {
1650 mTargetStack.moveToFront("reuseOrNewTask");
1651 }
1652 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001653 }
1654
1655 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001656 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1657 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1658 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1659 }
1660
Wale Ogunwale01d66562015-12-29 08:19:19 -08001661 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001662 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001663 // We only want to allow changing stack if the target task is not the top one,
1664 // otherwise we would move the launching task to the other side, rather than show
1665 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001666 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001667 if (moveStackAllowed) {
1668 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1669 mOptions);
1670 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001671
1672 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001673 mTargetStack = sourceStack;
1674 } else if (mTargetStack != sourceStack) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001675 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1676 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1677 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001678
Wale Ogunwale01d66562015-12-29 08:19:19 -08001679 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001680 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001681 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1682 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001683 } else if (mDoResume) {
1684 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001685 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001686
Wale Ogunwale01d66562015-12-29 08:19:19 -08001687 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1688 // In this case, we are adding the activity to an existing task, but the caller has
1689 // asked to clear that task if the activity is already running.
1690 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1691 mKeepCurTransition = true;
1692 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001693 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001694 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1695 // For paranoia, make sure we have correctly resumed the top activity.
1696 mTargetStack.mLastPausedActivity = null;
1697 if (mDoResume) {
1698 mSupervisor.resumeFocusedStackTopActivityLocked();
1699 }
1700 ActivityOptions.abort(mOptions);
1701 return START_DELIVERED_TO_TOP;
1702 }
1703 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1704 // In this case, we are launching an activity in our own task that may already be
1705 // running somewhere in the history, and we want to shuffle it to the front of the
1706 // stack if so.
1707 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1708 if (top != null) {
1709 final TaskRecord task = top.task;
1710 task.moveActivityToFrontLocked(top);
1711 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001712 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001713 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1714 mTargetStack.mLastPausedActivity = null;
1715 if (mDoResume) {
1716 mSupervisor.resumeFocusedStackTopActivityLocked();
1717 }
1718 return START_DELIVERED_TO_TOP;
1719 }
1720 }
1721
1722 // An existing activity is starting this new activity, so we want to keep the new one in
1723 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001724 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001725 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1726 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1727 return START_SUCCESS;
1728 }
1729
1730 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001731 // The caller is asking that the new activity be started in an explicit
1732 // task it has provided to us.
1733 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1734 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1735 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1736 }
1737
Wale Ogunwale01d66562015-12-29 08:19:19 -08001738 if (mLaunchBounds != null) {
1739 mInTask.updateOverrideConfiguration(mLaunchBounds);
1740 int stackId = mInTask.getLaunchStackId();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001741 if (stackId != mInTask.getStackId()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08001742 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(mInTask,
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08001743 stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001744 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001745 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001746 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001747 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001748 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001749 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001750 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001751 mTargetStack.moveTaskToFrontLocked(
1752 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1753
1754 // Check whether we should actually launch the new activity in to the task,
1755 // or just reuse the current activity on top.
1756 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001757 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
1758 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001759 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1760 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001761 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001762 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1763 // We don't need to start a new activity, and the client said not to do
1764 // anything if that is the case, so this is it!
1765 return START_RETURN_INTENT_TO_CALLER;
1766 }
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001767 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1768 mStartActivity.launchedFromPackage);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001769 return START_DELIVERED_TO_TOP;
1770 }
1771 }
1772
1773 if (!mAddingToTask) {
1774 // We don't actually want to have this activity added to the task, so just
1775 // stop here but still tell the caller that we consumed the intent.
1776 ActivityOptions.abort(mOptions);
1777 return START_TASK_TO_FRONT;
1778 }
1779
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001780 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
1781 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1782 + " in explicit task " + mStartActivity.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001783
1784 return START_SUCCESS;
1785 }
1786
1787 private void setTaskToCurrentTopOrCreateNewTask() {
1788 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1789 mOptions);
1790 if (mDoResume) {
1791 mTargetStack.moveToFront("addingToTopTask");
1792 }
1793 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001794 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001795 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1796 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001797 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
1798 mTargetStack.positionChildWindowContainerAtTop(task);
1799 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1800 + " in new guessed " + mStartActivity.task);
1801 }
1802
1803 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Winson Chungba7db922017-02-02 10:06:09 -08001804 if (mStartActivity.task == null || mStartActivity.task == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001805 parent.addActivityToTop(mStartActivity);
1806 } else {
1807 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
1808 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001809 }
1810
1811 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1812 boolean launchSingleTask, int launchFlags) {
1813 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1814 (launchSingleInstance || launchSingleTask)) {
1815 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1816 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1817 "\"singleInstance\" or \"singleTask\"");
1818 launchFlags &=
1819 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1820 } else {
1821 switch (r.info.documentLaunchMode) {
1822 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1823 break;
1824 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1825 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1826 break;
1827 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1828 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1829 break;
1830 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1831 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1832 break;
1833 }
1834 }
1835 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001836 }
1837
1838 final void doPendingActivityLaunchesLocked(boolean doResume) {
1839 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001840 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1841 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001842 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001843 final int result = startActivityUnchecked(
1844 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1845 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001846 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1847 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001848 } catch (Exception e) {
1849 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1850 pal.sendErrorResult(e.getMessage());
1851 }
1852 }
1853 }
1854
1855 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001856 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001857 final TaskRecord task = r.task;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001858 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001859 if (stack != null) {
1860 return stack;
1861 }
1862
Andrii Kulian02b7a832016-10-06 23:11:56 -07001863 final ActivityStack currentStack = task != null ? task.getStack() : null;
1864 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001865 if (mSupervisor.mFocusedStack != currentStack) {
1866 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1867 "computeStackFocus: Setting " + "focused stack to r=" + r
1868 + " task=" + task);
1869 } else {
1870 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1871 "computeStackFocus: Focused stack already="
1872 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001873 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001874 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001875 }
1876
1877 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1878 if (container != null) {
1879 // The first time put it on the desired stack, after this put on task stack.
1880 r.mInitialActivityContainer = null;
1881 return container.mStack;
1882 }
1883
1884 // The fullscreen stack can contain any task regardless of if the task is resizeable
1885 // 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 -07001886 // Same also applies to dynamic stacks, as they behave similar to fullscreen stack.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001887 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1888 // we can also put it in the focused stack.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001889 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001890 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1891 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1892 return mSupervisor.mFocusedStack;
1893 }
1894
Andrii Kulian16802aa2016-11-02 12:21:33 -07001895 // We first try to put the task in the first dynamic stack on home display.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001896 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1897 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1898 stack = homeDisplayStacks.get(stackNdx);
Andrii Kulian4ede3e02017-01-12 11:52:31 -08001899 if (isDynamicStack(stack.mStackId)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001900 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1901 "computeStackFocus: Setting focused stack=" + stack);
1902 return stack;
1903 }
1904 }
1905
1906 // If there is no suitable dynamic stack then we figure out which static stack to use.
1907 final int stackId = task != null ? task.getLaunchStackId() :
1908 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1909 FULLSCREEN_WORKSPACE_STACK_ID;
1910 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1911 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1912 + r + " stackId=" + stack.mStackId);
1913 return stack;
1914 }
1915
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001916 /** Check if provided activity record can launch in currently focused stack. */
1917 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
1918 // The fullscreen stack can contain any task regardless of if the task is resizeable
1919 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1920 // Same also applies to dynamic stacks, as they behave similar to fullscreen stack.
1921 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1922 // we can also put it in the focused stack.
1923 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
1924 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
1925 final boolean canUseFocusedStack;
1926 switch (focusedStackId) {
1927 case FULLSCREEN_WORKSPACE_STACK_ID:
1928 canUseFocusedStack = true;
1929 break;
Winson Chung83471632016-12-13 11:02:12 -08001930 case ASSISTANT_STACK_ID:
1931 canUseFocusedStack = r.isAssistantActivity();
1932 break;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001933 case DOCKED_STACK_ID:
Winson Chungd3395382016-12-13 11:49:09 -08001934 canUseFocusedStack = r.supportsSplitScreen();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001935 break;
1936 case FREEFORM_WORKSPACE_STACK_ID:
Winson Chungd3395382016-12-13 11:49:09 -08001937 canUseFocusedStack = r.supportsFreeform();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001938 break;
1939 default:
1940 canUseFocusedStack = isDynamicStack(focusedStackId)
1941 && mSupervisor.isCallerAllowedToLaunchOnDisplay(r.launchedFromPid,
1942 r.launchedFromUid, focusedStack.mDisplayId);
1943 }
1944
1945 return canUseFocusedStack
1946 && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks());
1947 }
1948
Wale Ogunwale854809c2015-12-27 16:18:19 -08001949 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001950 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001951
Winson Chung83471632016-12-13 11:02:12 -08001952 // If the activity is of a specific type, return the associated stack, creating it if
1953 // necessary
1954 if (r.isHomeActivity()) {
1955 return mSupervisor.mHomeStack;
1956 }
1957 if (r.isRecentsActivity()) {
1958 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1959 }
1960 if (r.isAssistantActivity()) {
1961 return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1962 }
1963
Jorim Jaggib8c58762016-04-20 17:58:29 -07001964 // We are reusing a task, keep the stack!
1965 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001966 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07001967 }
1968
Andrii Kulian16802aa2016-11-02 12:21:33 -07001969 final int launchDisplayId =
1970 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
1971
Wale Ogunwale854809c2015-12-27 16:18:19 -08001972 final int launchStackId =
1973 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1974
Andrii Kulian16802aa2016-11-02 12:21:33 -07001975 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
1976 throw new IllegalArgumentException(
1977 "Stack and display id can't be set at the same time.");
1978 }
1979
Wale Ogunwale854809c2015-12-27 16:18:19 -08001980 if (isValidLaunchStackId(launchStackId, r)) {
1981 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07001982 }
1983 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001984 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1985 // for this activity, so we put the activity in the fullscreen stack.
1986 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001987 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07001988 if (launchDisplayId != INVALID_DISPLAY) {
1989 // Stack id has higher priority than display id.
1990 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
1991 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001992
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001993 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001994 return null;
1995 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001996 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001997
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001998 // The parent activity doesn't want to launch the activity on top of itself, but
1999 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002000 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002001 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2002 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002003
2004 if (parentStack != mSupervisor.mFocusedStack) {
2005 // If task's parent stack is not focused - use it during adjacent launch.
2006 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002007 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002008 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2009 // If task is already on top of focused stack - use it. We don't want to move the
2010 // existing focused task to adjacent stack, just deliver new intent in this case.
2011 return mSupervisor.mFocusedStack;
2012 }
2013
Winson Chung83471632016-12-13 11:02:12 -08002014 if (parentStack != null && parentStack.isDockedStack()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002015 // If parent was in docked stack, the natural place to launch another activity
2016 // will be fullscreen, so it can appear alongside the docked window.
2017 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2018 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002019 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002020 // If the parent is not in the docked stack, we check if there is docked window
2021 // and if yes, we will launch into that stack. If not, we just put the new
2022 // activity into parent's stack, because we can't find a better place.
2023 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2024 if (dockedStack != null
2025 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2026 // There is a docked stack, but it isn't visible, so we can't launch into that.
2027 return null;
2028 } else {
2029 return dockedStack;
2030 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002031 }
2032 }
2033 }
2034
Andrii Kulian16802aa2016-11-02 12:21:33 -07002035 boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
Winson Chungd3395382016-12-13 11:49:09 -08002036 switch (stackId) {
2037 case INVALID_STACK_ID:
2038 case HOME_STACK_ID:
2039 return false;
2040 case FULLSCREEN_WORKSPACE_STACK_ID:
2041 return true;
2042 case FREEFORM_WORKSPACE_STACK_ID:
2043 return r.supportsFreeform();
2044 case DOCKED_STACK_ID:
2045 return r.supportsSplitScreen();
2046 case PINNED_STACK_ID:
2047 return r.supportsPictureInPicture();
2048 case RECENTS_STACK_ID:
2049 return r.isRecentsActivity();
Winson Chung83471632016-12-13 11:02:12 -08002050 case ASSISTANT_STACK_ID:
2051 return r.isAssistantActivity();
Winson Chungd3395382016-12-13 11:49:09 -08002052 default:
Andrii Kulian4acfd852017-01-26 19:43:13 -08002053 if (StackId.isDynamicStack(stackId)) {
2054 return true;
2055 }
Winson Chungd3395382016-12-13 11:49:09 -08002056 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
2057 return false;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002058 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002059 }
2060
Wale Ogunwale854809c2015-12-27 16:18:19 -08002061 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2062 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002063 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002064 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2065 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002066 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002067 }
2068 }
2069 return newBounds;
2070 }
2071
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002072 void setWindowManager(WindowManagerService wm) {
2073 mWindowManager = wm;
2074 }
2075
2076 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2077 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2078 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2079 if (pal.stack == stack) {
2080 mPendingActivityLaunches.remove(palNdx);
2081 }
2082 }
2083 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002084
2085 static boolean isDocumentLaunchesIntoExisting(int flags) {
2086 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2087 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2088 }
liulvpingcfa825f2016-09-26 20:00:15 +08002089
2090 boolean clearPendingActivityLaunchesLocked(String packageName) {
2091 boolean didSomething = false;
2092
2093 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2094 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2095 ActivityRecord r = pal.r;
2096 if (r != null && r.packageName.equals(packageName)) {
2097 mPendingActivityLaunches.remove(palNdx);
2098 didSomething = true;
2099 }
2100 }
2101 return didSomething;
2102 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002103}