blob: 6622b34c110668cc6f89c34a98023d4931880699 [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;
101import android.os.Binder;
102import android.os.Build;
103import android.os.Bundle;
104import android.os.IBinder;
105import android.os.RemoteException;
106import android.os.SystemClock;
107import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000108import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800109import android.service.voice.IVoiceInteractionSession;
110import android.util.EventLog;
111import android.util.Slog;
112import android.view.Display;
113
114import com.android.internal.app.HeavyWeightSwitcherActivity;
115import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800116import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
117import com.android.server.wm.WindowManagerService;
118
119import java.util.ArrayList;
120
121/**
122 * Controller for interpreting how and then launching activities.
123 *
124 * This class collects all the logic for determining how an intent and flags should be turned into
125 * an activity and associated task and stack.
126 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800127class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800128 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
129 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
130 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
131 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
132 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
133
134 private final ActivityManagerService mService;
135 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000136 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800137 private WindowManagerService mWindowManager;
138
139 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
140
Wale Ogunwale01d66562015-12-29 08:19:19 -0800141 // Share state variable among methods when starting an activity.
142 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700143 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800144 private Intent mIntent;
145 private int mCallingUid;
146 private ActivityOptions mOptions;
147
148 private boolean mLaunchSingleTop;
149 private boolean mLaunchSingleInstance;
150 private boolean mLaunchSingleTask;
151 private boolean mLaunchTaskBehind;
152 private int mLaunchFlags;
153
154 private Rect mLaunchBounds;
155
156 private ActivityRecord mNotTop;
157 private boolean mDoResume;
158 private int mStartFlags;
159 private ActivityRecord mSourceRecord;
160
161 private TaskRecord mInTask;
162 private boolean mAddingToTask;
163 private TaskRecord mReuseTask;
164
165 private ActivityInfo mNewTaskInfo;
166 private Intent mNewTaskIntent;
167 private ActivityStack mSourceStack;
168 private ActivityStack mTargetStack;
169 // TODO: Is the mMoveHome flag really needed?
170 private boolean mMovedHome;
171 private boolean mMovedToFront;
172 private boolean mNoAnimation;
173 private boolean mKeepCurTransition;
174
175 private IVoiceInteractionSession mVoiceSession;
176 private IVoiceInteractor mVoiceInteractor;
177
178 private void reset() {
179 mStartActivity = null;
180 mIntent = null;
181 mCallingUid = -1;
182 mOptions = null;
183
184 mLaunchSingleTop = false;
185 mLaunchSingleInstance = false;
186 mLaunchSingleTask = false;
187 mLaunchTaskBehind = false;
188 mLaunchFlags = 0;
189
190 mLaunchBounds = null;
191
192 mNotTop = null;
193 mDoResume = false;
194 mStartFlags = 0;
195 mSourceRecord = null;
196
197 mInTask = null;
198 mAddingToTask = false;
199 mReuseTask = null;
200
201 mNewTaskInfo = null;
202 mNewTaskIntent = null;
203 mSourceStack = null;
204
205 mTargetStack = null;
206 mMovedHome = false;
207 mMovedToFront = false;
208 mNoAnimation = false;
209 mKeepCurTransition = false;
210
211 mVoiceSession = null;
212 mVoiceInteractor = null;
213 }
214
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800215 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
216 mService = service;
217 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000218 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800219 }
220
221 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
222 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
223 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
224 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
225 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
226 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
227 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
228 TaskRecord inTask) {
229 int err = ActivityManager.START_SUCCESS;
230
231 ProcessRecord callerApp = null;
232 if (caller != null) {
233 callerApp = mService.getRecordForAppLocked(caller);
234 if (callerApp != null) {
235 callingPid = callerApp.pid;
236 callingUid = callerApp.info.uid;
237 } else {
238 Slog.w(TAG, "Unable to find app for caller " + caller
239 + " (pid=" + callingPid + ") when starting: "
240 + intent.toString());
241 err = ActivityManager.START_PERMISSION_DENIED;
242 }
243 }
244
245 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
246
247 if (err == ActivityManager.START_SUCCESS) {
248 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
249 + "} from uid " + callingUid
250 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
251 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
252 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
253 container.mActivityDisplay.mDisplayId)));
254 }
255
256 ActivityRecord sourceRecord = null;
257 ActivityRecord resultRecord = null;
258 if (resultTo != null) {
259 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
260 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
261 "Will send result to " + resultTo + " " + sourceRecord);
262 if (sourceRecord != null) {
263 if (requestCode >= 0 && !sourceRecord.finishing) {
264 resultRecord = sourceRecord;
265 }
266 }
267 }
268
269 final int launchFlags = intent.getFlags();
270
271 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
272 // Transfer the result target from the source activity to the new
273 // one being started, including any failures.
274 if (requestCode >= 0) {
275 ActivityOptions.abort(options);
276 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
277 }
278 resultRecord = sourceRecord.resultTo;
279 if (resultRecord != null && !resultRecord.isInStackLocked()) {
280 resultRecord = null;
281 }
282 resultWho = sourceRecord.resultWho;
283 requestCode = sourceRecord.requestCode;
284 sourceRecord.resultTo = null;
285 if (resultRecord != null) {
286 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
287 }
288 if (sourceRecord.launchedFromUid == callingUid) {
289 // The new activity is being launched from the same uid as the previous
290 // activity in the flow, and asking to forward its result back to the
291 // previous. In this case the activity is serving as a trampoline between
292 // the two, so we also want to update its launchedFromPackage to be the
293 // same as the previous activity. Note that this is safe, since we know
294 // these two packages come from the same uid; the caller could just as
295 // well have supplied that same package name itself. This specifially
296 // deals with the case of an intent picker/chooser being launched in the app
297 // flow to redirect to an activity picked by the user, where we want the final
298 // activity to consider it to have been launched by the previous app activity.
299 callingPackage = sourceRecord.launchedFromPackage;
300 }
301 }
302
303 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
304 // We couldn't find a class that can handle the given Intent.
305 // That's the end of that!
306 err = ActivityManager.START_INTENT_NOT_RESOLVED;
307 }
308
309 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
310 // We couldn't find the specific class specified in the Intent.
311 // Also the end of the line.
312 err = ActivityManager.START_CLASS_NOT_FOUND;
313 }
314
315 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
316 && sourceRecord.task.voiceSession != null) {
317 // If this activity is being launched as part of a voice session, we need
318 // to ensure that it is safe to do so. If the upcoming activity will also
319 // be part of the voice session, we can only launch it if it has explicitly
320 // said it supports the VOICE category, or it is a part of the calling app.
321 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
322 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
323 try {
324 intent.addCategory(Intent.CATEGORY_VOICE);
325 if (!AppGlobals.getPackageManager().activitySupportsIntent(
326 intent.getComponent(), intent, resolvedType)) {
327 Slog.w(TAG,
328 "Activity being started in current voice task does not support voice: "
329 + intent);
330 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
331 }
332 } catch (RemoteException e) {
333 Slog.w(TAG, "Failure checking voice capabilities", e);
334 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
335 }
336 }
337 }
338
339 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
340 // If the caller is starting a new voice session, just make sure the target
341 // is actually allowing it to run this way.
342 try {
343 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
344 intent, resolvedType)) {
345 Slog.w(TAG,
346 "Activity being started in new voice task does not support: "
347 + intent);
348 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
349 }
350 } catch (RemoteException e) {
351 Slog.w(TAG, "Failure checking voice capabilities", e);
352 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
353 }
354 }
355
356 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
357
Wale Ogunwale01d66562015-12-29 08:19:19 -0800358 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800359 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800360 resultStack.sendActivityResultLocked(
361 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800362 }
363 ActivityOptions.abort(options);
364 return err;
365 }
366
367 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
368 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100369 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800370 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
371 callingPid, resolvedType, aInfo.applicationInfo);
372
373 if (mService.mController != null) {
374 try {
375 // The Intent we give to the watcher has the extra data
376 // stripped off, since it can contain private information.
377 Intent watchIntent = intent.cloneFilter();
378 abort |= !mService.mController.activityStarting(watchIntent,
379 aInfo.applicationInfo.packageName);
380 } catch (RemoteException e) {
381 mService.mController = null;
382 }
383 }
384
Rubin Xu58d25992016-01-21 17:47:13 +0000385 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100386 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
387 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000388 intent = mInterceptor.mIntent;
389 rInfo = mInterceptor.mRInfo;
390 aInfo = mInterceptor.mAInfo;
391 resolvedType = mInterceptor.mResolvedType;
392 inTask = mInterceptor.mInTask;
393 callingPid = mInterceptor.mCallingPid;
394 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100395 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800396 if (abort) {
397 if (resultRecord != null) {
398 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800399 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800400 }
401 // We pretend to the caller that it was really started, but
402 // they will just get a cancel result.
403 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800404 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800405 }
406
407 // If permissions need a review before any of the app components can run, we
408 // launch the review activity and pass a pending intent to start the activity
409 // we are to launching now after the review is completed.
410 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
411 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
412 aInfo.packageName, userId)) {
413 IIntentSender target = mService.getIntentSenderLocked(
414 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
415 callingUid, userId, null, null, 0, new Intent[]{intent},
416 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
417 | PendingIntent.FLAG_ONE_SHOT, null);
418
419 final int flags = intent.getFlags();
420 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
421 newIntent.setFlags(flags
422 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
423 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
424 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
425 if (resultRecord != null) {
426 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
427 }
428 intent = newIntent;
429
430 resolvedType = null;
431 callingUid = realCallingUid;
432 callingPid = realCallingPid;
433
434 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
435 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
436 null /*profilerInfo*/);
437
438 if (DEBUG_PERMISSIONS_REVIEW) {
439 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
440 true, false) + "} from uid " + callingUid + " on display "
441 + (container == null ? (mSupervisor.mFocusedStack == null ?
442 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
443 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
444 container.mActivityDisplay.mDisplayId)));
445 }
446 }
447 }
448
449 // If we have an ephemeral app, abort the process of launching the resolved intent.
450 // Instead, launch the ephemeral installer. Once the installer is finished, it
451 // starts either the intent we resolved here [on install error] or the ephemeral
452 // app [on install success].
453 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
454 // Create a pending intent to start the intent resolved here.
455 final IIntentSender failureTarget = mService.getIntentSenderLocked(
456 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
457 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
458 new String[]{ resolvedType },
459 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
460 | PendingIntent.FLAG_IMMUTABLE, null);
461
462 // Create a pending intent to start the ephemeral application; force it to be
463 // directed to the ephemeral package.
464 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
465 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
466 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
467 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
468 new String[]{ resolvedType },
469 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
470 | PendingIntent.FLAG_IMMUTABLE, null);
471
472 int flags = intent.getFlags();
473 intent = new Intent();
474 intent.setFlags(flags
475 | Intent.FLAG_ACTIVITY_NEW_TASK
476 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
477 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
478 rInfo.ephemeralResolveInfo.getPackageName());
479 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
480 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
481
482 resolvedType = null;
483 callingUid = realCallingUid;
484 callingPid = realCallingPid;
485
486 rInfo = rInfo.ephemeralInstaller;
487 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
488 }
489
490 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
491 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
492 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
493 options);
494 if (outActivity != null) {
495 outActivity[0] = r;
496 }
497
498 if (r.appTimeTracker == null && sourceRecord != null) {
499 // If the caller didn't specify an explicit time tracker, we want to continue
500 // tracking under any it has.
501 r.appTimeTracker = sourceRecord.appTimeTracker;
502 }
503
504 final ActivityStack stack = mSupervisor.mFocusedStack;
505 if (voiceSession == null && (stack.mResumedActivity == null
506 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
507 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
508 realCallingPid, realCallingUid, "Activity start")) {
509 PendingActivityLaunch pal = new PendingActivityLaunch(r,
510 sourceRecord, startFlags, stack, callerApp);
511 mPendingActivityLaunches.add(pal);
512 ActivityOptions.abort(options);
513 return ActivityManager.START_SWITCHES_CANCELED;
514 }
515 }
516
517 if (mService.mDidAppSwitch) {
518 // This is the second allowed switch since we stopped switches,
519 // so now just generally allow switches. Use case: user presses
520 // home (switches disabled, switch to home, mDidAppSwitch now true);
521 // user taps a home icon (coming from home so allowed, we hit here
522 // and now allow anyone to switch again).
523 mService.mAppSwitchesAllowedTime = 0;
524 } else {
525 mService.mDidAppSwitch = true;
526 }
527
528 doPendingActivityLaunchesLocked(false);
529
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700530 try {
531 mService.mWindowManager.deferSurfaceLayout();
532 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
533 true, options, inTask);
534 } finally {
535 mService.mWindowManager.continueSurfaceLayout();
536 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800537 postStartActivityUncheckedProcessing(r, err, stack.mStackId);
538 return err;
539 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800540
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800541 void postStartActivityUncheckedProcessing(
542 ActivityRecord r, int result, int prevFocusedStackId) {
543
544 if (result < START_SUCCESS) {
545 // If someone asked to have the keyguard dismissed on the next activity start,
546 // but we are not actually doing an activity switch... just dismiss the keyguard now,
547 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800548 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800549 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800550 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800551
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800552 int startedActivityStackId = INVALID_STACK_ID;
553 if (r.task != null && r.task.stack != null) {
554 startedActivityStackId = r.task.stack.mStackId;
555 } else if (mTargetStack != null) {
556 startedActivityStackId = mTargetStack.mStackId;
557 }
558
559 if (startedActivityStackId == DOCKED_STACK_ID && prevFocusedStackId == HOME_STACK_ID) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100560 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
561 final ActivityRecord topActivityHomeStack = homeStack != null
562 ? homeStack.topRunningActivityLocked() : null;
563 if (topActivityHomeStack == null
564 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
565 // We launch an activity while being in home stack, which means either launcher or
566 // recents into docked stack. We don't want the launched activity to be alone in a
567 // docked stack, so we want to immediately launch recents too.
568 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700569 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100570 return;
571 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800572 }
573
574 if (startedActivityStackId == PINNED_STACK_ID
575 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
576 // The activity was already running in the pinned stack so it wasn't started, but either
577 // brought to the front or the new intent was delivered to it since it was already in
578 // front. Notify anyone interested in this piece of information.
579 mService.notifyPinnedActivityRestartAttemptLocked();
580 return;
581 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800582 }
583
584 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
585 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
586 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
587 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
588 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
589 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
590 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700591 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800592 null /*container*/, null /*inTask*/);
593 if (mSupervisor.inResumeTopActivity) {
594 // If we are in resume section already, home activity will be initialized, but not
595 // resumed (to avoid recursive resume) and will stay that way until something pokes it
596 // again. We need to schedule another resume.
597 mSupervisor.scheduleResumeTopActivities();
598 }
599 }
600
Tony Mak853304c2016-04-18 15:17:41 +0100601 void showConfirmDeviceCredential(int userId) {
602 // First, retrieve the stack that we want to resume after credential is confirmed.
603 ActivityStack targetStack;
604 ActivityStack fullscreenStack =
605 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
606 if (fullscreenStack != null &&
607 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
608 // Single window case and the case that the docked stack is shown with fullscreen stack.
609 targetStack = fullscreenStack;
610 } else {
611 // The case that the docked stack is shown with recent.
612 targetStack = mSupervisor.getStack(HOME_STACK_ID);
613 }
614 if (targetStack == null) {
615 return;
616 }
617 final KeyguardManager km = (KeyguardManager) mService.mContext
618 .getSystemService(Context.KEYGUARD_SERVICE);
619 final Intent credential =
620 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Mak853304c2016-04-18 15:17:41 +0100621 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
622 if (activityRecord != null) {
623 final IIntentSender target = mService.getIntentSenderLocked(
624 ActivityManager.INTENT_SENDER_ACTIVITY,
625 activityRecord.launchedFromPackage,
626 activityRecord.launchedFromUid,
627 activityRecord.userId,
628 null, null, 0,
629 new Intent[] { activityRecord.intent },
630 new String[] { activityRecord.resolvedType },
631 PendingIntent.FLAG_CANCEL_CURRENT |
632 PendingIntent.FLAG_ONE_SHOT |
633 PendingIntent.FLAG_IMMUTABLE,
634 null);
635 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
636 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100637 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100638 }
639 }
640
Tony Mak646fe992016-04-21 16:43:08 +0100641 void startConfirmCredentialIntent(Intent intent) {
642 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
643 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
644 FLAG_ACTIVITY_TASK_ON_HOME);
645 final ActivityOptions options = ActivityOptions.makeBasic();
646 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
647 mService.mContext.startActivityAsUser(intent, options.toBundle(),
648 UserHandle.CURRENT);
649 }
Tony Mak853304c2016-04-18 15:17:41 +0100650
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800651 final int startActivityMayWait(IApplicationThread caller, int callingUid,
652 String callingPackage, Intent intent, String resolvedType,
653 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
654 IBinder resultTo, String resultWho, int requestCode, int startFlags,
655 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
656 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
657 IActivityContainer iContainer, TaskRecord inTask) {
658 // Refuse possible leaked file descriptors
659 if (intent != null && intent.hasFileDescriptors()) {
660 throw new IllegalArgumentException("File descriptors passed in Intent");
661 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500662 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800663 boolean componentSpecified = intent.getComponent() != null;
664
665 // Save a copy in case ephemeral needs it
666 final Intent ephemeralIntent = new Intent(intent);
667 // Don't modify the client's object!
668 intent = new Intent(intent);
669
670 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000671 if (rInfo == null) {
672 UserInfo userInfo = mSupervisor.getUserInfo(userId);
673 if (userInfo != null && userInfo.isManagedProfile()) {
674 // Special case for managed profiles, if attempting to launch non-cryto aware
675 // app in a locked managed profile from an unlocked parent allow it to resolve
676 // as user will be sent via confirm credentials to unlock the profile.
677 UserManager userManager = UserManager.get(mService.mContext);
Tony Mak13436452016-02-24 11:08:38 +0000678 UserInfo parent = null;
679 long token = Binder.clearCallingIdentity();
680 try {
681 parent = userManager.getProfileParent(userId);
682 } finally {
683 Binder.restoreCallingIdentity(token);
684 }
Kenny Guyb1b30262016-02-09 16:02:35 +0000685 if (parent != null
686 && userManager.isUserUnlocked(parent.getUserHandle())
687 && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
688 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600689 PackageManager.MATCH_DIRECT_BOOT_AWARE
690 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000691 }
692 }
693 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800694 // Collect information about the target of the Intent.
695 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
696
697 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
698 ActivityStackSupervisor.ActivityContainer container =
699 (ActivityStackSupervisor.ActivityContainer)iContainer;
700 synchronized (mService) {
701 if (container != null && container.mParentActivity != null &&
702 container.mParentActivity.state != RESUMED) {
703 // Cannot start a child activity if the parent is not resumed.
704 return ActivityManager.START_CANCELED;
705 }
706 final int realCallingPid = Binder.getCallingPid();
707 final int realCallingUid = Binder.getCallingUid();
708 int callingPid;
709 if (callingUid >= 0) {
710 callingPid = -1;
711 } else if (caller == null) {
712 callingPid = realCallingPid;
713 callingUid = realCallingUid;
714 } else {
715 callingPid = callingUid = -1;
716 }
717
718 final ActivityStack stack;
719 if (container == null || container.mStack.isOnHomeDisplay()) {
720 stack = mSupervisor.mFocusedStack;
721 } else {
722 stack = container.mStack;
723 }
724 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
725 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
726 "Starting activity when config will change = " + stack.mConfigWillChange);
727
728 final long origId = Binder.clearCallingIdentity();
729
730 if (aInfo != null &&
731 (aInfo.applicationInfo.privateFlags
732 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
733 // This may be a heavy-weight process! Check to see if we already
734 // have another, different heavy-weight process running.
735 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
736 final ProcessRecord heavy = mService.mHeavyWeightProcess;
737 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
738 || !heavy.processName.equals(aInfo.processName))) {
739 int appCallingUid = callingUid;
740 if (caller != null) {
741 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
742 if (callerApp != null) {
743 appCallingUid = callerApp.info.uid;
744 } else {
745 Slog.w(TAG, "Unable to find app for caller " + caller
746 + " (pid=" + callingPid + ") when starting: "
747 + intent.toString());
748 ActivityOptions.abort(options);
749 return ActivityManager.START_PERMISSION_DENIED;
750 }
751 }
752
753 IIntentSender target = mService.getIntentSenderLocked(
754 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
755 appCallingUid, userId, null, null, 0, new Intent[] { intent },
756 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
757 | PendingIntent.FLAG_ONE_SHOT, null);
758
759 Intent newIntent = new Intent();
760 if (requestCode >= 0) {
761 // Caller is requesting a result.
762 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
763 }
764 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
765 new IntentSender(target));
766 if (heavy.activities.size() > 0) {
767 ActivityRecord hist = heavy.activities.get(0);
768 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
769 hist.packageName);
770 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
771 hist.task.taskId);
772 }
773 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
774 aInfo.packageName);
775 newIntent.setFlags(intent.getFlags());
776 newIntent.setClassName("android",
777 HeavyWeightSwitcherActivity.class.getName());
778 intent = newIntent;
779 resolvedType = null;
780 caller = null;
781 callingUid = Binder.getCallingUid();
782 callingPid = Binder.getCallingPid();
783 componentSpecified = true;
784 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
785 aInfo = rInfo != null ? rInfo.activityInfo : null;
786 if (aInfo != null) {
787 aInfo = mService.getActivityInfoForUser(aInfo, userId);
788 }
789 }
790 }
791 }
792
Jorim Jaggi275561a2016-02-23 10:11:02 -0500793 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800794 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
795 aInfo, rInfo, voiceSession, voiceInteractor,
796 resultTo, resultWho, requestCode, callingPid,
797 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500798 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
799 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800800
801 Binder.restoreCallingIdentity(origId);
802
803 if (stack.mConfigWillChange) {
804 // If the caller also wants to switch to a new configuration,
805 // do so now. This allows a clean switch, as we are waiting
806 // for the current activity to pause (so we will not destroy
807 // it), and have not yet started the next activity.
808 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
809 "updateConfiguration()");
810 stack.mConfigWillChange = false;
811 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
812 "Updating to new configuration after starting activity.");
813 mService.updateConfigurationLocked(config, null, false);
814 }
815
816 if (outResult != null) {
817 outResult.result = res;
818 if (res == ActivityManager.START_SUCCESS) {
819 mSupervisor.mWaitingActivityLaunched.add(outResult);
820 do {
821 try {
822 mService.wait();
823 } catch (InterruptedException e) {
824 }
825 } while (!outResult.timeout && outResult.who == null);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800826 } else if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800827 ActivityRecord r = stack.topRunningActivityLocked();
828 if (r.nowVisible && r.state == RESUMED) {
829 outResult.timeout = false;
830 outResult.who = new ComponentName(r.info.packageName, r.info.name);
831 outResult.totalTime = 0;
832 outResult.thisTime = 0;
833 } else {
834 outResult.thisTime = SystemClock.uptimeMillis();
835 mSupervisor.mWaitingActivityVisible.add(outResult);
836 do {
837 try {
838 mService.wait();
839 } catch (InterruptedException e) {
840 }
841 } while (!outResult.timeout && outResult.who == null);
842 }
843 }
844 }
845
Jorim Jaggi275561a2016-02-23 10:11:02 -0500846 final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
847 : null;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700848 final ActivityRecord launchedActivity = mReusedActivity != null
849 ? mReusedActivity : outRecord[0];
850 final ProcessRecord processRecord = launchedActivity != null
851 ? mService.mProcessNames.get(launchedActivity.processName,
852 launchedActivity.appInfo.uid)
853 : null;
854 final boolean processRunning = processRecord != null;
855
856 // We consider this a "process switch" if the process of the activity that gets launched
857 // didn't have an activity that was in started state. In this case, we assume that lot
858 // of caches might be purged so the time until it produces the first frame is very
859 // interesting.
860 final boolean processSwitch = processRecord == null
861 || !hasStartedActivity(processRecord, launchedActivity);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500862 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
Jorim Jaggibe67c902016-04-12 00:53:16 -0700863 processRunning, processSwitch);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800864 return res;
865 }
866 }
867
Jorim Jaggibe67c902016-04-12 00:53:16 -0700868 final boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
869 final ArrayList<ActivityRecord> activities = record.activities;
870 for (int i = activities.size() - 1; i >= 0; i--) {
871 final ActivityRecord activity = activities.get(i);
872 if (launchedActivity == activity) {
873 continue;
874 }
875 if (!activity.stopped) {
876 return true;
877 }
878 }
879 return false;
880 }
881
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800882 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
883 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
884 Bundle bOptions, int userId) {
885 if (intents == null) {
886 throw new NullPointerException("intents is null");
887 }
888 if (resolvedTypes == null) {
889 throw new NullPointerException("resolvedTypes is null");
890 }
891 if (intents.length != resolvedTypes.length) {
892 throw new IllegalArgumentException("intents are length different than resolvedTypes");
893 }
894
895
896 int callingPid;
897 if (callingUid >= 0) {
898 callingPid = -1;
899 } else if (caller == null) {
900 callingPid = Binder.getCallingPid();
901 callingUid = Binder.getCallingUid();
902 } else {
903 callingPid = callingUid = -1;
904 }
905 final long origId = Binder.clearCallingIdentity();
906 try {
907 synchronized (mService) {
908 ActivityRecord[] outActivity = new ActivityRecord[1];
909 for (int i=0; i<intents.length; i++) {
910 Intent intent = intents[i];
911 if (intent == null) {
912 continue;
913 }
914
915 // Refuse possible leaked file descriptors
916 if (intent != null && intent.hasFileDescriptors()) {
917 throw new IllegalArgumentException("File descriptors passed in Intent");
918 }
919
920 boolean componentSpecified = intent.getComponent() != null;
921
922 // Don't modify the client's object!
923 intent = new Intent(intent);
924
925 // Collect information about the target of the Intent.
926 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
927 null, userId);
928 // TODO: New, check if this is correct
929 aInfo = mService.getActivityInfoForUser(aInfo, userId);
930
931 if (aInfo != null &&
932 (aInfo.applicationInfo.privateFlags
933 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
934 throw new IllegalArgumentException(
935 "FLAG_CANT_SAVE_STATE not supported here");
936 }
937
938 ActivityOptions options = ActivityOptions.fromBundle(
939 i == intents.length - 1 ? bOptions : null);
940 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
941 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
942 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
943 options, false, componentSpecified, outActivity, null, null);
944 if (res < 0) {
945 return res;
946 }
947
948 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
949 }
950 }
951 } finally {
952 Binder.restoreCallingIdentity(origId);
953 }
954
Wale Ogunwale01d66562015-12-29 08:19:19 -0800955 return START_SUCCESS;
956 }
957
958 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
959 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
960 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
961
962 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
963 voiceInteractor);
964
965 computeLaunchingTaskFlags();
966
967 computeSourceStack();
968
969 mIntent.setFlags(mLaunchFlags);
970
Jorim Jaggibe67c902016-04-12 00:53:16 -0700971 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800972
Jorim Jaggi2adba072016-03-03 13:43:39 +0100973 final int preferredLaunchStackId =
974 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
975
Jorim Jaggibe67c902016-04-12 00:53:16 -0700976 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800977 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
978 // still needs to be a lock task mode violation since the task gets cleared out and
979 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700980 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800981 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
982 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
983 mSupervisor.showLockTaskToast();
984 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
985 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
986 }
987
988 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -0700989 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800990 }
Jorim Jaggibe67c902016-04-12 00:53:16 -0700991 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800992 // This task was started because of movement of the activity based on affinity...
993 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700994 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800995 }
996
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800997 // This code path leads to delivering a new intent, we want to make sure we schedule it
998 // as the first operation, in case the activity will be resumed as a result of later
999 // operations.
1000 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1001 || mLaunchSingleInstance || mLaunchSingleTask) {
1002 // In this situation we want to remove all activities from the task up to the one
1003 // being started. In most cases this means we are resetting the task to its initial
1004 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001005 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001006 mStartActivity, mLaunchFlags);
1007 if (top != null) {
1008 if (top.frontOfTask) {
1009 // Activity aliases may mean we use different intents for the top activity,
1010 // so make sure the task now has the identity of the new intent.
1011 top.task.setIntent(mStartActivity);
1012 }
1013 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1014 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1015 mStartActivity.launchedFromPackage);
1016 }
1017 }
1018
Jorim Jaggibe67c902016-04-12 00:53:16 -07001019 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001020
1021 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1022 // We don't need to start a new activity, and the client said not to do anything
1023 // if that is the case, so this is it! And for paranoia, make sure we have
1024 // correctly resumed the top activity.
1025 resumeTargetStackIfNeeded();
1026 return START_RETURN_INTENT_TO_CALLER;
1027 }
1028
Jorim Jaggibe67c902016-04-12 00:53:16 -07001029 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001030
1031 if (!mAddingToTask && mReuseTask == null) {
1032 // We didn't do anything... but it was needed (a.k.a., client don't use that
1033 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1034 resumeTargetStackIfNeeded();
1035 return START_TASK_TO_FRONT;
1036 }
1037 }
1038
1039 if (mStartActivity.packageName == null) {
1040 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1041 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1042 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1043 mStartActivity.requestCode, RESULT_CANCELED, null);
1044 }
1045 ActivityOptions.abort(mOptions);
1046 return START_CLASS_NOT_FOUND;
1047 }
1048
1049 // If the activity being launched is the same as the one currently at the top, then
1050 // we need to check if it should only be launched once.
1051 final ActivityStack topStack = mSupervisor.mFocusedStack;
1052 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1053 final boolean dontStart = top != null && mStartActivity.resultTo == null
1054 && top.realActivity.equals(mStartActivity.realActivity)
1055 && top.userId == mStartActivity.userId
1056 && top.app != null && top.app.thread != null
1057 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1058 || mLaunchSingleTop || mLaunchSingleTask);
1059 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001060 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001061 // For paranoia, make sure we have correctly resumed the top activity.
1062 topStack.mLastPausedActivity = null;
1063 if (mDoResume) {
1064 mSupervisor.resumeFocusedStackTopActivityLocked();
1065 }
1066 ActivityOptions.abort(mOptions);
1067 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1068 // We don't need to start a new activity, and the client said not to do
1069 // anything if that is the case, so this is it!
1070 return START_RETURN_INTENT_TO_CALLER;
1071 }
1072 top.deliverNewIntentLocked(
1073 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001074
1075 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1076 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1077 mSupervisor.handleNonResizableTaskIfNeeded(
1078 top.task, preferredLaunchStackId, topStack.mStackId);
1079
Wale Ogunwale01d66562015-12-29 08:19:19 -08001080 return START_DELIVERED_TO_TOP;
1081 }
1082
1083 boolean newTask = false;
1084 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1085 ? mSourceRecord.task : null;
1086
1087 // Should this be considered a new task?
1088 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1089 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1090 newTask = true;
1091 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1092
1093 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1094 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1095 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1096 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001097 if (!mMovedHome) {
1098 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001099 }
1100 } else if (mSourceRecord != null) {
1101 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1102 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1103 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1104 }
1105
1106 final int result = setTaskFromSourceRecord();
1107 if (result != START_SUCCESS) {
1108 return result;
1109 }
1110 } else if (mInTask != null) {
1111 // The caller is asking that the new activity be started in an explicit
1112 // task it has provided to us.
1113 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1114 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1115 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1116 }
1117
1118 final int result = setTaskFromInTask();
1119 if (result != START_SUCCESS) {
1120 return result;
1121 }
1122 } else {
1123 // This not being started from an existing activity, and not part of a new task...
1124 // just put it in the top task, though these days this case should never happen.
1125 setTaskToCurrentTopOrCreateNewTask();
1126 }
1127
1128 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1129 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1130
1131 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1132 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1133 }
1134 if (newTask) {
1135 EventLog.writeEvent(
1136 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1137 }
1138 ActivityStack.logStartActivity(
1139 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1140 mTargetStack.mLastPausedActivity = null;
1141 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1142 if (mDoResume) {
1143 if (!mLaunchTaskBehind) {
1144 // TODO(b/26381750): Remove this code after verification that all the decision
1145 // points above moved targetStack to the front which will also set the focus
1146 // activity.
1147 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1148 }
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001149 if (mTargetStack.isFocusable()) {
1150 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1151 mOptions);
1152 } else {
1153 // If the activity is not focusable, we can't resume it, but still would like to
1154 // make sure it becomes visible as it starts (this will also trigger entry
1155 // animation). An example of this are PIP activities.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001156 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001157 // Go ahead and tell window manager to execute app transition for this activity
1158 // since the app transition will not be triggered through the resume channel.
1159 mWindowManager.executeAppTransition();
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001160 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001161 } else {
1162 mTargetStack.addRecentActivityLocked(mStartActivity);
1163 }
1164 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1165
Jorim Jaggid53f0922016-04-06 22:16:23 -07001166 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001167 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001168
1169 return START_SUCCESS;
1170 }
1171
1172 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1173 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1174 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1175 reset();
1176
1177 mStartActivity = r;
1178 mIntent = r.intent;
1179 mOptions = options;
1180 mCallingUid = r.launchedFromUid;
1181 mSourceRecord = sourceRecord;
1182 mVoiceSession = voiceSession;
1183 mVoiceInteractor = voiceInteractor;
1184
1185 mLaunchBounds = getOverrideBounds(r, options, inTask);
1186
1187 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1188 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1189 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1190 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1191 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1192 mLaunchTaskBehind = r.mLaunchTaskBehind
1193 && !mLaunchSingleTask && !mLaunchSingleInstance
1194 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1195
1196 sendNewTaskResultRequestIfNeeded();
1197
1198 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1199 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1200 }
1201
1202 // If we are actually going to launch in to a new task, there are some cases where
1203 // we further want to do multiple task.
1204 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1205 if (mLaunchTaskBehind
1206 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1207 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1208 }
1209 }
1210
1211 // We'll invoke onUserLeaving before onPause only if the launching
1212 // activity did not explicitly state that this is an automated launch.
1213 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1214 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1215 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1216
1217 // If the caller has asked not to resume at this point, we make note
1218 // of this in the record so that we can skip it when trying to find
1219 // the top running activity.
1220 mDoResume = doResume;
1221 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1222 r.delayedResume = true;
1223 mDoResume = false;
1224 }
1225
1226 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1227
1228 mInTask = inTask;
1229 // In some flows in to this function, we retrieve the task record and hold on to it
1230 // without a lock before calling back in to here... so the task at this point may
1231 // not actually be in recents. Check for that, and if it isn't in recents just
1232 // consider it invalid.
1233 if (inTask != null && !inTask.inRecents) {
1234 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1235 mInTask = null;
1236 }
1237
1238 mStartFlags = startFlags;
1239 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1240 // is the same as the one making the call... or, as a special case, if we do not know
1241 // the caller then we count the current top activity as the caller.
1242 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1243 ActivityRecord checkedCaller = sourceRecord;
1244 if (checkedCaller == null) {
1245 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1246 mNotTop);
1247 }
1248 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1249 // Caller is not the same as launcher, so always needed.
1250 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1251 }
1252 }
1253
1254 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1255 }
1256
1257 private void sendNewTaskResultRequestIfNeeded() {
1258 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1259 && mStartActivity.resultTo.task.stack != null) {
1260 // For whatever reason this activity is being launched into a new task...
1261 // yet the caller has requested a result back. Well, that is pretty messed up,
1262 // so instead immediately send back a cancel and let the new task continue launched
1263 // as normal without a dependency on its originator.
1264 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1265 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1266 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1267 mStartActivity.resultTo = null;
1268 }
1269 }
1270
1271 private void computeLaunchingTaskFlags() {
1272 // If the caller is not coming from another activity, but has given us an explicit task into
1273 // which they would like us to launch the new activity, then let's see about doing that.
1274 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1275 final Intent baseIntent = mInTask.getBaseIntent();
1276 final ActivityRecord root = mInTask.getRootActivity();
1277 if (baseIntent == null) {
1278 ActivityOptions.abort(mOptions);
1279 throw new IllegalArgumentException("Launching into task without base intent: "
1280 + mInTask);
1281 }
1282
1283 // If this task is empty, then we are adding the first activity -- it
1284 // determines the root, and must be launching as a NEW_TASK.
1285 if (mLaunchSingleInstance || mLaunchSingleTask) {
1286 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1287 ActivityOptions.abort(mOptions);
1288 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1289 + mStartActivity + " into different task " + mInTask);
1290 }
1291 if (root != null) {
1292 ActivityOptions.abort(mOptions);
1293 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1294 + " has root " + root + " but target is singleInstance/Task");
1295 }
1296 }
1297
1298 // If task is empty, then adopt the interesting intent launch flags in to the
1299 // activity being started.
1300 if (root == null) {
1301 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1302 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1303 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1304 | (baseIntent.getFlags() & flagsOfInterest);
1305 mIntent.setFlags(mLaunchFlags);
1306 mInTask.setIntent(mStartActivity);
1307 mAddingToTask = true;
1308
1309 // If the task is not empty and the caller is asking to start it as the root of
1310 // a new task, then we don't actually want to start this on the task. We will
1311 // bring the task to the front, and possibly give it a new intent.
1312 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1313 mAddingToTask = false;
1314
1315 } else {
1316 mAddingToTask = true;
1317 }
1318
1319 mReuseTask = mInTask;
1320 } else {
1321 mInTask = null;
1322 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1323 // when in freeform workspace.
1324 // Also put noDisplay activities in the source task. These by itself can be placed
1325 // in any task/stack, however it could launch other activities like ResolverActivity,
1326 // and we want those to stay in the original task.
1327 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1328 && mSourceRecord.isFreeform()) {
1329 mAddingToTask = true;
1330 }
1331 }
1332
1333 if (mInTask == null) {
1334 if (mSourceRecord == null) {
1335 // This activity is not being started from another... in this
1336 // case we -always- start a new task.
1337 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1338 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1339 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1340 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1341 }
1342 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1343 // The original activity who is starting us is running as a single
1344 // instance... this new activity it is starting must go on its
1345 // own task.
1346 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1347 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1348 // The activity being started is a single instance... it always
1349 // gets launched into its own task.
1350 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1351 }
1352 }
1353 }
1354
1355 private void computeSourceStack() {
1356 if (mSourceRecord == null) {
1357 mSourceStack = null;
1358 return;
1359 }
1360 if (!mSourceRecord.finishing) {
1361 mSourceStack = mSourceRecord.task.stack;
1362 return;
1363 }
1364
1365 // If the source is finishing, we can't further count it as our source. This is because the
1366 // task it is associated with may now be empty and on its way out, so we don't want to
1367 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1368 // a task for it. But save the task information so it can be used when creating the new task.
1369 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1370 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1371 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1372 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1373 mNewTaskInfo = mSourceRecord.info;
1374 mNewTaskIntent = mSourceRecord.task.intent;
1375 }
1376 mSourceRecord = null;
1377 mSourceStack = null;
1378 }
1379
1380 /**
1381 * Decide whether the new activity should be inserted into an existing task. Returns null
1382 * if not or an ActivityRecord with the task into which the new activity should be added.
1383 */
1384 private ActivityRecord getReusableIntentActivity() {
1385 // We may want to try to place the new activity in to an existing task. We always
1386 // do this if the target activity is singleTask or singleInstance; we will also do
1387 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1388 // us to still place it in a new task: multi task, always doc mode, or being asked to
1389 // launch this as a new task behind the current one.
1390 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1391 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1392 || mLaunchSingleInstance || mLaunchSingleTask;
1393 // If bring to front is requested, and no result is requested and we have not been given
1394 // an explicit task to launch in to, and we can find a task that was started with this
1395 // same component, then instead of launching bring that one to the front.
1396 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1397 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001398 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1399 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1400 intentActivity = task != null ? task.getTopActivity() : null;
1401 } else if (putIntoExistingTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001402 // See if there is a task to bring to the front. If this is a SINGLE_INSTANCE
1403 // activity, there can be one and only one instance of it in the history, and it is
1404 // always in its own unique task, so we do a special search.
1405 intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info)
1406 : mSupervisor.findTaskLocked(mStartActivity);
1407 }
1408 return intentActivity;
1409 }
1410
1411 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1412 mTargetStack = intentActivity.task.stack;
1413 mTargetStack.mLastPausedActivity = null;
1414 // If the target task is not in the front, then we need to bring it to the front...
1415 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1416 // the same behavior as if a new instance was being started, which means not bringing it
1417 // to the front if the caller is not itself in the front.
1418 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1419 ActivityRecord curTop = (focusStack == null)
1420 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1421
1422 if (curTop != null && (curTop.task != intentActivity.task ||
1423 curTop.task != focusStack.topTask())) {
1424 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1425 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1426 mSourceStack.topActivity().task == mSourceRecord.task)) {
1427 // We really do want to push this one into the user's face, right now.
1428 if (mLaunchTaskBehind && mSourceRecord != null) {
1429 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1430 }
1431 mMovedHome = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001432
1433 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1434 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1435 // So no point resuming any of the activities here, it just wastes one extra
1436 // resuming, plus enter AND exit transitions.
1437 // Here we only want to bring the target stack forward. Transition will be applied
1438 // to the new activity that's started after the old ones are gone.
1439 final boolean willClearTask =
1440 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1441 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1442 if (!willClearTask) {
1443 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001444 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001445 if (launchStack == null || launchStack == mTargetStack) {
1446 // We only want to move to the front, if we aren't going to launch on a
1447 // different stack. If we launch on a different stack, we will put the
1448 // task on top there.
1449 mTargetStack.moveTaskToFrontLocked(
1450 intentActivity.task, mNoAnimation, mOptions,
1451 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1452 mMovedToFront = true;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001453 } else if ((launchStack.mStackId == DOCKED_STACK_ID
1454 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID)
1455 && (mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1456 // If we want to launch adjacent and mTargetStack is not the computed
1457 // launch stack - move task to top of computed stack.
1458 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1459 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1460 ANIMATE);
1461 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001462 }
1463 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001464 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001465 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001466 }
1467 }
1468 if (!mMovedToFront && mDoResume) {
1469 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1470 + " from " + intentActivity);
1471 mTargetStack.moveToFront("intentActivityFound");
1472 }
1473
Jorim Jaggid53f0922016-04-06 22:16:23 -07001474 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1475 mTargetStack.mStackId);
1476
Wale Ogunwale01d66562015-12-29 08:19:19 -08001477 // If the caller has requested that the target task be reset, then do so.
1478 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1479 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1480 }
1481 return intentActivity;
1482 }
1483
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001484 private void updateTaskReturnToType(
1485 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1486 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1487 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1488 // Caller wants to appear on home activity.
1489 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1490 return;
1491 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1492 // Task will be launched over the home stack, so return home.
1493 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1494 return;
1495 }
1496
1497 // Else we are coming from an application stack so return to an application.
1498 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1499 }
1500
Wale Ogunwale01d66562015-12-29 08:19:19 -08001501 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1502 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1503 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1504 // The caller has requested to completely replace any existing task with its new
1505 // activity. Well that should not be too hard...
1506 mReuseTask = intentActivity.task;
1507 mReuseTask.performClearTaskLocked();
1508 mReuseTask.setIntent(mStartActivity);
1509 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1510 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001511 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1512 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001513 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001514 // A special case: we need to start the activity because it is not currently
1515 // running, and the caller has asked to clear the current task to have this
1516 // activity at the top.
1517 mAddingToTask = true;
1518 // Now pretend like this activity is being started by the top of its task, so it
1519 // is put in the right place.
1520 mSourceRecord = intentActivity;
1521 final TaskRecord task = mSourceRecord.task;
1522 if (task != null && task.stack == null) {
1523 // Target stack got cleared when we all activities were removed above.
1524 // Go ahead and reset it.
1525 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1526 null /* bounds */, mLaunchFlags, mOptions);
1527 mTargetStack.addTask(task,
1528 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1529 }
1530 }
1531 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1532 // In this case the top activity on the task is the same as the one being launched,
1533 // so we take that as a request to bring the task to the foreground. If the top
1534 // activity in the task is the root activity, deliver this new intent to it if it
1535 // desires.
1536 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1537 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001538 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001539 intentActivity.task);
1540 if (intentActivity.frontOfTask) {
1541 intentActivity.task.setIntent(mStartActivity);
1542 }
1543 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1544 mStartActivity.launchedFromPackage);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -08001545 } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001546 // In this case we are launching the root activity of the task, but with a
1547 // different intent. We should start a new instance on top.
1548 mAddingToTask = true;
1549 mSourceRecord = intentActivity;
1550 }
1551 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1552 // In this case an activity is being launched in to an existing task, without
1553 // resetting that task. This is typically the situation of launching an activity
1554 // from a notification or shortcut. We want to place the new activity on top of the
1555 // current task.
1556 mAddingToTask = true;
1557 mSourceRecord = intentActivity;
1558 } else if (!intentActivity.task.rootWasReset) {
1559 // In this case we are launching into an existing task that has not yet been started
1560 // from its front door. The current task has been brought to the front. Ideally,
1561 // we'd probably like to place this new task at the bottom of its stack, but that's
1562 // a little hard to do with the current organization of the code so for now we'll
1563 // just drop it.
1564 intentActivity.task.setIntent(mStartActivity);
1565 }
1566 }
1567
1568 private void resumeTargetStackIfNeeded() {
1569 if (mDoResume) {
1570 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1571 if (!mMovedToFront) {
1572 // Make sure to notify Keyguard as well if we are not running an app transition
1573 // later.
1574 mSupervisor.notifyActivityDrawnForKeyguard();
1575 }
1576 } else {
1577 ActivityOptions.abort(mOptions);
1578 }
1579 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1580 }
1581
1582 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1583 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1584 mOptions);
1585 if (mDoResume) {
1586 mTargetStack.moveToFront("startingNewTask");
1587 }
1588
1589 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001590 final TaskRecord task = mTargetStack.createTaskRecord(
1591 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001592 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1593 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1594 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1595 mStartActivity.setTask(task, taskToAffiliate);
1596 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001597 final int stackId = mTargetStack.mStackId;
1598 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001599 mService.resizeStack(
1600 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001601 } else {
1602 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1603 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001604 }
1605 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1606 "Starting new activity " +
1607 mStartActivity + " in new task " + mStartActivity.task);
1608 } else {
1609 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1610 }
1611 }
1612
1613 private int setTaskFromSourceRecord() {
1614 final TaskRecord sourceTask = mSourceRecord.task;
1615 // We only want to allow changing stack if the target task is not the top one,
1616 // otherwise we would move the launching task to the other side, rather than show
1617 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001618 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1619 if (moveStackAllowed) {
1620 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1621 mOptions);
1622 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001623
1624 if (mTargetStack == null) {
1625 mTargetStack = sourceTask.stack;
1626 } else if (mTargetStack != sourceTask.stack) {
1627 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1628 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1629 }
1630 if (mDoResume) {
1631 mTargetStack.moveToFront("sourceStackToFront");
1632 }
1633 final TaskRecord topTask = mTargetStack.topTask();
1634 if (topTask != sourceTask) {
1635 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1636 mStartActivity.appTimeTracker, "sourceTaskToFront");
1637 }
1638 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1639 // In this case, we are adding the activity to an existing task, but the caller has
1640 // asked to clear that task if the activity is already running.
1641 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1642 mKeepCurTransition = true;
1643 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001644 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001645 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1646 // For paranoia, make sure we have correctly resumed the top activity.
1647 mTargetStack.mLastPausedActivity = null;
1648 if (mDoResume) {
1649 mSupervisor.resumeFocusedStackTopActivityLocked();
1650 }
1651 ActivityOptions.abort(mOptions);
1652 return START_DELIVERED_TO_TOP;
1653 }
1654 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1655 // In this case, we are launching an activity in our own task that may already be
1656 // running somewhere in the history, and we want to shuffle it to the front of the
1657 // stack if so.
1658 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1659 if (top != null) {
1660 final TaskRecord task = top.task;
1661 task.moveActivityToFrontLocked(top);
1662 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001663 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001664 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1665 mTargetStack.mLastPausedActivity = null;
1666 if (mDoResume) {
1667 mSupervisor.resumeFocusedStackTopActivityLocked();
1668 }
1669 return START_DELIVERED_TO_TOP;
1670 }
1671 }
1672
1673 // An existing activity is starting this new activity, so we want to keep the new one in
1674 // the same task as the one that is starting it.
1675 mStartActivity.setTask(sourceTask, null);
1676 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1677 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1678 return START_SUCCESS;
1679 }
1680
1681 private int setTaskFromInTask() {
1682 if (mLaunchBounds != null) {
1683 mInTask.updateOverrideConfiguration(mLaunchBounds);
1684 int stackId = mInTask.getLaunchStackId();
1685 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001686 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001687 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001688 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001689 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001690 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001691 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001692 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001693 }
1694 mTargetStack = mInTask.stack;
1695 mTargetStack.moveTaskToFrontLocked(
1696 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1697
1698 // Check whether we should actually launch the new activity in to the task,
1699 // or just reuse the current activity on top.
1700 ActivityRecord top = mInTask.getTopActivity();
1701 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1702 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1703 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001704 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001705 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1706 // We don't need to start a new activity, and the client said not to do
1707 // anything if that is the case, so this is it!
1708 return START_RETURN_INTENT_TO_CALLER;
1709 }
1710 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1711 return START_DELIVERED_TO_TOP;
1712 }
1713 }
1714
1715 if (!mAddingToTask) {
1716 // We don't actually want to have this activity added to the task, so just
1717 // stop here but still tell the caller that we consumed the intent.
1718 ActivityOptions.abort(mOptions);
1719 return START_TASK_TO_FRONT;
1720 }
1721
1722 mStartActivity.setTask(mInTask, null);
1723 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1724 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1725
1726 return START_SUCCESS;
1727 }
1728
1729 private void setTaskToCurrentTopOrCreateNewTask() {
1730 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1731 mOptions);
1732 if (mDoResume) {
1733 mTargetStack.moveToFront("addingToTopTask");
1734 }
1735 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001736 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1737 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1738 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001739 mStartActivity.setTask(task, null);
1740 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1741 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1742 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1743 }
1744
1745 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1746 boolean launchSingleTask, int launchFlags) {
1747 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1748 (launchSingleInstance || launchSingleTask)) {
1749 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1750 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1751 "\"singleInstance\" or \"singleTask\"");
1752 launchFlags &=
1753 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1754 } else {
1755 switch (r.info.documentLaunchMode) {
1756 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1757 break;
1758 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1759 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1760 break;
1761 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1762 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1763 break;
1764 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1765 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1766 break;
1767 }
1768 }
1769 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001770 }
1771
1772 final void doPendingActivityLaunchesLocked(boolean doResume) {
1773 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001774 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1775 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001776 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001777 final int result = startActivityUnchecked(
1778 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1779 postStartActivityUncheckedProcessing(
1780 pal.r, result, mSupervisor.mFocusedStack.mStackId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001781 } catch (Exception e) {
1782 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1783 pal.sendErrorResult(e.getMessage());
1784 }
1785 }
1786 }
1787
1788 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001789 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001790 final TaskRecord task = r.task;
1791 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1792 return mSupervisor.mHomeStack;
1793 }
1794
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001795 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001796 if (stack != null) {
1797 return stack;
1798 }
1799
1800 if (task != null && task.stack != null) {
1801 stack = task.stack;
1802 if (stack.isOnHomeDisplay()) {
1803 if (mSupervisor.mFocusedStack != stack) {
1804 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1805 "computeStackFocus: Setting " + "focused stack to r=" + r
1806 + " task=" + task);
1807 } else {
1808 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1809 "computeStackFocus: Focused stack already="
1810 + mSupervisor.mFocusedStack);
1811 }
1812 }
1813 return stack;
1814 }
1815
1816 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1817 if (container != null) {
1818 // The first time put it on the desired stack, after this put on task stack.
1819 r.mInitialActivityContainer = null;
1820 return container.mStack;
1821 }
1822
1823 // The fullscreen stack can contain any task regardless of if the task is resizeable
1824 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1825 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1826 // we can also put it in the focused stack.
1827 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001828 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1829 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1830 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001831 if (canUseFocusedStack && (!newTask
1832 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1833 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1834 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1835 return mSupervisor.mFocusedStack;
1836 }
1837
1838 // We first try to put the task in the first dynamic stack.
1839 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1840 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1841 stack = homeDisplayStacks.get(stackNdx);
1842 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1843 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1844 "computeStackFocus: Setting focused stack=" + stack);
1845 return stack;
1846 }
1847 }
1848
1849 // If there is no suitable dynamic stack then we figure out which static stack to use.
1850 final int stackId = task != null ? task.getLaunchStackId() :
1851 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1852 FULLSCREEN_WORKSPACE_STACK_ID;
1853 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1854 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1855 + r + " stackId=" + stack.mStackId);
1856 return stack;
1857 }
1858
Wale Ogunwale854809c2015-12-27 16:18:19 -08001859 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001860 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001861
1862 // We are reusing a task, keep the stack!
1863 if (mReuseTask != null) {
1864 return mReuseTask.stack;
1865 }
1866
Wale Ogunwale854809c2015-12-27 16:18:19 -08001867 final int launchStackId =
1868 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1869
1870 if (isValidLaunchStackId(launchStackId, r)) {
1871 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001872 } else if (launchStackId == DOCKED_STACK_ID) {
1873 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1874 // for this activity, so we put the activity in the fullscreen stack.
1875 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001876 }
1877
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001878 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001879 return null;
1880 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001881 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001882
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001883 // The parent activity doesn't want to launch the activity on top of itself, but
1884 // instead tries to put it onto other side in side-by-side mode.
1885 final ActivityStack parentStack = task != null ? task.stack
1886 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1887 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001888
1889 if (parentStack != mSupervisor.mFocusedStack) {
1890 // If task's parent stack is not focused - use it during adjacent launch.
1891 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001892 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001893 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1894 // If task is already on top of focused stack - use it. We don't want to move the
1895 // existing focused task to adjacent stack, just deliver new intent in this case.
1896 return mSupervisor.mFocusedStack;
1897 }
1898
1899 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1900 // If parent was in docked stack, the natural place to launch another activity
1901 // will be fullscreen, so it can appear alongside the docked window.
1902 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1903 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001904 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001905 // If the parent is not in the docked stack, we check if there is docked window
1906 // and if yes, we will launch into that stack. If not, we just put the new
1907 // activity into parent's stack, because we can't find a better place.
1908 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1909 if (dockedStack != null
1910 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1911 // There is a docked stack, but it isn't visible, so we can't launch into that.
1912 return null;
1913 } else {
1914 return dockedStack;
1915 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001916 }
1917 }
1918 }
1919
Wale Ogunwale854809c2015-12-27 16:18:19 -08001920 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1921 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1922 || !StackId.isStaticStack(stackId)) {
1923 return false;
1924 }
1925
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001926 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
1927 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
1928 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001929 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001930
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001931 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1932 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08001933 }
1934
1935 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1936 return false;
1937 }
1938
1939 final boolean supportsPip = mService.mSupportsPictureInPicture
1940 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1941 if (stackId == PINNED_STACK_ID && !supportsPip) {
1942 return false;
1943 }
1944 return true;
1945 }
1946
Wale Ogunwale854809c2015-12-27 16:18:19 -08001947 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1948 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001949 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08001950 if (mSupervisor.canUseActivityOptionsLaunchBounds(
1951 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001952 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08001953 }
1954 }
1955 return newBounds;
1956 }
1957
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001958 void setWindowManager(WindowManagerService wm) {
1959 mWindowManager = wm;
1960 }
1961
1962 void removePendingActivityLaunchesLocked(ActivityStack stack) {
1963 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1964 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1965 if (pal.stack == stack) {
1966 mPendingActivityLaunches.remove(palNdx);
1967 }
1968 }
1969 }
1970}