blob: 61e3ad5ea052a432ded801f947aa616f43ad3afd [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;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080028import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
29import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
30import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Wale Ogunwale854809c2015-12-27 16:18:19 -080031import static android.app.ActivityManager.StackId.HOME_STACK_ID;
32import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
33import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Andrii Kulian16802aa2016-11-02 12:21:33 -070034import static android.app.ActivityManager.StackId.isStaticStack;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080035import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080036import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
37import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010038import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080039import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080040import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080041import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080042import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
44import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080045import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
46import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
47import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
48import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
49import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080050import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080051import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
52import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
53import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
54import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Andrii Kulian16802aa2016-11-02 12:21:33 -070055import static android.view.Display.INVALID_DISPLAY;
56
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;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080073import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
74import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
75import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080076import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080077import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
78import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
79import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080080import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080081import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080082import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080083
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080084import android.app.ActivityManager;
85import android.app.ActivityOptions;
86import android.app.AppGlobals;
87import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080088import android.app.IApplicationThread;
Tony Mak853304c2016-04-18 15:17:41 +010089import android.app.KeyguardManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080090import android.app.PendingIntent;
91import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070092import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080093import android.content.ComponentName;
Tony Mak853304c2016-04-18 15:17:41 +010094import android.content.Context;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080095import android.content.IIntentSender;
96import android.content.Intent;
97import android.content.IntentSender;
98import android.content.pm.ActivityInfo;
99import android.content.pm.ApplicationInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000100import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800101import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000102import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800103import android.content.res.Configuration;
104import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700105import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.os.Bundle;
108import android.os.IBinder;
Wei Wang98f03f92016-05-18 11:32:52 -0700109import android.os.PowerManagerInternal;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import 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;
465 if (needsPhaseTwo) {
466 // request phase two resolution
467 mService.getPackageManagerInternalLocked().requestEphemeralResolutionPhaseTwo(
468 rInfo.ephemeralResponse, ephemeralIntent, resolvedType, intent,
469 callingPackage, userId);
470 }
471 intent = EphemeralResolver.buildEphemeralInstallerIntent(intent, ephemeralIntent,
472 callingPackage, resolvedType, userId, packageName, splitName, token,
473 needsPhaseTwo);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800474 resolvedType = null;
475 callingUid = realCallingUid;
476 callingPid = realCallingPid;
477
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800478 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
479 }
480
481 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
Andrii Kulian1779e612016-10-12 21:58:25 -0700482 intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord,
483 resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor,
484 container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800485 if (outActivity != null) {
486 outActivity[0] = r;
487 }
488
489 if (r.appTimeTracker == null && sourceRecord != null) {
490 // If the caller didn't specify an explicit time tracker, we want to continue
491 // tracking under any it has.
492 r.appTimeTracker = sourceRecord.appTimeTracker;
493 }
494
495 final ActivityStack stack = mSupervisor.mFocusedStack;
496 if (voiceSession == null && (stack.mResumedActivity == null
497 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
498 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
499 realCallingPid, realCallingUid, "Activity start")) {
500 PendingActivityLaunch pal = new PendingActivityLaunch(r,
501 sourceRecord, startFlags, stack, callerApp);
502 mPendingActivityLaunches.add(pal);
503 ActivityOptions.abort(options);
504 return ActivityManager.START_SWITCHES_CANCELED;
505 }
506 }
507
508 if (mService.mDidAppSwitch) {
509 // This is the second allowed switch since we stopped switches,
510 // so now just generally allow switches. Use case: user presses
511 // home (switches disabled, switch to home, mDidAppSwitch now true);
512 // user taps a home icon (coming from home so allowed, we hit here
513 // and now allow anyone to switch again).
514 mService.mAppSwitchesAllowedTime = 0;
515 } else {
516 mService.mDidAppSwitch = true;
517 }
518
519 doPendingActivityLaunchesLocked(false);
520
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700521 try {
522 mService.mWindowManager.deferSurfaceLayout();
523 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
524 true, options, inTask);
525 } finally {
526 mService.mWindowManager.continueSurfaceLayout();
527 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700528 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800529 return err;
530 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800531
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800532 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700533 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
534 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800535
536 if (result < START_SUCCESS) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800537 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800538 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800539
Chong Zhang5022da32016-06-21 16:31:37 -0700540 // We're waiting for an activity launch to finish, but that activity simply
541 // brought another activity to front. Let startActivityMayWait() know about
542 // this, so it waits for the new activity to become visible instead.
543 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
544 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
545 }
546
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800547 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700548 final ActivityStack currentStack = r.getStack();
549 if (currentStack != null) {
550 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800551 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700552 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800553 }
554
Jorim Jaggi352d5842016-05-19 10:20:28 -0700555 // If we launched the activity from a no display activity that was launched from the home
556 // screen, we also need to start recents to un-minimize the docked stack, since the
557 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700558 // Note that some apps have trampoline activities without noDisplay being set. In that case,
559 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
560 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700561 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
562 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700563 final boolean noDisplayActivityOverHome = sourceRecord != null
564 && sourceRecord.noDisplay
565 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700566 if (startedActivityStackId == DOCKED_STACK_ID
567 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100568 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
569 final ActivityRecord topActivityHomeStack = homeStack != null
570 ? homeStack.topRunningActivityLocked() : null;
571 if (topActivityHomeStack == null
572 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
573 // We launch an activity while being in home stack, which means either launcher or
574 // recents into docked stack. We don't want the launched activity to be alone in a
575 // docked stack, so we want to immediately launch recents too.
576 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700577 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100578 return;
579 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800580 }
581
582 if (startedActivityStackId == PINNED_STACK_ID
583 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
584 // The activity was already running in the pinned stack so it wasn't started, but either
585 // brought to the front or the new intent was delivered to it since it was already in
586 // front. Notify anyone interested in this piece of information.
Yorke Leebd54c2a2016-10-25 13:49:23 -0700587 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800588 return;
589 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800590 }
591
592 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -0800593 mSupervisor.moveHomeStackTaskToTop(reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800594 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
595 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
596 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
597 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
598 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700599 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800600 null /*container*/, null /*inTask*/);
601 if (mSupervisor.inResumeTopActivity) {
602 // If we are in resume section already, home activity will be initialized, but not
603 // resumed (to avoid recursive resume) and will stay that way until something pokes it
604 // again. We need to schedule another resume.
605 mSupervisor.scheduleResumeTopActivities();
606 }
607 }
608
Tony Mak853304c2016-04-18 15:17:41 +0100609 void showConfirmDeviceCredential(int userId) {
610 // First, retrieve the stack that we want to resume after credential is confirmed.
611 ActivityStack targetStack;
612 ActivityStack fullscreenStack =
613 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
614 if (fullscreenStack != null &&
615 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
616 // Single window case and the case that the docked stack is shown with fullscreen stack.
617 targetStack = fullscreenStack;
618 } else {
619 // The case that the docked stack is shown with recent.
620 targetStack = mSupervisor.getStack(HOME_STACK_ID);
621 }
622 if (targetStack == null) {
623 return;
624 }
625 final KeyguardManager km = (KeyguardManager) mService.mContext
626 .getSystemService(Context.KEYGUARD_SERVICE);
627 final Intent credential =
628 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100629 // For safety, check null here in case users changed the setting after the checking.
630 if (credential == null) {
631 return;
632 }
Tony Mak853304c2016-04-18 15:17:41 +0100633 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
634 if (activityRecord != null) {
635 final IIntentSender target = mService.getIntentSenderLocked(
636 ActivityManager.INTENT_SENDER_ACTIVITY,
637 activityRecord.launchedFromPackage,
638 activityRecord.launchedFromUid,
639 activityRecord.userId,
640 null, null, 0,
641 new Intent[] { activityRecord.intent },
642 new String[] { activityRecord.resolvedType },
643 PendingIntent.FLAG_CANCEL_CURRENT |
644 PendingIntent.FLAG_ONE_SHOT |
645 PendingIntent.FLAG_IMMUTABLE,
646 null);
647 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
648 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100649 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100650 }
651 }
652
Tony Mak646fe992016-04-21 16:43:08 +0100653 void startConfirmCredentialIntent(Intent intent) {
654 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
655 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
656 FLAG_ACTIVITY_TASK_ON_HOME);
657 final ActivityOptions options = ActivityOptions.makeBasic();
658 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
659 mService.mContext.startActivityAsUser(intent, options.toBundle(),
660 UserHandle.CURRENT);
661 }
Tony Mak853304c2016-04-18 15:17:41 +0100662
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800663 final int startActivityMayWait(IApplicationThread caller, int callingUid,
664 String callingPackage, Intent intent, String resolvedType,
665 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
666 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700667 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700668 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800669 IActivityContainer iContainer, TaskRecord inTask) {
670 // Refuse possible leaked file descriptors
671 if (intent != null && intent.hasFileDescriptors()) {
672 throw new IllegalArgumentException("File descriptors passed in Intent");
673 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500674 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800675 boolean componentSpecified = intent.getComponent() != null;
676
677 // Save a copy in case ephemeral needs it
678 final Intent ephemeralIntent = new Intent(intent);
679 // Don't modify the client's object!
680 intent = new Intent(intent);
681
682 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000683 if (rInfo == null) {
684 UserInfo userInfo = mSupervisor.getUserInfo(userId);
685 if (userInfo != null && userInfo.isManagedProfile()) {
686 // Special case for managed profiles, if attempting to launch non-cryto aware
687 // app in a locked managed profile from an unlocked parent allow it to resolve
688 // as user will be sent via confirm credentials to unlock the profile.
689 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700690 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000691 long token = Binder.clearCallingIdentity();
692 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700693 UserInfo parent = userManager.getProfileParent(userId);
694 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
695 && userManager.isUserUnlockingOrUnlocked(parent.id)
696 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000697 } finally {
698 Binder.restoreCallingIdentity(token);
699 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700700 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000701 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600702 PackageManager.MATCH_DIRECT_BOOT_AWARE
703 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000704 }
705 }
706 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800707 // Collect information about the target of the Intent.
708 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
709
710 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
711 ActivityStackSupervisor.ActivityContainer container =
712 (ActivityStackSupervisor.ActivityContainer)iContainer;
713 synchronized (mService) {
714 if (container != null && container.mParentActivity != null &&
715 container.mParentActivity.state != RESUMED) {
716 // Cannot start a child activity if the parent is not resumed.
717 return ActivityManager.START_CANCELED;
718 }
719 final int realCallingPid = Binder.getCallingPid();
720 final int realCallingUid = Binder.getCallingUid();
721 int callingPid;
722 if (callingUid >= 0) {
723 callingPid = -1;
724 } else if (caller == null) {
725 callingPid = realCallingPid;
726 callingUid = realCallingUid;
727 } else {
728 callingPid = callingUid = -1;
729 }
730
731 final ActivityStack stack;
732 if (container == null || container.mStack.isOnHomeDisplay()) {
733 stack = mSupervisor.mFocusedStack;
734 } else {
735 stack = container.mStack;
736 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700737 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700738 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800739 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
740 "Starting activity when config will change = " + stack.mConfigWillChange);
741
742 final long origId = Binder.clearCallingIdentity();
743
744 if (aInfo != null &&
745 (aInfo.applicationInfo.privateFlags
746 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
747 // This may be a heavy-weight process! Check to see if we already
748 // have another, different heavy-weight process running.
749 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
750 final ProcessRecord heavy = mService.mHeavyWeightProcess;
751 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
752 || !heavy.processName.equals(aInfo.processName))) {
753 int appCallingUid = callingUid;
754 if (caller != null) {
755 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
756 if (callerApp != null) {
757 appCallingUid = callerApp.info.uid;
758 } else {
759 Slog.w(TAG, "Unable to find app for caller " + caller
760 + " (pid=" + callingPid + ") when starting: "
761 + intent.toString());
762 ActivityOptions.abort(options);
763 return ActivityManager.START_PERMISSION_DENIED;
764 }
765 }
766
767 IIntentSender target = mService.getIntentSenderLocked(
768 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
769 appCallingUid, userId, null, null, 0, new Intent[] { intent },
770 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
771 | PendingIntent.FLAG_ONE_SHOT, null);
772
773 Intent newIntent = new Intent();
774 if (requestCode >= 0) {
775 // Caller is requesting a result.
776 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
777 }
778 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
779 new IntentSender(target));
780 if (heavy.activities.size() > 0) {
781 ActivityRecord hist = heavy.activities.get(0);
782 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
783 hist.packageName);
784 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
785 hist.task.taskId);
786 }
787 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
788 aInfo.packageName);
789 newIntent.setFlags(intent.getFlags());
790 newIntent.setClassName("android",
791 HeavyWeightSwitcherActivity.class.getName());
792 intent = newIntent;
793 resolvedType = null;
794 caller = null;
795 callingUid = Binder.getCallingUid();
796 callingPid = Binder.getCallingPid();
797 componentSpecified = true;
798 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
799 aInfo = rInfo != null ? rInfo.activityInfo : null;
800 if (aInfo != null) {
801 aInfo = mService.getActivityInfoForUser(aInfo, userId);
802 }
803 }
804 }
805 }
806
Jorim Jaggi275561a2016-02-23 10:11:02 -0500807 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800808 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
809 aInfo, rInfo, voiceSession, voiceInteractor,
810 resultTo, resultWho, requestCode, callingPid,
811 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500812 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
813 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800814
815 Binder.restoreCallingIdentity(origId);
816
817 if (stack.mConfigWillChange) {
818 // If the caller also wants to switch to a new configuration,
819 // do so now. This allows a clean switch, as we are waiting
820 // for the current activity to pause (so we will not destroy
821 // it), and have not yet started the next activity.
822 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
823 "updateConfiguration()");
824 stack.mConfigWillChange = false;
825 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
826 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700827 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800828 }
829
830 if (outResult != null) {
831 outResult.result = res;
832 if (res == ActivityManager.START_SUCCESS) {
833 mSupervisor.mWaitingActivityLaunched.add(outResult);
834 do {
835 try {
836 mService.wait();
837 } catch (InterruptedException e) {
838 }
Chong Zhang5022da32016-06-21 16:31:37 -0700839 } while (outResult.result != START_TASK_TO_FRONT
840 && !outResult.timeout && outResult.who == null);
841 if (outResult.result == START_TASK_TO_FRONT) {
842 res = START_TASK_TO_FRONT;
843 }
844 }
845 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800846 ActivityRecord r = stack.topRunningActivityLocked();
847 if (r.nowVisible && r.state == RESUMED) {
848 outResult.timeout = false;
849 outResult.who = new ComponentName(r.info.packageName, r.info.name);
850 outResult.totalTime = 0;
851 outResult.thisTime = 0;
852 } else {
853 outResult.thisTime = SystemClock.uptimeMillis();
854 mSupervisor.mWaitingActivityVisible.add(outResult);
855 do {
856 try {
857 mService.wait();
858 } catch (InterruptedException e) {
859 }
860 } while (!outResult.timeout && outResult.who == null);
861 }
862 }
863 }
864
Jorim Jaggibe67c902016-04-12 00:53:16 -0700865 final ActivityRecord launchedActivity = mReusedActivity != null
866 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700867 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800868 return res;
869 }
870 }
871
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800872 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
873 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
874 Bundle bOptions, int userId) {
875 if (intents == null) {
876 throw new NullPointerException("intents is null");
877 }
878 if (resolvedTypes == null) {
879 throw new NullPointerException("resolvedTypes is null");
880 }
881 if (intents.length != resolvedTypes.length) {
882 throw new IllegalArgumentException("intents are length different than resolvedTypes");
883 }
884
Makoto Onukid67b1872016-07-21 16:26:36 -0700885 final int realCallingPid = Binder.getCallingPid();
886 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800887
888 int callingPid;
889 if (callingUid >= 0) {
890 callingPid = -1;
891 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700892 callingPid = realCallingPid;
893 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800894 } else {
895 callingPid = callingUid = -1;
896 }
897 final long origId = Binder.clearCallingIdentity();
898 try {
899 synchronized (mService) {
900 ActivityRecord[] outActivity = new ActivityRecord[1];
901 for (int i=0; i<intents.length; i++) {
902 Intent intent = intents[i];
903 if (intent == null) {
904 continue;
905 }
906
907 // Refuse possible leaked file descriptors
908 if (intent != null && intent.hasFileDescriptors()) {
909 throw new IllegalArgumentException("File descriptors passed in Intent");
910 }
911
912 boolean componentSpecified = intent.getComponent() != null;
913
914 // Don't modify the client's object!
915 intent = new Intent(intent);
916
917 // Collect information about the target of the Intent.
918 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
919 null, userId);
920 // TODO: New, check if this is correct
921 aInfo = mService.getActivityInfoForUser(aInfo, userId);
922
923 if (aInfo != null &&
924 (aInfo.applicationInfo.privateFlags
925 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
926 throw new IllegalArgumentException(
927 "FLAG_CANT_SAVE_STATE not supported here");
928 }
929
930 ActivityOptions options = ActivityOptions.fromBundle(
931 i == intents.length - 1 ? bOptions : null);
932 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
933 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700934 callingPid, callingUid, callingPackage,
935 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800936 options, false, componentSpecified, outActivity, null, null);
937 if (res < 0) {
938 return res;
939 }
940
941 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
942 }
943 }
944 } finally {
945 Binder.restoreCallingIdentity(origId);
946 }
947
Wale Ogunwale01d66562015-12-29 08:19:19 -0800948 return START_SUCCESS;
949 }
950
Wei Wang65c7a152016-06-02 18:51:22 -0700951 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
Bryce Lee834abec2017-01-09 16:18:14 -0800952 boolean sendHint = forceSend;
953
954 if (!sendHint) {
955 // If not forced, send power hint when the activity's process is different than the
956 // current resumed activity.
957 final ActivityRecord resumedActivity = mSupervisor.getResumedActivityLocked();
958 sendHint = resumedActivity == null
959 || resumedActivity.app == null
960 || !resumedActivity.app.equals(mStartActivity.app);
961 }
962
963 if (sendHint && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700964 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700965 mPowerHintSent = true;
966 }
967 }
968
Wei Wang65c7a152016-06-02 18:51:22 -0700969 void sendPowerHintForLaunchEndIfNeeded() {
970 // Trigger launch power hint if activity is launched
971 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700972 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700973 mPowerHintSent = false;
974 }
975 }
976
Wale Ogunwale01d66562015-12-29 08:19:19 -0800977 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
978 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
979 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
980
981 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
982 voiceInteractor);
983
984 computeLaunchingTaskFlags();
985
986 computeSourceStack();
987
988 mIntent.setFlags(mLaunchFlags);
989
Jorim Jaggibe67c902016-04-12 00:53:16 -0700990 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800991
Jorim Jaggi2adba072016-03-03 13:43:39 +0100992 final int preferredLaunchStackId =
993 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
994
Jorim Jaggibe67c902016-04-12 00:53:16 -0700995 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800996 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
997 // still needs to be a lock task mode violation since the task gets cleared out and
998 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700999 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001000 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1001 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1002 mSupervisor.showLockTaskToast();
1003 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1004 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1005 }
1006
1007 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001008 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001009 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001010 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001011 // This task was started because of movement of the activity based on affinity...
1012 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001013 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001014 }
1015
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001016 // This code path leads to delivering a new intent, we want to make sure we schedule it
1017 // as the first operation, in case the activity will be resumed as a result of later
1018 // operations.
1019 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001020 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001021 || mLaunchSingleInstance || mLaunchSingleTask) {
1022 // In this situation we want to remove all activities from the task up to the one
1023 // being started. In most cases this means we are resetting the task to its initial
1024 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001025 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001026 mStartActivity, mLaunchFlags);
1027 if (top != null) {
1028 if (top.frontOfTask) {
1029 // Activity aliases may mean we use different intents for the top activity,
1030 // so make sure the task now has the identity of the new intent.
1031 top.task.setIntent(mStartActivity);
1032 }
1033 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1034 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1035 mStartActivity.launchedFromPackage);
1036 }
1037 }
1038
Wei Wang65c7a152016-06-02 18:51:22 -07001039 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001040
Jorim Jaggibe67c902016-04-12 00:53:16 -07001041 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001042
1043 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1044 // We don't need to start a new activity, and the client said not to do anything
1045 // if that is the case, so this is it! And for paranoia, make sure we have
1046 // correctly resumed the top activity.
1047 resumeTargetStackIfNeeded();
1048 return START_RETURN_INTENT_TO_CALLER;
1049 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001050 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001051
1052 if (!mAddingToTask && mReuseTask == null) {
1053 // We didn't do anything... but it was needed (a.k.a., client don't use that
1054 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1055 resumeTargetStackIfNeeded();
1056 return START_TASK_TO_FRONT;
1057 }
1058 }
1059
1060 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001061 final ActivityStack sourceStack = mStartActivity.resultTo != null
1062 ? mStartActivity.resultTo.getStack() : null;
1063 if (sourceStack != null) {
1064 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1065 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1066 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001067 }
1068 ActivityOptions.abort(mOptions);
1069 return START_CLASS_NOT_FOUND;
1070 }
1071
1072 // If the activity being launched is the same as the one currently at the top, then
1073 // we need to check if it should only be launched once.
1074 final ActivityStack topStack = mSupervisor.mFocusedStack;
Winson Chungb5c41b72016-12-07 15:00:47 -08001075 final ActivityRecord topFocused = topStack.topActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001076 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1077 final boolean dontStart = top != null && mStartActivity.resultTo == null
1078 && top.realActivity.equals(mStartActivity.realActivity)
1079 && top.userId == mStartActivity.userId
1080 && top.app != null && top.app.thread != null
1081 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1082 || mLaunchSingleTop || mLaunchSingleTask);
1083 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001084 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001085 // For paranoia, make sure we have correctly resumed the top activity.
1086 topStack.mLastPausedActivity = null;
1087 if (mDoResume) {
1088 mSupervisor.resumeFocusedStackTopActivityLocked();
1089 }
1090 ActivityOptions.abort(mOptions);
1091 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1092 // We don't need to start a new activity, and the client said not to do
1093 // anything if that is the case, so this is it!
1094 return START_RETURN_INTENT_TO_CALLER;
1095 }
1096 top.deliverNewIntentLocked(
1097 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001098
1099 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1100 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1101 mSupervisor.handleNonResizableTaskIfNeeded(
1102 top.task, preferredLaunchStackId, topStack.mStackId);
1103
Wale Ogunwale01d66562015-12-29 08:19:19 -08001104 return START_DELIVERED_TO_TOP;
1105 }
1106
1107 boolean newTask = false;
1108 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1109 ? mSourceRecord.task : null;
1110
1111 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001112 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001113 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1114 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1115 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001116 result = setTaskFromReuseOrCreateNewTask(
1117 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001118 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001119 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001120 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001121 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001122 } else {
1123 // This not being started from an existing activity, and not part of a new task...
1124 // just put it in the top task, though these days this case should never happen.
1125 setTaskToCurrentTopOrCreateNewTask();
1126 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001127 if (result != START_SUCCESS) {
1128 return result;
1129 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001130
1131 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1132 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1133
1134 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1135 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1136 }
1137 if (newTask) {
1138 EventLog.writeEvent(
1139 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1140 }
1141 ActivityStack.logStartActivity(
1142 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1143 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001144
Wei Wang65c7a152016-06-02 18:51:22 -07001145 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001146
Winson Chungb5c41b72016-12-07 15:00:47 -08001147 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1148 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001149 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001150 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1151 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001152 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1153 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001154 // If the activity is not focusable, we can't resume it, but still would like to
1155 // make sure it becomes visible as it starts (this will also trigger entry
1156 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001157 // Also, we don't want to resume activities in a task that currently has an overlay
1158 // as the starting activity just needs to be in the visible paused state until the
1159 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001160 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001161 // Go ahead and tell window manager to execute app transition for this activity
1162 // since the app transition will not be triggered through the resume channel.
1163 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001164 } else {
Winson Chung32066032016-11-04 11:55:21 -07001165 // If the target stack was not previously focusable (previous top running activity
1166 // on that stack was not visible) then any prior calls to move the stack to the
1167 // will not update the focused stack. If starting the new activity now allows the
1168 // task stack to be focusable, then ensure that we now update the focused stack
1169 // accordingly.
1170 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1171 mTargetStack.moveToFront("startActivityUnchecked");
1172 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001173 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1174 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001175 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001176 } else {
1177 mTargetStack.addRecentActivityLocked(mStartActivity);
1178 }
1179 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1180
Jorim Jaggid53f0922016-04-06 22:16:23 -07001181 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001182 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001183
1184 return START_SUCCESS;
1185 }
1186
1187 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1188 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1189 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1190 reset();
1191
1192 mStartActivity = r;
1193 mIntent = r.intent;
1194 mOptions = options;
1195 mCallingUid = r.launchedFromUid;
1196 mSourceRecord = sourceRecord;
1197 mVoiceSession = voiceSession;
1198 mVoiceInteractor = voiceInteractor;
1199
1200 mLaunchBounds = getOverrideBounds(r, options, inTask);
1201
1202 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1203 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1204 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1205 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1206 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1207 mLaunchTaskBehind = r.mLaunchTaskBehind
1208 && !mLaunchSingleTask && !mLaunchSingleInstance
1209 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1210
1211 sendNewTaskResultRequestIfNeeded();
1212
1213 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1214 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1215 }
1216
1217 // If we are actually going to launch in to a new task, there are some cases where
1218 // we further want to do multiple task.
1219 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1220 if (mLaunchTaskBehind
1221 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1222 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1223 }
1224 }
1225
1226 // We'll invoke onUserLeaving before onPause only if the launching
1227 // activity did not explicitly state that this is an automated launch.
1228 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1229 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1230 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1231
1232 // If the caller has asked not to resume at this point, we make note
1233 // of this in the record so that we can skip it when trying to find
1234 // the top running activity.
1235 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001236 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001237 r.delayedResume = true;
1238 mDoResume = false;
1239 }
1240
Wale Ogunwale3b232392016-05-13 15:37:13 -07001241 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1242 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001243 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1244 final ActivityRecord top = task != null ? task.getTopActivity() : null;
Robin Leebee64222017-01-06 17:12:55 +00001245 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001246
1247 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1248 // it!
1249 mDoResume = false;
1250 mAvoidMoveToFront = true;
1251 }
1252 }
1253
Wale Ogunwale01d66562015-12-29 08:19:19 -08001254 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1255
1256 mInTask = inTask;
1257 // In some flows in to this function, we retrieve the task record and hold on to it
1258 // without a lock before calling back in to here... so the task at this point may
1259 // not actually be in recents. Check for that, and if it isn't in recents just
1260 // consider it invalid.
1261 if (inTask != null && !inTask.inRecents) {
1262 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1263 mInTask = null;
1264 }
1265
1266 mStartFlags = startFlags;
1267 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1268 // is the same as the one making the call... or, as a special case, if we do not know
1269 // the caller then we count the current top activity as the caller.
1270 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1271 ActivityRecord checkedCaller = sourceRecord;
1272 if (checkedCaller == null) {
1273 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1274 mNotTop);
1275 }
1276 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1277 // Caller is not the same as launcher, so always needed.
1278 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1279 }
1280 }
1281
1282 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1283 }
1284
1285 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001286 final ActivityStack sourceStack = mStartActivity.resultTo != null
1287 ? mStartActivity.resultTo.getStack() : null;
1288 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001289 // For whatever reason this activity is being launched into a new task...
1290 // yet the caller has requested a result back. Well, that is pretty messed up,
1291 // so instead immediately send back a cancel and let the new task continue launched
1292 // as normal without a dependency on its originator.
1293 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001294 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1295 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1296 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001297 mStartActivity.resultTo = null;
1298 }
1299 }
1300
1301 private void computeLaunchingTaskFlags() {
1302 // If the caller is not coming from another activity, but has given us an explicit task into
1303 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001304 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001305 final Intent baseIntent = mInTask.getBaseIntent();
1306 final ActivityRecord root = mInTask.getRootActivity();
1307 if (baseIntent == null) {
1308 ActivityOptions.abort(mOptions);
1309 throw new IllegalArgumentException("Launching into task without base intent: "
1310 + mInTask);
1311 }
1312
1313 // If this task is empty, then we are adding the first activity -- it
1314 // determines the root, and must be launching as a NEW_TASK.
1315 if (mLaunchSingleInstance || mLaunchSingleTask) {
1316 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1317 ActivityOptions.abort(mOptions);
1318 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1319 + mStartActivity + " into different task " + mInTask);
1320 }
1321 if (root != null) {
1322 ActivityOptions.abort(mOptions);
1323 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1324 + " has root " + root + " but target is singleInstance/Task");
1325 }
1326 }
1327
1328 // If task is empty, then adopt the interesting intent launch flags in to the
1329 // activity being started.
1330 if (root == null) {
1331 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1332 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1333 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1334 | (baseIntent.getFlags() & flagsOfInterest);
1335 mIntent.setFlags(mLaunchFlags);
1336 mInTask.setIntent(mStartActivity);
1337 mAddingToTask = true;
1338
1339 // If the task is not empty and the caller is asking to start it as the root of
1340 // a new task, then we don't actually want to start this on the task. We will
1341 // bring the task to the front, and possibly give it a new intent.
1342 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1343 mAddingToTask = false;
1344
1345 } else {
1346 mAddingToTask = true;
1347 }
1348
1349 mReuseTask = mInTask;
1350 } else {
1351 mInTask = null;
1352 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1353 // when in freeform workspace.
1354 // Also put noDisplay activities in the source task. These by itself can be placed
1355 // in any task/stack, however it could launch other activities like ResolverActivity,
1356 // and we want those to stay in the original task.
1357 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1358 && mSourceRecord.isFreeform()) {
1359 mAddingToTask = true;
1360 }
1361 }
1362
1363 if (mInTask == null) {
1364 if (mSourceRecord == null) {
1365 // This activity is not being started from another... in this
1366 // case we -always- start a new task.
1367 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1368 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1369 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1370 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1371 }
1372 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1373 // The original activity who is starting us is running as a single
1374 // instance... this new activity it is starting must go on its
1375 // own task.
1376 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1377 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1378 // The activity being started is a single instance... it always
1379 // gets launched into its own task.
1380 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1381 }
1382 }
1383 }
1384
1385 private void computeSourceStack() {
1386 if (mSourceRecord == null) {
1387 mSourceStack = null;
1388 return;
1389 }
1390 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001391 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001392 return;
1393 }
1394
1395 // If the source is finishing, we can't further count it as our source. This is because the
1396 // task it is associated with may now be empty and on its way out, so we don't want to
1397 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1398 // a task for it. But save the task information so it can be used when creating the new task.
1399 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1400 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1401 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1402 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1403 mNewTaskInfo = mSourceRecord.info;
1404 mNewTaskIntent = mSourceRecord.task.intent;
1405 }
1406 mSourceRecord = null;
1407 mSourceStack = null;
1408 }
1409
1410 /**
1411 * Decide whether the new activity should be inserted into an existing task. Returns null
1412 * if not or an ActivityRecord with the task into which the new activity should be added.
1413 */
1414 private ActivityRecord getReusableIntentActivity() {
1415 // We may want to try to place the new activity in to an existing task. We always
1416 // do this if the target activity is singleTask or singleInstance; we will also do
1417 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1418 // us to still place it in a new task: multi task, always doc mode, or being asked to
1419 // launch this as a new task behind the current one.
1420 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1421 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1422 || mLaunchSingleInstance || mLaunchSingleTask;
1423 // If bring to front is requested, and no result is requested and we have not been given
1424 // an explicit task to launch in to, and we can find a task that was started with this
1425 // same component, then instead of launching bring that one to the front.
1426 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1427 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001428 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1429 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1430 intentActivity = task != null ? task.getTopActivity() : null;
1431 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001432 if (mLaunchSingleInstance) {
1433 // There can be one and only one instance of single instance activity in the
1434 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001435 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001436 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1437 // For the launch adjacent case we only want to put the activity in an existing
1438 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001439 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1440 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001441 } else {
1442 // Otherwise find the best task to put the activity in.
1443 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1444 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001445 }
1446 return intentActivity;
1447 }
1448
1449 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001450 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001451 mTargetStack.mLastPausedActivity = null;
1452 // If the target task is not in the front, then we need to bring it to the front...
1453 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1454 // the same behavior as if a new instance was being started, which means not bringing it
1455 // to the front if the caller is not itself in the front.
1456 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1457 ActivityRecord curTop = (focusStack == null)
1458 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1459
Jorim Jaggic875ae72016-04-26 22:41:06 -07001460 if (curTop != null
1461 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1462 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001463 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1464 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1465 mSourceStack.topActivity().task == mSourceRecord.task)) {
1466 // We really do want to push this one into the user's face, right now.
1467 if (mLaunchTaskBehind && mSourceRecord != null) {
1468 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1469 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001470 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001471
1472 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1473 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1474 // So no point resuming any of the activities here, it just wastes one extra
1475 // resuming, plus enter AND exit transitions.
1476 // Here we only want to bring the target stack forward. Transition will be applied
1477 // to the new activity that's started after the old ones are gone.
1478 final boolean willClearTask =
1479 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1480 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1481 if (!willClearTask) {
1482 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001483 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001484 if (launchStack == null || launchStack == mTargetStack) {
1485 // We only want to move to the front, if we aren't going to launch on a
1486 // different stack. If we launch on a different stack, we will put the
1487 // task on top there.
1488 mTargetStack.moveTaskToFrontLocked(
1489 intentActivity.task, mNoAnimation, mOptions,
1490 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1491 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001492 } else if (launchStack.mStackId == DOCKED_STACK_ID
1493 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1494 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1495 // If we want to launch adjacent and mTargetStack is not the computed
1496 // launch stack - move task to top of computed stack.
1497 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1498 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1499 ANIMATE);
1500 } else {
1501 // TODO: This should be reevaluated in MW v2.
1502 // We choose to move task to front instead of launching it adjacent
1503 // when specific stack was requested explicitly and it appeared to be
1504 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1505 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1506 mOptions, mStartActivity.appTimeTracker,
1507 "bringToFrontInsteadOfAdjacentLaunch");
1508 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001509 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001510 }
1511 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001512 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001513 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001514 }
1515 }
1516 if (!mMovedToFront && mDoResume) {
1517 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1518 + " from " + intentActivity);
1519 mTargetStack.moveToFront("intentActivityFound");
1520 }
1521
Jorim Jaggid53f0922016-04-06 22:16:23 -07001522 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1523 mTargetStack.mStackId);
1524
Wale Ogunwale01d66562015-12-29 08:19:19 -08001525 // If the caller has requested that the target task be reset, then do so.
1526 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1527 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1528 }
1529 return intentActivity;
1530 }
1531
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001532 private void updateTaskReturnToType(
1533 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001534 if (focusedStack != null && focusedStack.isHomeOrRecentsStack()
1535 && focusedStack.topTask() != null && focusedStack.topTask().isOnTopLauncher()) {
Jiaquan Hee13e9642016-06-15 15:16:13 -07001536 // Since an on-top launcher will is moved to back when tasks are launched from it,
1537 // those tasks should first try to return to a non-home activity.
1538 // This also makes sure that non-home activities are visible under a transparent
1539 // non-home activity.
1540 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1541 return;
1542 } else if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001543 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1544 // Caller wants to appear on home activity.
1545 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1546 return;
1547 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1548 // Task will be launched over the home stack, so return home.
1549 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1550 return;
1551 }
1552
1553 // Else we are coming from an application stack so return to an application.
1554 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1555 }
1556
Wale Ogunwale01d66562015-12-29 08:19:19 -08001557 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1558 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1559 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1560 // The caller has requested to completely replace any existing task with its new
1561 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001562 intentActivity.task.performClearTaskLocked();
1563 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001564 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001565 // When we clear the task - focus will be adjusted, which will bring another task
1566 // to top before we launch the activity we need. This will temporary swap their
1567 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1568 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001569 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1570 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001571 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1572 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001573 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001574 // A special case: we need to start the activity because it is not currently
1575 // running, and the caller has asked to clear the current task to have this
1576 // activity at the top.
1577 mAddingToTask = true;
1578 // Now pretend like this activity is being started by the top of its task, so it
1579 // is put in the right place.
1580 mSourceRecord = intentActivity;
1581 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001582 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001583 // Target stack got cleared when we all activities were removed above.
1584 // Go ahead and reset it.
1585 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1586 null /* bounds */, mLaunchFlags, mOptions);
1587 mTargetStack.addTask(task,
1588 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1589 }
1590 }
1591 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1592 // In this case the top activity on the task is the same as the one being launched,
1593 // so we take that as a request to bring the task to the foreground. If the top
1594 // activity in the task is the root activity, deliver this new intent to it if it
1595 // desires.
1596 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1597 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001598 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001599 intentActivity.task);
1600 if (intentActivity.frontOfTask) {
1601 intentActivity.task.setIntent(mStartActivity);
1602 }
1603 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1604 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001605 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001606 // In this case we are launching the root activity of the task, but with a
1607 // different intent. We should start a new instance on top.
1608 mAddingToTask = true;
1609 mSourceRecord = intentActivity;
1610 }
1611 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1612 // In this case an activity is being launched in to an existing task, without
1613 // resetting that task. This is typically the situation of launching an activity
1614 // from a notification or shortcut. We want to place the new activity on top of the
1615 // current task.
1616 mAddingToTask = true;
1617 mSourceRecord = intentActivity;
1618 } else if (!intentActivity.task.rootWasReset) {
1619 // In this case we are launching into an existing task that has not yet been started
1620 // from its front door. The current task has been brought to the front. Ideally,
1621 // we'd probably like to place this new task at the bottom of its stack, but that's
1622 // a little hard to do with the current organization of the code so for now we'll
1623 // just drop it.
1624 intentActivity.task.setIntent(mStartActivity);
1625 }
1626 }
1627
1628 private void resumeTargetStackIfNeeded() {
1629 if (mDoResume) {
1630 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001631 } else {
1632 ActivityOptions.abort(mOptions);
1633 }
1634 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1635 }
1636
Chong Zhang6cda19c2016-06-14 19:07:56 -07001637 private int setTaskFromReuseOrCreateNewTask(
1638 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1639 mTargetStack = computeStackFocus(
1640 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1641
1642 // Do no move the target stack to front yet, as we might bail if
1643 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001644
1645 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001646 final TaskRecord task = mTargetStack.createTaskRecord(
1647 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001648 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001649 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
1650 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity.mActivityType);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001651 mStartActivity.setTask(task, taskToAffiliate);
1652 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001653 final int stackId = mTargetStack.mStackId;
1654 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001655 mService.resizeStack(
1656 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001657 } else {
1658 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1659 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001660 }
1661 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1662 "Starting new activity " +
1663 mStartActivity + " in new task " + mStartActivity.task);
1664 } else {
1665 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1666 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001667
1668 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1669 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1670 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1671 }
1672
1673 if (!mMovedOtherTask) {
1674 // If stack id is specified in activity options, usually it means that activity is
1675 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1676 // that case we check the target stack.
1677 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1678 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1679 }
1680 if (mDoResume) {
1681 mTargetStack.moveToFront("reuseOrNewTask");
1682 }
1683 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001684 }
1685
1686 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001687 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1688 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1689 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1690 }
1691
Wale Ogunwale01d66562015-12-29 08:19:19 -08001692 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001693 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001694 // We only want to allow changing stack if the target task is not the top one,
1695 // otherwise we would move the launching task to the other side, rather than show
1696 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001697 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001698 if (moveStackAllowed) {
1699 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1700 mOptions);
1701 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001702
1703 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001704 mTargetStack = sourceStack;
1705 } else if (mTargetStack != sourceStack) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001706 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1707 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1708 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001709
Wale Ogunwale01d66562015-12-29 08:19:19 -08001710 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001711 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001712 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1713 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001714 } else if (mDoResume) {
1715 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001716 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001717
Wale Ogunwale01d66562015-12-29 08:19:19 -08001718 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1719 // In this case, we are adding the activity to an existing task, but the caller has
1720 // asked to clear that task if the activity is already running.
1721 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1722 mKeepCurTransition = true;
1723 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001724 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001725 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1726 // For paranoia, make sure we have correctly resumed the top activity.
1727 mTargetStack.mLastPausedActivity = null;
1728 if (mDoResume) {
1729 mSupervisor.resumeFocusedStackTopActivityLocked();
1730 }
1731 ActivityOptions.abort(mOptions);
1732 return START_DELIVERED_TO_TOP;
1733 }
1734 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1735 // In this case, we are launching an activity in our own task that may already be
1736 // running somewhere in the history, and we want to shuffle it to the front of the
1737 // stack if so.
1738 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1739 if (top != null) {
1740 final TaskRecord task = top.task;
1741 task.moveActivityToFrontLocked(top);
1742 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001743 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001744 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1745 mTargetStack.mLastPausedActivity = null;
1746 if (mDoResume) {
1747 mSupervisor.resumeFocusedStackTopActivityLocked();
1748 }
1749 return START_DELIVERED_TO_TOP;
1750 }
1751 }
1752
1753 // An existing activity is starting this new activity, so we want to keep the new one in
1754 // the same task as the one that is starting it.
1755 mStartActivity.setTask(sourceTask, null);
1756 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1757 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1758 return START_SUCCESS;
1759 }
1760
1761 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001762 // The caller is asking that the new activity be started in an explicit
1763 // task it has provided to us.
1764 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1765 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1766 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1767 }
1768
Wale Ogunwale01d66562015-12-29 08:19:19 -08001769 if (mLaunchBounds != null) {
1770 mInTask.updateOverrideConfiguration(mLaunchBounds);
1771 int stackId = mInTask.getLaunchStackId();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001772 if (stackId != mInTask.getStackId()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08001773 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(mInTask,
1774 stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront", true /* allowStackOnTop */);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001775 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001776 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001777 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001778 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001779 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001780 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001781 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001782 mTargetStack.moveTaskToFrontLocked(
1783 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1784
1785 // Check whether we should actually launch the new activity in to the task,
1786 // or just reuse the current activity on top.
1787 ActivityRecord top = mInTask.getTopActivity();
1788 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1789 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1790 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001791 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001792 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1793 // We don't need to start a new activity, and the client said not to do
1794 // anything if that is the case, so this is it!
1795 return START_RETURN_INTENT_TO_CALLER;
1796 }
1797 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1798 return START_DELIVERED_TO_TOP;
1799 }
1800 }
1801
1802 if (!mAddingToTask) {
1803 // We don't actually want to have this activity added to the task, so just
1804 // stop here but still tell the caller that we consumed the intent.
1805 ActivityOptions.abort(mOptions);
1806 return START_TASK_TO_FRONT;
1807 }
1808
1809 mStartActivity.setTask(mInTask, null);
1810 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1811 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1812
1813 return START_SUCCESS;
1814 }
1815
1816 private void setTaskToCurrentTopOrCreateNewTask() {
1817 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1818 mOptions);
1819 if (mDoResume) {
1820 mTargetStack.moveToFront("addingToTopTask");
1821 }
1822 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001823 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08001824 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
1825 mIntent, null, null, true, mStartActivity.mActivityType);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001826 mStartActivity.setTask(task, null);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08001827 mStartActivity.task.moveWindowContainerToTop(true /* includingParents */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001828 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1829 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1830 }
1831
1832 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1833 boolean launchSingleTask, int launchFlags) {
1834 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1835 (launchSingleInstance || launchSingleTask)) {
1836 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1837 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1838 "\"singleInstance\" or \"singleTask\"");
1839 launchFlags &=
1840 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1841 } else {
1842 switch (r.info.documentLaunchMode) {
1843 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1844 break;
1845 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1846 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1847 break;
1848 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1849 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1850 break;
1851 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1852 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1853 break;
1854 }
1855 }
1856 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001857 }
1858
1859 final void doPendingActivityLaunchesLocked(boolean doResume) {
1860 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001861 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1862 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001863 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001864 final int result = startActivityUnchecked(
1865 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1866 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001867 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1868 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001869 } catch (Exception e) {
1870 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1871 pal.sendErrorResult(e.getMessage());
1872 }
1873 }
1874 }
1875
1876 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001877 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001878 final TaskRecord task = r.task;
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001879 if (r.isRecentsActivity()) {
1880 return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1881 }
1882 if (r.isHomeActivity()) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001883 return mSupervisor.mHomeStack;
1884 }
1885
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001886 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001887 if (stack != null) {
1888 return stack;
1889 }
1890
Andrii Kulian02b7a832016-10-06 23:11:56 -07001891 final ActivityStack currentStack = task != null ? task.getStack() : null;
1892 if (currentStack != null) {
1893 if (currentStack.isOnHomeDisplay()) {
1894 if (mSupervisor.mFocusedStack != currentStack) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001895 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1896 "computeStackFocus: Setting " + "focused stack to r=" + r
1897 + " task=" + task);
1898 } else {
1899 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1900 "computeStackFocus: Focused stack already="
1901 + mSupervisor.mFocusedStack);
1902 }
1903 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001904 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001905 }
1906
1907 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1908 if (container != null) {
1909 // The first time put it on the desired stack, after this put on task stack.
1910 r.mInitialActivityContainer = null;
1911 return container.mStack;
1912 }
1913
1914 // The fullscreen stack can contain any task regardless of if the task is resizeable
1915 // 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 -07001916 // Same also applies to dynamic stacks, as they behave similar to fullscreen stack.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001917 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1918 // we can also put it in the focused stack.
1919 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001920 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1921 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
Andrii Kulian16802aa2016-11-02 12:21:33 -07001922 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced())
1923 || !isStaticStack(focusedStackId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001924 if (canUseFocusedStack && (!newTask
1925 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1926 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1927 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1928 return mSupervisor.mFocusedStack;
1929 }
1930
Andrii Kulian16802aa2016-11-02 12:21:33 -07001931 // We first try to put the task in the first dynamic stack on home display.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001932 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1933 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1934 stack = homeDisplayStacks.get(stackNdx);
1935 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1936 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1937 "computeStackFocus: Setting focused stack=" + stack);
1938 return stack;
1939 }
1940 }
1941
1942 // If there is no suitable dynamic stack then we figure out which static stack to use.
1943 final int stackId = task != null ? task.getLaunchStackId() :
1944 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1945 FULLSCREEN_WORKSPACE_STACK_ID;
1946 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1947 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1948 + r + " stackId=" + stack.mStackId);
1949 return stack;
1950 }
1951
Wale Ogunwale854809c2015-12-27 16:18:19 -08001952 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001953 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001954
1955 // We are reusing a task, keep the stack!
1956 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001957 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07001958 }
1959
Andrii Kulian16802aa2016-11-02 12:21:33 -07001960 final int launchDisplayId =
1961 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
1962
Wale Ogunwale854809c2015-12-27 16:18:19 -08001963 final int launchStackId =
1964 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1965
Andrii Kulian16802aa2016-11-02 12:21:33 -07001966 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
1967 throw new IllegalArgumentException(
1968 "Stack and display id can't be set at the same time.");
1969 }
1970
Wale Ogunwale854809c2015-12-27 16:18:19 -08001971 if (isValidLaunchStackId(launchStackId, r)) {
1972 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07001973 }
1974 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001975 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1976 // for this activity, so we put the activity in the fullscreen stack.
1977 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001978 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07001979 if (launchDisplayId != INVALID_DISPLAY) {
1980 // Stack id has higher priority than display id.
1981 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
1982 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001983
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001984 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001985 return null;
1986 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001987 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001988
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001989 // The parent activity doesn't want to launch the activity on top of itself, but
1990 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001991 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001992 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1993 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001994
1995 if (parentStack != mSupervisor.mFocusedStack) {
1996 // If task's parent stack is not focused - use it during adjacent launch.
1997 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001998 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001999 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2000 // If task is already on top of focused stack - use it. We don't want to move the
2001 // existing focused task to adjacent stack, just deliver new intent in this case.
2002 return mSupervisor.mFocusedStack;
2003 }
2004
2005 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2006 // If parent was in docked stack, the natural place to launch another activity
2007 // will be fullscreen, so it can appear alongside the docked window.
2008 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2009 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002010 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002011 // If the parent is not in the docked stack, we check if there is docked window
2012 // and if yes, we will launch into that stack. If not, we just put the new
2013 // activity into parent's stack, because we can't find a better place.
2014 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2015 if (dockedStack != null
2016 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2017 // There is a docked stack, but it isn't visible, so we can't launch into that.
2018 return null;
2019 } else {
2020 return dockedStack;
2021 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002022 }
2023 }
2024 }
2025
Andrii Kulian16802aa2016-11-02 12:21:33 -07002026 boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2027 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002028 return false;
2029 }
2030
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002031 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2032 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2033 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002034 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002035
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002036 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2037 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002038 }
2039
2040 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2041 return false;
2042 }
2043
2044 final boolean supportsPip = mService.mSupportsPictureInPicture
2045 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2046 if (stackId == PINNED_STACK_ID && !supportsPip) {
2047 return false;
2048 }
2049 return true;
2050 }
2051
Wale Ogunwale854809c2015-12-27 16:18:19 -08002052 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2053 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002054 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002055 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2056 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002057 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002058 }
2059 }
2060 return newBounds;
2061 }
2062
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002063 void setWindowManager(WindowManagerService wm) {
2064 mWindowManager = wm;
2065 }
2066
2067 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2068 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2069 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2070 if (pal.stack == stack) {
2071 mPendingActivityLaunches.remove(palNdx);
2072 }
2073 }
2074 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002075
2076 static boolean isDocumentLaunchesIntoExisting(int flags) {
2077 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2078 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2079 }
liulvpingcfa825f2016-09-26 20:00:15 +08002080
2081 boolean clearPendingActivityLaunchesLocked(String packageName) {
2082 boolean didSomething = false;
2083
2084 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2085 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2086 ActivityRecord r = pal.r;
2087 if (r != null && r.packageName.equals(packageName)) {
2088 mPendingActivityLaunches.remove(palNdx);
2089 didSomething = true;
2090 }
2091 }
2092 return didSomething;
2093 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002094}