blob: 006c13d97fd46fc2ebfbac4d0294226eb8be1b49 [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;
84import android.app.IActivityManager;
85import android.app.IApplicationThread;
Tony Mak853304c2016-04-18 15:17:41 +010086import android.app.KeyguardManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080087import android.app.PendingIntent;
88import android.app.ProfilerInfo;
89import 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) {
580 // If someone asked to have the keyguard dismissed on the next activity start,
581 // but we are not actually doing an activity switch... just dismiss the keyguard now,
582 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800583 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800584 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800585 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800586
Chong Zhang5022da32016-06-21 16:31:37 -0700587 // We're waiting for an activity launch to finish, but that activity simply
588 // brought another activity to front. Let startActivityMayWait() know about
589 // this, so it waits for the new activity to become visible instead.
590 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
591 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
592 }
593
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800594 int startedActivityStackId = INVALID_STACK_ID;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700595 final ActivityStack currentStack = r.getStack();
596 if (currentStack != null) {
597 startedActivityStackId = currentStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800598 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700599 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800600 }
601
Jorim Jaggi352d5842016-05-19 10:20:28 -0700602 // If we launched the activity from a no display activity that was launched from the home
603 // screen, we also need to start recents to un-minimize the docked stack, since the
604 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700605 // Note that some apps have trampoline activities without noDisplay being set. In that case,
606 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
607 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700608 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
609 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700610 final boolean noDisplayActivityOverHome = sourceRecord != null
611 && sourceRecord.noDisplay
612 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700613 if (startedActivityStackId == DOCKED_STACK_ID
614 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100615 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
616 final ActivityRecord topActivityHomeStack = homeStack != null
617 ? homeStack.topRunningActivityLocked() : null;
618 if (topActivityHomeStack == null
619 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
620 // We launch an activity while being in home stack, which means either launcher or
621 // recents into docked stack. We don't want the launched activity to be alone in a
622 // docked stack, so we want to immediately launch recents too.
623 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700624 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100625 return;
626 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800627 }
628
629 if (startedActivityStackId == PINNED_STACK_ID
630 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
631 // The activity was already running in the pinned stack so it wasn't started, but either
632 // brought to the front or the new intent was delivered to it since it was already in
633 // front. Notify anyone interested in this piece of information.
Yorke Leebd54c2a2016-10-25 13:49:23 -0700634 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800635 return;
636 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800637 }
638
639 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
640 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
641 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
642 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
643 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
644 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
645 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700646 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800647 null /*container*/, null /*inTask*/);
648 if (mSupervisor.inResumeTopActivity) {
649 // If we are in resume section already, home activity will be initialized, but not
650 // resumed (to avoid recursive resume) and will stay that way until something pokes it
651 // again. We need to schedule another resume.
652 mSupervisor.scheduleResumeTopActivities();
653 }
654 }
655
Tony Mak853304c2016-04-18 15:17:41 +0100656 void showConfirmDeviceCredential(int userId) {
657 // First, retrieve the stack that we want to resume after credential is confirmed.
658 ActivityStack targetStack;
659 ActivityStack fullscreenStack =
660 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
661 if (fullscreenStack != null &&
662 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
663 // Single window case and the case that the docked stack is shown with fullscreen stack.
664 targetStack = fullscreenStack;
665 } else {
666 // The case that the docked stack is shown with recent.
667 targetStack = mSupervisor.getStack(HOME_STACK_ID);
668 }
669 if (targetStack == null) {
670 return;
671 }
672 final KeyguardManager km = (KeyguardManager) mService.mContext
673 .getSystemService(Context.KEYGUARD_SERVICE);
674 final Intent credential =
675 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100676 // For safety, check null here in case users changed the setting after the checking.
677 if (credential == null) {
678 return;
679 }
Tony Mak853304c2016-04-18 15:17:41 +0100680 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
681 if (activityRecord != null) {
682 final IIntentSender target = mService.getIntentSenderLocked(
683 ActivityManager.INTENT_SENDER_ACTIVITY,
684 activityRecord.launchedFromPackage,
685 activityRecord.launchedFromUid,
686 activityRecord.userId,
687 null, null, 0,
688 new Intent[] { activityRecord.intent },
689 new String[] { activityRecord.resolvedType },
690 PendingIntent.FLAG_CANCEL_CURRENT |
691 PendingIntent.FLAG_ONE_SHOT |
692 PendingIntent.FLAG_IMMUTABLE,
693 null);
694 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
695 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100696 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100697 }
698 }
699
Tony Mak646fe992016-04-21 16:43:08 +0100700 void startConfirmCredentialIntent(Intent intent) {
701 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
702 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
703 FLAG_ACTIVITY_TASK_ON_HOME);
704 final ActivityOptions options = ActivityOptions.makeBasic();
705 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
706 mService.mContext.startActivityAsUser(intent, options.toBundle(),
707 UserHandle.CURRENT);
708 }
Tony Mak853304c2016-04-18 15:17:41 +0100709
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800710 final int startActivityMayWait(IApplicationThread caller, int callingUid,
711 String callingPackage, Intent intent, String resolvedType,
712 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
713 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Andrii Kulian8072d112016-09-16 11:11:01 -0700714 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult,
715 Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800716 IActivityContainer iContainer, TaskRecord inTask) {
717 // Refuse possible leaked file descriptors
718 if (intent != null && intent.hasFileDescriptors()) {
719 throw new IllegalArgumentException("File descriptors passed in Intent");
720 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500721 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800722 boolean componentSpecified = intent.getComponent() != null;
723
724 // Save a copy in case ephemeral needs it
725 final Intent ephemeralIntent = new Intent(intent);
726 // Don't modify the client's object!
727 intent = new Intent(intent);
728
729 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000730 if (rInfo == null) {
731 UserInfo userInfo = mSupervisor.getUserInfo(userId);
732 if (userInfo != null && userInfo.isManagedProfile()) {
733 // Special case for managed profiles, if attempting to launch non-cryto aware
734 // app in a locked managed profile from an unlocked parent allow it to resolve
735 // as user will be sent via confirm credentials to unlock the profile.
736 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700737 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000738 long token = Binder.clearCallingIdentity();
739 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700740 UserInfo parent = userManager.getProfileParent(userId);
741 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
742 && userManager.isUserUnlockingOrUnlocked(parent.id)
743 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000744 } finally {
745 Binder.restoreCallingIdentity(token);
746 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700747 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000748 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600749 PackageManager.MATCH_DIRECT_BOOT_AWARE
750 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000751 }
752 }
753 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800754 // Collect information about the target of the Intent.
755 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
756
757 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
758 ActivityStackSupervisor.ActivityContainer container =
759 (ActivityStackSupervisor.ActivityContainer)iContainer;
760 synchronized (mService) {
761 if (container != null && container.mParentActivity != null &&
762 container.mParentActivity.state != RESUMED) {
763 // Cannot start a child activity if the parent is not resumed.
764 return ActivityManager.START_CANCELED;
765 }
766 final int realCallingPid = Binder.getCallingPid();
767 final int realCallingUid = Binder.getCallingUid();
768 int callingPid;
769 if (callingUid >= 0) {
770 callingPid = -1;
771 } else if (caller == null) {
772 callingPid = realCallingPid;
773 callingUid = realCallingUid;
774 } else {
775 callingPid = callingUid = -1;
776 }
777
778 final ActivityStack stack;
779 if (container == null || container.mStack.isOnHomeDisplay()) {
780 stack = mSupervisor.mFocusedStack;
781 } else {
782 stack = container.mStack;
783 }
Andrii Kulian8072d112016-09-16 11:11:01 -0700784 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700785 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800786 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
787 "Starting activity when config will change = " + stack.mConfigWillChange);
788
789 final long origId = Binder.clearCallingIdentity();
790
791 if (aInfo != null &&
792 (aInfo.applicationInfo.privateFlags
793 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
794 // This may be a heavy-weight process! Check to see if we already
795 // have another, different heavy-weight process running.
796 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
797 final ProcessRecord heavy = mService.mHeavyWeightProcess;
798 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
799 || !heavy.processName.equals(aInfo.processName))) {
800 int appCallingUid = callingUid;
801 if (caller != null) {
802 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
803 if (callerApp != null) {
804 appCallingUid = callerApp.info.uid;
805 } else {
806 Slog.w(TAG, "Unable to find app for caller " + caller
807 + " (pid=" + callingPid + ") when starting: "
808 + intent.toString());
809 ActivityOptions.abort(options);
810 return ActivityManager.START_PERMISSION_DENIED;
811 }
812 }
813
814 IIntentSender target = mService.getIntentSenderLocked(
815 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
816 appCallingUid, userId, null, null, 0, new Intent[] { intent },
817 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
818 | PendingIntent.FLAG_ONE_SHOT, null);
819
820 Intent newIntent = new Intent();
821 if (requestCode >= 0) {
822 // Caller is requesting a result.
823 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
824 }
825 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
826 new IntentSender(target));
827 if (heavy.activities.size() > 0) {
828 ActivityRecord hist = heavy.activities.get(0);
829 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
830 hist.packageName);
831 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
832 hist.task.taskId);
833 }
834 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
835 aInfo.packageName);
836 newIntent.setFlags(intent.getFlags());
837 newIntent.setClassName("android",
838 HeavyWeightSwitcherActivity.class.getName());
839 intent = newIntent;
840 resolvedType = null;
841 caller = null;
842 callingUid = Binder.getCallingUid();
843 callingPid = Binder.getCallingPid();
844 componentSpecified = true;
845 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
846 aInfo = rInfo != null ? rInfo.activityInfo : null;
847 if (aInfo != null) {
848 aInfo = mService.getActivityInfoForUser(aInfo, userId);
849 }
850 }
851 }
852 }
853
Jorim Jaggi275561a2016-02-23 10:11:02 -0500854 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800855 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
856 aInfo, rInfo, voiceSession, voiceInteractor,
857 resultTo, resultWho, requestCode, callingPid,
858 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500859 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
860 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800861
862 Binder.restoreCallingIdentity(origId);
863
864 if (stack.mConfigWillChange) {
865 // If the caller also wants to switch to a new configuration,
866 // do so now. This allows a clean switch, as we are waiting
867 // for the current activity to pause (so we will not destroy
868 // it), and have not yet started the next activity.
869 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
870 "updateConfiguration()");
871 stack.mConfigWillChange = false;
872 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
873 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -0700874 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800875 }
876
877 if (outResult != null) {
878 outResult.result = res;
879 if (res == ActivityManager.START_SUCCESS) {
880 mSupervisor.mWaitingActivityLaunched.add(outResult);
881 do {
882 try {
883 mService.wait();
884 } catch (InterruptedException e) {
885 }
Chong Zhang5022da32016-06-21 16:31:37 -0700886 } while (outResult.result != START_TASK_TO_FRONT
887 && !outResult.timeout && outResult.who == null);
888 if (outResult.result == START_TASK_TO_FRONT) {
889 res = START_TASK_TO_FRONT;
890 }
891 }
892 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800893 ActivityRecord r = stack.topRunningActivityLocked();
894 if (r.nowVisible && r.state == RESUMED) {
895 outResult.timeout = false;
896 outResult.who = new ComponentName(r.info.packageName, r.info.name);
897 outResult.totalTime = 0;
898 outResult.thisTime = 0;
899 } else {
900 outResult.thisTime = SystemClock.uptimeMillis();
901 mSupervisor.mWaitingActivityVisible.add(outResult);
902 do {
903 try {
904 mService.wait();
905 } catch (InterruptedException e) {
906 }
907 } while (!outResult.timeout && outResult.who == null);
908 }
909 }
910 }
911
Jorim Jaggibe67c902016-04-12 00:53:16 -0700912 final ActivityRecord launchedActivity = mReusedActivity != null
913 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700914 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800915 return res;
916 }
917 }
918
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800919 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
920 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
921 Bundle bOptions, int userId) {
922 if (intents == null) {
923 throw new NullPointerException("intents is null");
924 }
925 if (resolvedTypes == null) {
926 throw new NullPointerException("resolvedTypes is null");
927 }
928 if (intents.length != resolvedTypes.length) {
929 throw new IllegalArgumentException("intents are length different than resolvedTypes");
930 }
931
Makoto Onukid67b1872016-07-21 16:26:36 -0700932 final int realCallingPid = Binder.getCallingPid();
933 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800934
935 int callingPid;
936 if (callingUid >= 0) {
937 callingPid = -1;
938 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700939 callingPid = realCallingPid;
940 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800941 } else {
942 callingPid = callingUid = -1;
943 }
944 final long origId = Binder.clearCallingIdentity();
945 try {
946 synchronized (mService) {
947 ActivityRecord[] outActivity = new ActivityRecord[1];
948 for (int i=0; i<intents.length; i++) {
949 Intent intent = intents[i];
950 if (intent == null) {
951 continue;
952 }
953
954 // Refuse possible leaked file descriptors
955 if (intent != null && intent.hasFileDescriptors()) {
956 throw new IllegalArgumentException("File descriptors passed in Intent");
957 }
958
959 boolean componentSpecified = intent.getComponent() != null;
960
961 // Don't modify the client's object!
962 intent = new Intent(intent);
963
964 // Collect information about the target of the Intent.
965 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
966 null, userId);
967 // TODO: New, check if this is correct
968 aInfo = mService.getActivityInfoForUser(aInfo, userId);
969
970 if (aInfo != null &&
971 (aInfo.applicationInfo.privateFlags
972 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
973 throw new IllegalArgumentException(
974 "FLAG_CANT_SAVE_STATE not supported here");
975 }
976
977 ActivityOptions options = ActivityOptions.fromBundle(
978 i == intents.length - 1 ? bOptions : null);
979 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
980 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700981 callingPid, callingUid, callingPackage,
982 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800983 options, false, componentSpecified, outActivity, null, null);
984 if (res < 0) {
985 return res;
986 }
987
988 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
989 }
990 }
991 } finally {
992 Binder.restoreCallingIdentity(origId);
993 }
994
Wale Ogunwale01d66562015-12-29 08:19:19 -0800995 return START_SUCCESS;
996 }
997
Wei Wang65c7a152016-06-02 18:51:22 -0700998 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
999 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -07001000 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1001 final ActivityRecord curTop = (focusStack == null)
1002 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1003 if ((forceSend || (!mPowerHintSent && curTop != null &&
1004 curTop.task != null && mStartActivity != null &&
1005 curTop.task != mStartActivity.task )) &&
1006 mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -07001007 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -07001008 mPowerHintSent = true;
1009 }
1010 }
1011
Wei Wang65c7a152016-06-02 18:51:22 -07001012 void sendPowerHintForLaunchEndIfNeeded() {
1013 // Trigger launch power hint if activity is launched
1014 if (mPowerHintSent && mService.mLocalPowerManager != null) {
Ruchi Kandoi0d434042016-10-03 09:12:02 -07001015 mService.mLocalPowerManager.powerHint(PowerHint.LAUNCH, 0);
Wei Wang65c7a152016-06-02 18:51:22 -07001016 mPowerHintSent = false;
1017 }
1018 }
1019
Wale Ogunwale01d66562015-12-29 08:19:19 -08001020 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1021 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1022 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1023
1024 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1025 voiceInteractor);
1026
1027 computeLaunchingTaskFlags();
1028
1029 computeSourceStack();
1030
1031 mIntent.setFlags(mLaunchFlags);
1032
Jorim Jaggibe67c902016-04-12 00:53:16 -07001033 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001034
Jorim Jaggi2adba072016-03-03 13:43:39 +01001035 final int preferredLaunchStackId =
1036 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1037
Jorim Jaggibe67c902016-04-12 00:53:16 -07001038 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001039 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1040 // still needs to be a lock task mode violation since the task gets cleared out and
1041 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001042 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001043 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1044 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1045 mSupervisor.showLockTaskToast();
1046 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1047 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1048 }
1049
1050 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001051 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001052 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001053 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001054 // This task was started because of movement of the activity based on affinity...
1055 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001056 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001057 }
1058
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001059 // This code path leads to delivering a new intent, we want to make sure we schedule it
1060 // as the first operation, in case the activity will be resumed as a result of later
1061 // operations.
1062 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001063 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001064 || mLaunchSingleInstance || mLaunchSingleTask) {
1065 // In this situation we want to remove all activities from the task up to the one
1066 // being started. In most cases this means we are resetting the task to its initial
1067 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001068 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001069 mStartActivity, mLaunchFlags);
1070 if (top != null) {
1071 if (top.frontOfTask) {
1072 // Activity aliases may mean we use different intents for the top activity,
1073 // so make sure the task now has the identity of the new intent.
1074 top.task.setIntent(mStartActivity);
1075 }
1076 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1077 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1078 mStartActivity.launchedFromPackage);
1079 }
1080 }
1081
Wei Wang65c7a152016-06-02 18:51:22 -07001082 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001083
Jorim Jaggibe67c902016-04-12 00:53:16 -07001084 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001085
1086 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1087 // We don't need to start a new activity, and the client said not to do anything
1088 // if that is the case, so this is it! And for paranoia, make sure we have
1089 // correctly resumed the top activity.
1090 resumeTargetStackIfNeeded();
1091 return START_RETURN_INTENT_TO_CALLER;
1092 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001093 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001094
1095 if (!mAddingToTask && mReuseTask == null) {
1096 // We didn't do anything... but it was needed (a.k.a., client don't use that
1097 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1098 resumeTargetStackIfNeeded();
1099 return START_TASK_TO_FRONT;
1100 }
1101 }
1102
1103 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001104 final ActivityStack sourceStack = mStartActivity.resultTo != null
1105 ? mStartActivity.resultTo.getStack() : null;
1106 if (sourceStack != null) {
1107 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1108 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1109 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001110 }
1111 ActivityOptions.abort(mOptions);
1112 return START_CLASS_NOT_FOUND;
1113 }
1114
1115 // If the activity being launched is the same as the one currently at the top, then
1116 // we need to check if it should only be launched once.
1117 final ActivityStack topStack = mSupervisor.mFocusedStack;
1118 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1119 final boolean dontStart = top != null && mStartActivity.resultTo == null
1120 && top.realActivity.equals(mStartActivity.realActivity)
1121 && top.userId == mStartActivity.userId
1122 && top.app != null && top.app.thread != null
1123 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1124 || mLaunchSingleTop || mLaunchSingleTask);
1125 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001126 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001127 // For paranoia, make sure we have correctly resumed the top activity.
1128 topStack.mLastPausedActivity = null;
1129 if (mDoResume) {
1130 mSupervisor.resumeFocusedStackTopActivityLocked();
1131 }
1132 ActivityOptions.abort(mOptions);
1133 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1134 // We don't need to start a new activity, and the client said not to do
1135 // anything if that is the case, so this is it!
1136 return START_RETURN_INTENT_TO_CALLER;
1137 }
1138 top.deliverNewIntentLocked(
1139 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001140
1141 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1142 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1143 mSupervisor.handleNonResizableTaskIfNeeded(
1144 top.task, preferredLaunchStackId, topStack.mStackId);
1145
Wale Ogunwale01d66562015-12-29 08:19:19 -08001146 return START_DELIVERED_TO_TOP;
1147 }
1148
1149 boolean newTask = false;
1150 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1151 ? mSourceRecord.task : null;
1152
1153 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001154 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001155 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1156 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1157 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001158 result = setTaskFromReuseOrCreateNewTask(
1159 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001160 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001161 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001162 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001163 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001164 } else {
1165 // This not being started from an existing activity, and not part of a new task...
1166 // just put it in the top task, though these days this case should never happen.
1167 setTaskToCurrentTopOrCreateNewTask();
1168 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001169 if (result != START_SUCCESS) {
1170 return result;
1171 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001172
1173 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1174 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1175
1176 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1177 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1178 }
1179 if (newTask) {
1180 EventLog.writeEvent(
1181 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1182 }
1183 ActivityStack.logStartActivity(
1184 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1185 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001186
Wei Wang65c7a152016-06-02 18:51:22 -07001187 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001188
Wale Ogunwale01d66562015-12-29 08:19:19 -08001189 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1190 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001191 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1192 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001193 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1194 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001195 // If the activity is not focusable, we can't resume it, but still would like to
1196 // make sure it becomes visible as it starts (this will also trigger entry
1197 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001198 // Also, we don't want to resume activities in a task that currently has an overlay
1199 // as the starting activity just needs to be in the visible paused state until the
1200 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001201 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001202 // Go ahead and tell window manager to execute app transition for this activity
1203 // since the app transition will not be triggered through the resume channel.
1204 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001205 } else {
1206 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1207 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001208 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001209 } else {
1210 mTargetStack.addRecentActivityLocked(mStartActivity);
1211 }
1212 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1213
Jorim Jaggid53f0922016-04-06 22:16:23 -07001214 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001215 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001216
1217 return START_SUCCESS;
1218 }
1219
1220 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1221 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1222 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1223 reset();
1224
1225 mStartActivity = r;
1226 mIntent = r.intent;
1227 mOptions = options;
1228 mCallingUid = r.launchedFromUid;
1229 mSourceRecord = sourceRecord;
1230 mVoiceSession = voiceSession;
1231 mVoiceInteractor = voiceInteractor;
1232
1233 mLaunchBounds = getOverrideBounds(r, options, inTask);
1234
1235 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1236 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1237 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1238 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1239 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1240 mLaunchTaskBehind = r.mLaunchTaskBehind
1241 && !mLaunchSingleTask && !mLaunchSingleInstance
1242 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1243
1244 sendNewTaskResultRequestIfNeeded();
1245
1246 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1247 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1248 }
1249
1250 // If we are actually going to launch in to a new task, there are some cases where
1251 // we further want to do multiple task.
1252 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1253 if (mLaunchTaskBehind
1254 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1255 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1256 }
1257 }
1258
1259 // We'll invoke onUserLeaving before onPause only if the launching
1260 // activity did not explicitly state that this is an automated launch.
1261 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1262 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1263 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1264
1265 // If the caller has asked not to resume at this point, we make note
1266 // of this in the record so that we can skip it when trying to find
1267 // the top running activity.
1268 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001269 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001270 r.delayedResume = true;
1271 mDoResume = false;
1272 }
1273
Wale Ogunwale3b232392016-05-13 15:37:13 -07001274 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1275 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001276 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1277 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1278 if (top != null && !top.visible) {
1279
1280 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1281 // it!
1282 mDoResume = false;
1283 mAvoidMoveToFront = true;
1284 }
1285 }
1286
Wale Ogunwale01d66562015-12-29 08:19:19 -08001287 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1288
1289 mInTask = inTask;
1290 // In some flows in to this function, we retrieve the task record and hold on to it
1291 // without a lock before calling back in to here... so the task at this point may
1292 // not actually be in recents. Check for that, and if it isn't in recents just
1293 // consider it invalid.
1294 if (inTask != null && !inTask.inRecents) {
1295 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1296 mInTask = null;
1297 }
1298
1299 mStartFlags = startFlags;
1300 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1301 // is the same as the one making the call... or, as a special case, if we do not know
1302 // the caller then we count the current top activity as the caller.
1303 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1304 ActivityRecord checkedCaller = sourceRecord;
1305 if (checkedCaller == null) {
1306 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1307 mNotTop);
1308 }
1309 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1310 // Caller is not the same as launcher, so always needed.
1311 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1312 }
1313 }
1314
1315 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1316 }
1317
1318 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001319 final ActivityStack sourceStack = mStartActivity.resultTo != null
1320 ? mStartActivity.resultTo.getStack() : null;
1321 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001322 // For whatever reason this activity is being launched into a new task...
1323 // yet the caller has requested a result back. Well, that is pretty messed up,
1324 // so instead immediately send back a cancel and let the new task continue launched
1325 // as normal without a dependency on its originator.
1326 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001327 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1328 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1329 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001330 mStartActivity.resultTo = null;
1331 }
1332 }
1333
1334 private void computeLaunchingTaskFlags() {
1335 // If the caller is not coming from another activity, but has given us an explicit task into
1336 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001337 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001338 final Intent baseIntent = mInTask.getBaseIntent();
1339 final ActivityRecord root = mInTask.getRootActivity();
1340 if (baseIntent == null) {
1341 ActivityOptions.abort(mOptions);
1342 throw new IllegalArgumentException("Launching into task without base intent: "
1343 + mInTask);
1344 }
1345
1346 // If this task is empty, then we are adding the first activity -- it
1347 // determines the root, and must be launching as a NEW_TASK.
1348 if (mLaunchSingleInstance || mLaunchSingleTask) {
1349 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1350 ActivityOptions.abort(mOptions);
1351 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1352 + mStartActivity + " into different task " + mInTask);
1353 }
1354 if (root != null) {
1355 ActivityOptions.abort(mOptions);
1356 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1357 + " has root " + root + " but target is singleInstance/Task");
1358 }
1359 }
1360
1361 // If task is empty, then adopt the interesting intent launch flags in to the
1362 // activity being started.
1363 if (root == null) {
1364 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1365 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1366 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1367 | (baseIntent.getFlags() & flagsOfInterest);
1368 mIntent.setFlags(mLaunchFlags);
1369 mInTask.setIntent(mStartActivity);
1370 mAddingToTask = true;
1371
1372 // If the task is not empty and the caller is asking to start it as the root of
1373 // a new task, then we don't actually want to start this on the task. We will
1374 // bring the task to the front, and possibly give it a new intent.
1375 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1376 mAddingToTask = false;
1377
1378 } else {
1379 mAddingToTask = true;
1380 }
1381
1382 mReuseTask = mInTask;
1383 } else {
1384 mInTask = null;
1385 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1386 // when in freeform workspace.
1387 // Also put noDisplay activities in the source task. These by itself can be placed
1388 // in any task/stack, however it could launch other activities like ResolverActivity,
1389 // and we want those to stay in the original task.
1390 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1391 && mSourceRecord.isFreeform()) {
1392 mAddingToTask = true;
1393 }
1394 }
1395
1396 if (mInTask == null) {
1397 if (mSourceRecord == null) {
1398 // This activity is not being started from another... in this
1399 // case we -always- start a new task.
1400 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1401 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1402 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1403 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1404 }
1405 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1406 // The original activity who is starting us is running as a single
1407 // instance... this new activity it is starting must go on its
1408 // own task.
1409 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1410 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1411 // The activity being started is a single instance... it always
1412 // gets launched into its own task.
1413 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1414 }
1415 }
1416 }
1417
1418 private void computeSourceStack() {
1419 if (mSourceRecord == null) {
1420 mSourceStack = null;
1421 return;
1422 }
1423 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001424 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001425 return;
1426 }
1427
1428 // If the source is finishing, we can't further count it as our source. This is because the
1429 // task it is associated with may now be empty and on its way out, so we don't want to
1430 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1431 // a task for it. But save the task information so it can be used when creating the new task.
1432 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1433 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1434 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1435 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1436 mNewTaskInfo = mSourceRecord.info;
1437 mNewTaskIntent = mSourceRecord.task.intent;
1438 }
1439 mSourceRecord = null;
1440 mSourceStack = null;
1441 }
1442
1443 /**
1444 * Decide whether the new activity should be inserted into an existing task. Returns null
1445 * if not or an ActivityRecord with the task into which the new activity should be added.
1446 */
1447 private ActivityRecord getReusableIntentActivity() {
1448 // We may want to try to place the new activity in to an existing task. We always
1449 // do this if the target activity is singleTask or singleInstance; we will also do
1450 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1451 // us to still place it in a new task: multi task, always doc mode, or being asked to
1452 // launch this as a new task behind the current one.
1453 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1454 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1455 || mLaunchSingleInstance || mLaunchSingleTask;
1456 // If bring to front is requested, and no result is requested and we have not been given
1457 // an explicit task to launch in to, and we can find a task that was started with this
1458 // same component, then instead of launching bring that one to the front.
1459 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1460 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001461 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1462 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1463 intentActivity = task != null ? task.getTopActivity() : null;
1464 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001465 if (mLaunchSingleInstance) {
1466 // There can be one and only one instance of single instance activity in the
1467 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001468 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001469 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1470 // For the launch adjacent case we only want to put the activity in an existing
1471 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001472 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1473 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001474 } else {
1475 // Otherwise find the best task to put the activity in.
1476 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1477 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001478 }
1479 return intentActivity;
1480 }
1481
1482 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001483 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001484 mTargetStack.mLastPausedActivity = null;
1485 // If the target task is not in the front, then we need to bring it to the front...
1486 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1487 // the same behavior as if a new instance was being started, which means not bringing it
1488 // to the front if the caller is not itself in the front.
1489 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1490 ActivityRecord curTop = (focusStack == null)
1491 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1492
Jorim Jaggic875ae72016-04-26 22:41:06 -07001493 if (curTop != null
1494 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1495 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001496 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1497 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1498 mSourceStack.topActivity().task == mSourceRecord.task)) {
1499 // We really do want to push this one into the user's face, right now.
1500 if (mLaunchTaskBehind && mSourceRecord != null) {
1501 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1502 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001503 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001504
1505 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1506 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1507 // So no point resuming any of the activities here, it just wastes one extra
1508 // resuming, plus enter AND exit transitions.
1509 // Here we only want to bring the target stack forward. Transition will be applied
1510 // to the new activity that's started after the old ones are gone.
1511 final boolean willClearTask =
1512 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1513 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1514 if (!willClearTask) {
1515 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001516 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001517 if (launchStack == null || launchStack == mTargetStack) {
1518 // We only want to move to the front, if we aren't going to launch on a
1519 // different stack. If we launch on a different stack, we will put the
1520 // task on top there.
1521 mTargetStack.moveTaskToFrontLocked(
1522 intentActivity.task, mNoAnimation, mOptions,
1523 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1524 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001525 } else if (launchStack.mStackId == DOCKED_STACK_ID
1526 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1527 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1528 // If we want to launch adjacent and mTargetStack is not the computed
1529 // launch stack - move task to top of computed stack.
1530 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1531 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1532 ANIMATE);
1533 } else {
1534 // TODO: This should be reevaluated in MW v2.
1535 // We choose to move task to front instead of launching it adjacent
1536 // when specific stack was requested explicitly and it appeared to be
1537 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1538 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1539 mOptions, mStartActivity.appTimeTracker,
1540 "bringToFrontInsteadOfAdjacentLaunch");
1541 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001542 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001543 }
1544 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001545 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001546 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001547 }
1548 }
1549 if (!mMovedToFront && mDoResume) {
1550 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1551 + " from " + intentActivity);
1552 mTargetStack.moveToFront("intentActivityFound");
1553 }
1554
Jorim Jaggid53f0922016-04-06 22:16:23 -07001555 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1556 mTargetStack.mStackId);
1557
Wale Ogunwale01d66562015-12-29 08:19:19 -08001558 // If the caller has requested that the target task be reset, then do so.
1559 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1560 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1561 }
1562 return intentActivity;
1563 }
1564
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001565 private void updateTaskReturnToType(
1566 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Jiaquan Hee13e9642016-06-15 15:16:13 -07001567 if (focusedStack != null && focusedStack.isHomeStack() &&
1568 focusedStack.topTask().isOnTopLauncher()) {
1569 // Since an on-top launcher will is moved to back when tasks are launched from it,
1570 // those tasks should first try to return to a non-home activity.
1571 // This also makes sure that non-home activities are visible under a transparent
1572 // non-home activity.
1573 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1574 return;
1575 } else if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001576 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1577 // Caller wants to appear on home activity.
1578 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1579 return;
1580 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1581 // Task will be launched over the home stack, so return home.
1582 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1583 return;
1584 }
1585
1586 // Else we are coming from an application stack so return to an application.
1587 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1588 }
1589
Wale Ogunwale01d66562015-12-29 08:19:19 -08001590 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1591 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1592 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1593 // The caller has requested to completely replace any existing task with its new
1594 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001595 intentActivity.task.performClearTaskLocked();
1596 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001597 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001598 // When we clear the task - focus will be adjusted, which will bring another task
1599 // to top before we launch the activity we need. This will temporary swap their
1600 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1601 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001602 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1603 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001604 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1605 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001606 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001607 // A special case: we need to start the activity because it is not currently
1608 // running, and the caller has asked to clear the current task to have this
1609 // activity at the top.
1610 mAddingToTask = true;
1611 // Now pretend like this activity is being started by the top of its task, so it
1612 // is put in the right place.
1613 mSourceRecord = intentActivity;
1614 final TaskRecord task = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001615 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001616 // Target stack got cleared when we all activities were removed above.
1617 // Go ahead and reset it.
1618 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1619 null /* bounds */, mLaunchFlags, mOptions);
1620 mTargetStack.addTask(task,
1621 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1622 }
1623 }
1624 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1625 // In this case the top activity on the task is the same as the one being launched,
1626 // so we take that as a request to bring the task to the foreground. If the top
1627 // activity in the task is the root activity, deliver this new intent to it if it
1628 // desires.
1629 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1630 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001631 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001632 intentActivity.task);
1633 if (intentActivity.frontOfTask) {
1634 intentActivity.task.setIntent(mStartActivity);
1635 }
1636 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1637 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001638 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001639 // In this case we are launching the root activity of the task, but with a
1640 // different intent. We should start a new instance on top.
1641 mAddingToTask = true;
1642 mSourceRecord = intentActivity;
1643 }
1644 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1645 // In this case an activity is being launched in to an existing task, without
1646 // resetting that task. This is typically the situation of launching an activity
1647 // from a notification or shortcut. We want to place the new activity on top of the
1648 // current task.
1649 mAddingToTask = true;
1650 mSourceRecord = intentActivity;
1651 } else if (!intentActivity.task.rootWasReset) {
1652 // In this case we are launching into an existing task that has not yet been started
1653 // from its front door. The current task has been brought to the front. Ideally,
1654 // we'd probably like to place this new task at the bottom of its stack, but that's
1655 // a little hard to do with the current organization of the code so for now we'll
1656 // just drop it.
1657 intentActivity.task.setIntent(mStartActivity);
1658 }
1659 }
1660
1661 private void resumeTargetStackIfNeeded() {
1662 if (mDoResume) {
1663 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1664 if (!mMovedToFront) {
1665 // Make sure to notify Keyguard as well if we are not running an app transition
1666 // later.
1667 mSupervisor.notifyActivityDrawnForKeyguard();
1668 }
1669 } else {
1670 ActivityOptions.abort(mOptions);
1671 }
1672 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1673 }
1674
Chong Zhang6cda19c2016-06-14 19:07:56 -07001675 private int setTaskFromReuseOrCreateNewTask(
1676 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1677 mTargetStack = computeStackFocus(
1678 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1679
1680 // Do no move the target stack to front yet, as we might bail if
1681 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001682
1683 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001684 final TaskRecord task = mTargetStack.createTaskRecord(
1685 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001686 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1687 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1688 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1689 mStartActivity.setTask(task, taskToAffiliate);
1690 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001691 final int stackId = mTargetStack.mStackId;
1692 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001693 mService.resizeStack(
1694 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001695 } else {
1696 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1697 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001698 }
1699 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1700 "Starting new activity " +
1701 mStartActivity + " in new task " + mStartActivity.task);
1702 } else {
1703 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1704 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001705
1706 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1707 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1708 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1709 }
1710
1711 if (!mMovedOtherTask) {
1712 // If stack id is specified in activity options, usually it means that activity is
1713 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1714 // that case we check the target stack.
1715 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1716 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1717 }
1718 if (mDoResume) {
1719 mTargetStack.moveToFront("reuseOrNewTask");
1720 }
1721 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001722 }
1723
1724 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001725 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1726 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1727 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1728 }
1729
Wale Ogunwale01d66562015-12-29 08:19:19 -08001730 final TaskRecord sourceTask = mSourceRecord.task;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001731 final ActivityStack sourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001732 // We only want to allow changing stack if the target task is not the top one,
1733 // otherwise we would move the launching task to the other side, rather than show
1734 // two side by side.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001735 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask;
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001736 if (moveStackAllowed) {
1737 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1738 mOptions);
1739 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001740
1741 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001742 mTargetStack = sourceStack;
1743 } else if (mTargetStack != sourceStack) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001744 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1745 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1746 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001747
Wale Ogunwale01d66562015-12-29 08:19:19 -08001748 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001749 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001750 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1751 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001752 } else if (mDoResume) {
1753 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001754 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001755
Wale Ogunwale01d66562015-12-29 08:19:19 -08001756 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1757 // In this case, we are adding the activity to an existing task, but the caller has
1758 // asked to clear that task if the activity is already running.
1759 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1760 mKeepCurTransition = true;
1761 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001762 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001763 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1764 // For paranoia, make sure we have correctly resumed the top activity.
1765 mTargetStack.mLastPausedActivity = null;
1766 if (mDoResume) {
1767 mSupervisor.resumeFocusedStackTopActivityLocked();
1768 }
1769 ActivityOptions.abort(mOptions);
1770 return START_DELIVERED_TO_TOP;
1771 }
1772 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1773 // In this case, we are launching an activity in our own task that may already be
1774 // running somewhere in the history, and we want to shuffle it to the front of the
1775 // stack if so.
1776 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1777 if (top != null) {
1778 final TaskRecord task = top.task;
1779 task.moveActivityToFrontLocked(top);
1780 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001781 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001782 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1783 mTargetStack.mLastPausedActivity = null;
1784 if (mDoResume) {
1785 mSupervisor.resumeFocusedStackTopActivityLocked();
1786 }
1787 return START_DELIVERED_TO_TOP;
1788 }
1789 }
1790
1791 // An existing activity is starting this new activity, so we want to keep the new one in
1792 // the same task as the one that is starting it.
1793 mStartActivity.setTask(sourceTask, null);
1794 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1795 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1796 return START_SUCCESS;
1797 }
1798
1799 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001800 // The caller is asking that the new activity be started in an explicit
1801 // task it has provided to us.
1802 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1803 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1804 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1805 }
1806
Wale Ogunwale01d66562015-12-29 08:19:19 -08001807 if (mLaunchBounds != null) {
1808 mInTask.updateOverrideConfiguration(mLaunchBounds);
1809 int stackId = mInTask.getLaunchStackId();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001810 if (stackId != mInTask.getStackId()) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001811 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001812 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001813 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001814 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001815 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001816 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001817 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001818 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001819 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001820 mTargetStack.moveTaskToFrontLocked(
1821 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1822
1823 // Check whether we should actually launch the new activity in to the task,
1824 // or just reuse the current activity on top.
1825 ActivityRecord top = mInTask.getTopActivity();
1826 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1827 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1828 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001829 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001830 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1831 // We don't need to start a new activity, and the client said not to do
1832 // anything if that is the case, so this is it!
1833 return START_RETURN_INTENT_TO_CALLER;
1834 }
1835 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1836 return START_DELIVERED_TO_TOP;
1837 }
1838 }
1839
1840 if (!mAddingToTask) {
1841 // We don't actually want to have this activity added to the task, so just
1842 // stop here but still tell the caller that we consumed the intent.
1843 ActivityOptions.abort(mOptions);
1844 return START_TASK_TO_FRONT;
1845 }
1846
1847 mStartActivity.setTask(mInTask, null);
1848 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1849 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1850
1851 return START_SUCCESS;
1852 }
1853
1854 private void setTaskToCurrentTopOrCreateNewTask() {
1855 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1856 mOptions);
1857 if (mDoResume) {
1858 mTargetStack.moveToFront("addingToTopTask");
1859 }
1860 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001861 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1862 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1863 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001864 mStartActivity.setTask(task, null);
1865 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1866 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1867 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1868 }
1869
1870 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1871 boolean launchSingleTask, int launchFlags) {
1872 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1873 (launchSingleInstance || launchSingleTask)) {
1874 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1875 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1876 "\"singleInstance\" or \"singleTask\"");
1877 launchFlags &=
1878 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1879 } else {
1880 switch (r.info.documentLaunchMode) {
1881 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1882 break;
1883 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1884 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1885 break;
1886 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1887 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1888 break;
1889 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1890 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1891 break;
1892 }
1893 }
1894 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001895 }
1896
1897 final void doPendingActivityLaunchesLocked(boolean doResume) {
1898 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001899 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1900 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001901 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001902 final int result = startActivityUnchecked(
1903 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1904 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001905 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1906 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001907 } catch (Exception e) {
1908 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1909 pal.sendErrorResult(e.getMessage());
1910 }
1911 }
1912 }
1913
1914 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001915 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001916 final TaskRecord task = r.task;
1917 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1918 return mSupervisor.mHomeStack;
1919 }
1920
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001921 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001922 if (stack != null) {
1923 return stack;
1924 }
1925
Andrii Kulian02b7a832016-10-06 23:11:56 -07001926 final ActivityStack currentStack = task != null ? task.getStack() : null;
1927 if (currentStack != null) {
1928 if (currentStack.isOnHomeDisplay()) {
1929 if (mSupervisor.mFocusedStack != currentStack) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001930 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1931 "computeStackFocus: Setting " + "focused stack to r=" + r
1932 + " task=" + task);
1933 } else {
1934 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1935 "computeStackFocus: Focused stack already="
1936 + mSupervisor.mFocusedStack);
1937 }
1938 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001939 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001940 }
1941
1942 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1943 if (container != null) {
1944 // The first time put it on the desired stack, after this put on task stack.
1945 r.mInitialActivityContainer = null;
1946 return container.mStack;
1947 }
1948
1949 // The fullscreen stack can contain any task regardless of if the task is resizeable
1950 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1951 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1952 // we can also put it in the focused stack.
1953 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001954 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1955 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1956 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001957 if (canUseFocusedStack && (!newTask
1958 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1959 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1960 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1961 return mSupervisor.mFocusedStack;
1962 }
1963
1964 // We first try to put the task in the first dynamic stack.
1965 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1966 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1967 stack = homeDisplayStacks.get(stackNdx);
1968 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1969 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1970 "computeStackFocus: Setting focused stack=" + stack);
1971 return stack;
1972 }
1973 }
1974
1975 // If there is no suitable dynamic stack then we figure out which static stack to use.
1976 final int stackId = task != null ? task.getLaunchStackId() :
1977 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1978 FULLSCREEN_WORKSPACE_STACK_ID;
1979 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1980 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1981 + r + " stackId=" + stack.mStackId);
1982 return stack;
1983 }
1984
Wale Ogunwale854809c2015-12-27 16:18:19 -08001985 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001986 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001987
1988 // We are reusing a task, keep the stack!
1989 if (mReuseTask != null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001990 return mReuseTask.getStack();
Jorim Jaggib8c58762016-04-20 17:58:29 -07001991 }
1992
Wale Ogunwale854809c2015-12-27 16:18:19 -08001993 final int launchStackId =
1994 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1995
1996 if (isValidLaunchStackId(launchStackId, r)) {
1997 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001998 } else if (launchStackId == DOCKED_STACK_ID) {
1999 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
2000 // for this activity, so we put the activity in the fullscreen stack.
2001 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08002002 }
2003
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002004 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002005 return null;
2006 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002007 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002008
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002009 // The parent activity doesn't want to launch the activity on top of itself, but
2010 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002011 final ActivityStack parentStack = task != null ? task.getStack()
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002012 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2013 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002014
2015 if (parentStack != mSupervisor.mFocusedStack) {
2016 // If task's parent stack is not focused - use it during adjacent launch.
2017 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002018 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002019 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2020 // If task is already on top of focused stack - use it. We don't want to move the
2021 // existing focused task to adjacent stack, just deliver new intent in this case.
2022 return mSupervisor.mFocusedStack;
2023 }
2024
2025 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2026 // If parent was in docked stack, the natural place to launch another activity
2027 // will be fullscreen, so it can appear alongside the docked window.
2028 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2029 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002030 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002031 // If the parent is not in the docked stack, we check if there is docked window
2032 // and if yes, we will launch into that stack. If not, we just put the new
2033 // activity into parent's stack, because we can't find a better place.
2034 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2035 if (dockedStack != null
2036 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2037 // There is a docked stack, but it isn't visible, so we can't launch into that.
2038 return null;
2039 } else {
2040 return dockedStack;
2041 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002042 }
2043 }
2044 }
2045
Wale Ogunwale854809c2015-12-27 16:18:19 -08002046 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2047 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2048 || !StackId.isStaticStack(stackId)) {
2049 return false;
2050 }
2051
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002052 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2053 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2054 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002055 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002056
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002057 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2058 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002059 }
2060
2061 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2062 return false;
2063 }
2064
2065 final boolean supportsPip = mService.mSupportsPictureInPicture
2066 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2067 if (stackId == PINNED_STACK_ID && !supportsPip) {
2068 return false;
2069 }
2070 return true;
2071 }
2072
Wale Ogunwale854809c2015-12-27 16:18:19 -08002073 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2074 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002075 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002076 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2077 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002078 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002079 }
2080 }
2081 return newBounds;
2082 }
2083
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002084 void setWindowManager(WindowManagerService wm) {
2085 mWindowManager = wm;
2086 }
2087
2088 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2089 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2090 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2091 if (pal.stack == stack) {
2092 mPendingActivityLaunches.remove(palNdx);
2093 }
2094 }
2095 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002096
2097 static boolean isDocumentLaunchesIntoExisting(int flags) {
2098 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2099 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2100 }
liulvpingcfa825f2016-09-26 20:00:15 +08002101
2102 boolean clearPendingActivityLaunchesLocked(String packageName) {
2103 boolean didSomething = false;
2104
2105 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2106 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2107 ActivityRecord r = pal.r;
2108 if (r != null && r.packageName.equals(packageName)) {
2109 mPendingActivityLaunches.remove(palNdx);
2110 didSomething = true;
2111 }
2112 }
2113 return didSomething;
2114 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002115}