blob: dff7cefae456e9a4ebcee964c9365956eeb8816c [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;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080035import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
36import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010037import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080038import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080039import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080040import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080041import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080042import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
43import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080044import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
45import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
46import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
47import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
48import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080049import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080050import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
52import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
53import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Andrii Kulian16802aa2016-11-02 12:21:33 -070054import static android.view.Display.INVALID_DISPLAY;
55
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080056import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080059import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080060import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
62import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
63import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
66import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
68import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
69import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
70import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080071import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080072import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
73import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
74import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080075import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
77import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
78import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080079import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080080import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080081import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080082
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080083import android.app.ActivityManager;
84import android.app.ActivityOptions;
85import android.app.AppGlobals;
86import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080087import android.app.IApplicationThread;
Tony Mak853304c2016-04-18 15:17:41 +010088import android.app.KeyguardManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080089import android.app.PendingIntent;
90import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070091import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080092import android.content.ComponentName;
Tony Mak853304c2016-04-18 15:17:41 +010093import android.content.Context;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.content.IIntentSender;
95import android.content.Intent;
96import android.content.IntentSender;
97import android.content.pm.ActivityInfo;
98import android.content.pm.ApplicationInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000099import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800100import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +0000101import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800102import android.content.res.Configuration;
103import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700104import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800105import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.os.Bundle;
107import android.os.IBinder;
Wei Wang98f03f92016-05-18 11:32:52 -0700108import android.os.PowerManagerInternal;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800109import android.os.RemoteException;
110import android.os.SystemClock;
111import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000112import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800113import android.service.voice.IVoiceInteractionSession;
114import android.util.EventLog;
115import android.util.Slog;
116import android.view.Display;
117
118import com.android.internal.app.HeavyWeightSwitcherActivity;
119import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800120import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800121import com.android.server.pm.EphemeralResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800122import com.android.server.wm.WindowManagerService;
123
124import java.util.ArrayList;
125
126/**
127 * Controller for interpreting how and then launching activities.
128 *
129 * This class collects all the logic for determining how an intent and flags should be turned into
130 * an activity and associated task and stack.
131 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800132class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800133 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
134 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
135 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
136 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
137 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
138
139 private final ActivityManagerService mService;
140 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000141 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800142 private WindowManagerService mWindowManager;
143
144 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
145
Wale Ogunwale01d66562015-12-29 08:19:19 -0800146 // Share state variable among methods when starting an activity.
147 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700148 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800149 private Intent mIntent;
150 private int mCallingUid;
151 private ActivityOptions mOptions;
152
153 private boolean mLaunchSingleTop;
154 private boolean mLaunchSingleInstance;
155 private boolean mLaunchSingleTask;
156 private boolean mLaunchTaskBehind;
157 private int mLaunchFlags;
158
159 private Rect mLaunchBounds;
160
161 private ActivityRecord mNotTop;
162 private boolean mDoResume;
163 private int mStartFlags;
164 private ActivityRecord mSourceRecord;
165
166 private TaskRecord mInTask;
167 private boolean mAddingToTask;
168 private TaskRecord mReuseTask;
169
170 private ActivityInfo mNewTaskInfo;
171 private Intent mNewTaskIntent;
172 private ActivityStack mSourceStack;
173 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700174 // Indicates that we moved other task and are going to put something on top soon, so
175 // we don't want to show it redundantly or accidentally change what's shown below.
176 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800177 private boolean mMovedToFront;
178 private boolean mNoAnimation;
179 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700180 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700181 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800182
183 private IVoiceInteractionSession mVoiceSession;
184 private IVoiceInteractor mVoiceInteractor;
185
186 private void reset() {
187 mStartActivity = null;
188 mIntent = null;
189 mCallingUid = -1;
190 mOptions = null;
191
192 mLaunchSingleTop = false;
193 mLaunchSingleInstance = false;
194 mLaunchSingleTask = false;
195 mLaunchTaskBehind = false;
196 mLaunchFlags = 0;
197
198 mLaunchBounds = null;
199
200 mNotTop = null;
201 mDoResume = false;
202 mStartFlags = 0;
203 mSourceRecord = null;
204
205 mInTask = null;
206 mAddingToTask = false;
207 mReuseTask = null;
208
209 mNewTaskInfo = null;
210 mNewTaskIntent = null;
211 mSourceStack = null;
212
213 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700214 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800215 mMovedToFront = false;
216 mNoAnimation = false;
217 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700218 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800219
220 mVoiceSession = null;
221 mVoiceInteractor = null;
222 }
223
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800224 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
225 mService = service;
226 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000227 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800228 }
229
230 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
231 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
232 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
233 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
234 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
235 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
236 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
237 TaskRecord inTask) {
238 int err = ActivityManager.START_SUCCESS;
239
240 ProcessRecord callerApp = null;
241 if (caller != null) {
242 callerApp = mService.getRecordForAppLocked(caller);
243 if (callerApp != null) {
244 callingPid = callerApp.pid;
245 callingUid = callerApp.info.uid;
246 } else {
247 Slog.w(TAG, "Unable to find app for caller " + caller
248 + " (pid=" + callingPid + ") when starting: "
249 + intent.toString());
250 err = ActivityManager.START_PERMISSION_DENIED;
251 }
252 }
253
254 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
255
256 if (err == ActivityManager.START_SUCCESS) {
257 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800258 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800259 }
260
261 ActivityRecord sourceRecord = null;
262 ActivityRecord resultRecord = null;
263 if (resultTo != null) {
264 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
265 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
266 "Will send result to " + resultTo + " " + sourceRecord);
267 if (sourceRecord != null) {
268 if (requestCode >= 0 && !sourceRecord.finishing) {
269 resultRecord = sourceRecord;
270 }
271 }
272 }
273
274 final int launchFlags = intent.getFlags();
275
276 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
277 // Transfer the result target from the source activity to the new
278 // one being started, including any failures.
279 if (requestCode >= 0) {
280 ActivityOptions.abort(options);
281 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
282 }
283 resultRecord = sourceRecord.resultTo;
284 if (resultRecord != null && !resultRecord.isInStackLocked()) {
285 resultRecord = null;
286 }
287 resultWho = sourceRecord.resultWho;
288 requestCode = sourceRecord.requestCode;
289 sourceRecord.resultTo = null;
290 if (resultRecord != null) {
291 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
292 }
293 if (sourceRecord.launchedFromUid == callingUid) {
294 // The new activity is being launched from the same uid as the previous
295 // activity in the flow, and asking to forward its result back to the
296 // previous. In this case the activity is serving as a trampoline between
297 // the two, so we also want to update its launchedFromPackage to be the
298 // same as the previous activity. Note that this is safe, since we know
299 // these two packages come from the same uid; the caller could just as
300 // well have supplied that same package name itself. This specifially
301 // deals with the case of an intent picker/chooser being launched in the app
302 // flow to redirect to an activity picked by the user, where we want the final
303 // activity to consider it to have been launched by the previous app activity.
304 callingPackage = sourceRecord.launchedFromPackage;
305 }
306 }
307
308 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
309 // We couldn't find a class that can handle the given Intent.
310 // That's the end of that!
311 err = ActivityManager.START_INTENT_NOT_RESOLVED;
312 }
313
314 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
315 // We couldn't find the specific class specified in the Intent.
316 // Also the end of the line.
317 err = ActivityManager.START_CLASS_NOT_FOUND;
318 }
319
320 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
321 && sourceRecord.task.voiceSession != null) {
322 // If this activity is being launched as part of a voice session, we need
323 // to ensure that it is safe to do so. If the upcoming activity will also
324 // be part of the voice session, we can only launch it if it has explicitly
325 // said it supports the VOICE category, or it is a part of the calling app.
326 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
327 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
328 try {
329 intent.addCategory(Intent.CATEGORY_VOICE);
330 if (!AppGlobals.getPackageManager().activitySupportsIntent(
331 intent.getComponent(), intent, resolvedType)) {
332 Slog.w(TAG,
333 "Activity being started in current voice task does not support voice: "
334 + intent);
335 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
336 }
337 } catch (RemoteException e) {
338 Slog.w(TAG, "Failure checking voice capabilities", e);
339 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
340 }
341 }
342 }
343
344 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
345 // If the caller is starting a new voice session, just make sure the target
346 // is actually allowing it to run this way.
347 try {
348 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
349 intent, resolvedType)) {
350 Slog.w(TAG,
351 "Activity being started in new voice task does not support: "
352 + intent);
353 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
354 }
355 } catch (RemoteException e) {
356 Slog.w(TAG, "Failure checking voice capabilities", e);
357 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
358 }
359 }
360
Andrii Kulian02b7a832016-10-06 23:11:56 -0700361 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800362
Wale Ogunwale01d66562015-12-29 08:19:19 -0800363 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800364 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800365 resultStack.sendActivityResultLocked(
366 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800367 }
368 ActivityOptions.abort(options);
369 return err;
370 }
371
372 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
373 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100374 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800375 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
376 callingPid, resolvedType, aInfo.applicationInfo);
377
378 if (mService.mController != null) {
379 try {
380 // The Intent we give to the watcher has the extra data
381 // stripped off, since it can contain private information.
382 Intent watchIntent = intent.cloneFilter();
383 abort |= !mService.mController.activityStarting(watchIntent,
384 aInfo.applicationInfo.packageName);
385 } catch (RemoteException e) {
386 mService.mController = null;
387 }
388 }
389
Rubin Xu58d25992016-01-21 17:47:13 +0000390 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100391 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
392 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000393 intent = mInterceptor.mIntent;
394 rInfo = mInterceptor.mRInfo;
395 aInfo = mInterceptor.mAInfo;
396 resolvedType = mInterceptor.mResolvedType;
397 inTask = mInterceptor.mInTask;
398 callingPid = mInterceptor.mCallingPid;
399 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100400 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800401 if (abort) {
402 if (resultRecord != null) {
403 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800404 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800405 }
406 // We pretend to the caller that it was really started, but
407 // they will just get a cancel result.
408 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800409 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800410 }
411
412 // If permissions need a review before any of the app components can run, we
413 // launch the review activity and pass a pending intent to start the activity
414 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700415 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800416 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
417 aInfo.packageName, userId)) {
418 IIntentSender target = mService.getIntentSenderLocked(
419 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
420 callingUid, userId, null, null, 0, new Intent[]{intent},
421 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
422 | PendingIntent.FLAG_ONE_SHOT, null);
423
424 final int flags = intent.getFlags();
425 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
426 newIntent.setFlags(flags
427 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
428 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
429 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
430 if (resultRecord != null) {
431 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
432 }
433 intent = newIntent;
434
435 resolvedType = null;
436 callingUid = realCallingUid;
437 callingPid = realCallingPid;
438
439 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
440 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
441 null /*profilerInfo*/);
442
443 if (DEBUG_PERMISSIONS_REVIEW) {
444 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
445 true, false) + "} from uid " + callingUid + " on display "
446 + (container == null ? (mSupervisor.mFocusedStack == null ?
447 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
448 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
449 container.mActivityDisplay.mDisplayId)));
450 }
451 }
452 }
453
454 // If we have an ephemeral app, abort the process of launching the resolved intent.
455 // Instead, launch the ephemeral installer. Once the installer is finished, it
456 // starts either the intent we resolved here [on install error] or the ephemeral
457 // app [on install success].
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800458 if (rInfo != null && rInfo.ephemeralResponse != null) {
Todd Kennedye5195dd2016-10-19 15:29:19 -0700459 final String packageName =
Todd Kennedy01ad0c72016-11-11 15:33:12 -0800460 rInfo.ephemeralResponse.resolveInfo.getPackageName();
461 final String splitName = rInfo.ephemeralResponse.splitName;
462 final boolean needsPhaseTwo = rInfo.ephemeralResponse.needsPhase2;
463 final String token = rInfo.ephemeralResponse.token;
464 if (needsPhaseTwo) {
465 // request phase two resolution
466 mService.getPackageManagerInternalLocked().requestEphemeralResolutionPhaseTwo(
467 rInfo.ephemeralResponse, ephemeralIntent, resolvedType, intent,
468 callingPackage, userId);
469 }
470 intent = EphemeralResolver.buildEphemeralInstallerIntent(intent, ephemeralIntent,
471 callingPackage, resolvedType, userId, packageName, splitName, token,
472 needsPhaseTwo);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800473 resolvedType = null;
474 callingUid = realCallingUid;
475 callingPid = realCallingPid;
476
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800477 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
478 }
479
480 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
Andrii Kulian1779e612016-10-12 21:58:25 -0700481 intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord,
482 resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor,
483 container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800484 if (outActivity != null) {
485 outActivity[0] = r;
486 }
487
488 if (r.appTimeTracker == null && sourceRecord != null) {
489 // If the caller didn't specify an explicit time tracker, we want to continue
490 // tracking under any it has.
491 r.appTimeTracker = sourceRecord.appTimeTracker;
492 }
493
494 final ActivityStack stack = mSupervisor.mFocusedStack;
495 if (voiceSession == null && (stack.mResumedActivity == null
496 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
497 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
498 realCallingPid, realCallingUid, "Activity start")) {
499 PendingActivityLaunch pal = new PendingActivityLaunch(r,
500 sourceRecord, startFlags, stack, callerApp);
501 mPendingActivityLaunches.add(pal);
502 ActivityOptions.abort(options);
503 return ActivityManager.START_SWITCHES_CANCELED;
504 }
505 }
506
507 if (mService.mDidAppSwitch) {
508 // This is the second allowed switch since we stopped switches,
509 // so now just generally allow switches. Use case: user presses
510 // home (switches disabled, switch to home, mDidAppSwitch now true);
511 // user taps a home icon (coming from home so allowed, we hit here
512 // and now allow anyone to switch again).
513 mService.mAppSwitchesAllowedTime = 0;
514 } else {
515 mService.mDidAppSwitch = true;
516 }
517
518 doPendingActivityLaunchesLocked(false);
519
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700520 try {
521 mService.mWindowManager.deferSurfaceLayout();
522 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
523 true, options, inTask);
524 } finally {
525 mService.mWindowManager.continueSurfaceLayout();
526 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700527 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800528 return err;
529 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800530
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800531 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700532 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
533 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800534
535 if (result < START_SUCCESS) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800536 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800537 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800538
Chong Zhang5022da32016-06-21 16:31:37 -0700539 // We're waiting for an activity launch to finish, but that activity simply
540 // brought another activity to front. Let startActivityMayWait() know about
541 // this, so it waits for the new activity to become visible instead.
542 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
543 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
544 }
545
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800546 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700547 final ActivityStack currentStack = r.getStack();
548 if (currentStack != null) {
549 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800550 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700551 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800552 }
553
Jorim Jaggi352d5842016-05-19 10:20:28 -0700554 // If we launched the activity from a no display activity that was launched from the home
555 // screen, we also need to start recents to un-minimize the docked stack, since the
556 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700557 // Note that some apps have trampoline activities without noDisplay being set. In that case,
558 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
559 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700560 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
561 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700562 final boolean noDisplayActivityOverHome = sourceRecord != null
563 && sourceRecord.noDisplay
564 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700565 if (startedActivityStackId == DOCKED_STACK_ID
566 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100567 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
568 final ActivityRecord topActivityHomeStack = homeStack != null
569 ? homeStack.topRunningActivityLocked() : null;
570 if (topActivityHomeStack == null
571 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
572 // We launch an activity while being in home stack, which means either launcher or
573 // recents into docked stack. We don't want the launched activity to be alone in a
574 // docked stack, so we want to immediately launch recents too.
575 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700576 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100577 return;
578 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800579 }
580
581 if (startedActivityStackId == PINNED_STACK_ID
582 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
583 // The activity was already running in the pinned stack so it wasn't started, but either
584 // brought to the front or the new intent was delivered to it since it was already in
585 // front. Notify anyone interested in this piece of information.
Yorke Leebd54c2a2016-10-25 13:49:23 -0700586 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800587 return;
588 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800589 }
590
591 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
592 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
593 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
594 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
595 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
596 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
597 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700598 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800599 null /*container*/, null /*inTask*/);
600 if (mSupervisor.inResumeTopActivity) {
601 // If we are in resume section already, home activity will be initialized, but not
602 // resumed (to avoid recursive resume) and will stay that way until something pokes it
603 // again. We need to schedule another resume.
604 mSupervisor.scheduleResumeTopActivities();
605 }
606 }
607
Tony Mak853304c2016-04-18 15:17:41 +0100608 void showConfirmDeviceCredential(int userId) {
609 // First, retrieve the stack that we want to resume after credential is confirmed.
610 ActivityStack targetStack;
611 ActivityStack fullscreenStack =
612 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
613 if (fullscreenStack != null &&
614 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
615 // Single window case and the case that the docked stack is shown with fullscreen stack.
616 targetStack = fullscreenStack;
617 } else {
618 // The case that the docked stack is shown with recent.
619 targetStack = mSupervisor.getStack(HOME_STACK_ID);
620 }
621 if (targetStack == null) {
622 return;
623 }
624 final KeyguardManager km = (KeyguardManager) mService.mContext
625 .getSystemService(Context.KEYGUARD_SERVICE);
626 final Intent credential =
627 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100628 // For safety, check null here in case users changed the setting after the checking.
629 if (credential == null) {
630 return;
631 }
Tony Mak853304c2016-04-18 15:17:41 +0100632 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
633 if (activityRecord != null) {
634 final IIntentSender target = mService.getIntentSenderLocked(
635 ActivityManager.INTENT_SENDER_ACTIVITY,
636 activityRecord.launchedFromPackage,
637 activityRecord.launchedFromUid,
638 activityRecord.userId,
639 null, null, 0,
640 new Intent[] { activityRecord.intent },
641 new String[] { activityRecord.resolvedType },
642 PendingIntent.FLAG_CANCEL_CURRENT |
643 PendingIntent.FLAG_ONE_SHOT |
644 PendingIntent.FLAG_IMMUTABLE,
645 null);
646 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
647 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100648 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100649 }
650 }
651
Tony Mak646fe992016-04-21 16:43:08 +0100652 void startConfirmCredentialIntent(Intent intent) {
653 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
654 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
655 FLAG_ACTIVITY_TASK_ON_HOME);
656 final ActivityOptions options = ActivityOptions.makeBasic();
657 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
658 mService.mContext.startActivityAsUser(intent, options.toBundle(),
659 UserHandle.CURRENT);
660 }
Tony Mak853304c2016-04-18 15:17:41 +0100661
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800662 final int startActivityMayWait(IApplicationThread caller, int callingUid,
663 String callingPackage, Intent intent, String resolvedType,
664 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
665 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700666 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700667 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800668 IActivityContainer iContainer, TaskRecord inTask) {
669 // Refuse possible leaked file descriptors
670 if (intent != null && intent.hasFileDescriptors()) {
671 throw new IllegalArgumentException("File descriptors passed in Intent");
672 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500673 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800674 boolean componentSpecified = intent.getComponent() != null;
675
676 // Save a copy in case ephemeral needs it
677 final Intent ephemeralIntent = new Intent(intent);
678 // Don't modify the client's object!
679 intent = new Intent(intent);
680
681 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000682 if (rInfo == null) {
683 UserInfo userInfo = mSupervisor.getUserInfo(userId);
684 if (userInfo != null && userInfo.isManagedProfile()) {
685 // Special case for managed profiles, if attempting to launch non-cryto aware
686 // app in a locked managed profile from an unlocked parent allow it to resolve
687 // as user will be sent via confirm credentials to unlock the profile.
688 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700689 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000690 long token = Binder.clearCallingIdentity();
691 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700692 UserInfo parent = userManager.getProfileParent(userId);
693 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
694 && userManager.isUserUnlockingOrUnlocked(parent.id)
695 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000696 } finally {
697 Binder.restoreCallingIdentity(token);
698 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700699 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000700 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600701 PackageManager.MATCH_DIRECT_BOOT_AWARE
702 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000703 }
704 }
705 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800706 // Collect information about the target of the Intent.
707 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
708
709 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
710 ActivityStackSupervisor.ActivityContainer container =
711 (ActivityStackSupervisor.ActivityContainer)iContainer;
712 synchronized (mService) {
713 if (container != null && container.mParentActivity != null &&
714 container.mParentActivity.state != RESUMED) {
715 // Cannot start a child activity if the parent is not resumed.
716 return ActivityManager.START_CANCELED;
717 }
718 final int realCallingPid = Binder.getCallingPid();
719 final int realCallingUid = Binder.getCallingUid();
720 int callingPid;
721 if (callingUid >= 0) {
722 callingPid = -1;
723 } else if (caller == null) {
724 callingPid = realCallingPid;
725 callingUid = realCallingUid;
726 } else {
727 callingPid = callingUid = -1;
728 }
729
730 final ActivityStack stack;
731 if (container == null || container.mStack.isOnHomeDisplay()) {
732 stack = mSupervisor.mFocusedStack;
733 } else {
734 stack = container.mStack;
735 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700736 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700737 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800738 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
739 "Starting activity when config will change = " + stack.mConfigWillChange);
740
741 final long origId = Binder.clearCallingIdentity();
742
743 if (aInfo != null &&
744 (aInfo.applicationInfo.privateFlags
745 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
746 // This may be a heavy-weight process! Check to see if we already
747 // have another, different heavy-weight process running.
748 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
749 final ProcessRecord heavy = mService.mHeavyWeightProcess;
750 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
751 || !heavy.processName.equals(aInfo.processName))) {
752 int appCallingUid = callingUid;
753 if (caller != null) {
754 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
755 if (callerApp != null) {
756 appCallingUid = callerApp.info.uid;
757 } else {
758 Slog.w(TAG, "Unable to find app for caller " + caller
759 + " (pid=" + callingPid + ") when starting: "
760 + intent.toString());
761 ActivityOptions.abort(options);
762 return ActivityManager.START_PERMISSION_DENIED;
763 }
764 }
765
766 IIntentSender target = mService.getIntentSenderLocked(
767 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
768 appCallingUid, userId, null, null, 0, new Intent[] { intent },
769 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
770 | PendingIntent.FLAG_ONE_SHOT, null);
771
772 Intent newIntent = new Intent();
773 if (requestCode >= 0) {
774 // Caller is requesting a result.
775 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
776 }
777 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
778 new IntentSender(target));
779 if (heavy.activities.size() > 0) {
780 ActivityRecord hist = heavy.activities.get(0);
781 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
782 hist.packageName);
783 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
784 hist.task.taskId);
785 }
786 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
787 aInfo.packageName);
788 newIntent.setFlags(intent.getFlags());
789 newIntent.setClassName("android",
790 HeavyWeightSwitcherActivity.class.getName());
791 intent = newIntent;
792 resolvedType = null;
793 caller = null;
794 callingUid = Binder.getCallingUid();
795 callingPid = Binder.getCallingPid();
796 componentSpecified = true;
797 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
798 aInfo = rInfo != null ? rInfo.activityInfo : null;
799 if (aInfo != null) {
800 aInfo = mService.getActivityInfoForUser(aInfo, userId);
801 }
802 }
803 }
804 }
805
Jorim Jaggi275561a2016-02-23 10:11:02 -0500806 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800807 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
808 aInfo, rInfo, voiceSession, voiceInteractor,
809 resultTo, resultWho, requestCode, callingPid,
810 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500811 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
812 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800813
814 Binder.restoreCallingIdentity(origId);
815
816 if (stack.mConfigWillChange) {
817 // If the caller also wants to switch to a new configuration,
818 // do so now. This allows a clean switch, as we are waiting
819 // for the current activity to pause (so we will not destroy
820 // it), and have not yet started the next activity.
821 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
822 "updateConfiguration()");
823 stack.mConfigWillChange = false;
824 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
825 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700826 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800827 }
828
829 if (outResult != null) {
830 outResult.result = res;
831 if (res == ActivityManager.START_SUCCESS) {
832 mSupervisor.mWaitingActivityLaunched.add(outResult);
833 do {
834 try {
835 mService.wait();
836 } catch (InterruptedException e) {
837 }
Chong Zhang5022da32016-06-21 16:31:37 -0700838 } while (outResult.result != START_TASK_TO_FRONT
839 && !outResult.timeout && outResult.who == null);
840 if (outResult.result == START_TASK_TO_FRONT) {
841 res = START_TASK_TO_FRONT;
842 }
843 }
844 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800845 ActivityRecord r = stack.topRunningActivityLocked();
846 if (r.nowVisible && r.state == RESUMED) {
847 outResult.timeout = false;
848 outResult.who = new ComponentName(r.info.packageName, r.info.name);
849 outResult.totalTime = 0;
850 outResult.thisTime = 0;
851 } else {
852 outResult.thisTime = SystemClock.uptimeMillis();
853 mSupervisor.mWaitingActivityVisible.add(outResult);
854 do {
855 try {
856 mService.wait();
857 } catch (InterruptedException e) {
858 }
859 } while (!outResult.timeout && outResult.who == null);
860 }
861 }
862 }
863
Jorim Jaggibe67c902016-04-12 00:53:16 -0700864 final ActivityRecord launchedActivity = mReusedActivity != null
865 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700866 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800867 return res;
868 }
869 }
870
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800871 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
872 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
873 Bundle bOptions, int userId) {
874 if (intents == null) {
875 throw new NullPointerException("intents is null");
876 }
877 if (resolvedTypes == null) {
878 throw new NullPointerException("resolvedTypes is null");
879 }
880 if (intents.length != resolvedTypes.length) {
881 throw new IllegalArgumentException("intents are length different than resolvedTypes");
882 }
883
Makoto Onukid67b1872016-07-21 16:26:36 -0700884 final int realCallingPid = Binder.getCallingPid();
885 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800886
887 int callingPid;
888 if (callingUid >= 0) {
889 callingPid = -1;
890 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700891 callingPid = realCallingPid;
892 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800893 } else {
894 callingPid = callingUid = -1;
895 }
896 final long origId = Binder.clearCallingIdentity();
897 try {
898 synchronized (mService) {
899 ActivityRecord[] outActivity = new ActivityRecord[1];
900 for (int i=0; i<intents.length; i++) {
901 Intent intent = intents[i];
902 if (intent == null) {
903 continue;
904 }
905
906 // Refuse possible leaked file descriptors
907 if (intent != null && intent.hasFileDescriptors()) {
908 throw new IllegalArgumentException("File descriptors passed in Intent");
909 }
910
911 boolean componentSpecified = intent.getComponent() != null;
912
913 // Don't modify the client's object!
914 intent = new Intent(intent);
915
916 // Collect information about the target of the Intent.
917 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
918 null, userId);
919 // TODO: New, check if this is correct
920 aInfo = mService.getActivityInfoForUser(aInfo, userId);
921
922 if (aInfo != null &&
923 (aInfo.applicationInfo.privateFlags
924 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
925 throw new IllegalArgumentException(
926 "FLAG_CANT_SAVE_STATE not supported here");
927 }
928
929 ActivityOptions options = ActivityOptions.fromBundle(
930 i == intents.length - 1 ? bOptions : null);
931 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
932 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700933 callingPid, callingUid, callingPackage,
934 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800935 options, false, componentSpecified, outActivity, null, null);
936 if (res < 0) {
937 return res;
938 }
939
940 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
941 }
942 }
943 } finally {
944 Binder.restoreCallingIdentity(origId);
945 }
946
Wale Ogunwale01d66562015-12-29 08:19:19 -0800947 return START_SUCCESS;
948 }
949
Wei Wang65c7a152016-06-02 18:51:22 -0700950 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
951 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -0700952 final ActivityStack focusStack = mSupervisor.getFocusedStack();
953 final ActivityRecord curTop = (focusStack == null)
954 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
955 if ((forceSend || (!mPowerHintSent && curTop != null &&
956 curTop.task != null && mStartActivity != null &&
957 curTop.task != mStartActivity.task )) &&
958 mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700959 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700960 mPowerHintSent = true;
961 }
962 }
963
Wei Wang65c7a152016-06-02 18:51:22 -0700964 void sendPowerHintForLaunchEndIfNeeded() {
965 // Trigger launch power hint if activity is launched
966 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700967 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -0700968 mPowerHintSent = false;
969 }
970 }
971
Wale Ogunwale01d66562015-12-29 08:19:19 -0800972 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
973 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
974 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
975
976 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
977 voiceInteractor);
978
979 computeLaunchingTaskFlags();
980
981 computeSourceStack();
982
983 mIntent.setFlags(mLaunchFlags);
984
Jorim Jaggibe67c902016-04-12 00:53:16 -0700985 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800986
Jorim Jaggi2adba072016-03-03 13:43:39 +0100987 final int preferredLaunchStackId =
988 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
989
Jorim Jaggibe67c902016-04-12 00:53:16 -0700990 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800991 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
992 // still needs to be a lock task mode violation since the task gets cleared out and
993 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700994 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800995 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
996 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
997 mSupervisor.showLockTaskToast();
998 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
999 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1000 }
1001
1002 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001003 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001004 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001005 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001006 // This task was started because of movement of the activity based on affinity...
1007 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001008 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001009 }
1010
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001011 // This code path leads to delivering a new intent, we want to make sure we schedule it
1012 // as the first operation, in case the activity will be resumed as a result of later
1013 // operations.
1014 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001015 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001016 || mLaunchSingleInstance || mLaunchSingleTask) {
1017 // In this situation we want to remove all activities from the task up to the one
1018 // being started. In most cases this means we are resetting the task to its initial
1019 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001020 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001021 mStartActivity, mLaunchFlags);
1022 if (top != null) {
1023 if (top.frontOfTask) {
1024 // Activity aliases may mean we use different intents for the top activity,
1025 // so make sure the task now has the identity of the new intent.
1026 top.task.setIntent(mStartActivity);
1027 }
1028 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1029 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1030 mStartActivity.launchedFromPackage);
1031 }
1032 }
1033
Wei Wang65c7a152016-06-02 18:51:22 -07001034 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001035
Jorim Jaggibe67c902016-04-12 00:53:16 -07001036 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001037
1038 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1039 // We don't need to start a new activity, and the client said not to do anything
1040 // if that is the case, so this is it! And for paranoia, make sure we have
1041 // correctly resumed the top activity.
1042 resumeTargetStackIfNeeded();
1043 return START_RETURN_INTENT_TO_CALLER;
1044 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001045 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001046
1047 if (!mAddingToTask && mReuseTask == null) {
1048 // We didn't do anything... but it was needed (a.k.a., client don't use that
1049 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1050 resumeTargetStackIfNeeded();
1051 return START_TASK_TO_FRONT;
1052 }
1053 }
1054
1055 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001056 final ActivityStack sourceStack = mStartActivity.resultTo != null
1057 ? mStartActivity.resultTo.getStack() : null;
1058 if (sourceStack != null) {
1059 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1060 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1061 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001062 }
1063 ActivityOptions.abort(mOptions);
1064 return START_CLASS_NOT_FOUND;
1065 }
1066
1067 // If the activity being launched is the same as the one currently at the top, then
1068 // we need to check if it should only be launched once.
1069 final ActivityStack topStack = mSupervisor.mFocusedStack;
1070 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1071 final boolean dontStart = top != null && mStartActivity.resultTo == null
1072 && top.realActivity.equals(mStartActivity.realActivity)
1073 && top.userId == mStartActivity.userId
1074 && top.app != null && top.app.thread != null
1075 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1076 || mLaunchSingleTop || mLaunchSingleTask);
1077 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001078 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001079 // For paranoia, make sure we have correctly resumed the top activity.
1080 topStack.mLastPausedActivity = null;
1081 if (mDoResume) {
1082 mSupervisor.resumeFocusedStackTopActivityLocked();
1083 }
1084 ActivityOptions.abort(mOptions);
1085 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1086 // We don't need to start a new activity, and the client said not to do
1087 // anything if that is the case, so this is it!
1088 return START_RETURN_INTENT_TO_CALLER;
1089 }
1090 top.deliverNewIntentLocked(
1091 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001092
1093 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1094 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1095 mSupervisor.handleNonResizableTaskIfNeeded(
1096 top.task, preferredLaunchStackId, topStack.mStackId);
1097
Wale Ogunwale01d66562015-12-29 08:19:19 -08001098 return START_DELIVERED_TO_TOP;
1099 }
1100
1101 boolean newTask = false;
1102 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1103 ? mSourceRecord.task : null;
1104
1105 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001106 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001107 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1108 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1109 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001110 result = setTaskFromReuseOrCreateNewTask(
1111 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001112 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001113 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001114 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001115 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001116 } else {
1117 // This not being started from an existing activity, and not part of a new task...
1118 // just put it in the top task, though these days this case should never happen.
1119 setTaskToCurrentTopOrCreateNewTask();
1120 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001121 if (result != START_SUCCESS) {
1122 return result;
1123 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001124
1125 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1126 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1127
1128 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1129 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1130 }
1131 if (newTask) {
1132 EventLog.writeEvent(
1133 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1134 }
1135 ActivityStack.logStartActivity(
1136 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1137 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001138
Wei Wang65c7a152016-06-02 18:51:22 -07001139 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001140
Wale Ogunwale01d66562015-12-29 08:19:19 -08001141 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1142 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001143 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1144 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001145 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1146 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001147 // If the activity is not focusable, we can't resume it, but still would like to
1148 // make sure it becomes visible as it starts (this will also trigger entry
1149 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001150 // Also, we don't want to resume activities in a task that currently has an overlay
1151 // as the starting activity just needs to be in the visible paused state until the
1152 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001153 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001154 // Go ahead and tell window manager to execute app transition for this activity
1155 // since the app transition will not be triggered through the resume channel.
1156 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001157 } else {
Winson Chung32066032016-11-04 11:55:21 -07001158 // If the target stack was not previously focusable (previous top running activity
1159 // on that stack was not visible) then any prior calls to move the stack to the
1160 // will not update the focused stack. If starting the new activity now allows the
1161 // task stack to be focusable, then ensure that we now update the focused stack
1162 // accordingly.
1163 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1164 mTargetStack.moveToFront("startActivityUnchecked");
1165 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001166 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1167 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001168 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001169 } else {
1170 mTargetStack.addRecentActivityLocked(mStartActivity);
1171 }
1172 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1173
Jorim Jaggid53f0922016-04-06 22:16:23 -07001174 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001175 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001176
1177 return START_SUCCESS;
1178 }
1179
1180 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1181 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1182 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1183 reset();
1184
1185 mStartActivity = r;
1186 mIntent = r.intent;
1187 mOptions = options;
1188 mCallingUid = r.launchedFromUid;
1189 mSourceRecord = sourceRecord;
1190 mVoiceSession = voiceSession;
1191 mVoiceInteractor = voiceInteractor;
1192
1193 mLaunchBounds = getOverrideBounds(r, options, inTask);
1194
1195 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1196 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1197 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1198 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1199 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1200 mLaunchTaskBehind = r.mLaunchTaskBehind
1201 && !mLaunchSingleTask && !mLaunchSingleInstance
1202 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1203
1204 sendNewTaskResultRequestIfNeeded();
1205
1206 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1207 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1208 }
1209
1210 // If we are actually going to launch in to a new task, there are some cases where
1211 // we further want to do multiple task.
1212 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1213 if (mLaunchTaskBehind
1214 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1215 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1216 }
1217 }
1218
1219 // We'll invoke onUserLeaving before onPause only if the launching
1220 // activity did not explicitly state that this is an automated launch.
1221 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1222 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1223 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1224
1225 // If the caller has asked not to resume at this point, we make note
1226 // of this in the record so that we can skip it when trying to find
1227 // the top running activity.
1228 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001229 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001230 r.delayedResume = true;
1231 mDoResume = false;
1232 }
1233
Wale Ogunwale3b232392016-05-13 15:37:13 -07001234 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1235 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001236 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1237 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1238 if (top != null && !top.visible) {
1239
1240 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1241 // it!
1242 mDoResume = false;
1243 mAvoidMoveToFront = true;
1244 }
1245 }
1246
Wale Ogunwale01d66562015-12-29 08:19:19 -08001247 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1248
1249 mInTask = inTask;
1250 // In some flows in to this function, we retrieve the task record and hold on to it
1251 // without a lock before calling back in to here... so the task at this point may
1252 // not actually be in recents. Check for that, and if it isn't in recents just
1253 // consider it invalid.
1254 if (inTask != null && !inTask.inRecents) {
1255 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1256 mInTask = null;
1257 }
1258
1259 mStartFlags = startFlags;
1260 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1261 // is the same as the one making the call... or, as a special case, if we do not know
1262 // the caller then we count the current top activity as the caller.
1263 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1264 ActivityRecord checkedCaller = sourceRecord;
1265 if (checkedCaller == null) {
1266 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1267 mNotTop);
1268 }
1269 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1270 // Caller is not the same as launcher, so always needed.
1271 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1272 }
1273 }
1274
1275 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1276 }
1277
1278 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001279 final ActivityStack sourceStack = mStartActivity.resultTo != null
1280 ? mStartActivity.resultTo.getStack() : null;
1281 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001282 // For whatever reason this activity is being launched into a new task...
1283 // yet the caller has requested a result back. Well, that is pretty messed up,
1284 // so instead immediately send back a cancel and let the new task continue launched
1285 // as normal without a dependency on its originator.
1286 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001287 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1288 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1289 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001290 mStartActivity.resultTo = null;
1291 }
1292 }
1293
1294 private void computeLaunchingTaskFlags() {
1295 // If the caller is not coming from another activity, but has given us an explicit task into
1296 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001297 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001298 final Intent baseIntent = mInTask.getBaseIntent();
1299 final ActivityRecord root = mInTask.getRootActivity();
1300 if (baseIntent == null) {
1301 ActivityOptions.abort(mOptions);
1302 throw new IllegalArgumentException("Launching into task without base intent: "
1303 + mInTask);
1304 }
1305
1306 // If this task is empty, then we are adding the first activity -- it
1307 // determines the root, and must be launching as a NEW_TASK.
1308 if (mLaunchSingleInstance || mLaunchSingleTask) {
1309 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1310 ActivityOptions.abort(mOptions);
1311 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1312 + mStartActivity + " into different task " + mInTask);
1313 }
1314 if (root != null) {
1315 ActivityOptions.abort(mOptions);
1316 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1317 + " has root " + root + " but target is singleInstance/Task");
1318 }
1319 }
1320
1321 // If task is empty, then adopt the interesting intent launch flags in to the
1322 // activity being started.
1323 if (root == null) {
1324 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1325 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1326 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1327 | (baseIntent.getFlags() & flagsOfInterest);
1328 mIntent.setFlags(mLaunchFlags);
1329 mInTask.setIntent(mStartActivity);
1330 mAddingToTask = true;
1331
1332 // If the task is not empty and the caller is asking to start it as the root of
1333 // a new task, then we don't actually want to start this on the task. We will
1334 // bring the task to the front, and possibly give it a new intent.
1335 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1336 mAddingToTask = false;
1337
1338 } else {
1339 mAddingToTask = true;
1340 }
1341
1342 mReuseTask = mInTask;
1343 } else {
1344 mInTask = null;
1345 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1346 // when in freeform workspace.
1347 // Also put noDisplay activities in the source task. These by itself can be placed
1348 // in any task/stack, however it could launch other activities like ResolverActivity,
1349 // and we want those to stay in the original task.
1350 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1351 && mSourceRecord.isFreeform()) {
1352 mAddingToTask = true;
1353 }
1354 }
1355
1356 if (mInTask == null) {
1357 if (mSourceRecord == null) {
1358 // This activity is not being started from another... in this
1359 // case we -always- start a new task.
1360 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1361 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1362 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1363 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1364 }
1365 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1366 // The original activity who is starting us is running as a single
1367 // instance... this new activity it is starting must go on its
1368 // own task.
1369 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1370 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1371 // The activity being started is a single instance... it always
1372 // gets launched into its own task.
1373 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1374 }
1375 }
1376 }
1377
1378 private void computeSourceStack() {
1379 if (mSourceRecord == null) {
1380 mSourceStack = null;
1381 return;
1382 }
1383 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001384 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001385 return;
1386 }
1387
1388 // If the source is finishing, we can't further count it as our source. This is because the
1389 // task it is associated with may now be empty and on its way out, so we don't want to
1390 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1391 // a task for it. But save the task information so it can be used when creating the new task.
1392 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1393 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1394 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1395 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1396 mNewTaskInfo = mSourceRecord.info;
1397 mNewTaskIntent = mSourceRecord.task.intent;
1398 }
1399 mSourceRecord = null;
1400 mSourceStack = null;
1401 }
1402
1403 /**
1404 * Decide whether the new activity should be inserted into an existing task. Returns null
1405 * if not or an ActivityRecord with the task into which the new activity should be added.
1406 */
1407 private ActivityRecord getReusableIntentActivity() {
1408 // We may want to try to place the new activity in to an existing task. We always
1409 // do this if the target activity is singleTask or singleInstance; we will also do
1410 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1411 // us to still place it in a new task: multi task, always doc mode, or being asked to
1412 // launch this as a new task behind the current one.
1413 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1414 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1415 || mLaunchSingleInstance || mLaunchSingleTask;
1416 // If bring to front is requested, and no result is requested and we have not been given
1417 // an explicit task to launch in to, and we can find a task that was started with this
1418 // same component, then instead of launching bring that one to the front.
1419 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1420 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001421 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1422 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1423 intentActivity = task != null ? task.getTopActivity() : null;
1424 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001425 if (mLaunchSingleInstance) {
1426 // There can be one and only one instance of single instance activity in the
1427 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001428 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001429 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1430 // For the launch adjacent case we only want to put the activity in an existing
1431 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001432 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1433 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001434 } else {
1435 // Otherwise find the best task to put the activity in.
1436 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1437 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001438 }
1439 return intentActivity;
1440 }
1441
1442 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001443 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001444 mTargetStack.mLastPausedActivity = null;
1445 // If the target task is not in the front, then we need to bring it to the front...
1446 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1447 // the same behavior as if a new instance was being started, which means not bringing it
1448 // to the front if the caller is not itself in the front.
1449 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1450 ActivityRecord curTop = (focusStack == null)
1451 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1452
Jorim Jaggic875ae72016-04-26 22:41:06 -07001453 if (curTop != null
1454 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1455 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001456 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1457 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1458 mSourceStack.topActivity().task == mSourceRecord.task)) {
1459 // We really do want to push this one into the user's face, right now.
1460 if (mLaunchTaskBehind && mSourceRecord != null) {
1461 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1462 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001463 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001464
1465 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1466 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1467 // So no point resuming any of the activities here, it just wastes one extra
1468 // resuming, plus enter AND exit transitions.
1469 // Here we only want to bring the target stack forward. Transition will be applied
1470 // to the new activity that's started after the old ones are gone.
1471 final boolean willClearTask =
1472 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1473 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1474 if (!willClearTask) {
1475 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001476 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001477 if (launchStack == null || launchStack == mTargetStack) {
1478 // We only want to move to the front, if we aren't going to launch on a
1479 // different stack. If we launch on a different stack, we will put the
1480 // task on top there.
1481 mTargetStack.moveTaskToFrontLocked(
1482 intentActivity.task, mNoAnimation, mOptions,
1483 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1484 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001485 } else if (launchStack.mStackId == DOCKED_STACK_ID
1486 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1487 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1488 // If we want to launch adjacent and mTargetStack is not the computed
1489 // launch stack - move task to top of computed stack.
1490 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1491 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1492 ANIMATE);
1493 } else {
1494 // TODO: This should be reevaluated in MW v2.
1495 // We choose to move task to front instead of launching it adjacent
1496 // when specific stack was requested explicitly and it appeared to be
1497 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1498 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1499 mOptions, mStartActivity.appTimeTracker,
1500 "bringToFrontInsteadOfAdjacentLaunch");
1501 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001502 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001503 }
1504 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001505 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001506 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001507 }
1508 }
1509 if (!mMovedToFront && mDoResume) {
1510 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1511 + " from " + intentActivity);
1512 mTargetStack.moveToFront("intentActivityFound");
1513 }
1514
Jorim Jaggid53f0922016-04-06 22:16:23 -07001515 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1516 mTargetStack.mStackId);
1517
Wale Ogunwale01d66562015-12-29 08:19:19 -08001518 // If the caller has requested that the target task be reset, then do so.
1519 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1520 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1521 }
1522 return intentActivity;
1523 }
1524
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001525 private void updateTaskReturnToType(
1526 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Wale Ogunwalecdc0ddc2016-11-17 10:34:58 -08001527 if (focusedStack != null && focusedStack.isHomeStack() && focusedStack.topTask() != null
1528 && focusedStack.topTask().isOnTopLauncher()) {
Jiaquan Hee13e9642016-06-15 15:16:13 -07001529 // Since an on-top launcher will is moved to back when tasks are launched from it,
1530 // those tasks should first try to return to a non-home activity.
1531 // This also makes sure that non-home activities are visible under a transparent
1532 // non-home activity.
1533 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1534 return;
1535 } else if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001536 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1537 // Caller wants to appear on home activity.
1538 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1539 return;
1540 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1541 // Task will be launched over the home stack, so return home.
1542 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1543 return;
1544 }
1545
1546 // Else we are coming from an application stack so return to an application.
1547 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1548 }
1549
Wale Ogunwale01d66562015-12-29 08:19:19 -08001550 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1551 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1552 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1553 // The caller has requested to completely replace any existing task with its new
1554 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001555 intentActivity.task.performClearTaskLocked();
1556 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001557 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001558 // When we clear the task - focus will be adjusted, which will bring another task
1559 // to top before we launch the activity we need. This will temporary swap their
1560 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1561 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001562 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1563 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001564 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1565 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001566 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001567 // A special case: we need to start the activity because it is not currently
1568 // running, and the caller has asked to clear the current task to have this
1569 // activity at the top.
1570 mAddingToTask = true;
1571 // Now pretend like this activity is being started by the top of its task, so it
1572 // is put in the right place.
1573 mSourceRecord = intentActivity;
1574 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001575 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001576 // Target stack got cleared when we all activities were removed above.
1577 // Go ahead and reset it.
1578 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1579 null /* bounds */, mLaunchFlags, mOptions);
1580 mTargetStack.addTask(task,
1581 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1582 }
1583 }
1584 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1585 // In this case the top activity on the task is the same as the one being launched,
1586 // so we take that as a request to bring the task to the foreground. If the top
1587 // activity in the task is the root activity, deliver this new intent to it if it
1588 // desires.
1589 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1590 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001591 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001592 intentActivity.task);
1593 if (intentActivity.frontOfTask) {
1594 intentActivity.task.setIntent(mStartActivity);
1595 }
1596 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1597 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001598 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001599 // In this case we are launching the root activity of the task, but with a
1600 // different intent. We should start a new instance on top.
1601 mAddingToTask = true;
1602 mSourceRecord = intentActivity;
1603 }
1604 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1605 // In this case an activity is being launched in to an existing task, without
1606 // resetting that task. This is typically the situation of launching an activity
1607 // from a notification or shortcut. We want to place the new activity on top of the
1608 // current task.
1609 mAddingToTask = true;
1610 mSourceRecord = intentActivity;
1611 } else if (!intentActivity.task.rootWasReset) {
1612 // In this case we are launching into an existing task that has not yet been started
1613 // from its front door. The current task has been brought to the front. Ideally,
1614 // we'd probably like to place this new task at the bottom of its stack, but that's
1615 // a little hard to do with the current organization of the code so for now we'll
1616 // just drop it.
1617 intentActivity.task.setIntent(mStartActivity);
1618 }
1619 }
1620
1621 private void resumeTargetStackIfNeeded() {
1622 if (mDoResume) {
1623 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001624 } else {
1625 ActivityOptions.abort(mOptions);
1626 }
1627 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1628 }
1629
Chong Zhang6cda19c2016-06-14 19:07:56 -07001630 private int setTaskFromReuseOrCreateNewTask(
1631 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1632 mTargetStack = computeStackFocus(
1633 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1634
1635 // Do no move the target stack to front yet, as we might bail if
1636 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001637
1638 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001639 final TaskRecord task = mTargetStack.createTaskRecord(
1640 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001641 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1642 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1643 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1644 mStartActivity.setTask(task, taskToAffiliate);
1645 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001646 final int stackId = mTargetStack.mStackId;
1647 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001648 mService.resizeStack(
1649 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001650 } else {
1651 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1652 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001653 }
1654 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1655 "Starting new activity " +
1656 mStartActivity + " in new task " + mStartActivity.task);
1657 } else {
1658 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1659 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001660
1661 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1662 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1663 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1664 }
1665
1666 if (!mMovedOtherTask) {
1667 // If stack id is specified in activity options, usually it means that activity is
1668 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1669 // that case we check the target stack.
1670 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1671 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1672 }
1673 if (mDoResume) {
1674 mTargetStack.moveToFront("reuseOrNewTask");
1675 }
1676 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001677 }
1678
1679 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001680 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1681 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1682 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1683 }
1684
Wale Ogunwale01d66562015-12-29 08:19:19 -08001685 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001686 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001687 // We only want to allow changing stack if the target task is not the top one,
1688 // otherwise we would move the launching task to the other side, rather than show
1689 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001690 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001691 if (moveStackAllowed) {
1692 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1693 mOptions);
1694 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001695
1696 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001697 mTargetStack = sourceStack;
1698 } else if (mTargetStack != sourceStack) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001699 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1700 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1701 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001702
Wale Ogunwale01d66562015-12-29 08:19:19 -08001703 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001704 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001705 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1706 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001707 } else if (mDoResume) {
1708 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001709 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001710
Wale Ogunwale01d66562015-12-29 08:19:19 -08001711 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1712 // In this case, we are adding the activity to an existing task, but the caller has
1713 // asked to clear that task if the activity is already running.
1714 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1715 mKeepCurTransition = true;
1716 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001717 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001718 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1719 // For paranoia, make sure we have correctly resumed the top activity.
1720 mTargetStack.mLastPausedActivity = null;
1721 if (mDoResume) {
1722 mSupervisor.resumeFocusedStackTopActivityLocked();
1723 }
1724 ActivityOptions.abort(mOptions);
1725 return START_DELIVERED_TO_TOP;
1726 }
1727 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1728 // In this case, we are launching an activity in our own task that may already be
1729 // running somewhere in the history, and we want to shuffle it to the front of the
1730 // stack if so.
1731 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1732 if (top != null) {
1733 final TaskRecord task = top.task;
1734 task.moveActivityToFrontLocked(top);
1735 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001736 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001737 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1738 mTargetStack.mLastPausedActivity = null;
1739 if (mDoResume) {
1740 mSupervisor.resumeFocusedStackTopActivityLocked();
1741 }
1742 return START_DELIVERED_TO_TOP;
1743 }
1744 }
1745
1746 // An existing activity is starting this new activity, so we want to keep the new one in
1747 // the same task as the one that is starting it.
1748 mStartActivity.setTask(sourceTask, null);
1749 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1750 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1751 return START_SUCCESS;
1752 }
1753
1754 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001755 // The caller is asking that the new activity be started in an explicit
1756 // task it has provided to us.
1757 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1758 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1759 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1760 }
1761
Wale Ogunwale01d66562015-12-29 08:19:19 -08001762 if (mLaunchBounds != null) {
1763 mInTask.updateOverrideConfiguration(mLaunchBounds);
1764 int stackId = mInTask.getLaunchStackId();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001765 if (stackId != mInTask.getStackId()) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001766 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001767 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001768 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001769 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001770 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001771 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001772 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001773 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001774 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001775 mTargetStack.moveTaskToFrontLocked(
1776 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1777
1778 // Check whether we should actually launch the new activity in to the task,
1779 // or just reuse the current activity on top.
1780 ActivityRecord top = mInTask.getTopActivity();
1781 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1782 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1783 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001784 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001785 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1786 // We don't need to start a new activity, and the client said not to do
1787 // anything if that is the case, so this is it!
1788 return START_RETURN_INTENT_TO_CALLER;
1789 }
1790 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1791 return START_DELIVERED_TO_TOP;
1792 }
1793 }
1794
1795 if (!mAddingToTask) {
1796 // We don't actually want to have this activity added to the task, so just
1797 // stop here but still tell the caller that we consumed the intent.
1798 ActivityOptions.abort(mOptions);
1799 return START_TASK_TO_FRONT;
1800 }
1801
1802 mStartActivity.setTask(mInTask, null);
1803 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1804 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1805
1806 return START_SUCCESS;
1807 }
1808
1809 private void setTaskToCurrentTopOrCreateNewTask() {
1810 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1811 mOptions);
1812 if (mDoResume) {
1813 mTargetStack.moveToFront("addingToTopTask");
1814 }
1815 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001816 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1817 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1818 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001819 mStartActivity.setTask(task, null);
1820 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1821 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1822 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1823 }
1824
1825 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1826 boolean launchSingleTask, int launchFlags) {
1827 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1828 (launchSingleInstance || launchSingleTask)) {
1829 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1830 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1831 "\"singleInstance\" or \"singleTask\"");
1832 launchFlags &=
1833 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1834 } else {
1835 switch (r.info.documentLaunchMode) {
1836 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1837 break;
1838 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1839 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1840 break;
1841 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1842 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1843 break;
1844 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1845 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1846 break;
1847 }
1848 }
1849 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001850 }
1851
1852 final void doPendingActivityLaunchesLocked(boolean doResume) {
1853 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001854 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1855 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001856 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001857 final int result = startActivityUnchecked(
1858 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1859 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001860 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1861 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001862 } catch (Exception e) {
1863 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1864 pal.sendErrorResult(e.getMessage());
1865 }
1866 }
1867 }
1868
1869 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001870 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001871 final TaskRecord task = r.task;
1872 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1873 return mSupervisor.mHomeStack;
1874 }
1875
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001876 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001877 if (stack != null) {
1878 return stack;
1879 }
1880
Andrii Kulian02b7a832016-10-06 23:11:56 -07001881 final ActivityStack currentStack = task != null ? task.getStack() : null;
1882 if (currentStack != null) {
1883 if (currentStack.isOnHomeDisplay()) {
1884 if (mSupervisor.mFocusedStack != currentStack) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001885 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1886 "computeStackFocus: Setting " + "focused stack to r=" + r
1887 + " task=" + task);
1888 } else {
1889 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1890 "computeStackFocus: Focused stack already="
1891 + mSupervisor.mFocusedStack);
1892 }
1893 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001894 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001895 }
1896
1897 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1898 if (container != null) {
1899 // The first time put it on the desired stack, after this put on task stack.
1900 r.mInitialActivityContainer = null;
1901 return container.mStack;
1902 }
1903
1904 // The fullscreen stack can contain any task regardless of if the task is resizeable
1905 // 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 -07001906 // Same also applies to dynamic stacks, as they behave similar to fullscreen stack.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001907 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1908 // we can also put it in the focused stack.
1909 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001910 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1911 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
Andrii Kulian16802aa2016-11-02 12:21:33 -07001912 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced())
1913 || !isStaticStack(focusedStackId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001914 if (canUseFocusedStack && (!newTask
1915 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1916 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1917 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1918 return mSupervisor.mFocusedStack;
1919 }
1920
Andrii Kulian16802aa2016-11-02 12:21:33 -07001921 // We first try to put the task in the first dynamic stack on home display.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001922 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1923 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1924 stack = homeDisplayStacks.get(stackNdx);
1925 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1926 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1927 "computeStackFocus: Setting focused stack=" + stack);
1928 return stack;
1929 }
1930 }
1931
1932 // If there is no suitable dynamic stack then we figure out which static stack to use.
1933 final int stackId = task != null ? task.getLaunchStackId() :
1934 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1935 FULLSCREEN_WORKSPACE_STACK_ID;
1936 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1937 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1938 + r + " stackId=" + stack.mStackId);
1939 return stack;
1940 }
1941
Wale Ogunwale854809c2015-12-27 16:18:19 -08001942 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001943 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001944
1945 // We are reusing a task, keep the stack!
1946 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001947 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07001948 }
1949
Andrii Kulian16802aa2016-11-02 12:21:33 -07001950 final int launchDisplayId =
1951 (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
1952
Wale Ogunwale854809c2015-12-27 16:18:19 -08001953 final int launchStackId =
1954 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1955
Andrii Kulian16802aa2016-11-02 12:21:33 -07001956 if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
1957 throw new IllegalArgumentException(
1958 "Stack and display id can't be set at the same time.");
1959 }
1960
Wale Ogunwale854809c2015-12-27 16:18:19 -08001961 if (isValidLaunchStackId(launchStackId, r)) {
1962 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Andrii Kulian16802aa2016-11-02 12:21:33 -07001963 }
1964 if (launchStackId == DOCKED_STACK_ID) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001965 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1966 // for this activity, so we put the activity in the fullscreen stack.
1967 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001968 }
Andrii Kulian16802aa2016-11-02 12:21:33 -07001969 if (launchDisplayId != INVALID_DISPLAY) {
1970 // Stack id has higher priority than display id.
1971 return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
1972 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001973
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001974 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001975 return null;
1976 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001977 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001978
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001979 // The parent activity doesn't want to launch the activity on top of itself, but
1980 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001981 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001982 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1983 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001984
1985 if (parentStack != mSupervisor.mFocusedStack) {
1986 // If task's parent stack is not focused - use it during adjacent launch.
1987 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001988 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001989 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1990 // If task is already on top of focused stack - use it. We don't want to move the
1991 // existing focused task to adjacent stack, just deliver new intent in this case.
1992 return mSupervisor.mFocusedStack;
1993 }
1994
1995 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1996 // If parent was in docked stack, the natural place to launch another activity
1997 // will be fullscreen, so it can appear alongside the docked window.
1998 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1999 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002000 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002001 // If the parent is not in the docked stack, we check if there is docked window
2002 // and if yes, we will launch into that stack. If not, we just put the new
2003 // activity into parent's stack, because we can't find a better place.
2004 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2005 if (dockedStack != null
2006 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2007 // There is a docked stack, but it isn't visible, so we can't launch into that.
2008 return null;
2009 } else {
2010 return dockedStack;
2011 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002012 }
2013 }
2014 }
2015
Andrii Kulian16802aa2016-11-02 12:21:33 -07002016 boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2017 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002018 return false;
2019 }
2020
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002021 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2022 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2023 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002024 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002025
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002026 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2027 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002028 }
2029
2030 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2031 return false;
2032 }
2033
2034 final boolean supportsPip = mService.mSupportsPictureInPicture
2035 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2036 if (stackId == PINNED_STACK_ID && !supportsPip) {
2037 return false;
2038 }
2039 return true;
2040 }
2041
Wale Ogunwale854809c2015-12-27 16:18:19 -08002042 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2043 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002044 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002045 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2046 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002047 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002048 }
2049 }
2050 return newBounds;
2051 }
2052
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002053 void setWindowManager(WindowManagerService wm) {
2054 mWindowManager = wm;
2055 }
2056
2057 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2058 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2059 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2060 if (pal.stack == stack) {
2061 mPendingActivityLaunches.remove(palNdx);
2062 }
2063 }
2064 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002065
2066 static boolean isDocumentLaunchesIntoExisting(int flags) {
2067 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2068 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2069 }
liulvpingcfa825f2016-09-26 20:00:15 +08002070
2071 boolean clearPendingActivityLaunchesLocked(String packageName) {
2072 boolean didSomething = false;
2073
2074 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2075 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2076 ActivityRecord r = pal.r;
2077 if (r != null && r.packageName.equals(packageName)) {
2078 mPendingActivityLaunches.remove(palNdx);
2079 didSomething = true;
2080 }
2081 }
2082 return didSomething;
2083 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002084}