blob: e4ec16994507934a6bbca80112d4b6b317e94474 [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;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080034import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
35import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Tony Mak646fe992016-04-21 16:43:08 +010036import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080037import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080039import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080040import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080041import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
42import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
44import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
45import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
46import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
47import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080048import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080049import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
50import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
52import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080053import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
54import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
55import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080056import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080057import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
61import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
65import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
66import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
67import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080068import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080069import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
70import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
71import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080072import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080073import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
74import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
75import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080076import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080077import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080078import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080079
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080080import android.app.ActivityManager;
81import android.app.ActivityOptions;
82import android.app.AppGlobals;
83import android.app.IActivityContainer;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080084import android.app.IApplicationThread;
Tony Mak853304c2016-04-18 15:17:41 +010085import android.app.KeyguardManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080086import android.app.PendingIntent;
87import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070088import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080089import android.content.ComponentName;
Tony Mak853304c2016-04-18 15:17:41 +010090import android.content.Context;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080091import android.content.IIntentSender;
92import android.content.Intent;
93import android.content.IntentSender;
94import android.content.pm.ActivityInfo;
95import android.content.pm.ApplicationInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000096import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000098import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080099import android.content.res.Configuration;
100import android.graphics.Rect;
Ruchi Kandoi0d434042016-10-03 09:12:02 -0700101import android.hardware.power.V1_0.PowerHint;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800102import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800103import android.os.Bundle;
104import android.os.IBinder;
Wei Wang98f03f92016-05-18 11:32:52 -0700105import android.os.PowerManagerInternal;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.os.RemoteException;
107import android.os.SystemClock;
108import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000109import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import android.service.voice.IVoiceInteractionSession;
111import android.util.EventLog;
112import android.util.Slog;
113import android.view.Display;
114
115import com.android.internal.app.HeavyWeightSwitcherActivity;
116import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800117import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
118import com.android.server.wm.WindowManagerService;
119
120import java.util.ArrayList;
121
122/**
123 * Controller for interpreting how and then launching activities.
124 *
125 * This class collects all the logic for determining how an intent and flags should be turned into
126 * an activity and associated task and stack.
127 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800128class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800129 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
130 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
131 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
132 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
133 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
134
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700135 // TODO b/30204367 remove when the platform fully supports ephemeral applications
136 private static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false;
137
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800138 private final ActivityManagerService mService;
139 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000140 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800141 private WindowManagerService mWindowManager;
142
143 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
144
Wale Ogunwale01d66562015-12-29 08:19:19 -0800145 // Share state variable among methods when starting an activity.
146 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700147 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800148 private Intent mIntent;
149 private int mCallingUid;
150 private ActivityOptions mOptions;
151
152 private boolean mLaunchSingleTop;
153 private boolean mLaunchSingleInstance;
154 private boolean mLaunchSingleTask;
155 private boolean mLaunchTaskBehind;
156 private int mLaunchFlags;
157
158 private Rect mLaunchBounds;
159
160 private ActivityRecord mNotTop;
161 private boolean mDoResume;
162 private int mStartFlags;
163 private ActivityRecord mSourceRecord;
164
165 private TaskRecord mInTask;
166 private boolean mAddingToTask;
167 private TaskRecord mReuseTask;
168
169 private ActivityInfo mNewTaskInfo;
170 private Intent mNewTaskIntent;
171 private ActivityStack mSourceStack;
172 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700173 // Indicates that we moved other task and are going to put something on top soon, so
174 // we don't want to show it redundantly or accidentally change what's shown below.
175 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800176 private boolean mMovedToFront;
177 private boolean mNoAnimation;
178 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700179 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700180 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800181
182 private IVoiceInteractionSession mVoiceSession;
183 private IVoiceInteractor mVoiceInteractor;
184
185 private void reset() {
186 mStartActivity = null;
187 mIntent = null;
188 mCallingUid = -1;
189 mOptions = null;
190
191 mLaunchSingleTop = false;
192 mLaunchSingleInstance = false;
193 mLaunchSingleTask = false;
194 mLaunchTaskBehind = false;
195 mLaunchFlags = 0;
196
197 mLaunchBounds = null;
198
199 mNotTop = null;
200 mDoResume = false;
201 mStartFlags = 0;
202 mSourceRecord = null;
203
204 mInTask = null;
205 mAddingToTask = false;
206 mReuseTask = null;
207
208 mNewTaskInfo = null;
209 mNewTaskIntent = null;
210 mSourceStack = null;
211
212 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700213 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800214 mMovedToFront = false;
215 mNoAnimation = false;
216 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700217 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800218
219 mVoiceSession = null;
220 mVoiceInteractor = null;
221 }
222
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800223 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
224 mService = service;
225 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000226 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800227 }
228
229 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
230 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
231 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
232 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
233 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
234 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
235 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
236 TaskRecord inTask) {
237 int err = ActivityManager.START_SUCCESS;
238
239 ProcessRecord callerApp = null;
240 if (caller != null) {
241 callerApp = mService.getRecordForAppLocked(caller);
242 if (callerApp != null) {
243 callingPid = callerApp.pid;
244 callingUid = callerApp.info.uid;
245 } else {
246 Slog.w(TAG, "Unable to find app for caller " + caller
247 + " (pid=" + callingPid + ") when starting: "
248 + intent.toString());
249 err = ActivityManager.START_PERMISSION_DENIED;
250 }
251 }
252
253 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
254
255 if (err == ActivityManager.START_SUCCESS) {
256 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
257 + "} from uid " + callingUid
258 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
259 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
260 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
261 container.mActivityDisplay.mDisplayId)));
262 }
263
264 ActivityRecord sourceRecord = null;
265 ActivityRecord resultRecord = null;
266 if (resultTo != null) {
267 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
268 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
269 "Will send result to " + resultTo + " " + sourceRecord);
270 if (sourceRecord != null) {
271 if (requestCode >= 0 && !sourceRecord.finishing) {
272 resultRecord = sourceRecord;
273 }
274 }
275 }
276
277 final int launchFlags = intent.getFlags();
278
279 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
280 // Transfer the result target from the source activity to the new
281 // one being started, including any failures.
282 if (requestCode >= 0) {
283 ActivityOptions.abort(options);
284 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
285 }
286 resultRecord = sourceRecord.resultTo;
287 if (resultRecord != null && !resultRecord.isInStackLocked()) {
288 resultRecord = null;
289 }
290 resultWho = sourceRecord.resultWho;
291 requestCode = sourceRecord.requestCode;
292 sourceRecord.resultTo = null;
293 if (resultRecord != null) {
294 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
295 }
296 if (sourceRecord.launchedFromUid == callingUid) {
297 // The new activity is being launched from the same uid as the previous
298 // activity in the flow, and asking to forward its result back to the
299 // previous. In this case the activity is serving as a trampoline between
300 // the two, so we also want to update its launchedFromPackage to be the
301 // same as the previous activity. Note that this is safe, since we know
302 // these two packages come from the same uid; the caller could just as
303 // well have supplied that same package name itself. This specifially
304 // deals with the case of an intent picker/chooser being launched in the app
305 // flow to redirect to an activity picked by the user, where we want the final
306 // activity to consider it to have been launched by the previous app activity.
307 callingPackage = sourceRecord.launchedFromPackage;
308 }
309 }
310
311 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
312 // We couldn't find a class that can handle the given Intent.
313 // That's the end of that!
314 err = ActivityManager.START_INTENT_NOT_RESOLVED;
315 }
316
317 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
318 // We couldn't find the specific class specified in the Intent.
319 // Also the end of the line.
320 err = ActivityManager.START_CLASS_NOT_FOUND;
321 }
322
323 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
324 && sourceRecord.task.voiceSession != null) {
325 // If this activity is being launched as part of a voice session, we need
326 // to ensure that it is safe to do so. If the upcoming activity will also
327 // be part of the voice session, we can only launch it if it has explicitly
328 // said it supports the VOICE category, or it is a part of the calling app.
329 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
330 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
331 try {
332 intent.addCategory(Intent.CATEGORY_VOICE);
333 if (!AppGlobals.getPackageManager().activitySupportsIntent(
334 intent.getComponent(), intent, resolvedType)) {
335 Slog.w(TAG,
336 "Activity being started in current voice task does not support voice: "
337 + intent);
338 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
339 }
340 } catch (RemoteException e) {
341 Slog.w(TAG, "Failure checking voice capabilities", e);
342 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
343 }
344 }
345 }
346
347 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
348 // If the caller is starting a new voice session, just make sure the target
349 // is actually allowing it to run this way.
350 try {
351 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
352 intent, resolvedType)) {
353 Slog.w(TAG,
354 "Activity being started in new voice task does not support: "
355 + intent);
356 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
357 }
358 } catch (RemoteException e) {
359 Slog.w(TAG, "Failure checking voice capabilities", e);
360 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
361 }
362 }
363
Andrii Kulian02b7a832016-10-06 23:11:56 -0700364 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800365
Wale Ogunwale01d66562015-12-29 08:19:19 -0800366 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800367 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800368 resultStack.sendActivityResultLocked(
369 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800370 }
371 ActivityOptions.abort(options);
372 return err;
373 }
374
375 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
376 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100377 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800378 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
379 callingPid, resolvedType, aInfo.applicationInfo);
380
381 if (mService.mController != null) {
382 try {
383 // The Intent we give to the watcher has the extra data
384 // stripped off, since it can contain private information.
385 Intent watchIntent = intent.cloneFilter();
386 abort |= !mService.mController.activityStarting(watchIntent,
387 aInfo.applicationInfo.packageName);
388 } catch (RemoteException e) {
389 mService.mController = null;
390 }
391 }
392
Rubin Xu58d25992016-01-21 17:47:13 +0000393 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100394 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
395 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000396 intent = mInterceptor.mIntent;
397 rInfo = mInterceptor.mRInfo;
398 aInfo = mInterceptor.mAInfo;
399 resolvedType = mInterceptor.mResolvedType;
400 inTask = mInterceptor.mInTask;
401 callingPid = mInterceptor.mCallingPid;
402 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100403 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800404 if (abort) {
405 if (resultRecord != null) {
406 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800407 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800408 }
409 // We pretend to the caller that it was really started, but
410 // they will just get a cancel result.
411 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800412 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800413 }
414
415 // If permissions need a review before any of the app components can run, we
416 // launch the review activity and pass a pending intent to start the activity
417 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700418 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800419 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
420 aInfo.packageName, userId)) {
421 IIntentSender target = mService.getIntentSenderLocked(
422 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
423 callingUid, userId, null, null, 0, new Intent[]{intent},
424 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
425 | PendingIntent.FLAG_ONE_SHOT, null);
426
427 final int flags = intent.getFlags();
428 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
429 newIntent.setFlags(flags
430 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
431 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
432 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
433 if (resultRecord != null) {
434 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
435 }
436 intent = newIntent;
437
438 resolvedType = null;
439 callingUid = realCallingUid;
440 callingPid = realCallingPid;
441
442 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
443 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
444 null /*profilerInfo*/);
445
446 if (DEBUG_PERMISSIONS_REVIEW) {
447 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
448 true, false) + "} from uid " + callingUid + " on display "
449 + (container == null ? (mSupervisor.mFocusedStack == null ?
450 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
451 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
452 container.mActivityDisplay.mDisplayId)));
453 }
454 }
455 }
456
457 // If we have an ephemeral app, abort the process of launching the resolved intent.
458 // Instead, launch the ephemeral installer. Once the installer is finished, it
459 // starts either the intent we resolved here [on install error] or the ephemeral
460 // app [on install success].
461 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700462 intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
463 rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
464 userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800465 resolvedType = null;
466 callingUid = realCallingUid;
467 callingPid = realCallingPid;
468
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800469 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
470 }
471
472 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
Andrii Kulian1779e612016-10-12 21:58:25 -0700473 intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord,
474 resultWho, requestCode, componentSpecified, voiceSession != null, mSupervisor,
475 container, options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800476 if (outActivity != null) {
477 outActivity[0] = r;
478 }
479
480 if (r.appTimeTracker == null && sourceRecord != null) {
481 // If the caller didn't specify an explicit time tracker, we want to continue
482 // tracking under any it has.
483 r.appTimeTracker = sourceRecord.appTimeTracker;
484 }
485
486 final ActivityStack stack = mSupervisor.mFocusedStack;
487 if (voiceSession == null && (stack.mResumedActivity == null
488 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
489 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
490 realCallingPid, realCallingUid, "Activity start")) {
491 PendingActivityLaunch pal = new PendingActivityLaunch(r,
492 sourceRecord, startFlags, stack, callerApp);
493 mPendingActivityLaunches.add(pal);
494 ActivityOptions.abort(options);
495 return ActivityManager.START_SWITCHES_CANCELED;
496 }
497 }
498
499 if (mService.mDidAppSwitch) {
500 // This is the second allowed switch since we stopped switches,
501 // so now just generally allow switches. Use case: user presses
502 // home (switches disabled, switch to home, mDidAppSwitch now true);
503 // user taps a home icon (coming from home so allowed, we hit here
504 // and now allow anyone to switch again).
505 mService.mAppSwitchesAllowedTime = 0;
506 } else {
507 mService.mDidAppSwitch = true;
508 }
509
510 doPendingActivityLaunchesLocked(false);
511
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700512 try {
513 mService.mWindowManager.deferSurfaceLayout();
514 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
515 true, options, inTask);
516 } finally {
517 mService.mWindowManager.continueSurfaceLayout();
518 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700519 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800520 return err;
521 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800522
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700523 /**
524 * Builds and returns an intent to launch the ephemeral installer.
525 */
526 private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
527 String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
528 final Intent nonEphemeralIntent = new Intent(origIntent);
529 nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
530 // Intent that is launched if the ephemeral package couldn't be installed
531 // for any reason.
532 final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(
533 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
534 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1,
535 new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType },
536 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
537 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
538
539 final Intent ephemeralIntent;
540 if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
541 // Force the intent to be directed to the ephemeral package
542 ephemeralIntent = new Intent(origIntent);
543 ephemeralIntent.setPackage(ephemeralPackage);
544 } else {
545 // Success intent goes back to the installer
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700546 ephemeralIntent = new Intent(launchIntent);
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700547 }
548
549 // Intent that is eventually launched if the ephemeral package was
550 // installed successfully. This will actually be launched by a platform
551 // broadcast receiver.
552 final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
553 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
554 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
555 new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
556 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
557 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
558
559 // Finally build the actual intent to launch the ephemeral installer
560 int flags = launchIntent.getFlags();
561 final Intent intent = new Intent();
562 intent.setFlags(flags
563 | Intent.FLAG_ACTIVITY_NEW_TASK
564 | Intent.FLAG_ACTIVITY_CLEAR_TASK
565 | Intent.FLAG_ACTIVITY_NO_HISTORY
566 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
567 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
568 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
569 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
570 // TODO: Remove when the platform has fully implemented ephemeral apps
Todd Kennedy52f179f2016-09-21 15:53:50 -0700571 intent.setData(origIntent.getData().buildUpon().clearQuery().build());
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700572 return intent;
573 }
574
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800575 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700576 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
577 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800578
579 if (result < START_SUCCESS) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800580 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800581 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800582
Chong Zhang5022da32016-06-21 16:31:37 -0700583 // We're waiting for an activity launch to finish, but that activity simply
584 // brought another activity to front. Let startActivityMayWait() know about
585 // this, so it waits for the new activity to become visible instead.
586 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
587 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
588 }
589
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800590 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700591 final ActivityStack currentStack = r.getStack();
592 if (currentStack != null) {
593 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800594 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700595 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800596 }
597
Jorim Jaggi352d5842016-05-19 10:20:28 -0700598 // If we launched the activity from a no display activity that was launched from the home
599 // screen, we also need to start recents to un-minimize the docked stack, since the
600 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700601 // Note that some apps have trampoline activities without noDisplay being set. In that case,
602 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
603 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700604 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
605 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700606 final boolean noDisplayActivityOverHome = sourceRecord != null
607 && sourceRecord.noDisplay
608 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700609 if (startedActivityStackId == DOCKED_STACK_ID
610 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100611 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
612 final ActivityRecord topActivityHomeStack = homeStack != null
613 ? homeStack.topRunningActivityLocked() : null;
614 if (topActivityHomeStack == null
615 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
616 // We launch an activity while being in home stack, which means either launcher or
617 // recents into docked stack. We don't want the launched activity to be alone in a
618 // docked stack, so we want to immediately launch recents too.
619 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700620 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100621 return;
622 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800623 }
624
625 if (startedActivityStackId == PINNED_STACK_ID
626 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
627 // The activity was already running in the pinned stack so it wasn't started, but either
628 // brought to the front or the new intent was delivered to it since it was already in
629 // front. Notify anyone interested in this piece of information.
Yorke Leebd54c2a2016-10-25 13:49:23 -0700630 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800631 return;
632 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800633 }
634
635 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
636 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
637 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
638 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
639 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
640 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
641 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700642 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800643 null /*container*/, null /*inTask*/);
644 if (mSupervisor.inResumeTopActivity) {
645 // If we are in resume section already, home activity will be initialized, but not
646 // resumed (to avoid recursive resume) and will stay that way until something pokes it
647 // again. We need to schedule another resume.
648 mSupervisor.scheduleResumeTopActivities();
649 }
650 }
651
Tony Mak853304c2016-04-18 15:17:41 +0100652 void showConfirmDeviceCredential(int userId) {
653 // First, retrieve the stack that we want to resume after credential is confirmed.
654 ActivityStack targetStack;
655 ActivityStack fullscreenStack =
656 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
657 if (fullscreenStack != null &&
658 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
659 // Single window case and the case that the docked stack is shown with fullscreen stack.
660 targetStack = fullscreenStack;
661 } else {
662 // The case that the docked stack is shown with recent.
663 targetStack = mSupervisor.getStack(HOME_STACK_ID);
664 }
665 if (targetStack == null) {
666 return;
667 }
668 final KeyguardManager km = (KeyguardManager) mService.mContext
669 .getSystemService(Context.KEYGUARD_SERVICE);
670 final Intent credential =
671 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100672 // For safety, check null here in case users changed the setting after the checking.
673 if (credential == null) {
674 return;
675 }
Tony Mak853304c2016-04-18 15:17:41 +0100676 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
677 if (activityRecord != null) {
678 final IIntentSender target = mService.getIntentSenderLocked(
679 ActivityManager.INTENT_SENDER_ACTIVITY,
680 activityRecord.launchedFromPackage,
681 activityRecord.launchedFromUid,
682 activityRecord.userId,
683 null, null, 0,
684 new Intent[] { activityRecord.intent },
685 new String[] { activityRecord.resolvedType },
686 PendingIntent.FLAG_CANCEL_CURRENT |
687 PendingIntent.FLAG_ONE_SHOT |
688 PendingIntent.FLAG_IMMUTABLE,
689 null);
690 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
691 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100692 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100693 }
694 }
695
Tony Mak646fe992016-04-21 16:43:08 +0100696 void startConfirmCredentialIntent(Intent intent) {
697 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
698 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
699 FLAG_ACTIVITY_TASK_ON_HOME);
700 final ActivityOptions options = ActivityOptions.makeBasic();
701 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
702 mService.mContext.startActivityAsUser(intent, options.toBundle(),
703 UserHandle.CURRENT);
704 }
Tony Mak853304c2016-04-18 15:17:41 +0100705
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800706 final int startActivityMayWait(IApplicationThread caller, int callingUid,
707 String callingPackage, Intent intent, String resolvedType,
708 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
709 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700710 ProfilerInfo profilerInfo, WaitResult outResult,
Andrii Kulian8072d112016-09-16 11:11:01 -0700711 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800712 IActivityContainer iContainer, TaskRecord inTask) {
713 // Refuse possible leaked file descriptors
714 if (intent != null && intent.hasFileDescriptors()) {
715 throw new IllegalArgumentException("File descriptors passed in Intent");
716 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500717 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800718 boolean componentSpecified = intent.getComponent() != null;
719
720 // Save a copy in case ephemeral needs it
721 final Intent ephemeralIntent = new Intent(intent);
722 // Don't modify the client's object!
723 intent = new Intent(intent);
724
725 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000726 if (rInfo == null) {
727 UserInfo userInfo = mSupervisor.getUserInfo(userId);
728 if (userInfo != null && userInfo.isManagedProfile()) {
729 // Special case for managed profiles, if attempting to launch non-cryto aware
730 // app in a locked managed profile from an unlocked parent allow it to resolve
731 // as user will be sent via confirm credentials to unlock the profile.
732 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700733 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000734 long token = Binder.clearCallingIdentity();
735 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700736 UserInfo parent = userManager.getProfileParent(userId);
737 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
738 && userManager.isUserUnlockingOrUnlocked(parent.id)
739 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000740 } finally {
741 Binder.restoreCallingIdentity(token);
742 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700743 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000744 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600745 PackageManager.MATCH_DIRECT_BOOT_AWARE
746 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000747 }
748 }
749 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800750 // Collect information about the target of the Intent.
751 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
752
753 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
754 ActivityStackSupervisor.ActivityContainer container =
755 (ActivityStackSupervisor.ActivityContainer)iContainer;
756 synchronized (mService) {
757 if (container != null && container.mParentActivity != null &&
758 container.mParentActivity.state != RESUMED) {
759 // Cannot start a child activity if the parent is not resumed.
760 return ActivityManager.START_CANCELED;
761 }
762 final int realCallingPid = Binder.getCallingPid();
763 final int realCallingUid = Binder.getCallingUid();
764 int callingPid;
765 if (callingUid >= 0) {
766 callingPid = -1;
767 } else if (caller == null) {
768 callingPid = realCallingPid;
769 callingUid = realCallingUid;
770 } else {
771 callingPid = callingUid = -1;
772 }
773
774 final ActivityStack stack;
775 if (container == null || container.mStack.isOnHomeDisplay()) {
776 stack = mSupervisor.mFocusedStack;
777 } else {
778 stack = container.mStack;
779 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700780 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700781 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800782 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
783 "Starting activity when config will change = " + stack.mConfigWillChange);
784
785 final long origId = Binder.clearCallingIdentity();
786
787 if (aInfo != null &&
788 (aInfo.applicationInfo.privateFlags
789 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
790 // This may be a heavy-weight process! Check to see if we already
791 // have another, different heavy-weight process running.
792 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
793 final ProcessRecord heavy = mService.mHeavyWeightProcess;
794 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
795 || !heavy.processName.equals(aInfo.processName))) {
796 int appCallingUid = callingUid;
797 if (caller != null) {
798 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
799 if (callerApp != null) {
800 appCallingUid = callerApp.info.uid;
801 } else {
802 Slog.w(TAG, "Unable to find app for caller " + caller
803 + " (pid=" + callingPid + ") when starting: "
804 + intent.toString());
805 ActivityOptions.abort(options);
806 return ActivityManager.START_PERMISSION_DENIED;
807 }
808 }
809
810 IIntentSender target = mService.getIntentSenderLocked(
811 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
812 appCallingUid, userId, null, null, 0, new Intent[] { intent },
813 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
814 | PendingIntent.FLAG_ONE_SHOT, null);
815
816 Intent newIntent = new Intent();
817 if (requestCode >= 0) {
818 // Caller is requesting a result.
819 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
820 }
821 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
822 new IntentSender(target));
823 if (heavy.activities.size() > 0) {
824 ActivityRecord hist = heavy.activities.get(0);
825 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
826 hist.packageName);
827 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
828 hist.task.taskId);
829 }
830 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
831 aInfo.packageName);
832 newIntent.setFlags(intent.getFlags());
833 newIntent.setClassName("android",
834 HeavyWeightSwitcherActivity.class.getName());
835 intent = newIntent;
836 resolvedType = null;
837 caller = null;
838 callingUid = Binder.getCallingUid();
839 callingPid = Binder.getCallingPid();
840 componentSpecified = true;
841 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
842 aInfo = rInfo != null ? rInfo.activityInfo : null;
843 if (aInfo != null) {
844 aInfo = mService.getActivityInfoForUser(aInfo, userId);
845 }
846 }
847 }
848 }
849
Jorim Jaggi275561a2016-02-23 10:11:02 -0500850 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800851 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
852 aInfo, rInfo, voiceSession, voiceInteractor,
853 resultTo, resultWho, requestCode, callingPid,
854 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500855 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
856 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800857
858 Binder.restoreCallingIdentity(origId);
859
860 if (stack.mConfigWillChange) {
861 // If the caller also wants to switch to a new configuration,
862 // do so now. This allows a clean switch, as we are waiting
863 // for the current activity to pause (so we will not destroy
864 // it), and have not yet started the next activity.
865 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
866 "updateConfiguration()");
867 stack.mConfigWillChange = false;
868 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
869 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700870 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800871 }
872
873 if (outResult != null) {
874 outResult.result = res;
875 if (res == ActivityManager.START_SUCCESS) {
876 mSupervisor.mWaitingActivityLaunched.add(outResult);
877 do {
878 try {
879 mService.wait();
880 } catch (InterruptedException e) {
881 }
Chong Zhang5022da32016-06-21 16:31:37 -0700882 } while (outResult.result != START_TASK_TO_FRONT
883 && !outResult.timeout && outResult.who == null);
884 if (outResult.result == START_TASK_TO_FRONT) {
885 res = START_TASK_TO_FRONT;
886 }
887 }
888 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800889 ActivityRecord r = stack.topRunningActivityLocked();
890 if (r.nowVisible && r.state == RESUMED) {
891 outResult.timeout = false;
892 outResult.who = new ComponentName(r.info.packageName, r.info.name);
893 outResult.totalTime = 0;
894 outResult.thisTime = 0;
895 } else {
896 outResult.thisTime = SystemClock.uptimeMillis();
897 mSupervisor.mWaitingActivityVisible.add(outResult);
898 do {
899 try {
900 mService.wait();
901 } catch (InterruptedException e) {
902 }
903 } while (!outResult.timeout && outResult.who == null);
904 }
905 }
906 }
907
Jorim Jaggibe67c902016-04-12 00:53:16 -0700908 final ActivityRecord launchedActivity = mReusedActivity != null
909 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700910 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800911 return res;
912 }
913 }
914
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800915 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
916 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
917 Bundle bOptions, int userId) {
918 if (intents == null) {
919 throw new NullPointerException("intents is null");
920 }
921 if (resolvedTypes == null) {
922 throw new NullPointerException("resolvedTypes is null");
923 }
924 if (intents.length != resolvedTypes.length) {
925 throw new IllegalArgumentException("intents are length different than resolvedTypes");
926 }
927
Makoto Onukid67b1872016-07-21 16:26:36 -0700928 final int realCallingPid = Binder.getCallingPid();
929 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800930
931 int callingPid;
932 if (callingUid >= 0) {
933 callingPid = -1;
934 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700935 callingPid = realCallingPid;
936 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800937 } else {
938 callingPid = callingUid = -1;
939 }
940 final long origId = Binder.clearCallingIdentity();
941 try {
942 synchronized (mService) {
943 ActivityRecord[] outActivity = new ActivityRecord[1];
944 for (int i=0; i<intents.length; i++) {
945 Intent intent = intents[i];
946 if (intent == null) {
947 continue;
948 }
949
950 // Refuse possible leaked file descriptors
951 if (intent != null && intent.hasFileDescriptors()) {
952 throw new IllegalArgumentException("File descriptors passed in Intent");
953 }
954
955 boolean componentSpecified = intent.getComponent() != null;
956
957 // Don't modify the client's object!
958 intent = new Intent(intent);
959
960 // Collect information about the target of the Intent.
961 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
962 null, userId);
963 // TODO: New, check if this is correct
964 aInfo = mService.getActivityInfoForUser(aInfo, userId);
965
966 if (aInfo != null &&
967 (aInfo.applicationInfo.privateFlags
968 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
969 throw new IllegalArgumentException(
970 "FLAG_CANT_SAVE_STATE not supported here");
971 }
972
973 ActivityOptions options = ActivityOptions.fromBundle(
974 i == intents.length - 1 ? bOptions : null);
975 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
976 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700977 callingPid, callingUid, callingPackage,
978 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800979 options, false, componentSpecified, outActivity, null, null);
980 if (res < 0) {
981 return res;
982 }
983
984 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
985 }
986 }
987 } finally {
988 Binder.restoreCallingIdentity(origId);
989 }
990
Wale Ogunwale01d66562015-12-29 08:19:19 -0800991 return START_SUCCESS;
992 }
993
Wei Wang65c7a152016-06-02 18:51:22 -0700994 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
995 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -0700996 final ActivityStack focusStack = mSupervisor.getFocusedStack();
997 final ActivityRecord curTop = (focusStack == null)
998 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
999 if ((forceSend || (!mPowerHintSent && curTop != null &&
1000 curTop.task != null && mStartActivity != null &&
1001 curTop.task != mStartActivity.task )) &&
1002 mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -07001003 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -07001004 mPowerHintSent = true;
1005 }
1006 }
1007
Wei Wang65c7a152016-06-02 18:51:22 -07001008 void sendPowerHintForLaunchEndIfNeeded() {
1009 // Trigger launch power hint if activity is launched
1010 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -07001011 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -07001012 mPowerHintSent = false;
1013 }
1014 }
1015
Wale Ogunwale01d66562015-12-29 08:19:19 -08001016 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1017 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1018 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1019
1020 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1021 voiceInteractor);
1022
1023 computeLaunchingTaskFlags();
1024
1025 computeSourceStack();
1026
1027 mIntent.setFlags(mLaunchFlags);
1028
Jorim Jaggibe67c902016-04-12 00:53:16 -07001029 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001030
Jorim Jaggi2adba072016-03-03 13:43:39 +01001031 final int preferredLaunchStackId =
1032 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1033
Jorim Jaggibe67c902016-04-12 00:53:16 -07001034 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001035 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1036 // still needs to be a lock task mode violation since the task gets cleared out and
1037 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001038 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001039 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1040 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1041 mSupervisor.showLockTaskToast();
1042 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1043 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1044 }
1045
1046 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001047 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001048 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001049 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001050 // This task was started because of movement of the activity based on affinity...
1051 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001052 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001053 }
1054
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001055 // This code path leads to delivering a new intent, we want to make sure we schedule it
1056 // as the first operation, in case the activity will be resumed as a result of later
1057 // operations.
1058 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001059 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001060 || mLaunchSingleInstance || mLaunchSingleTask) {
1061 // In this situation we want to remove all activities from the task up to the one
1062 // being started. In most cases this means we are resetting the task to its initial
1063 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001064 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001065 mStartActivity, mLaunchFlags);
1066 if (top != null) {
1067 if (top.frontOfTask) {
1068 // Activity aliases may mean we use different intents for the top activity,
1069 // so make sure the task now has the identity of the new intent.
1070 top.task.setIntent(mStartActivity);
1071 }
1072 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1073 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1074 mStartActivity.launchedFromPackage);
1075 }
1076 }
1077
Wei Wang65c7a152016-06-02 18:51:22 -07001078 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001079
Jorim Jaggibe67c902016-04-12 00:53:16 -07001080 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001081
1082 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1083 // We don't need to start a new activity, and the client said not to do anything
1084 // if that is the case, so this is it! And for paranoia, make sure we have
1085 // correctly resumed the top activity.
1086 resumeTargetStackIfNeeded();
1087 return START_RETURN_INTENT_TO_CALLER;
1088 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001089 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001090
1091 if (!mAddingToTask && mReuseTask == null) {
1092 // We didn't do anything... but it was needed (a.k.a., client don't use that
1093 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1094 resumeTargetStackIfNeeded();
1095 return START_TASK_TO_FRONT;
1096 }
1097 }
1098
1099 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001100 final ActivityStack sourceStack = mStartActivity.resultTo != null
1101 ? mStartActivity.resultTo.getStack() : null;
1102 if (sourceStack != null) {
1103 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1104 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1105 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001106 }
1107 ActivityOptions.abort(mOptions);
1108 return START_CLASS_NOT_FOUND;
1109 }
1110
1111 // If the activity being launched is the same as the one currently at the top, then
1112 // we need to check if it should only be launched once.
1113 final ActivityStack topStack = mSupervisor.mFocusedStack;
1114 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1115 final boolean dontStart = top != null && mStartActivity.resultTo == null
1116 && top.realActivity.equals(mStartActivity.realActivity)
1117 && top.userId == mStartActivity.userId
1118 && top.app != null && top.app.thread != null
1119 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1120 || mLaunchSingleTop || mLaunchSingleTask);
1121 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001122 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001123 // For paranoia, make sure we have correctly resumed the top activity.
1124 topStack.mLastPausedActivity = null;
1125 if (mDoResume) {
1126 mSupervisor.resumeFocusedStackTopActivityLocked();
1127 }
1128 ActivityOptions.abort(mOptions);
1129 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1130 // We don't need to start a new activity, and the client said not to do
1131 // anything if that is the case, so this is it!
1132 return START_RETURN_INTENT_TO_CALLER;
1133 }
1134 top.deliverNewIntentLocked(
1135 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001136
1137 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1138 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1139 mSupervisor.handleNonResizableTaskIfNeeded(
1140 top.task, preferredLaunchStackId, topStack.mStackId);
1141
Wale Ogunwale01d66562015-12-29 08:19:19 -08001142 return START_DELIVERED_TO_TOP;
1143 }
1144
1145 boolean newTask = false;
1146 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1147 ? mSourceRecord.task : null;
1148
1149 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001150 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001151 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1152 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1153 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001154 result = setTaskFromReuseOrCreateNewTask(
1155 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001156 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001157 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001158 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001159 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001160 } else {
1161 // This not being started from an existing activity, and not part of a new task...
1162 // just put it in the top task, though these days this case should never happen.
1163 setTaskToCurrentTopOrCreateNewTask();
1164 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001165 if (result != START_SUCCESS) {
1166 return result;
1167 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001168
1169 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1170 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1171
1172 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1173 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1174 }
1175 if (newTask) {
1176 EventLog.writeEvent(
1177 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1178 }
1179 ActivityStack.logStartActivity(
1180 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1181 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001182
Wei Wang65c7a152016-06-02 18:51:22 -07001183 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001184
Wale Ogunwale01d66562015-12-29 08:19:19 -08001185 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1186 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001187 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1188 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001189 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1190 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001191 // If the activity is not focusable, we can't resume it, but still would like to
1192 // make sure it becomes visible as it starts (this will also trigger entry
1193 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001194 // Also, we don't want to resume activities in a task that currently has an overlay
1195 // as the starting activity just needs to be in the visible paused state until the
1196 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001197 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001198 // Go ahead and tell window manager to execute app transition for this activity
1199 // since the app transition will not be triggered through the resume channel.
1200 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001201 } else {
1202 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1203 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001204 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001205 } else {
1206 mTargetStack.addRecentActivityLocked(mStartActivity);
1207 }
1208 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1209
Jorim Jaggid53f0922016-04-06 22:16:23 -07001210 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001211 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001212
1213 return START_SUCCESS;
1214 }
1215
1216 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1217 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1218 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1219 reset();
1220
1221 mStartActivity = r;
1222 mIntent = r.intent;
1223 mOptions = options;
1224 mCallingUid = r.launchedFromUid;
1225 mSourceRecord = sourceRecord;
1226 mVoiceSession = voiceSession;
1227 mVoiceInteractor = voiceInteractor;
1228
1229 mLaunchBounds = getOverrideBounds(r, options, inTask);
1230
1231 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1232 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1233 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1234 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1235 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1236 mLaunchTaskBehind = r.mLaunchTaskBehind
1237 && !mLaunchSingleTask && !mLaunchSingleInstance
1238 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1239
1240 sendNewTaskResultRequestIfNeeded();
1241
1242 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1243 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1244 }
1245
1246 // If we are actually going to launch in to a new task, there are some cases where
1247 // we further want to do multiple task.
1248 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1249 if (mLaunchTaskBehind
1250 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1251 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1252 }
1253 }
1254
1255 // We'll invoke onUserLeaving before onPause only if the launching
1256 // activity did not explicitly state that this is an automated launch.
1257 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1258 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1259 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1260
1261 // If the caller has asked not to resume at this point, we make note
1262 // of this in the record so that we can skip it when trying to find
1263 // the top running activity.
1264 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001265 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001266 r.delayedResume = true;
1267 mDoResume = false;
1268 }
1269
Wale Ogunwale3b232392016-05-13 15:37:13 -07001270 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1271 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001272 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1273 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1274 if (top != null && !top.visible) {
1275
1276 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1277 // it!
1278 mDoResume = false;
1279 mAvoidMoveToFront = true;
1280 }
1281 }
1282
Wale Ogunwale01d66562015-12-29 08:19:19 -08001283 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1284
1285 mInTask = inTask;
1286 // In some flows in to this function, we retrieve the task record and hold on to it
1287 // without a lock before calling back in to here... so the task at this point may
1288 // not actually be in recents. Check for that, and if it isn't in recents just
1289 // consider it invalid.
1290 if (inTask != null && !inTask.inRecents) {
1291 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1292 mInTask = null;
1293 }
1294
1295 mStartFlags = startFlags;
1296 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1297 // is the same as the one making the call... or, as a special case, if we do not know
1298 // the caller then we count the current top activity as the caller.
1299 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1300 ActivityRecord checkedCaller = sourceRecord;
1301 if (checkedCaller == null) {
1302 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1303 mNotTop);
1304 }
1305 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1306 // Caller is not the same as launcher, so always needed.
1307 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1308 }
1309 }
1310
1311 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1312 }
1313
1314 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001315 final ActivityStack sourceStack = mStartActivity.resultTo != null
1316 ? mStartActivity.resultTo.getStack() : null;
1317 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001318 // For whatever reason this activity is being launched into a new task...
1319 // yet the caller has requested a result back. Well, that is pretty messed up,
1320 // so instead immediately send back a cancel and let the new task continue launched
1321 // as normal without a dependency on its originator.
1322 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001323 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1324 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1325 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001326 mStartActivity.resultTo = null;
1327 }
1328 }
1329
1330 private void computeLaunchingTaskFlags() {
1331 // If the caller is not coming from another activity, but has given us an explicit task into
1332 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001333 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001334 final Intent baseIntent = mInTask.getBaseIntent();
1335 final ActivityRecord root = mInTask.getRootActivity();
1336 if (baseIntent == null) {
1337 ActivityOptions.abort(mOptions);
1338 throw new IllegalArgumentException("Launching into task without base intent: "
1339 + mInTask);
1340 }
1341
1342 // If this task is empty, then we are adding the first activity -- it
1343 // determines the root, and must be launching as a NEW_TASK.
1344 if (mLaunchSingleInstance || mLaunchSingleTask) {
1345 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1346 ActivityOptions.abort(mOptions);
1347 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1348 + mStartActivity + " into different task " + mInTask);
1349 }
1350 if (root != null) {
1351 ActivityOptions.abort(mOptions);
1352 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1353 + " has root " + root + " but target is singleInstance/Task");
1354 }
1355 }
1356
1357 // If task is empty, then adopt the interesting intent launch flags in to the
1358 // activity being started.
1359 if (root == null) {
1360 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1361 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1362 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1363 | (baseIntent.getFlags() & flagsOfInterest);
1364 mIntent.setFlags(mLaunchFlags);
1365 mInTask.setIntent(mStartActivity);
1366 mAddingToTask = true;
1367
1368 // If the task is not empty and the caller is asking to start it as the root of
1369 // a new task, then we don't actually want to start this on the task. We will
1370 // bring the task to the front, and possibly give it a new intent.
1371 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1372 mAddingToTask = false;
1373
1374 } else {
1375 mAddingToTask = true;
1376 }
1377
1378 mReuseTask = mInTask;
1379 } else {
1380 mInTask = null;
1381 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1382 // when in freeform workspace.
1383 // Also put noDisplay activities in the source task. These by itself can be placed
1384 // in any task/stack, however it could launch other activities like ResolverActivity,
1385 // and we want those to stay in the original task.
1386 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1387 && mSourceRecord.isFreeform()) {
1388 mAddingToTask = true;
1389 }
1390 }
1391
1392 if (mInTask == null) {
1393 if (mSourceRecord == null) {
1394 // This activity is not being started from another... in this
1395 // case we -always- start a new task.
1396 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1397 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1398 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1399 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1400 }
1401 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1402 // The original activity who is starting us is running as a single
1403 // instance... this new activity it is starting must go on its
1404 // own task.
1405 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1406 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1407 // The activity being started is a single instance... it always
1408 // gets launched into its own task.
1409 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1410 }
1411 }
1412 }
1413
1414 private void computeSourceStack() {
1415 if (mSourceRecord == null) {
1416 mSourceStack = null;
1417 return;
1418 }
1419 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001420 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001421 return;
1422 }
1423
1424 // If the source is finishing, we can't further count it as our source. This is because the
1425 // task it is associated with may now be empty and on its way out, so we don't want to
1426 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1427 // a task for it. But save the task information so it can be used when creating the new task.
1428 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1429 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1430 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1431 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1432 mNewTaskInfo = mSourceRecord.info;
1433 mNewTaskIntent = mSourceRecord.task.intent;
1434 }
1435 mSourceRecord = null;
1436 mSourceStack = null;
1437 }
1438
1439 /**
1440 * Decide whether the new activity should be inserted into an existing task. Returns null
1441 * if not or an ActivityRecord with the task into which the new activity should be added.
1442 */
1443 private ActivityRecord getReusableIntentActivity() {
1444 // We may want to try to place the new activity in to an existing task. We always
1445 // do this if the target activity is singleTask or singleInstance; we will also do
1446 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1447 // us to still place it in a new task: multi task, always doc mode, or being asked to
1448 // launch this as a new task behind the current one.
1449 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1450 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1451 || mLaunchSingleInstance || mLaunchSingleTask;
1452 // If bring to front is requested, and no result is requested and we have not been given
1453 // an explicit task to launch in to, and we can find a task that was started with this
1454 // same component, then instead of launching bring that one to the front.
1455 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1456 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001457 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1458 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1459 intentActivity = task != null ? task.getTopActivity() : null;
1460 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001461 if (mLaunchSingleInstance) {
1462 // There can be one and only one instance of single instance activity in the
1463 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001464 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001465 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1466 // For the launch adjacent case we only want to put the activity in an existing
1467 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001468 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1469 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001470 } else {
1471 // Otherwise find the best task to put the activity in.
1472 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1473 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001474 }
1475 return intentActivity;
1476 }
1477
1478 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001479 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001480 mTargetStack.mLastPausedActivity = null;
1481 // If the target task is not in the front, then we need to bring it to the front...
1482 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1483 // the same behavior as if a new instance was being started, which means not bringing it
1484 // to the front if the caller is not itself in the front.
1485 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1486 ActivityRecord curTop = (focusStack == null)
1487 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1488
Jorim Jaggic875ae72016-04-26 22:41:06 -07001489 if (curTop != null
1490 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1491 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001492 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1493 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1494 mSourceStack.topActivity().task == mSourceRecord.task)) {
1495 // We really do want to push this one into the user's face, right now.
1496 if (mLaunchTaskBehind && mSourceRecord != null) {
1497 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1498 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001499 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001500
1501 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1502 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1503 // So no point resuming any of the activities here, it just wastes one extra
1504 // resuming, plus enter AND exit transitions.
1505 // Here we only want to bring the target stack forward. Transition will be applied
1506 // to the new activity that's started after the old ones are gone.
1507 final boolean willClearTask =
1508 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1509 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1510 if (!willClearTask) {
1511 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001512 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001513 if (launchStack == null || launchStack == mTargetStack) {
1514 // We only want to move to the front, if we aren't going to launch on a
1515 // different stack. If we launch on a different stack, we will put the
1516 // task on top there.
1517 mTargetStack.moveTaskToFrontLocked(
1518 intentActivity.task, mNoAnimation, mOptions,
1519 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1520 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001521 } else if (launchStack.mStackId == DOCKED_STACK_ID
1522 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1523 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1524 // If we want to launch adjacent and mTargetStack is not the computed
1525 // launch stack - move task to top of computed stack.
1526 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1527 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1528 ANIMATE);
1529 } else {
1530 // TODO: This should be reevaluated in MW v2.
1531 // We choose to move task to front instead of launching it adjacent
1532 // when specific stack was requested explicitly and it appeared to be
1533 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1534 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1535 mOptions, mStartActivity.appTimeTracker,
1536 "bringToFrontInsteadOfAdjacentLaunch");
1537 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001538 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001539 }
1540 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001541 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001542 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001543 }
1544 }
1545 if (!mMovedToFront && mDoResume) {
1546 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1547 + " from " + intentActivity);
1548 mTargetStack.moveToFront("intentActivityFound");
1549 }
1550
Jorim Jaggid53f0922016-04-06 22:16:23 -07001551 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1552 mTargetStack.mStackId);
1553
Wale Ogunwale01d66562015-12-29 08:19:19 -08001554 // If the caller has requested that the target task be reset, then do so.
1555 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1556 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1557 }
1558 return intentActivity;
1559 }
1560
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001561 private void updateTaskReturnToType(
1562 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Jiaquan Hee13e9642016-06-15 15:16:13 -07001563 if (focusedStack != null && focusedStack.isHomeStack() &&
1564 focusedStack.topTask().isOnTopLauncher()) {
1565 // Since an on-top launcher will is moved to back when tasks are launched from it,
1566 // those tasks should first try to return to a non-home activity.
1567 // This also makes sure that non-home activities are visible under a transparent
1568 // non-home activity.
1569 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1570 return;
1571 } else if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001572 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1573 // Caller wants to appear on home activity.
1574 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1575 return;
1576 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1577 // Task will be launched over the home stack, so return home.
1578 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1579 return;
1580 }
1581
1582 // Else we are coming from an application stack so return to an application.
1583 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1584 }
1585
Wale Ogunwale01d66562015-12-29 08:19:19 -08001586 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1587 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1588 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1589 // The caller has requested to completely replace any existing task with its new
1590 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001591 intentActivity.task.performClearTaskLocked();
1592 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001593 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001594 // When we clear the task - focus will be adjusted, which will bring another task
1595 // to top before we launch the activity we need. This will temporary swap their
1596 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1597 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001598 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1599 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001600 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1601 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001602 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001603 // A special case: we need to start the activity because it is not currently
1604 // running, and the caller has asked to clear the current task to have this
1605 // activity at the top.
1606 mAddingToTask = true;
1607 // Now pretend like this activity is being started by the top of its task, so it
1608 // is put in the right place.
1609 mSourceRecord = intentActivity;
1610 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001611 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001612 // Target stack got cleared when we all activities were removed above.
1613 // Go ahead and reset it.
1614 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1615 null /* bounds */, mLaunchFlags, mOptions);
1616 mTargetStack.addTask(task,
1617 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1618 }
1619 }
1620 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1621 // In this case the top activity on the task is the same as the one being launched,
1622 // so we take that as a request to bring the task to the foreground. If the top
1623 // activity in the task is the root activity, deliver this new intent to it if it
1624 // desires.
1625 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1626 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001627 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001628 intentActivity.task);
1629 if (intentActivity.frontOfTask) {
1630 intentActivity.task.setIntent(mStartActivity);
1631 }
1632 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1633 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001634 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001635 // In this case we are launching the root activity of the task, but with a
1636 // different intent. We should start a new instance on top.
1637 mAddingToTask = true;
1638 mSourceRecord = intentActivity;
1639 }
1640 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1641 // In this case an activity is being launched in to an existing task, without
1642 // resetting that task. This is typically the situation of launching an activity
1643 // from a notification or shortcut. We want to place the new activity on top of the
1644 // current task.
1645 mAddingToTask = true;
1646 mSourceRecord = intentActivity;
1647 } else if (!intentActivity.task.rootWasReset) {
1648 // In this case we are launching into an existing task that has not yet been started
1649 // from its front door. The current task has been brought to the front. Ideally,
1650 // we'd probably like to place this new task at the bottom of its stack, but that's
1651 // a little hard to do with the current organization of the code so for now we'll
1652 // just drop it.
1653 intentActivity.task.setIntent(mStartActivity);
1654 }
1655 }
1656
1657 private void resumeTargetStackIfNeeded() {
1658 if (mDoResume) {
1659 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001660 } else {
1661 ActivityOptions.abort(mOptions);
1662 }
1663 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1664 }
1665
Chong Zhang6cda19c2016-06-14 19:07:56 -07001666 private int setTaskFromReuseOrCreateNewTask(
1667 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1668 mTargetStack = computeStackFocus(
1669 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1670
1671 // Do no move the target stack to front yet, as we might bail if
1672 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001673
1674 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001675 final TaskRecord task = mTargetStack.createTaskRecord(
1676 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001677 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1678 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1679 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1680 mStartActivity.setTask(task, taskToAffiliate);
1681 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001682 final int stackId = mTargetStack.mStackId;
1683 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001684 mService.resizeStack(
1685 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001686 } else {
1687 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1688 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001689 }
1690 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1691 "Starting new activity " +
1692 mStartActivity + " in new task " + mStartActivity.task);
1693 } else {
1694 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1695 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001696
1697 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1698 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1699 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1700 }
1701
1702 if (!mMovedOtherTask) {
1703 // If stack id is specified in activity options, usually it means that activity is
1704 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1705 // that case we check the target stack.
1706 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1707 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1708 }
1709 if (mDoResume) {
1710 mTargetStack.moveToFront("reuseOrNewTask");
1711 }
1712 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001713 }
1714
1715 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001716 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1717 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1718 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1719 }
1720
Wale Ogunwale01d66562015-12-29 08:19:19 -08001721 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001722 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001723 // We only want to allow changing stack if the target task is not the top one,
1724 // otherwise we would move the launching task to the other side, rather than show
1725 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001726 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001727 if (moveStackAllowed) {
1728 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1729 mOptions);
1730 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001731
1732 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001733 mTargetStack = sourceStack;
1734 } else if (mTargetStack != sourceStack) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001735 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1736 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1737 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001738
Wale Ogunwale01d66562015-12-29 08:19:19 -08001739 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001740 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001741 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1742 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001743 } else if (mDoResume) {
1744 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001745 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001746
Wale Ogunwale01d66562015-12-29 08:19:19 -08001747 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1748 // In this case, we are adding the activity to an existing task, but the caller has
1749 // asked to clear that task if the activity is already running.
1750 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1751 mKeepCurTransition = true;
1752 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001753 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001754 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1755 // For paranoia, make sure we have correctly resumed the top activity.
1756 mTargetStack.mLastPausedActivity = null;
1757 if (mDoResume) {
1758 mSupervisor.resumeFocusedStackTopActivityLocked();
1759 }
1760 ActivityOptions.abort(mOptions);
1761 return START_DELIVERED_TO_TOP;
1762 }
1763 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1764 // In this case, we are launching an activity in our own task that may already be
1765 // running somewhere in the history, and we want to shuffle it to the front of the
1766 // stack if so.
1767 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1768 if (top != null) {
1769 final TaskRecord task = top.task;
1770 task.moveActivityToFrontLocked(top);
1771 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001772 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001773 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1774 mTargetStack.mLastPausedActivity = null;
1775 if (mDoResume) {
1776 mSupervisor.resumeFocusedStackTopActivityLocked();
1777 }
1778 return START_DELIVERED_TO_TOP;
1779 }
1780 }
1781
1782 // An existing activity is starting this new activity, so we want to keep the new one in
1783 // the same task as the one that is starting it.
1784 mStartActivity.setTask(sourceTask, null);
1785 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1786 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1787 return START_SUCCESS;
1788 }
1789
1790 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001791 // The caller is asking that the new activity be started in an explicit
1792 // task it has provided to us.
1793 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1794 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1795 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1796 }
1797
Wale Ogunwale01d66562015-12-29 08:19:19 -08001798 if (mLaunchBounds != null) {
1799 mInTask.updateOverrideConfiguration(mLaunchBounds);
1800 int stackId = mInTask.getLaunchStackId();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001801 if (stackId != mInTask.getStackId()) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001802 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001803 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001804 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001805 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001806 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001807 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001808 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001809 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001810 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001811 mTargetStack.moveTaskToFrontLocked(
1812 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1813
1814 // Check whether we should actually launch the new activity in to the task,
1815 // or just reuse the current activity on top.
1816 ActivityRecord top = mInTask.getTopActivity();
1817 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1818 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1819 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001820 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001821 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1822 // We don't need to start a new activity, and the client said not to do
1823 // anything if that is the case, so this is it!
1824 return START_RETURN_INTENT_TO_CALLER;
1825 }
1826 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1827 return START_DELIVERED_TO_TOP;
1828 }
1829 }
1830
1831 if (!mAddingToTask) {
1832 // We don't actually want to have this activity added to the task, so just
1833 // stop here but still tell the caller that we consumed the intent.
1834 ActivityOptions.abort(mOptions);
1835 return START_TASK_TO_FRONT;
1836 }
1837
1838 mStartActivity.setTask(mInTask, null);
1839 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1840 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1841
1842 return START_SUCCESS;
1843 }
1844
1845 private void setTaskToCurrentTopOrCreateNewTask() {
1846 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1847 mOptions);
1848 if (mDoResume) {
1849 mTargetStack.moveToFront("addingToTopTask");
1850 }
1851 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001852 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1853 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1854 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001855 mStartActivity.setTask(task, null);
1856 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1857 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1858 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1859 }
1860
1861 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1862 boolean launchSingleTask, int launchFlags) {
1863 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1864 (launchSingleInstance || launchSingleTask)) {
1865 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1866 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1867 "\"singleInstance\" or \"singleTask\"");
1868 launchFlags &=
1869 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1870 } else {
1871 switch (r.info.documentLaunchMode) {
1872 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1873 break;
1874 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1875 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1876 break;
1877 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1878 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1879 break;
1880 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1881 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1882 break;
1883 }
1884 }
1885 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001886 }
1887
1888 final void doPendingActivityLaunchesLocked(boolean doResume) {
1889 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001890 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1891 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001892 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001893 final int result = startActivityUnchecked(
1894 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1895 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001896 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1897 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001898 } catch (Exception e) {
1899 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1900 pal.sendErrorResult(e.getMessage());
1901 }
1902 }
1903 }
1904
1905 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001906 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001907 final TaskRecord task = r.task;
1908 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1909 return mSupervisor.mHomeStack;
1910 }
1911
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001912 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001913 if (stack != null) {
1914 return stack;
1915 }
1916
Andrii Kulian02b7a832016-10-06 23:11:56 -07001917 final ActivityStack currentStack = task != null ? task.getStack() : null;
1918 if (currentStack != null) {
1919 if (currentStack.isOnHomeDisplay()) {
1920 if (mSupervisor.mFocusedStack != currentStack) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001921 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1922 "computeStackFocus: Setting " + "focused stack to r=" + r
1923 + " task=" + task);
1924 } else {
1925 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1926 "computeStackFocus: Focused stack already="
1927 + mSupervisor.mFocusedStack);
1928 }
1929 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001930 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001931 }
1932
1933 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1934 if (container != null) {
1935 // The first time put it on the desired stack, after this put on task stack.
1936 r.mInitialActivityContainer = null;
1937 return container.mStack;
1938 }
1939
1940 // The fullscreen stack can contain any task regardless of if the task is resizeable
1941 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1942 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1943 // we can also put it in the focused stack.
1944 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001945 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1946 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1947 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001948 if (canUseFocusedStack && (!newTask
1949 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1950 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1951 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1952 return mSupervisor.mFocusedStack;
1953 }
1954
1955 // We first try to put the task in the first dynamic stack.
1956 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1957 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1958 stack = homeDisplayStacks.get(stackNdx);
1959 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1960 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1961 "computeStackFocus: Setting focused stack=" + stack);
1962 return stack;
1963 }
1964 }
1965
1966 // If there is no suitable dynamic stack then we figure out which static stack to use.
1967 final int stackId = task != null ? task.getLaunchStackId() :
1968 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1969 FULLSCREEN_WORKSPACE_STACK_ID;
1970 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1971 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1972 + r + " stackId=" + stack.mStackId);
1973 return stack;
1974 }
1975
Wale Ogunwale854809c2015-12-27 16:18:19 -08001976 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001977 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001978
1979 // We are reusing a task, keep the stack!
1980 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001981 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07001982 }
1983
Wale Ogunwale854809c2015-12-27 16:18:19 -08001984 final int launchStackId =
1985 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1986
1987 if (isValidLaunchStackId(launchStackId, r)) {
1988 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001989 } else if (launchStackId == DOCKED_STACK_ID) {
1990 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1991 // for this activity, so we put the activity in the fullscreen stack.
1992 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001993 }
1994
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001995 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001996 return null;
1997 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001998 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001999
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002000 // The parent activity doesn't want to launch the activity on top of itself, but
2001 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002002 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002003 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2004 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002005
2006 if (parentStack != mSupervisor.mFocusedStack) {
2007 // If task's parent stack is not focused - use it during adjacent launch.
2008 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002009 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002010 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2011 // If task is already on top of focused stack - use it. We don't want to move the
2012 // existing focused task to adjacent stack, just deliver new intent in this case.
2013 return mSupervisor.mFocusedStack;
2014 }
2015
2016 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2017 // If parent was in docked stack, the natural place to launch another activity
2018 // will be fullscreen, so it can appear alongside the docked window.
2019 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2020 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002021 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002022 // If the parent is not in the docked stack, we check if there is docked window
2023 // and if yes, we will launch into that stack. If not, we just put the new
2024 // activity into parent's stack, because we can't find a better place.
2025 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2026 if (dockedStack != null
2027 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2028 // There is a docked stack, but it isn't visible, so we can't launch into that.
2029 return null;
2030 } else {
2031 return dockedStack;
2032 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002033 }
2034 }
2035 }
2036
Wale Ogunwale854809c2015-12-27 16:18:19 -08002037 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2038 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2039 || !StackId.isStaticStack(stackId)) {
2040 return false;
2041 }
2042
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002043 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2044 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2045 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002046 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002047
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002048 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2049 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002050 }
2051
2052 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2053 return false;
2054 }
2055
2056 final boolean supportsPip = mService.mSupportsPictureInPicture
2057 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2058 if (stackId == PINNED_STACK_ID && !supportsPip) {
2059 return false;
2060 }
2061 return true;
2062 }
2063
Wale Ogunwale854809c2015-12-27 16:18:19 -08002064 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2065 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002066 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002067 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2068 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002069 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002070 }
2071 }
2072 return newBounds;
2073 }
2074
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002075 void setWindowManager(WindowManagerService wm) {
2076 mWindowManager = wm;
2077 }
2078
2079 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2080 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2081 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2082 if (pal.stack == stack) {
2083 mPendingActivityLaunches.remove(palNdx);
2084 }
2085 }
2086 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002087
2088 static boolean isDocumentLaunchesIntoExisting(int flags) {
2089 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2090 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2091 }
liulvpingcfa825f2016-09-26 20:00:15 +08002092
2093 boolean clearPendingActivityLaunchesLocked(String packageName) {
2094 boolean didSomething = false;
2095
2096 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2097 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2098 ActivityRecord r = pal.r;
2099 if (r != null && r.packageName.equals(packageName)) {
2100 mPendingActivityLaunches.remove(palNdx);
2101 didSomething = true;
2102 }
2103 }
2104 return didSomething;
2105 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002106}