blob: 82ec80c6288c1dee98927563261d533661199c99 [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;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700174 private boolean mAvoidMoveToFront;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800175
176 private IVoiceInteractionSession mVoiceSession;
177 private IVoiceInteractor mVoiceInteractor;
178
179 private void reset() {
180 mStartActivity = null;
181 mIntent = null;
182 mCallingUid = -1;
183 mOptions = null;
184
185 mLaunchSingleTop = false;
186 mLaunchSingleInstance = false;
187 mLaunchSingleTask = false;
188 mLaunchTaskBehind = false;
189 mLaunchFlags = 0;
190
191 mLaunchBounds = null;
192
193 mNotTop = null;
194 mDoResume = false;
195 mStartFlags = 0;
196 mSourceRecord = null;
197
198 mInTask = null;
199 mAddingToTask = false;
200 mReuseTask = null;
201
202 mNewTaskInfo = null;
203 mNewTaskIntent = null;
204 mSourceStack = null;
205
206 mTargetStack = null;
207 mMovedHome = false;
208 mMovedToFront = false;
209 mNoAnimation = false;
210 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700211 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800212
213 mVoiceSession = null;
214 mVoiceInteractor = null;
215 }
216
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800217 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
218 mService = service;
219 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000220 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800221 }
222
223 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
224 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
225 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
226 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
227 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
228 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
229 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
230 TaskRecord inTask) {
231 int err = ActivityManager.START_SUCCESS;
232
233 ProcessRecord callerApp = null;
234 if (caller != null) {
235 callerApp = mService.getRecordForAppLocked(caller);
236 if (callerApp != null) {
237 callingPid = callerApp.pid;
238 callingUid = callerApp.info.uid;
239 } else {
240 Slog.w(TAG, "Unable to find app for caller " + caller
241 + " (pid=" + callingPid + ") when starting: "
242 + intent.toString());
243 err = ActivityManager.START_PERMISSION_DENIED;
244 }
245 }
246
247 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
248
249 if (err == ActivityManager.START_SUCCESS) {
250 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
251 + "} from uid " + callingUid
252 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
253 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
254 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
255 container.mActivityDisplay.mDisplayId)));
256 }
257
258 ActivityRecord sourceRecord = null;
259 ActivityRecord resultRecord = null;
260 if (resultTo != null) {
261 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
262 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
263 "Will send result to " + resultTo + " " + sourceRecord);
264 if (sourceRecord != null) {
265 if (requestCode >= 0 && !sourceRecord.finishing) {
266 resultRecord = sourceRecord;
267 }
268 }
269 }
270
271 final int launchFlags = intent.getFlags();
272
273 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
274 // Transfer the result target from the source activity to the new
275 // one being started, including any failures.
276 if (requestCode >= 0) {
277 ActivityOptions.abort(options);
278 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
279 }
280 resultRecord = sourceRecord.resultTo;
281 if (resultRecord != null && !resultRecord.isInStackLocked()) {
282 resultRecord = null;
283 }
284 resultWho = sourceRecord.resultWho;
285 requestCode = sourceRecord.requestCode;
286 sourceRecord.resultTo = null;
287 if (resultRecord != null) {
288 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
289 }
290 if (sourceRecord.launchedFromUid == callingUid) {
291 // The new activity is being launched from the same uid as the previous
292 // activity in the flow, and asking to forward its result back to the
293 // previous. In this case the activity is serving as a trampoline between
294 // the two, so we also want to update its launchedFromPackage to be the
295 // same as the previous activity. Note that this is safe, since we know
296 // these two packages come from the same uid; the caller could just as
297 // well have supplied that same package name itself. This specifially
298 // deals with the case of an intent picker/chooser being launched in the app
299 // flow to redirect to an activity picked by the user, where we want the final
300 // activity to consider it to have been launched by the previous app activity.
301 callingPackage = sourceRecord.launchedFromPackage;
302 }
303 }
304
305 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
306 // We couldn't find a class that can handle the given Intent.
307 // That's the end of that!
308 err = ActivityManager.START_INTENT_NOT_RESOLVED;
309 }
310
311 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
312 // We couldn't find the specific class specified in the Intent.
313 // Also the end of the line.
314 err = ActivityManager.START_CLASS_NOT_FOUND;
315 }
316
317 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
318 && sourceRecord.task.voiceSession != null) {
319 // If this activity is being launched as part of a voice session, we need
320 // to ensure that it is safe to do so. If the upcoming activity will also
321 // be part of the voice session, we can only launch it if it has explicitly
322 // said it supports the VOICE category, or it is a part of the calling app.
323 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
324 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
325 try {
326 intent.addCategory(Intent.CATEGORY_VOICE);
327 if (!AppGlobals.getPackageManager().activitySupportsIntent(
328 intent.getComponent(), intent, resolvedType)) {
329 Slog.w(TAG,
330 "Activity being started in current voice task does not support voice: "
331 + intent);
332 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
333 }
334 } catch (RemoteException e) {
335 Slog.w(TAG, "Failure checking voice capabilities", e);
336 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
337 }
338 }
339 }
340
341 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
342 // If the caller is starting a new voice session, just make sure the target
343 // is actually allowing it to run this way.
344 try {
345 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
346 intent, resolvedType)) {
347 Slog.w(TAG,
348 "Activity being started in new voice task does not support: "
349 + intent);
350 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
351 }
352 } catch (RemoteException e) {
353 Slog.w(TAG, "Failure checking voice capabilities", e);
354 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
355 }
356 }
357
358 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
359
Wale Ogunwale01d66562015-12-29 08:19:19 -0800360 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800361 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800362 resultStack.sendActivityResultLocked(
363 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800364 }
365 ActivityOptions.abort(options);
366 return err;
367 }
368
369 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
370 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100371 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800372 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
373 callingPid, resolvedType, aInfo.applicationInfo);
374
375 if (mService.mController != null) {
376 try {
377 // The Intent we give to the watcher has the extra data
378 // stripped off, since it can contain private information.
379 Intent watchIntent = intent.cloneFilter();
380 abort |= !mService.mController.activityStarting(watchIntent,
381 aInfo.applicationInfo.packageName);
382 } catch (RemoteException e) {
383 mService.mController = null;
384 }
385 }
386
Rubin Xu58d25992016-01-21 17:47:13 +0000387 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100388 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
389 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000390 intent = mInterceptor.mIntent;
391 rInfo = mInterceptor.mRInfo;
392 aInfo = mInterceptor.mAInfo;
393 resolvedType = mInterceptor.mResolvedType;
394 inTask = mInterceptor.mInTask;
395 callingPid = mInterceptor.mCallingPid;
396 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100397 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800398 if (abort) {
399 if (resultRecord != null) {
400 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800401 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800402 }
403 // We pretend to the caller that it was really started, but
404 // they will just get a cancel result.
405 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800406 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800407 }
408
409 // If permissions need a review before any of the app components can run, we
410 // launch the review activity and pass a pending intent to start the activity
411 // we are to launching now after the review is completed.
412 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
413 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
414 aInfo.packageName, userId)) {
415 IIntentSender target = mService.getIntentSenderLocked(
416 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
417 callingUid, userId, null, null, 0, new Intent[]{intent},
418 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
419 | PendingIntent.FLAG_ONE_SHOT, null);
420
421 final int flags = intent.getFlags();
422 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
423 newIntent.setFlags(flags
424 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
425 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
426 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
427 if (resultRecord != null) {
428 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
429 }
430 intent = newIntent;
431
432 resolvedType = null;
433 callingUid = realCallingUid;
434 callingPid = realCallingPid;
435
436 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
437 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
438 null /*profilerInfo*/);
439
440 if (DEBUG_PERMISSIONS_REVIEW) {
441 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
442 true, false) + "} from uid " + callingUid + " on display "
443 + (container == null ? (mSupervisor.mFocusedStack == null ?
444 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
445 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
446 container.mActivityDisplay.mDisplayId)));
447 }
448 }
449 }
450
451 // If we have an ephemeral app, abort the process of launching the resolved intent.
452 // Instead, launch the ephemeral installer. Once the installer is finished, it
453 // starts either the intent we resolved here [on install error] or the ephemeral
454 // app [on install success].
455 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
456 // Create a pending intent to start the intent resolved here.
457 final IIntentSender failureTarget = mService.getIntentSenderLocked(
458 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
459 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
460 new String[]{ resolvedType },
461 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
462 | PendingIntent.FLAG_IMMUTABLE, null);
463
464 // Create a pending intent to start the ephemeral application; force it to be
465 // directed to the ephemeral package.
466 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
467 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
468 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
469 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
470 new String[]{ resolvedType },
471 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
472 | PendingIntent.FLAG_IMMUTABLE, null);
473
474 int flags = intent.getFlags();
475 intent = new Intent();
476 intent.setFlags(flags
477 | Intent.FLAG_ACTIVITY_NEW_TASK
478 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
479 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
480 rInfo.ephemeralResolveInfo.getPackageName());
481 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
482 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
483
484 resolvedType = null;
485 callingUid = realCallingUid;
486 callingPid = realCallingPid;
487
488 rInfo = rInfo.ephemeralInstaller;
489 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
490 }
491
492 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
493 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
494 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
495 options);
496 if (outActivity != null) {
497 outActivity[0] = r;
498 }
499
500 if (r.appTimeTracker == null && sourceRecord != null) {
501 // If the caller didn't specify an explicit time tracker, we want to continue
502 // tracking under any it has.
503 r.appTimeTracker = sourceRecord.appTimeTracker;
504 }
505
506 final ActivityStack stack = mSupervisor.mFocusedStack;
507 if (voiceSession == null && (stack.mResumedActivity == null
508 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
509 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
510 realCallingPid, realCallingUid, "Activity start")) {
511 PendingActivityLaunch pal = new PendingActivityLaunch(r,
512 sourceRecord, startFlags, stack, callerApp);
513 mPendingActivityLaunches.add(pal);
514 ActivityOptions.abort(options);
515 return ActivityManager.START_SWITCHES_CANCELED;
516 }
517 }
518
519 if (mService.mDidAppSwitch) {
520 // This is the second allowed switch since we stopped switches,
521 // so now just generally allow switches. Use case: user presses
522 // home (switches disabled, switch to home, mDidAppSwitch now true);
523 // user taps a home icon (coming from home so allowed, we hit here
524 // and now allow anyone to switch again).
525 mService.mAppSwitchesAllowedTime = 0;
526 } else {
527 mService.mDidAppSwitch = true;
528 }
529
530 doPendingActivityLaunchesLocked(false);
531
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700532 try {
533 mService.mWindowManager.deferSurfaceLayout();
534 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
535 true, options, inTask);
536 } finally {
537 mService.mWindowManager.continueSurfaceLayout();
538 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800539 postStartActivityUncheckedProcessing(r, err, stack.mStackId);
540 return err;
541 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800542
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800543 void postStartActivityUncheckedProcessing(
544 ActivityRecord r, int result, int prevFocusedStackId) {
545
546 if (result < START_SUCCESS) {
547 // If someone asked to have the keyguard dismissed on the next activity start,
548 // but we are not actually doing an activity switch... just dismiss the keyguard now,
549 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800550 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800551 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800552 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800553
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800554 int startedActivityStackId = INVALID_STACK_ID;
555 if (r.task != null && r.task.stack != null) {
556 startedActivityStackId = r.task.stack.mStackId;
557 } else if (mTargetStack != null) {
558 startedActivityStackId = mTargetStack.mStackId;
559 }
560
561 if (startedActivityStackId == DOCKED_STACK_ID && prevFocusedStackId == HOME_STACK_ID) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100562 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
563 final ActivityRecord topActivityHomeStack = homeStack != null
564 ? homeStack.topRunningActivityLocked() : null;
565 if (topActivityHomeStack == null
566 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
567 // We launch an activity while being in home stack, which means either launcher or
568 // recents into docked stack. We don't want the launched activity to be alone in a
569 // docked stack, so we want to immediately launch recents too.
570 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700571 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100572 return;
573 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800574 }
575
576 if (startedActivityStackId == PINNED_STACK_ID
577 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
578 // The activity was already running in the pinned stack so it wasn't started, but either
579 // brought to the front or the new intent was delivered to it since it was already in
580 // front. Notify anyone interested in this piece of information.
581 mService.notifyPinnedActivityRestartAttemptLocked();
582 return;
583 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800584 }
585
586 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
587 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
588 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
589 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
590 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
591 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
592 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700593 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800594 null /*container*/, null /*inTask*/);
595 if (mSupervisor.inResumeTopActivity) {
596 // If we are in resume section already, home activity will be initialized, but not
597 // resumed (to avoid recursive resume) and will stay that way until something pokes it
598 // again. We need to schedule another resume.
599 mSupervisor.scheduleResumeTopActivities();
600 }
601 }
602
Tony Mak853304c2016-04-18 15:17:41 +0100603 void showConfirmDeviceCredential(int userId) {
604 // First, retrieve the stack that we want to resume after credential is confirmed.
605 ActivityStack targetStack;
606 ActivityStack fullscreenStack =
607 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
608 if (fullscreenStack != null &&
609 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
610 // Single window case and the case that the docked stack is shown with fullscreen stack.
611 targetStack = fullscreenStack;
612 } else {
613 // The case that the docked stack is shown with recent.
614 targetStack = mSupervisor.getStack(HOME_STACK_ID);
615 }
616 if (targetStack == null) {
617 return;
618 }
619 final KeyguardManager km = (KeyguardManager) mService.mContext
620 .getSystemService(Context.KEYGUARD_SERVICE);
621 final Intent credential =
622 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Mak853304c2016-04-18 15:17:41 +0100623 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
624 if (activityRecord != null) {
625 final IIntentSender target = mService.getIntentSenderLocked(
626 ActivityManager.INTENT_SENDER_ACTIVITY,
627 activityRecord.launchedFromPackage,
628 activityRecord.launchedFromUid,
629 activityRecord.userId,
630 null, null, 0,
631 new Intent[] { activityRecord.intent },
632 new String[] { activityRecord.resolvedType },
633 PendingIntent.FLAG_CANCEL_CURRENT |
634 PendingIntent.FLAG_ONE_SHOT |
635 PendingIntent.FLAG_IMMUTABLE,
636 null);
637 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
638 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100639 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100640 }
641 }
642
Tony Mak646fe992016-04-21 16:43:08 +0100643 void startConfirmCredentialIntent(Intent intent) {
644 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
645 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
646 FLAG_ACTIVITY_TASK_ON_HOME);
647 final ActivityOptions options = ActivityOptions.makeBasic();
648 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
649 mService.mContext.startActivityAsUser(intent, options.toBundle(),
650 UserHandle.CURRENT);
651 }
Tony Mak853304c2016-04-18 15:17:41 +0100652
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800653 final int startActivityMayWait(IApplicationThread caller, int callingUid,
654 String callingPackage, Intent intent, String resolvedType,
655 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
656 IBinder resultTo, String resultWho, int requestCode, int startFlags,
657 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
658 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
659 IActivityContainer iContainer, TaskRecord inTask) {
660 // Refuse possible leaked file descriptors
661 if (intent != null && intent.hasFileDescriptors()) {
662 throw new IllegalArgumentException("File descriptors passed in Intent");
663 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500664 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800665 boolean componentSpecified = intent.getComponent() != null;
666
667 // Save a copy in case ephemeral needs it
668 final Intent ephemeralIntent = new Intent(intent);
669 // Don't modify the client's object!
670 intent = new Intent(intent);
671
672 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000673 if (rInfo == null) {
674 UserInfo userInfo = mSupervisor.getUserInfo(userId);
675 if (userInfo != null && userInfo.isManagedProfile()) {
676 // Special case for managed profiles, if attempting to launch non-cryto aware
677 // app in a locked managed profile from an unlocked parent allow it to resolve
678 // as user will be sent via confirm credentials to unlock the profile.
679 UserManager userManager = UserManager.get(mService.mContext);
Tony Mak13436452016-02-24 11:08:38 +0000680 UserInfo parent = null;
681 long token = Binder.clearCallingIdentity();
682 try {
683 parent = userManager.getProfileParent(userId);
684 } finally {
685 Binder.restoreCallingIdentity(token);
686 }
Kenny Guyb1b30262016-02-09 16:02:35 +0000687 if (parent != null
Jeff Sharkeyce18c812016-04-27 16:00:41 -0600688 && userManager.isUserUnlockingOrUnlocked(parent.getUserHandle())
689 && !userManager.isUserUnlockingOrUnlocked(userInfo.getUserHandle())) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000690 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600691 PackageManager.MATCH_DIRECT_BOOT_AWARE
692 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000693 }
694 }
695 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800696 // Collect information about the target of the Intent.
697 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
698
699 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
700 ActivityStackSupervisor.ActivityContainer container =
701 (ActivityStackSupervisor.ActivityContainer)iContainer;
702 synchronized (mService) {
703 if (container != null && container.mParentActivity != null &&
704 container.mParentActivity.state != RESUMED) {
705 // Cannot start a child activity if the parent is not resumed.
706 return ActivityManager.START_CANCELED;
707 }
708 final int realCallingPid = Binder.getCallingPid();
709 final int realCallingUid = Binder.getCallingUid();
710 int callingPid;
711 if (callingUid >= 0) {
712 callingPid = -1;
713 } else if (caller == null) {
714 callingPid = realCallingPid;
715 callingUid = realCallingUid;
716 } else {
717 callingPid = callingUid = -1;
718 }
719
720 final ActivityStack stack;
721 if (container == null || container.mStack.isOnHomeDisplay()) {
722 stack = mSupervisor.mFocusedStack;
723 } else {
724 stack = container.mStack;
725 }
726 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
727 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
728 "Starting activity when config will change = " + stack.mConfigWillChange);
729
730 final long origId = Binder.clearCallingIdentity();
731
732 if (aInfo != null &&
733 (aInfo.applicationInfo.privateFlags
734 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
735 // This may be a heavy-weight process! Check to see if we already
736 // have another, different heavy-weight process running.
737 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
738 final ProcessRecord heavy = mService.mHeavyWeightProcess;
739 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
740 || !heavy.processName.equals(aInfo.processName))) {
741 int appCallingUid = callingUid;
742 if (caller != null) {
743 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
744 if (callerApp != null) {
745 appCallingUid = callerApp.info.uid;
746 } else {
747 Slog.w(TAG, "Unable to find app for caller " + caller
748 + " (pid=" + callingPid + ") when starting: "
749 + intent.toString());
750 ActivityOptions.abort(options);
751 return ActivityManager.START_PERMISSION_DENIED;
752 }
753 }
754
755 IIntentSender target = mService.getIntentSenderLocked(
756 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
757 appCallingUid, userId, null, null, 0, new Intent[] { intent },
758 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
759 | PendingIntent.FLAG_ONE_SHOT, null);
760
761 Intent newIntent = new Intent();
762 if (requestCode >= 0) {
763 // Caller is requesting a result.
764 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
765 }
766 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
767 new IntentSender(target));
768 if (heavy.activities.size() > 0) {
769 ActivityRecord hist = heavy.activities.get(0);
770 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
771 hist.packageName);
772 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
773 hist.task.taskId);
774 }
775 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
776 aInfo.packageName);
777 newIntent.setFlags(intent.getFlags());
778 newIntent.setClassName("android",
779 HeavyWeightSwitcherActivity.class.getName());
780 intent = newIntent;
781 resolvedType = null;
782 caller = null;
783 callingUid = Binder.getCallingUid();
784 callingPid = Binder.getCallingPid();
785 componentSpecified = true;
786 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
787 aInfo = rInfo != null ? rInfo.activityInfo : null;
788 if (aInfo != null) {
789 aInfo = mService.getActivityInfoForUser(aInfo, userId);
790 }
791 }
792 }
793 }
794
Jorim Jaggi275561a2016-02-23 10:11:02 -0500795 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800796 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
797 aInfo, rInfo, voiceSession, voiceInteractor,
798 resultTo, resultWho, requestCode, callingPid,
799 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500800 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
801 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800802
803 Binder.restoreCallingIdentity(origId);
804
805 if (stack.mConfigWillChange) {
806 // If the caller also wants to switch to a new configuration,
807 // do so now. This allows a clean switch, as we are waiting
808 // for the current activity to pause (so we will not destroy
809 // it), and have not yet started the next activity.
810 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
811 "updateConfiguration()");
812 stack.mConfigWillChange = false;
813 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
814 "Updating to new configuration after starting activity.");
815 mService.updateConfigurationLocked(config, null, false);
816 }
817
818 if (outResult != null) {
819 outResult.result = res;
820 if (res == ActivityManager.START_SUCCESS) {
821 mSupervisor.mWaitingActivityLaunched.add(outResult);
822 do {
823 try {
824 mService.wait();
825 } catch (InterruptedException e) {
826 }
827 } while (!outResult.timeout && outResult.who == null);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800828 } else if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800829 ActivityRecord r = stack.topRunningActivityLocked();
830 if (r.nowVisible && r.state == RESUMED) {
831 outResult.timeout = false;
832 outResult.who = new ComponentName(r.info.packageName, r.info.name);
833 outResult.totalTime = 0;
834 outResult.thisTime = 0;
835 } else {
836 outResult.thisTime = SystemClock.uptimeMillis();
837 mSupervisor.mWaitingActivityVisible.add(outResult);
838 do {
839 try {
840 mService.wait();
841 } catch (InterruptedException e) {
842 }
843 } while (!outResult.timeout && outResult.who == null);
844 }
845 }
846 }
847
Jorim Jaggi275561a2016-02-23 10:11:02 -0500848 final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
849 : null;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700850 final ActivityRecord launchedActivity = mReusedActivity != null
851 ? mReusedActivity : outRecord[0];
852 final ProcessRecord processRecord = launchedActivity != null
853 ? mService.mProcessNames.get(launchedActivity.processName,
854 launchedActivity.appInfo.uid)
855 : null;
856 final boolean processRunning = processRecord != null;
857
858 // We consider this a "process switch" if the process of the activity that gets launched
859 // didn't have an activity that was in started state. In this case, we assume that lot
860 // of caches might be purged so the time until it produces the first frame is very
861 // interesting.
862 final boolean processSwitch = processRecord == null
863 || !hasStartedActivity(processRecord, launchedActivity);
Jorim Jaggi275561a2016-02-23 10:11:02 -0500864 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
Jorim Jaggibe67c902016-04-12 00:53:16 -0700865 processRunning, processSwitch);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800866 return res;
867 }
868 }
869
Jorim Jaggibe67c902016-04-12 00:53:16 -0700870 final boolean hasStartedActivity(ProcessRecord record, ActivityRecord launchedActivity) {
871 final ArrayList<ActivityRecord> activities = record.activities;
872 for (int i = activities.size() - 1; i >= 0; i--) {
873 final ActivityRecord activity = activities.get(i);
874 if (launchedActivity == activity) {
875 continue;
876 }
877 if (!activity.stopped) {
878 return true;
879 }
880 }
881 return false;
882 }
883
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800884 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
885 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
886 Bundle bOptions, int userId) {
887 if (intents == null) {
888 throw new NullPointerException("intents is null");
889 }
890 if (resolvedTypes == null) {
891 throw new NullPointerException("resolvedTypes is null");
892 }
893 if (intents.length != resolvedTypes.length) {
894 throw new IllegalArgumentException("intents are length different than resolvedTypes");
895 }
896
897
898 int callingPid;
899 if (callingUid >= 0) {
900 callingPid = -1;
901 } else if (caller == null) {
902 callingPid = Binder.getCallingPid();
903 callingUid = Binder.getCallingUid();
904 } else {
905 callingPid = callingUid = -1;
906 }
907 final long origId = Binder.clearCallingIdentity();
908 try {
909 synchronized (mService) {
910 ActivityRecord[] outActivity = new ActivityRecord[1];
911 for (int i=0; i<intents.length; i++) {
912 Intent intent = intents[i];
913 if (intent == null) {
914 continue;
915 }
916
917 // Refuse possible leaked file descriptors
918 if (intent != null && intent.hasFileDescriptors()) {
919 throw new IllegalArgumentException("File descriptors passed in Intent");
920 }
921
922 boolean componentSpecified = intent.getComponent() != null;
923
924 // Don't modify the client's object!
925 intent = new Intent(intent);
926
927 // Collect information about the target of the Intent.
928 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
929 null, userId);
930 // TODO: New, check if this is correct
931 aInfo = mService.getActivityInfoForUser(aInfo, userId);
932
933 if (aInfo != null &&
934 (aInfo.applicationInfo.privateFlags
935 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
936 throw new IllegalArgumentException(
937 "FLAG_CANT_SAVE_STATE not supported here");
938 }
939
940 ActivityOptions options = ActivityOptions.fromBundle(
941 i == intents.length - 1 ? bOptions : null);
942 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
943 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
944 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
945 options, false, componentSpecified, outActivity, null, null);
946 if (res < 0) {
947 return res;
948 }
949
950 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
951 }
952 }
953 } finally {
954 Binder.restoreCallingIdentity(origId);
955 }
956
Wale Ogunwale01d66562015-12-29 08:19:19 -0800957 return START_SUCCESS;
958 }
959
960 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
961 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
962 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
963
964 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
965 voiceInteractor);
966
967 computeLaunchingTaskFlags();
968
969 computeSourceStack();
970
971 mIntent.setFlags(mLaunchFlags);
972
Jorim Jaggibe67c902016-04-12 00:53:16 -0700973 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800974
Jorim Jaggi2adba072016-03-03 13:43:39 +0100975 final int preferredLaunchStackId =
976 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
977
Jorim Jaggibe67c902016-04-12 00:53:16 -0700978 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800979 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
980 // still needs to be a lock task mode violation since the task gets cleared out and
981 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700982 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800983 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
984 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
985 mSupervisor.showLockTaskToast();
986 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
987 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
988 }
989
990 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -0700991 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800992 }
Jorim Jaggibe67c902016-04-12 00:53:16 -0700993 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800994 // This task was started because of movement of the activity based on affinity...
995 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700996 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800997 }
998
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800999 // This code path leads to delivering a new intent, we want to make sure we schedule it
1000 // as the first operation, in case the activity will be resumed as a result of later
1001 // operations.
1002 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1003 || mLaunchSingleInstance || mLaunchSingleTask) {
1004 // In this situation we want to remove all activities from the task up to the one
1005 // being started. In most cases this means we are resetting the task to its initial
1006 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001007 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001008 mStartActivity, mLaunchFlags);
1009 if (top != null) {
1010 if (top.frontOfTask) {
1011 // Activity aliases may mean we use different intents for the top activity,
1012 // so make sure the task now has the identity of the new intent.
1013 top.task.setIntent(mStartActivity);
1014 }
1015 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1016 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1017 mStartActivity.launchedFromPackage);
1018 }
1019 }
1020
Jorim Jaggibe67c902016-04-12 00:53:16 -07001021 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001022
1023 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1024 // We don't need to start a new activity, and the client said not to do anything
1025 // if that is the case, so this is it! And for paranoia, make sure we have
1026 // correctly resumed the top activity.
1027 resumeTargetStackIfNeeded();
1028 return START_RETURN_INTENT_TO_CALLER;
1029 }
1030
Jorim Jaggibe67c902016-04-12 00:53:16 -07001031 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001032
1033 if (!mAddingToTask && mReuseTask == null) {
1034 // We didn't do anything... but it was needed (a.k.a., client don't use that
1035 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1036 resumeTargetStackIfNeeded();
1037 return START_TASK_TO_FRONT;
1038 }
1039 }
1040
1041 if (mStartActivity.packageName == null) {
1042 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1043 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1044 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1045 mStartActivity.requestCode, RESULT_CANCELED, null);
1046 }
1047 ActivityOptions.abort(mOptions);
1048 return START_CLASS_NOT_FOUND;
1049 }
1050
1051 // If the activity being launched is the same as the one currently at the top, then
1052 // we need to check if it should only be launched once.
1053 final ActivityStack topStack = mSupervisor.mFocusedStack;
1054 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1055 final boolean dontStart = top != null && mStartActivity.resultTo == null
1056 && top.realActivity.equals(mStartActivity.realActivity)
1057 && top.userId == mStartActivity.userId
1058 && top.app != null && top.app.thread != null
1059 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1060 || mLaunchSingleTop || mLaunchSingleTask);
1061 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001062 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001063 // For paranoia, make sure we have correctly resumed the top activity.
1064 topStack.mLastPausedActivity = null;
1065 if (mDoResume) {
1066 mSupervisor.resumeFocusedStackTopActivityLocked();
1067 }
1068 ActivityOptions.abort(mOptions);
1069 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1070 // We don't need to start a new activity, and the client said not to do
1071 // anything if that is the case, so this is it!
1072 return START_RETURN_INTENT_TO_CALLER;
1073 }
1074 top.deliverNewIntentLocked(
1075 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001076
1077 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1078 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1079 mSupervisor.handleNonResizableTaskIfNeeded(
1080 top.task, preferredLaunchStackId, topStack.mStackId);
1081
Wale Ogunwale01d66562015-12-29 08:19:19 -08001082 return START_DELIVERED_TO_TOP;
1083 }
1084
1085 boolean newTask = false;
1086 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1087 ? mSourceRecord.task : null;
1088
1089 // Should this be considered a new task?
1090 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1091 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1092 newTask = true;
1093 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1094
1095 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1096 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1097 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1098 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001099 if (!mMovedHome) {
1100 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001101 }
1102 } else if (mSourceRecord != null) {
1103 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1104 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1105 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1106 }
1107
1108 final int result = setTaskFromSourceRecord();
1109 if (result != START_SUCCESS) {
1110 return result;
1111 }
1112 } else if (mInTask != null) {
1113 // The caller is asking that the new activity be started in an explicit
1114 // task it has provided to us.
1115 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1116 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1117 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1118 }
1119
1120 final int result = setTaskFromInTask();
1121 if (result != START_SUCCESS) {
1122 return result;
1123 }
1124 } else {
1125 // This not being started from an existing activity, and not part of a new task...
1126 // just put it in the top task, though these days this case should never happen.
1127 setTaskToCurrentTopOrCreateNewTask();
1128 }
1129
1130 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1131 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1132
1133 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1134 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1135 }
1136 if (newTask) {
1137 EventLog.writeEvent(
1138 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1139 }
1140 ActivityStack.logStartActivity(
1141 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1142 mTargetStack.mLastPausedActivity = null;
1143 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1144 if (mDoResume) {
1145 if (!mLaunchTaskBehind) {
1146 // TODO(b/26381750): Remove this code after verification that all the decision
1147 // points above moved targetStack to the front which will also set the focus
1148 // activity.
1149 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1150 }
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001151 if (mTargetStack.isFocusable()) {
1152 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1153 mOptions);
1154 } else {
1155 // If the activity is not focusable, we can't resume it, but still would like to
1156 // make sure it becomes visible as it starts (this will also trigger entry
1157 // animation). An example of this are PIP activities.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001158 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001159 // Go ahead and tell window manager to execute app transition for this activity
1160 // since the app transition will not be triggered through the resume channel.
1161 mWindowManager.executeAppTransition();
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001162 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001163 } else {
1164 mTargetStack.addRecentActivityLocked(mStartActivity);
1165 }
1166 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1167
Jorim Jaggid53f0922016-04-06 22:16:23 -07001168 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001169 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001170
1171 return START_SUCCESS;
1172 }
1173
1174 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1175 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1176 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1177 reset();
1178
1179 mStartActivity = r;
1180 mIntent = r.intent;
1181 mOptions = options;
1182 mCallingUid = r.launchedFromUid;
1183 mSourceRecord = sourceRecord;
1184 mVoiceSession = voiceSession;
1185 mVoiceInteractor = voiceInteractor;
1186
1187 mLaunchBounds = getOverrideBounds(r, options, inTask);
1188
1189 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1190 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1191 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1192 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1193 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1194 mLaunchTaskBehind = r.mLaunchTaskBehind
1195 && !mLaunchSingleTask && !mLaunchSingleInstance
1196 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1197
1198 sendNewTaskResultRequestIfNeeded();
1199
1200 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1201 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1202 }
1203
1204 // If we are actually going to launch in to a new task, there are some cases where
1205 // we further want to do multiple task.
1206 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1207 if (mLaunchTaskBehind
1208 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1209 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1210 }
1211 }
1212
1213 // We'll invoke onUserLeaving before onPause only if the launching
1214 // activity did not explicitly state that this is an automated launch.
1215 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1216 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1217 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1218
1219 // If the caller has asked not to resume at this point, we make note
1220 // of this in the record so that we can skip it when trying to find
1221 // the top running activity.
1222 mDoResume = doResume;
1223 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1224 r.delayedResume = true;
1225 mDoResume = false;
1226 }
1227
Jorim Jaggic875ae72016-04-26 22:41:06 -07001228 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getAvoidMoveToFront()) {
1229 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1230 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1231 if (top != null && !top.visible) {
1232
1233 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1234 // it!
1235 mDoResume = false;
1236 mAvoidMoveToFront = true;
1237 }
1238 }
1239
Wale Ogunwale01d66562015-12-29 08:19:19 -08001240 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1241
1242 mInTask = inTask;
1243 // In some flows in to this function, we retrieve the task record and hold on to it
1244 // without a lock before calling back in to here... so the task at this point may
1245 // not actually be in recents. Check for that, and if it isn't in recents just
1246 // consider it invalid.
1247 if (inTask != null && !inTask.inRecents) {
1248 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1249 mInTask = null;
1250 }
1251
1252 mStartFlags = startFlags;
1253 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1254 // is the same as the one making the call... or, as a special case, if we do not know
1255 // the caller then we count the current top activity as the caller.
1256 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1257 ActivityRecord checkedCaller = sourceRecord;
1258 if (checkedCaller == null) {
1259 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1260 mNotTop);
1261 }
1262 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1263 // Caller is not the same as launcher, so always needed.
1264 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1265 }
1266 }
1267
1268 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1269 }
1270
1271 private void sendNewTaskResultRequestIfNeeded() {
1272 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1273 && mStartActivity.resultTo.task.stack != null) {
1274 // For whatever reason this activity is being launched into a new task...
1275 // yet the caller has requested a result back. Well, that is pretty messed up,
1276 // so instead immediately send back a cancel and let the new task continue launched
1277 // as normal without a dependency on its originator.
1278 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1279 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1280 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1281 mStartActivity.resultTo = null;
1282 }
1283 }
1284
1285 private void computeLaunchingTaskFlags() {
1286 // If the caller is not coming from another activity, but has given us an explicit task into
1287 // which they would like us to launch the new activity, then let's see about doing that.
1288 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1289 final Intent baseIntent = mInTask.getBaseIntent();
1290 final ActivityRecord root = mInTask.getRootActivity();
1291 if (baseIntent == null) {
1292 ActivityOptions.abort(mOptions);
1293 throw new IllegalArgumentException("Launching into task without base intent: "
1294 + mInTask);
1295 }
1296
1297 // If this task is empty, then we are adding the first activity -- it
1298 // determines the root, and must be launching as a NEW_TASK.
1299 if (mLaunchSingleInstance || mLaunchSingleTask) {
1300 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1301 ActivityOptions.abort(mOptions);
1302 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1303 + mStartActivity + " into different task " + mInTask);
1304 }
1305 if (root != null) {
1306 ActivityOptions.abort(mOptions);
1307 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1308 + " has root " + root + " but target is singleInstance/Task");
1309 }
1310 }
1311
1312 // If task is empty, then adopt the interesting intent launch flags in to the
1313 // activity being started.
1314 if (root == null) {
1315 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1316 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1317 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1318 | (baseIntent.getFlags() & flagsOfInterest);
1319 mIntent.setFlags(mLaunchFlags);
1320 mInTask.setIntent(mStartActivity);
1321 mAddingToTask = true;
1322
1323 // If the task is not empty and the caller is asking to start it as the root of
1324 // a new task, then we don't actually want to start this on the task. We will
1325 // bring the task to the front, and possibly give it a new intent.
1326 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1327 mAddingToTask = false;
1328
1329 } else {
1330 mAddingToTask = true;
1331 }
1332
1333 mReuseTask = mInTask;
1334 } else {
1335 mInTask = null;
1336 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1337 // when in freeform workspace.
1338 // Also put noDisplay activities in the source task. These by itself can be placed
1339 // in any task/stack, however it could launch other activities like ResolverActivity,
1340 // and we want those to stay in the original task.
1341 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1342 && mSourceRecord.isFreeform()) {
1343 mAddingToTask = true;
1344 }
1345 }
1346
1347 if (mInTask == null) {
1348 if (mSourceRecord == null) {
1349 // This activity is not being started from another... in this
1350 // case we -always- start a new task.
1351 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1352 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1353 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1354 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1355 }
1356 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1357 // The original activity who is starting us is running as a single
1358 // instance... this new activity it is starting must go on its
1359 // own task.
1360 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1361 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1362 // The activity being started is a single instance... it always
1363 // gets launched into its own task.
1364 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1365 }
1366 }
1367 }
1368
1369 private void computeSourceStack() {
1370 if (mSourceRecord == null) {
1371 mSourceStack = null;
1372 return;
1373 }
1374 if (!mSourceRecord.finishing) {
1375 mSourceStack = mSourceRecord.task.stack;
1376 return;
1377 }
1378
1379 // If the source is finishing, we can't further count it as our source. This is because the
1380 // task it is associated with may now be empty and on its way out, so we don't want to
1381 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1382 // a task for it. But save the task information so it can be used when creating the new task.
1383 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1384 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1385 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1386 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1387 mNewTaskInfo = mSourceRecord.info;
1388 mNewTaskIntent = mSourceRecord.task.intent;
1389 }
1390 mSourceRecord = null;
1391 mSourceStack = null;
1392 }
1393
1394 /**
1395 * Decide whether the new activity should be inserted into an existing task. Returns null
1396 * if not or an ActivityRecord with the task into which the new activity should be added.
1397 */
1398 private ActivityRecord getReusableIntentActivity() {
1399 // We may want to try to place the new activity in to an existing task. We always
1400 // do this if the target activity is singleTask or singleInstance; we will also do
1401 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1402 // us to still place it in a new task: multi task, always doc mode, or being asked to
1403 // launch this as a new task behind the current one.
1404 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1405 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1406 || mLaunchSingleInstance || mLaunchSingleTask;
1407 // If bring to front is requested, and no result is requested and we have not been given
1408 // an explicit task to launch in to, and we can find a task that was started with this
1409 // same component, then instead of launching bring that one to the front.
1410 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1411 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001412 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1413 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1414 intentActivity = task != null ? task.getTopActivity() : null;
1415 } else if (putIntoExistingTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001416 // See if there is a task to bring to the front. If this is a SINGLE_INSTANCE
1417 // activity, there can be one and only one instance of it in the history, and it is
1418 // always in its own unique task, so we do a special search.
1419 intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info)
1420 : mSupervisor.findTaskLocked(mStartActivity);
1421 }
1422 return intentActivity;
1423 }
1424
1425 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1426 mTargetStack = intentActivity.task.stack;
1427 mTargetStack.mLastPausedActivity = null;
1428 // If the target task is not in the front, then we need to bring it to the front...
1429 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1430 // the same behavior as if a new instance was being started, which means not bringing it
1431 // to the front if the caller is not itself in the front.
1432 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1433 ActivityRecord curTop = (focusStack == null)
1434 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1435
Jorim Jaggic875ae72016-04-26 22:41:06 -07001436 if (curTop != null
1437 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1438 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001439 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1440 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1441 mSourceStack.topActivity().task == mSourceRecord.task)) {
1442 // We really do want to push this one into the user's face, right now.
1443 if (mLaunchTaskBehind && mSourceRecord != null) {
1444 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1445 }
1446 mMovedHome = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001447
1448 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1449 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1450 // So no point resuming any of the activities here, it just wastes one extra
1451 // resuming, plus enter AND exit transitions.
1452 // Here we only want to bring the target stack forward. Transition will be applied
1453 // to the new activity that's started after the old ones are gone.
1454 final boolean willClearTask =
1455 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1456 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1457 if (!willClearTask) {
1458 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001459 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001460 if (launchStack == null || launchStack == mTargetStack) {
1461 // We only want to move to the front, if we aren't going to launch on a
1462 // different stack. If we launch on a different stack, we will put the
1463 // task on top there.
1464 mTargetStack.moveTaskToFrontLocked(
1465 intentActivity.task, mNoAnimation, mOptions,
1466 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1467 mMovedToFront = true;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001468 } else if ((launchStack.mStackId == DOCKED_STACK_ID
1469 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID)
1470 && (mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1471 // If we want to launch adjacent and mTargetStack is not the computed
1472 // launch stack - move task to top of computed stack.
1473 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1474 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1475 ANIMATE);
1476 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001477 }
1478 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001479 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001480 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001481 }
1482 }
1483 if (!mMovedToFront && mDoResume) {
1484 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1485 + " from " + intentActivity);
1486 mTargetStack.moveToFront("intentActivityFound");
1487 }
1488
Jorim Jaggid53f0922016-04-06 22:16:23 -07001489 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1490 mTargetStack.mStackId);
1491
Wale Ogunwale01d66562015-12-29 08:19:19 -08001492 // If the caller has requested that the target task be reset, then do so.
1493 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1494 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1495 }
1496 return intentActivity;
1497 }
1498
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001499 private void updateTaskReturnToType(
1500 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1501 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1502 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1503 // Caller wants to appear on home activity.
1504 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1505 return;
1506 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1507 // Task will be launched over the home stack, so return home.
1508 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1509 return;
1510 }
1511
1512 // Else we are coming from an application stack so return to an application.
1513 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1514 }
1515
Wale Ogunwale01d66562015-12-29 08:19:19 -08001516 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1517 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1518 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1519 // The caller has requested to completely replace any existing task with its new
1520 // activity. Well that should not be too hard...
1521 mReuseTask = intentActivity.task;
1522 mReuseTask.performClearTaskLocked();
1523 mReuseTask.setIntent(mStartActivity);
1524 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1525 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001526 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1527 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001528 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001529 // A special case: we need to start the activity because it is not currently
1530 // running, and the caller has asked to clear the current task to have this
1531 // activity at the top.
1532 mAddingToTask = true;
1533 // Now pretend like this activity is being started by the top of its task, so it
1534 // is put in the right place.
1535 mSourceRecord = intentActivity;
1536 final TaskRecord task = mSourceRecord.task;
1537 if (task != null && task.stack == null) {
1538 // Target stack got cleared when we all activities were removed above.
1539 // Go ahead and reset it.
1540 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1541 null /* bounds */, mLaunchFlags, mOptions);
1542 mTargetStack.addTask(task,
1543 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1544 }
1545 }
1546 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1547 // In this case the top activity on the task is the same as the one being launched,
1548 // so we take that as a request to bring the task to the foreground. If the top
1549 // activity in the task is the root activity, deliver this new intent to it if it
1550 // desires.
1551 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1552 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001553 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001554 intentActivity.task);
1555 if (intentActivity.frontOfTask) {
1556 intentActivity.task.setIntent(mStartActivity);
1557 }
1558 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1559 mStartActivity.launchedFromPackage);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -08001560 } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001561 // In this case we are launching the root activity of the task, but with a
1562 // different intent. We should start a new instance on top.
1563 mAddingToTask = true;
1564 mSourceRecord = intentActivity;
1565 }
1566 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1567 // In this case an activity is being launched in to an existing task, without
1568 // resetting that task. This is typically the situation of launching an activity
1569 // from a notification or shortcut. We want to place the new activity on top of the
1570 // current task.
1571 mAddingToTask = true;
1572 mSourceRecord = intentActivity;
1573 } else if (!intentActivity.task.rootWasReset) {
1574 // In this case we are launching into an existing task that has not yet been started
1575 // from its front door. The current task has been brought to the front. Ideally,
1576 // we'd probably like to place this new task at the bottom of its stack, but that's
1577 // a little hard to do with the current organization of the code so for now we'll
1578 // just drop it.
1579 intentActivity.task.setIntent(mStartActivity);
1580 }
1581 }
1582
1583 private void resumeTargetStackIfNeeded() {
1584 if (mDoResume) {
1585 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1586 if (!mMovedToFront) {
1587 // Make sure to notify Keyguard as well if we are not running an app transition
1588 // later.
1589 mSupervisor.notifyActivityDrawnForKeyguard();
1590 }
1591 } else {
1592 ActivityOptions.abort(mOptions);
1593 }
1594 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1595 }
1596
1597 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1598 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1599 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001600
1601 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001602 final TaskRecord task = mTargetStack.createTaskRecord(
1603 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001604 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1605 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1606 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1607 mStartActivity.setTask(task, taskToAffiliate);
1608 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001609 final int stackId = mTargetStack.mStackId;
1610 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001611 mService.resizeStack(
1612 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001613 } else {
1614 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1615 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001616 }
1617 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1618 "Starting new activity " +
1619 mStartActivity + " in new task " + mStartActivity.task);
1620 } else {
1621 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1622 }
1623 }
1624
1625 private int setTaskFromSourceRecord() {
1626 final TaskRecord sourceTask = mSourceRecord.task;
1627 // We only want to allow changing stack if the target task is not the top one,
1628 // otherwise we would move the launching task to the other side, rather than show
1629 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001630 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1631 if (moveStackAllowed) {
1632 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1633 mOptions);
1634 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001635
1636 if (mTargetStack == null) {
1637 mTargetStack = sourceTask.stack;
1638 } else if (mTargetStack != sourceTask.stack) {
1639 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1640 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1641 }
1642 if (mDoResume) {
1643 mTargetStack.moveToFront("sourceStackToFront");
1644 }
1645 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001646 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001647 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1648 mStartActivity.appTimeTracker, "sourceTaskToFront");
1649 }
1650 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1651 // In this case, we are adding the activity to an existing task, but the caller has
1652 // asked to clear that task if the activity is already running.
1653 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1654 mKeepCurTransition = true;
1655 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001656 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001657 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1658 // For paranoia, make sure we have correctly resumed the top activity.
1659 mTargetStack.mLastPausedActivity = null;
1660 if (mDoResume) {
1661 mSupervisor.resumeFocusedStackTopActivityLocked();
1662 }
1663 ActivityOptions.abort(mOptions);
1664 return START_DELIVERED_TO_TOP;
1665 }
1666 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1667 // In this case, we are launching an activity in our own task that may already be
1668 // running somewhere in the history, and we want to shuffle it to the front of the
1669 // stack if so.
1670 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1671 if (top != null) {
1672 final TaskRecord task = top.task;
1673 task.moveActivityToFrontLocked(top);
1674 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001675 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001676 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1677 mTargetStack.mLastPausedActivity = null;
1678 if (mDoResume) {
1679 mSupervisor.resumeFocusedStackTopActivityLocked();
1680 }
1681 return START_DELIVERED_TO_TOP;
1682 }
1683 }
1684
1685 // An existing activity is starting this new activity, so we want to keep the new one in
1686 // the same task as the one that is starting it.
1687 mStartActivity.setTask(sourceTask, null);
1688 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1689 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1690 return START_SUCCESS;
1691 }
1692
1693 private int setTaskFromInTask() {
1694 if (mLaunchBounds != null) {
1695 mInTask.updateOverrideConfiguration(mLaunchBounds);
1696 int stackId = mInTask.getLaunchStackId();
1697 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001698 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001699 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001700 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001701 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001702 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001703 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001704 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001705 }
1706 mTargetStack = mInTask.stack;
1707 mTargetStack.moveTaskToFrontLocked(
1708 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1709
1710 // Check whether we should actually launch the new activity in to the task,
1711 // or just reuse the current activity on top.
1712 ActivityRecord top = mInTask.getTopActivity();
1713 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1714 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1715 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001716 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001717 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1718 // We don't need to start a new activity, and the client said not to do
1719 // anything if that is the case, so this is it!
1720 return START_RETURN_INTENT_TO_CALLER;
1721 }
1722 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1723 return START_DELIVERED_TO_TOP;
1724 }
1725 }
1726
1727 if (!mAddingToTask) {
1728 // We don't actually want to have this activity added to the task, so just
1729 // stop here but still tell the caller that we consumed the intent.
1730 ActivityOptions.abort(mOptions);
1731 return START_TASK_TO_FRONT;
1732 }
1733
1734 mStartActivity.setTask(mInTask, null);
1735 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1736 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1737
1738 return START_SUCCESS;
1739 }
1740
1741 private void setTaskToCurrentTopOrCreateNewTask() {
1742 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1743 mOptions);
1744 if (mDoResume) {
1745 mTargetStack.moveToFront("addingToTopTask");
1746 }
1747 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001748 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1749 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1750 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001751 mStartActivity.setTask(task, null);
1752 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1753 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1754 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1755 }
1756
1757 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1758 boolean launchSingleTask, int launchFlags) {
1759 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1760 (launchSingleInstance || launchSingleTask)) {
1761 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1762 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1763 "\"singleInstance\" or \"singleTask\"");
1764 launchFlags &=
1765 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1766 } else {
1767 switch (r.info.documentLaunchMode) {
1768 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1769 break;
1770 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1771 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1772 break;
1773 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1774 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1775 break;
1776 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1777 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1778 break;
1779 }
1780 }
1781 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001782 }
1783
1784 final void doPendingActivityLaunchesLocked(boolean doResume) {
1785 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001786 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1787 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001788 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001789 final int result = startActivityUnchecked(
1790 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1791 postStartActivityUncheckedProcessing(
1792 pal.r, result, mSupervisor.mFocusedStack.mStackId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001793 } catch (Exception e) {
1794 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1795 pal.sendErrorResult(e.getMessage());
1796 }
1797 }
1798 }
1799
1800 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001801 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001802 final TaskRecord task = r.task;
1803 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1804 return mSupervisor.mHomeStack;
1805 }
1806
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001807 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001808 if (stack != null) {
1809 return stack;
1810 }
1811
1812 if (task != null && task.stack != null) {
1813 stack = task.stack;
1814 if (stack.isOnHomeDisplay()) {
1815 if (mSupervisor.mFocusedStack != stack) {
1816 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1817 "computeStackFocus: Setting " + "focused stack to r=" + r
1818 + " task=" + task);
1819 } else {
1820 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1821 "computeStackFocus: Focused stack already="
1822 + mSupervisor.mFocusedStack);
1823 }
1824 }
1825 return stack;
1826 }
1827
1828 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1829 if (container != null) {
1830 // The first time put it on the desired stack, after this put on task stack.
1831 r.mInitialActivityContainer = null;
1832 return container.mStack;
1833 }
1834
1835 // The fullscreen stack can contain any task regardless of if the task is resizeable
1836 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1837 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1838 // we can also put it in the focused stack.
1839 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001840 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1841 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1842 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001843 if (canUseFocusedStack && (!newTask
1844 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1845 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1846 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1847 return mSupervisor.mFocusedStack;
1848 }
1849
1850 // We first try to put the task in the first dynamic stack.
1851 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1852 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1853 stack = homeDisplayStacks.get(stackNdx);
1854 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1855 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1856 "computeStackFocus: Setting focused stack=" + stack);
1857 return stack;
1858 }
1859 }
1860
1861 // If there is no suitable dynamic stack then we figure out which static stack to use.
1862 final int stackId = task != null ? task.getLaunchStackId() :
1863 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1864 FULLSCREEN_WORKSPACE_STACK_ID;
1865 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1866 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1867 + r + " stackId=" + stack.mStackId);
1868 return stack;
1869 }
1870
Wale Ogunwale854809c2015-12-27 16:18:19 -08001871 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001872 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001873
1874 // We are reusing a task, keep the stack!
1875 if (mReuseTask != null) {
1876 return mReuseTask.stack;
1877 }
1878
Wale Ogunwale854809c2015-12-27 16:18:19 -08001879 final int launchStackId =
1880 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1881
1882 if (isValidLaunchStackId(launchStackId, r)) {
1883 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001884 } else if (launchStackId == DOCKED_STACK_ID) {
1885 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1886 // for this activity, so we put the activity in the fullscreen stack.
1887 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001888 }
1889
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001890 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001891 return null;
1892 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001893 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001894
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001895 // The parent activity doesn't want to launch the activity on top of itself, but
1896 // instead tries to put it onto other side in side-by-side mode.
1897 final ActivityStack parentStack = task != null ? task.stack
1898 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1899 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001900
1901 if (parentStack != mSupervisor.mFocusedStack) {
1902 // If task's parent stack is not focused - use it during adjacent launch.
1903 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001904 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001905 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1906 // If task is already on top of focused stack - use it. We don't want to move the
1907 // existing focused task to adjacent stack, just deliver new intent in this case.
1908 return mSupervisor.mFocusedStack;
1909 }
1910
1911 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1912 // If parent was in docked stack, the natural place to launch another activity
1913 // will be fullscreen, so it can appear alongside the docked window.
1914 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1915 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001916 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001917 // If the parent is not in the docked stack, we check if there is docked window
1918 // and if yes, we will launch into that stack. If not, we just put the new
1919 // activity into parent's stack, because we can't find a better place.
1920 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1921 if (dockedStack != null
1922 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1923 // There is a docked stack, but it isn't visible, so we can't launch into that.
1924 return null;
1925 } else {
1926 return dockedStack;
1927 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001928 }
1929 }
1930 }
1931
Wale Ogunwale854809c2015-12-27 16:18:19 -08001932 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1933 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1934 || !StackId.isStaticStack(stackId)) {
1935 return false;
1936 }
1937
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001938 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
1939 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
1940 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001941 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001942
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001943 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1944 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08001945 }
1946
1947 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1948 return false;
1949 }
1950
1951 final boolean supportsPip = mService.mSupportsPictureInPicture
1952 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1953 if (stackId == PINNED_STACK_ID && !supportsPip) {
1954 return false;
1955 }
1956 return true;
1957 }
1958
Wale Ogunwale854809c2015-12-27 16:18:19 -08001959 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1960 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001961 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08001962 if (mSupervisor.canUseActivityOptionsLaunchBounds(
1963 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001964 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08001965 }
1966 }
1967 return newBounds;
1968 }
1969
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001970 void setWindowManager(WindowManagerService wm) {
1971 mWindowManager = wm;
1972 }
1973
1974 void removePendingActivityLaunchesLocked(ActivityStack stack) {
1975 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1976 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1977 if (pal.stack == stack) {
1978 mPendingActivityLaunches.remove(palNdx);
1979 }
1980 }
1981 }
1982}