blob: 32a798b33bcf7f75ff0dda1d1e9a4e47f2476c2d [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;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700169 // Indicates that we moved other task and are going to put something on top soon, so
170 // we don't want to show it redundantly or accidentally change what's shown below.
171 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800172 private boolean mMovedToFront;
173 private boolean mNoAnimation;
174 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700175 private boolean mAvoidMoveToFront;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800176
177 private IVoiceInteractionSession mVoiceSession;
178 private IVoiceInteractor mVoiceInteractor;
179
180 private void reset() {
181 mStartActivity = null;
182 mIntent = null;
183 mCallingUid = -1;
184 mOptions = null;
185
186 mLaunchSingleTop = false;
187 mLaunchSingleInstance = false;
188 mLaunchSingleTask = false;
189 mLaunchTaskBehind = false;
190 mLaunchFlags = 0;
191
192 mLaunchBounds = null;
193
194 mNotTop = null;
195 mDoResume = false;
196 mStartFlags = 0;
197 mSourceRecord = null;
198
199 mInTask = null;
200 mAddingToTask = false;
201 mReuseTask = null;
202
203 mNewTaskInfo = null;
204 mNewTaskIntent = null;
205 mSourceStack = null;
206
207 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700208 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800209 mMovedToFront = false;
210 mNoAnimation = false;
211 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700212 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800213
214 mVoiceSession = null;
215 mVoiceInteractor = null;
216 }
217
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800218 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
219 mService = service;
220 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000221 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800222 }
223
224 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
225 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
226 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
227 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
228 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
229 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
230 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
231 TaskRecord inTask) {
232 int err = ActivityManager.START_SUCCESS;
233
234 ProcessRecord callerApp = null;
235 if (caller != null) {
236 callerApp = mService.getRecordForAppLocked(caller);
237 if (callerApp != null) {
238 callingPid = callerApp.pid;
239 callingUid = callerApp.info.uid;
240 } else {
241 Slog.w(TAG, "Unable to find app for caller " + caller
242 + " (pid=" + callingPid + ") when starting: "
243 + intent.toString());
244 err = ActivityManager.START_PERMISSION_DENIED;
245 }
246 }
247
248 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
249
250 if (err == ActivityManager.START_SUCCESS) {
251 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
252 + "} from uid " + callingUid
253 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
254 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
255 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
256 container.mActivityDisplay.mDisplayId)));
257 }
258
259 ActivityRecord sourceRecord = null;
260 ActivityRecord resultRecord = null;
261 if (resultTo != null) {
262 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
263 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
264 "Will send result to " + resultTo + " " + sourceRecord);
265 if (sourceRecord != null) {
266 if (requestCode >= 0 && !sourceRecord.finishing) {
267 resultRecord = sourceRecord;
268 }
269 }
270 }
271
272 final int launchFlags = intent.getFlags();
273
274 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
275 // Transfer the result target from the source activity to the new
276 // one being started, including any failures.
277 if (requestCode >= 0) {
278 ActivityOptions.abort(options);
279 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
280 }
281 resultRecord = sourceRecord.resultTo;
282 if (resultRecord != null && !resultRecord.isInStackLocked()) {
283 resultRecord = null;
284 }
285 resultWho = sourceRecord.resultWho;
286 requestCode = sourceRecord.requestCode;
287 sourceRecord.resultTo = null;
288 if (resultRecord != null) {
289 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
290 }
291 if (sourceRecord.launchedFromUid == callingUid) {
292 // The new activity is being launched from the same uid as the previous
293 // activity in the flow, and asking to forward its result back to the
294 // previous. In this case the activity is serving as a trampoline between
295 // the two, so we also want to update its launchedFromPackage to be the
296 // same as the previous activity. Note that this is safe, since we know
297 // these two packages come from the same uid; the caller could just as
298 // well have supplied that same package name itself. This specifially
299 // deals with the case of an intent picker/chooser being launched in the app
300 // flow to redirect to an activity picked by the user, where we want the final
301 // activity to consider it to have been launched by the previous app activity.
302 callingPackage = sourceRecord.launchedFromPackage;
303 }
304 }
305
306 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
307 // We couldn't find a class that can handle the given Intent.
308 // That's the end of that!
309 err = ActivityManager.START_INTENT_NOT_RESOLVED;
310 }
311
312 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
313 // We couldn't find the specific class specified in the Intent.
314 // Also the end of the line.
315 err = ActivityManager.START_CLASS_NOT_FOUND;
316 }
317
318 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
319 && sourceRecord.task.voiceSession != null) {
320 // If this activity is being launched as part of a voice session, we need
321 // to ensure that it is safe to do so. If the upcoming activity will also
322 // be part of the voice session, we can only launch it if it has explicitly
323 // said it supports the VOICE category, or it is a part of the calling app.
324 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
325 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
326 try {
327 intent.addCategory(Intent.CATEGORY_VOICE);
328 if (!AppGlobals.getPackageManager().activitySupportsIntent(
329 intent.getComponent(), intent, resolvedType)) {
330 Slog.w(TAG,
331 "Activity being started in current voice task does not support voice: "
332 + intent);
333 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
334 }
335 } catch (RemoteException e) {
336 Slog.w(TAG, "Failure checking voice capabilities", e);
337 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
338 }
339 }
340 }
341
342 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
343 // If the caller is starting a new voice session, just make sure the target
344 // is actually allowing it to run this way.
345 try {
346 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
347 intent, resolvedType)) {
348 Slog.w(TAG,
349 "Activity being started in new voice task does not support: "
350 + intent);
351 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
352 }
353 } catch (RemoteException e) {
354 Slog.w(TAG, "Failure checking voice capabilities", e);
355 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
356 }
357 }
358
359 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
360
Wale Ogunwale01d66562015-12-29 08:19:19 -0800361 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800362 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800363 resultStack.sendActivityResultLocked(
364 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800365 }
366 ActivityOptions.abort(options);
367 return err;
368 }
369
370 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
371 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100372 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800373 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
374 callingPid, resolvedType, aInfo.applicationInfo);
375
376 if (mService.mController != null) {
377 try {
378 // The Intent we give to the watcher has the extra data
379 // stripped off, since it can contain private information.
380 Intent watchIntent = intent.cloneFilter();
381 abort |= !mService.mController.activityStarting(watchIntent,
382 aInfo.applicationInfo.packageName);
383 } catch (RemoteException e) {
384 mService.mController = null;
385 }
386 }
387
Rubin Xu58d25992016-01-21 17:47:13 +0000388 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100389 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
390 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000391 intent = mInterceptor.mIntent;
392 rInfo = mInterceptor.mRInfo;
393 aInfo = mInterceptor.mAInfo;
394 resolvedType = mInterceptor.mResolvedType;
395 inTask = mInterceptor.mInTask;
396 callingPid = mInterceptor.mCallingPid;
397 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100398 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800399 if (abort) {
400 if (resultRecord != null) {
401 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800402 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800403 }
404 // We pretend to the caller that it was really started, but
405 // they will just get a cancel result.
406 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800407 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800408 }
409
410 // If permissions need a review before any of the app components can run, we
411 // launch the review activity and pass a pending intent to start the activity
412 // we are to launching now after the review is completed.
413 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
414 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
415 aInfo.packageName, userId)) {
416 IIntentSender target = mService.getIntentSenderLocked(
417 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
418 callingUid, userId, null, null, 0, new Intent[]{intent},
419 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
420 | PendingIntent.FLAG_ONE_SHOT, null);
421
422 final int flags = intent.getFlags();
423 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
424 newIntent.setFlags(flags
425 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
426 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
427 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
428 if (resultRecord != null) {
429 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
430 }
431 intent = newIntent;
432
433 resolvedType = null;
434 callingUid = realCallingUid;
435 callingPid = realCallingPid;
436
437 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
438 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
439 null /*profilerInfo*/);
440
441 if (DEBUG_PERMISSIONS_REVIEW) {
442 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
443 true, false) + "} from uid " + callingUid + " on display "
444 + (container == null ? (mSupervisor.mFocusedStack == null ?
445 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
446 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
447 container.mActivityDisplay.mDisplayId)));
448 }
449 }
450 }
451
452 // If we have an ephemeral app, abort the process of launching the resolved intent.
453 // Instead, launch the ephemeral installer. Once the installer is finished, it
454 // starts either the intent we resolved here [on install error] or the ephemeral
455 // app [on install success].
456 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
457 // Create a pending intent to start the intent resolved here.
458 final IIntentSender failureTarget = mService.getIntentSenderLocked(
459 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
460 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
461 new String[]{ resolvedType },
462 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
463 | PendingIntent.FLAG_IMMUTABLE, null);
464
465 // Create a pending intent to start the ephemeral application; force it to be
466 // directed to the ephemeral package.
467 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
468 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
469 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
470 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
471 new String[]{ resolvedType },
472 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
473 | PendingIntent.FLAG_IMMUTABLE, null);
474
475 int flags = intent.getFlags();
476 intent = new Intent();
477 intent.setFlags(flags
478 | Intent.FLAG_ACTIVITY_NEW_TASK
479 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
480 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
481 rInfo.ephemeralResolveInfo.getPackageName());
482 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
483 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
484
485 resolvedType = null;
486 callingUid = realCallingUid;
487 callingPid = realCallingPid;
488
489 rInfo = rInfo.ephemeralInstaller;
490 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
491 }
492
493 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
494 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
495 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
Wale Ogunwale1affbbc2016-05-01 09:03:52 -0700496 options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800497 if (outActivity != null) {
498 outActivity[0] = r;
499 }
500
501 if (r.appTimeTracker == null && sourceRecord != null) {
502 // If the caller didn't specify an explicit time tracker, we want to continue
503 // tracking under any it has.
504 r.appTimeTracker = sourceRecord.appTimeTracker;
505 }
506
507 final ActivityStack stack = mSupervisor.mFocusedStack;
508 if (voiceSession == null && (stack.mResumedActivity == null
509 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
510 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
511 realCallingPid, realCallingUid, "Activity start")) {
512 PendingActivityLaunch pal = new PendingActivityLaunch(r,
513 sourceRecord, startFlags, stack, callerApp);
514 mPendingActivityLaunches.add(pal);
515 ActivityOptions.abort(options);
516 return ActivityManager.START_SWITCHES_CANCELED;
517 }
518 }
519
520 if (mService.mDidAppSwitch) {
521 // This is the second allowed switch since we stopped switches,
522 // so now just generally allow switches. Use case: user presses
523 // home (switches disabled, switch to home, mDidAppSwitch now true);
524 // user taps a home icon (coming from home so allowed, we hit here
525 // and now allow anyone to switch again).
526 mService.mAppSwitchesAllowedTime = 0;
527 } else {
528 mService.mDidAppSwitch = true;
529 }
530
531 doPendingActivityLaunchesLocked(false);
532
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700533 try {
534 mService.mWindowManager.deferSurfaceLayout();
535 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
536 true, options, inTask);
537 } finally {
538 mService.mWindowManager.continueSurfaceLayout();
539 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700540 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800541 return err;
542 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800543
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800544 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700545 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
546 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800547
548 if (result < START_SUCCESS) {
549 // If someone asked to have the keyguard dismissed on the next activity start,
550 // but we are not actually doing an activity switch... just dismiss the keyguard now,
551 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800552 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800553 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800554 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800555
Chong Zhang5022da32016-06-21 16:31:37 -0700556 // We're waiting for an activity launch to finish, but that activity simply
557 // brought another activity to front. Let startActivityMayWait() know about
558 // this, so it waits for the new activity to become visible instead.
559 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
560 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
561 }
562
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800563 int startedActivityStackId = INVALID_STACK_ID;
564 if (r.task != null && r.task.stack != null) {
565 startedActivityStackId = r.task.stack.mStackId;
566 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700567 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800568 }
569
Jorim Jaggi352d5842016-05-19 10:20:28 -0700570 // If we launched the activity from a no display activity that was launched from the home
571 // screen, we also need to start recents to un-minimize the docked stack, since the
572 // noDisplay activity will be finished shortly after.
573 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
574 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700575 final boolean noDisplayActivityOverHome = sourceRecord != null
576 && sourceRecord.noDisplay
577 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700578 if (startedActivityStackId == DOCKED_STACK_ID
579 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100580 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
581 final ActivityRecord topActivityHomeStack = homeStack != null
582 ? homeStack.topRunningActivityLocked() : null;
583 if (topActivityHomeStack == null
584 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
585 // We launch an activity while being in home stack, which means either launcher or
586 // recents into docked stack. We don't want the launched activity to be alone in a
587 // docked stack, so we want to immediately launch recents too.
588 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700589 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100590 return;
591 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800592 }
593
594 if (startedActivityStackId == PINNED_STACK_ID
595 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
596 // The activity was already running in the pinned stack so it wasn't started, but either
597 // brought to the front or the new intent was delivered to it since it was already in
598 // front. Notify anyone interested in this piece of information.
599 mService.notifyPinnedActivityRestartAttemptLocked();
600 return;
601 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800602 }
603
604 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
605 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
606 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
607 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
608 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
609 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
610 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700611 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800612 null /*container*/, null /*inTask*/);
613 if (mSupervisor.inResumeTopActivity) {
614 // If we are in resume section already, home activity will be initialized, but not
615 // resumed (to avoid recursive resume) and will stay that way until something pokes it
616 // again. We need to schedule another resume.
617 mSupervisor.scheduleResumeTopActivities();
618 }
619 }
620
Tony Mak853304c2016-04-18 15:17:41 +0100621 void showConfirmDeviceCredential(int userId) {
622 // First, retrieve the stack that we want to resume after credential is confirmed.
623 ActivityStack targetStack;
624 ActivityStack fullscreenStack =
625 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
626 if (fullscreenStack != null &&
627 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
628 // Single window case and the case that the docked stack is shown with fullscreen stack.
629 targetStack = fullscreenStack;
630 } else {
631 // The case that the docked stack is shown with recent.
632 targetStack = mSupervisor.getStack(HOME_STACK_ID);
633 }
634 if (targetStack == null) {
635 return;
636 }
637 final KeyguardManager km = (KeyguardManager) mService.mContext
638 .getSystemService(Context.KEYGUARD_SERVICE);
639 final Intent credential =
640 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100641 // For safety, check null here in case users changed the setting after the checking.
642 if (credential == null) {
643 return;
644 }
Tony Mak853304c2016-04-18 15:17:41 +0100645 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
646 if (activityRecord != null) {
647 final IIntentSender target = mService.getIntentSenderLocked(
648 ActivityManager.INTENT_SENDER_ACTIVITY,
649 activityRecord.launchedFromPackage,
650 activityRecord.launchedFromUid,
651 activityRecord.userId,
652 null, null, 0,
653 new Intent[] { activityRecord.intent },
654 new String[] { activityRecord.resolvedType },
655 PendingIntent.FLAG_CANCEL_CURRENT |
656 PendingIntent.FLAG_ONE_SHOT |
657 PendingIntent.FLAG_IMMUTABLE,
658 null);
659 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
660 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100661 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100662 }
663 }
664
Tony Mak646fe992016-04-21 16:43:08 +0100665 void startConfirmCredentialIntent(Intent intent) {
666 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
667 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
668 FLAG_ACTIVITY_TASK_ON_HOME);
669 final ActivityOptions options = ActivityOptions.makeBasic();
670 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
671 mService.mContext.startActivityAsUser(intent, options.toBundle(),
672 UserHandle.CURRENT);
673 }
Tony Mak853304c2016-04-18 15:17:41 +0100674
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800675 final int startActivityMayWait(IApplicationThread caller, int callingUid,
676 String callingPackage, Intent intent, String resolvedType,
677 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
678 IBinder resultTo, String resultWho, int requestCode, int startFlags,
679 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
680 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
681 IActivityContainer iContainer, TaskRecord inTask) {
682 // Refuse possible leaked file descriptors
683 if (intent != null && intent.hasFileDescriptors()) {
684 throw new IllegalArgumentException("File descriptors passed in Intent");
685 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500686 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800687 boolean componentSpecified = intent.getComponent() != null;
688
689 // Save a copy in case ephemeral needs it
690 final Intent ephemeralIntent = new Intent(intent);
691 // Don't modify the client's object!
692 intent = new Intent(intent);
693
694 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000695 if (rInfo == null) {
696 UserInfo userInfo = mSupervisor.getUserInfo(userId);
697 if (userInfo != null && userInfo.isManagedProfile()) {
698 // Special case for managed profiles, if attempting to launch non-cryto aware
699 // app in a locked managed profile from an unlocked parent allow it to resolve
700 // as user will be sent via confirm credentials to unlock the profile.
701 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700702 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000703 long token = Binder.clearCallingIdentity();
704 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700705 UserInfo parent = userManager.getProfileParent(userId);
706 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
707 && userManager.isUserUnlockingOrUnlocked(parent.id)
708 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000709 } finally {
710 Binder.restoreCallingIdentity(token);
711 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700712 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000713 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600714 PackageManager.MATCH_DIRECT_BOOT_AWARE
715 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000716 }
717 }
718 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800719 // Collect information about the target of the Intent.
720 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
721
722 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
723 ActivityStackSupervisor.ActivityContainer container =
724 (ActivityStackSupervisor.ActivityContainer)iContainer;
725 synchronized (mService) {
726 if (container != null && container.mParentActivity != null &&
727 container.mParentActivity.state != RESUMED) {
728 // Cannot start a child activity if the parent is not resumed.
729 return ActivityManager.START_CANCELED;
730 }
731 final int realCallingPid = Binder.getCallingPid();
732 final int realCallingUid = Binder.getCallingUid();
733 int callingPid;
734 if (callingUid >= 0) {
735 callingPid = -1;
736 } else if (caller == null) {
737 callingPid = realCallingPid;
738 callingUid = realCallingUid;
739 } else {
740 callingPid = callingUid = -1;
741 }
742
743 final ActivityStack stack;
744 if (container == null || container.mStack.isOnHomeDisplay()) {
745 stack = mSupervisor.mFocusedStack;
746 } else {
747 stack = container.mStack;
748 }
749 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
750 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
751 "Starting activity when config will change = " + stack.mConfigWillChange);
752
753 final long origId = Binder.clearCallingIdentity();
754
755 if (aInfo != null &&
756 (aInfo.applicationInfo.privateFlags
757 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
758 // This may be a heavy-weight process! Check to see if we already
759 // have another, different heavy-weight process running.
760 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
761 final ProcessRecord heavy = mService.mHeavyWeightProcess;
762 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
763 || !heavy.processName.equals(aInfo.processName))) {
764 int appCallingUid = callingUid;
765 if (caller != null) {
766 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
767 if (callerApp != null) {
768 appCallingUid = callerApp.info.uid;
769 } else {
770 Slog.w(TAG, "Unable to find app for caller " + caller
771 + " (pid=" + callingPid + ") when starting: "
772 + intent.toString());
773 ActivityOptions.abort(options);
774 return ActivityManager.START_PERMISSION_DENIED;
775 }
776 }
777
778 IIntentSender target = mService.getIntentSenderLocked(
779 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
780 appCallingUid, userId, null, null, 0, new Intent[] { intent },
781 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
782 | PendingIntent.FLAG_ONE_SHOT, null);
783
784 Intent newIntent = new Intent();
785 if (requestCode >= 0) {
786 // Caller is requesting a result.
787 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
788 }
789 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
790 new IntentSender(target));
791 if (heavy.activities.size() > 0) {
792 ActivityRecord hist = heavy.activities.get(0);
793 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
794 hist.packageName);
795 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
796 hist.task.taskId);
797 }
798 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
799 aInfo.packageName);
800 newIntent.setFlags(intent.getFlags());
801 newIntent.setClassName("android",
802 HeavyWeightSwitcherActivity.class.getName());
803 intent = newIntent;
804 resolvedType = null;
805 caller = null;
806 callingUid = Binder.getCallingUid();
807 callingPid = Binder.getCallingPid();
808 componentSpecified = true;
809 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
810 aInfo = rInfo != null ? rInfo.activityInfo : null;
811 if (aInfo != null) {
812 aInfo = mService.getActivityInfoForUser(aInfo, userId);
813 }
814 }
815 }
816 }
817
Jorim Jaggi275561a2016-02-23 10:11:02 -0500818 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800819 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
820 aInfo, rInfo, voiceSession, voiceInteractor,
821 resultTo, resultWho, requestCode, callingPid,
822 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500823 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
824 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800825
826 Binder.restoreCallingIdentity(origId);
827
828 if (stack.mConfigWillChange) {
829 // If the caller also wants to switch to a new configuration,
830 // do so now. This allows a clean switch, as we are waiting
831 // for the current activity to pause (so we will not destroy
832 // it), and have not yet started the next activity.
833 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
834 "updateConfiguration()");
835 stack.mConfigWillChange = false;
836 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
837 "Updating to new configuration after starting activity.");
838 mService.updateConfigurationLocked(config, null, false);
839 }
840
841 if (outResult != null) {
842 outResult.result = res;
843 if (res == ActivityManager.START_SUCCESS) {
844 mSupervisor.mWaitingActivityLaunched.add(outResult);
845 do {
846 try {
847 mService.wait();
848 } catch (InterruptedException e) {
849 }
Chong Zhang5022da32016-06-21 16:31:37 -0700850 } while (outResult.result != START_TASK_TO_FRONT
851 && !outResult.timeout && outResult.who == null);
852 if (outResult.result == START_TASK_TO_FRONT) {
853 res = START_TASK_TO_FRONT;
854 }
855 }
856 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800857 ActivityRecord r = stack.topRunningActivityLocked();
858 if (r.nowVisible && r.state == RESUMED) {
859 outResult.timeout = false;
860 outResult.who = new ComponentName(r.info.packageName, r.info.name);
861 outResult.totalTime = 0;
862 outResult.thisTime = 0;
863 } else {
864 outResult.thisTime = SystemClock.uptimeMillis();
865 mSupervisor.mWaitingActivityVisible.add(outResult);
866 do {
867 try {
868 mService.wait();
869 } catch (InterruptedException e) {
870 }
871 } while (!outResult.timeout && outResult.who == null);
872 }
873 }
874 }
875
Jorim Jaggibe67c902016-04-12 00:53:16 -0700876 final ActivityRecord launchedActivity = mReusedActivity != null
877 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700878 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800879 return res;
880 }
881 }
882
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800883 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
884 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
885 Bundle bOptions, int userId) {
886 if (intents == null) {
887 throw new NullPointerException("intents is null");
888 }
889 if (resolvedTypes == null) {
890 throw new NullPointerException("resolvedTypes is null");
891 }
892 if (intents.length != resolvedTypes.length) {
893 throw new IllegalArgumentException("intents are length different than resolvedTypes");
894 }
895
896
897 int callingPid;
898 if (callingUid >= 0) {
899 callingPid = -1;
900 } else if (caller == null) {
901 callingPid = Binder.getCallingPid();
902 callingUid = Binder.getCallingUid();
903 } else {
904 callingPid = callingUid = -1;
905 }
906 final long origId = Binder.clearCallingIdentity();
907 try {
908 synchronized (mService) {
909 ActivityRecord[] outActivity = new ActivityRecord[1];
910 for (int i=0; i<intents.length; i++) {
911 Intent intent = intents[i];
912 if (intent == null) {
913 continue;
914 }
915
916 // Refuse possible leaked file descriptors
917 if (intent != null && intent.hasFileDescriptors()) {
918 throw new IllegalArgumentException("File descriptors passed in Intent");
919 }
920
921 boolean componentSpecified = intent.getComponent() != null;
922
923 // Don't modify the client's object!
924 intent = new Intent(intent);
925
926 // Collect information about the target of the Intent.
927 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
928 null, userId);
929 // TODO: New, check if this is correct
930 aInfo = mService.getActivityInfoForUser(aInfo, userId);
931
932 if (aInfo != null &&
933 (aInfo.applicationInfo.privateFlags
934 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
935 throw new IllegalArgumentException(
936 "FLAG_CANT_SAVE_STATE not supported here");
937 }
938
939 ActivityOptions options = ActivityOptions.fromBundle(
940 i == intents.length - 1 ? bOptions : null);
941 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
942 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
943 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
944 options, false, componentSpecified, outActivity, null, null);
945 if (res < 0) {
946 return res;
947 }
948
949 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
950 }
951 }
952 } finally {
953 Binder.restoreCallingIdentity(origId);
954 }
955
Wale Ogunwale01d66562015-12-29 08:19:19 -0800956 return START_SUCCESS;
957 }
958
959 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
960 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
961 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
962
963 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
964 voiceInteractor);
965
966 computeLaunchingTaskFlags();
967
968 computeSourceStack();
969
970 mIntent.setFlags(mLaunchFlags);
971
Jorim Jaggibe67c902016-04-12 00:53:16 -0700972 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800973
Jorim Jaggi2adba072016-03-03 13:43:39 +0100974 final int preferredLaunchStackId =
975 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
976
Jorim Jaggibe67c902016-04-12 00:53:16 -0700977 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800978 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
979 // still needs to be a lock task mode violation since the task gets cleared out and
980 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700981 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800982 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
983 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
984 mSupervisor.showLockTaskToast();
985 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
986 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
987 }
988
989 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -0700990 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800991 }
Jorim Jaggibe67c902016-04-12 00:53:16 -0700992 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800993 // This task was started because of movement of the activity based on affinity...
994 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -0700995 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800996 }
997
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800998 // This code path leads to delivering a new intent, we want to make sure we schedule it
999 // as the first operation, in case the activity will be resumed as a result of later
1000 // operations.
1001 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1002 || mLaunchSingleInstance || mLaunchSingleTask) {
1003 // In this situation we want to remove all activities from the task up to the one
1004 // being started. In most cases this means we are resetting the task to its initial
1005 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001006 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001007 mStartActivity, mLaunchFlags);
1008 if (top != null) {
1009 if (top.frontOfTask) {
1010 // Activity aliases may mean we use different intents for the top activity,
1011 // so make sure the task now has the identity of the new intent.
1012 top.task.setIntent(mStartActivity);
1013 }
1014 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1015 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1016 mStartActivity.launchedFromPackage);
1017 }
1018 }
1019
Jorim Jaggibe67c902016-04-12 00:53:16 -07001020 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001021
1022 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1023 // We don't need to start a new activity, and the client said not to do anything
1024 // if that is the case, so this is it! And for paranoia, make sure we have
1025 // correctly resumed the top activity.
1026 resumeTargetStackIfNeeded();
1027 return START_RETURN_INTENT_TO_CALLER;
1028 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001029 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001030
1031 if (!mAddingToTask && mReuseTask == null) {
1032 // We didn't do anything... but it was needed (a.k.a., client don't use that
1033 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1034 resumeTargetStackIfNeeded();
1035 return START_TASK_TO_FRONT;
1036 }
1037 }
1038
1039 if (mStartActivity.packageName == null) {
1040 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1041 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1042 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1043 mStartActivity.requestCode, RESULT_CANCELED, null);
1044 }
1045 ActivityOptions.abort(mOptions);
1046 return START_CLASS_NOT_FOUND;
1047 }
1048
1049 // If the activity being launched is the same as the one currently at the top, then
1050 // we need to check if it should only be launched once.
1051 final ActivityStack topStack = mSupervisor.mFocusedStack;
1052 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1053 final boolean dontStart = top != null && mStartActivity.resultTo == null
1054 && top.realActivity.equals(mStartActivity.realActivity)
1055 && top.userId == mStartActivity.userId
1056 && top.app != null && top.app.thread != null
1057 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1058 || mLaunchSingleTop || mLaunchSingleTask);
1059 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001060 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001061 // For paranoia, make sure we have correctly resumed the top activity.
1062 topStack.mLastPausedActivity = null;
1063 if (mDoResume) {
1064 mSupervisor.resumeFocusedStackTopActivityLocked();
1065 }
1066 ActivityOptions.abort(mOptions);
1067 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1068 // We don't need to start a new activity, and the client said not to do
1069 // anything if that is the case, so this is it!
1070 return START_RETURN_INTENT_TO_CALLER;
1071 }
1072 top.deliverNewIntentLocked(
1073 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001074
1075 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1076 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1077 mSupervisor.handleNonResizableTaskIfNeeded(
1078 top.task, preferredLaunchStackId, topStack.mStackId);
1079
Wale Ogunwale01d66562015-12-29 08:19:19 -08001080 return START_DELIVERED_TO_TOP;
1081 }
1082
1083 boolean newTask = false;
1084 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1085 ? mSourceRecord.task : null;
1086
1087 // Should this be considered a new task?
1088 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1089 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1090 newTask = true;
1091 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1092
1093 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1094 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1095 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1096 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001097 if (!mMovedOtherTask) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001098 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001099 }
1100 } else if (mSourceRecord != null) {
1101 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1102 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1103 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1104 }
1105
1106 final int result = setTaskFromSourceRecord();
1107 if (result != START_SUCCESS) {
1108 return result;
1109 }
1110 } else if (mInTask != null) {
1111 // The caller is asking that the new activity be started in an explicit
1112 // task it has provided to us.
1113 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1114 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1115 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1116 }
1117
1118 final int result = setTaskFromInTask();
1119 if (result != START_SUCCESS) {
1120 return result;
1121 }
1122 } else {
1123 // This not being started from an existing activity, and not part of a new task...
1124 // just put it in the top task, though these days this case should never happen.
1125 setTaskToCurrentTopOrCreateNewTask();
1126 }
1127
1128 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1129 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1130
1131 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1132 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1133 }
1134 if (newTask) {
1135 EventLog.writeEvent(
1136 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1137 }
1138 ActivityStack.logStartActivity(
1139 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1140 mTargetStack.mLastPausedActivity = null;
1141 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1142 if (mDoResume) {
1143 if (!mLaunchTaskBehind) {
1144 // TODO(b/26381750): Remove this code after verification that all the decision
1145 // points above moved targetStack to the front which will also set the focus
1146 // activity.
1147 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1148 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001149 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1150 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001151 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1152 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001153 // If the activity is not focusable, we can't resume it, but still would like to
1154 // make sure it becomes visible as it starts (this will also trigger entry
1155 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001156 // Also, we don't want to resume activities in a task that currently has an overlay
1157 // as the starting activity just needs to be in the visible paused state until the
1158 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001159 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001160 // Go ahead and tell window manager to execute app transition for this activity
1161 // since the app transition will not be triggered through the resume channel.
1162 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001163 } else {
1164 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1165 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001166 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001167 } else {
1168 mTargetStack.addRecentActivityLocked(mStartActivity);
1169 }
1170 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1171
Jorim Jaggid53f0922016-04-06 22:16:23 -07001172 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001173 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001174
1175 return START_SUCCESS;
1176 }
1177
1178 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1179 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1180 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1181 reset();
1182
1183 mStartActivity = r;
1184 mIntent = r.intent;
1185 mOptions = options;
1186 mCallingUid = r.launchedFromUid;
1187 mSourceRecord = sourceRecord;
1188 mVoiceSession = voiceSession;
1189 mVoiceInteractor = voiceInteractor;
1190
1191 mLaunchBounds = getOverrideBounds(r, options, inTask);
1192
1193 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1194 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1195 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1196 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1197 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1198 mLaunchTaskBehind = r.mLaunchTaskBehind
1199 && !mLaunchSingleTask && !mLaunchSingleInstance
1200 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1201
1202 sendNewTaskResultRequestIfNeeded();
1203
1204 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1205 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1206 }
1207
1208 // If we are actually going to launch in to a new task, there are some cases where
1209 // we further want to do multiple task.
1210 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1211 if (mLaunchTaskBehind
1212 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1213 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1214 }
1215 }
1216
1217 // We'll invoke onUserLeaving before onPause only if the launching
1218 // activity did not explicitly state that this is an automated launch.
1219 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1220 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1221 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1222
1223 // If the caller has asked not to resume at this point, we make note
1224 // of this in the record so that we can skip it when trying to find
1225 // the top running activity.
1226 mDoResume = doResume;
1227 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1228 r.delayedResume = true;
1229 mDoResume = false;
1230 }
1231
Wale Ogunwale3b232392016-05-13 15:37:13 -07001232 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1233 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001234 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1235 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1236 if (top != null && !top.visible) {
1237
1238 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1239 // it!
1240 mDoResume = false;
1241 mAvoidMoveToFront = true;
1242 }
1243 }
1244
Wale Ogunwale01d66562015-12-29 08:19:19 -08001245 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1246
1247 mInTask = inTask;
1248 // In some flows in to this function, we retrieve the task record and hold on to it
1249 // without a lock before calling back in to here... so the task at this point may
1250 // not actually be in recents. Check for that, and if it isn't in recents just
1251 // consider it invalid.
1252 if (inTask != null && !inTask.inRecents) {
1253 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1254 mInTask = null;
1255 }
1256
1257 mStartFlags = startFlags;
1258 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1259 // is the same as the one making the call... or, as a special case, if we do not know
1260 // the caller then we count the current top activity as the caller.
1261 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1262 ActivityRecord checkedCaller = sourceRecord;
1263 if (checkedCaller == null) {
1264 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1265 mNotTop);
1266 }
1267 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1268 // Caller is not the same as launcher, so always needed.
1269 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1270 }
1271 }
1272
1273 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1274 }
1275
1276 private void sendNewTaskResultRequestIfNeeded() {
1277 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1278 && mStartActivity.resultTo.task.stack != null) {
1279 // For whatever reason this activity is being launched into a new task...
1280 // yet the caller has requested a result back. Well, that is pretty messed up,
1281 // so instead immediately send back a cancel and let the new task continue launched
1282 // as normal without a dependency on its originator.
1283 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1284 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1285 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1286 mStartActivity.resultTo = null;
1287 }
1288 }
1289
1290 private void computeLaunchingTaskFlags() {
1291 // If the caller is not coming from another activity, but has given us an explicit task into
1292 // which they would like us to launch the new activity, then let's see about doing that.
1293 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1294 final Intent baseIntent = mInTask.getBaseIntent();
1295 final ActivityRecord root = mInTask.getRootActivity();
1296 if (baseIntent == null) {
1297 ActivityOptions.abort(mOptions);
1298 throw new IllegalArgumentException("Launching into task without base intent: "
1299 + mInTask);
1300 }
1301
1302 // If this task is empty, then we are adding the first activity -- it
1303 // determines the root, and must be launching as a NEW_TASK.
1304 if (mLaunchSingleInstance || mLaunchSingleTask) {
1305 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1306 ActivityOptions.abort(mOptions);
1307 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1308 + mStartActivity + " into different task " + mInTask);
1309 }
1310 if (root != null) {
1311 ActivityOptions.abort(mOptions);
1312 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1313 + " has root " + root + " but target is singleInstance/Task");
1314 }
1315 }
1316
1317 // If task is empty, then adopt the interesting intent launch flags in to the
1318 // activity being started.
1319 if (root == null) {
1320 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1321 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1322 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1323 | (baseIntent.getFlags() & flagsOfInterest);
1324 mIntent.setFlags(mLaunchFlags);
1325 mInTask.setIntent(mStartActivity);
1326 mAddingToTask = true;
1327
1328 // If the task is not empty and the caller is asking to start it as the root of
1329 // a new task, then we don't actually want to start this on the task. We will
1330 // bring the task to the front, and possibly give it a new intent.
1331 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1332 mAddingToTask = false;
1333
1334 } else {
1335 mAddingToTask = true;
1336 }
1337
1338 mReuseTask = mInTask;
1339 } else {
1340 mInTask = null;
1341 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1342 // when in freeform workspace.
1343 // Also put noDisplay activities in the source task. These by itself can be placed
1344 // in any task/stack, however it could launch other activities like ResolverActivity,
1345 // and we want those to stay in the original task.
1346 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1347 && mSourceRecord.isFreeform()) {
1348 mAddingToTask = true;
1349 }
1350 }
1351
1352 if (mInTask == null) {
1353 if (mSourceRecord == null) {
1354 // This activity is not being started from another... in this
1355 // case we -always- start a new task.
1356 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1357 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1358 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1359 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1360 }
1361 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1362 // The original activity who is starting us is running as a single
1363 // instance... this new activity it is starting must go on its
1364 // own task.
1365 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1366 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1367 // The activity being started is a single instance... it always
1368 // gets launched into its own task.
1369 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1370 }
1371 }
1372 }
1373
1374 private void computeSourceStack() {
1375 if (mSourceRecord == null) {
1376 mSourceStack = null;
1377 return;
1378 }
1379 if (!mSourceRecord.finishing) {
1380 mSourceStack = mSourceRecord.task.stack;
1381 return;
1382 }
1383
1384 // If the source is finishing, we can't further count it as our source. This is because the
1385 // task it is associated with may now be empty and on its way out, so we don't want to
1386 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1387 // a task for it. But save the task information so it can be used when creating the new task.
1388 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1389 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1390 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1391 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1392 mNewTaskInfo = mSourceRecord.info;
1393 mNewTaskIntent = mSourceRecord.task.intent;
1394 }
1395 mSourceRecord = null;
1396 mSourceStack = null;
1397 }
1398
1399 /**
1400 * Decide whether the new activity should be inserted into an existing task. Returns null
1401 * if not or an ActivityRecord with the task into which the new activity should be added.
1402 */
1403 private ActivityRecord getReusableIntentActivity() {
1404 // We may want to try to place the new activity in to an existing task. We always
1405 // do this if the target activity is singleTask or singleInstance; we will also do
1406 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1407 // us to still place it in a new task: multi task, always doc mode, or being asked to
1408 // launch this as a new task behind the current one.
1409 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1410 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1411 || mLaunchSingleInstance || mLaunchSingleTask;
1412 // If bring to front is requested, and no result is requested and we have not been given
1413 // an explicit task to launch in to, and we can find a task that was started with this
1414 // same component, then instead of launching bring that one to the front.
1415 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1416 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001417 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1418 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1419 intentActivity = task != null ? task.getTopActivity() : null;
1420 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001421 if (mLaunchSingleInstance) {
1422 // There can be one and only one instance of single instance activity in the
1423 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001424 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001425 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1426 // For the launch adjacent case we only want to put the activity in an existing
1427 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001428 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1429 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001430 } else {
1431 // Otherwise find the best task to put the activity in.
1432 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1433 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001434 }
1435 return intentActivity;
1436 }
1437
1438 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1439 mTargetStack = intentActivity.task.stack;
1440 mTargetStack.mLastPausedActivity = null;
1441 // If the target task is not in the front, then we need to bring it to the front...
1442 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1443 // the same behavior as if a new instance was being started, which means not bringing it
1444 // to the front if the caller is not itself in the front.
1445 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1446 ActivityRecord curTop = (focusStack == null)
1447 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1448
Jorim Jaggic875ae72016-04-26 22:41:06 -07001449 if (curTop != null
1450 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1451 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001452 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1453 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1454 mSourceStack.topActivity().task == mSourceRecord.task)) {
1455 // We really do want to push this one into the user's face, right now.
1456 if (mLaunchTaskBehind && mSourceRecord != null) {
1457 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1458 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001459 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001460
1461 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1462 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1463 // So no point resuming any of the activities here, it just wastes one extra
1464 // resuming, plus enter AND exit transitions.
1465 // Here we only want to bring the target stack forward. Transition will be applied
1466 // to the new activity that's started after the old ones are gone.
1467 final boolean willClearTask =
1468 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1469 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1470 if (!willClearTask) {
1471 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001472 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001473 if (launchStack == null || launchStack == mTargetStack) {
1474 // We only want to move to the front, if we aren't going to launch on a
1475 // different stack. If we launch on a different stack, we will put the
1476 // task on top there.
1477 mTargetStack.moveTaskToFrontLocked(
1478 intentActivity.task, mNoAnimation, mOptions,
1479 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1480 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001481 } else if (launchStack.mStackId == DOCKED_STACK_ID
1482 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1483 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1484 // If we want to launch adjacent and mTargetStack is not the computed
1485 // launch stack - move task to top of computed stack.
1486 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1487 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1488 ANIMATE);
1489 } else {
1490 // TODO: This should be reevaluated in MW v2.
1491 // We choose to move task to front instead of launching it adjacent
1492 // when specific stack was requested explicitly and it appeared to be
1493 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1494 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1495 mOptions, mStartActivity.appTimeTracker,
1496 "bringToFrontInsteadOfAdjacentLaunch");
1497 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001498 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001499 }
1500 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001501 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001502 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001503 }
1504 }
1505 if (!mMovedToFront && mDoResume) {
1506 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1507 + " from " + intentActivity);
1508 mTargetStack.moveToFront("intentActivityFound");
1509 }
1510
Jorim Jaggid53f0922016-04-06 22:16:23 -07001511 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1512 mTargetStack.mStackId);
1513
Wale Ogunwale01d66562015-12-29 08:19:19 -08001514 // If the caller has requested that the target task be reset, then do so.
1515 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1516 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1517 }
1518 return intentActivity;
1519 }
1520
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001521 private void updateTaskReturnToType(
1522 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1523 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1524 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1525 // Caller wants to appear on home activity.
1526 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1527 return;
1528 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1529 // Task will be launched over the home stack, so return home.
1530 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1531 return;
1532 }
1533
1534 // Else we are coming from an application stack so return to an application.
1535 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1536 }
1537
Wale Ogunwale01d66562015-12-29 08:19:19 -08001538 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1539 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1540 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1541 // The caller has requested to completely replace any existing task with its new
1542 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001543 intentActivity.task.performClearTaskLocked();
1544 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001545 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001546 // When we clear the task - focus will be adjusted, which will bring another task
1547 // to top before we launch the activity we need. This will temporary swap their
1548 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1549 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001550 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1551 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001552 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1553 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001554 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001555 // A special case: we need to start the activity because it is not currently
1556 // running, and the caller has asked to clear the current task to have this
1557 // activity at the top.
1558 mAddingToTask = true;
1559 // Now pretend like this activity is being started by the top of its task, so it
1560 // is put in the right place.
1561 mSourceRecord = intentActivity;
1562 final TaskRecord task = mSourceRecord.task;
1563 if (task != null && task.stack == null) {
1564 // Target stack got cleared when we all activities were removed above.
1565 // Go ahead and reset it.
1566 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1567 null /* bounds */, mLaunchFlags, mOptions);
1568 mTargetStack.addTask(task,
1569 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1570 }
1571 }
1572 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1573 // In this case the top activity on the task is the same as the one being launched,
1574 // so we take that as a request to bring the task to the foreground. If the top
1575 // activity in the task is the root activity, deliver this new intent to it if it
1576 // desires.
1577 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1578 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001579 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001580 intentActivity.task);
1581 if (intentActivity.frontOfTask) {
1582 intentActivity.task.setIntent(mStartActivity);
1583 }
1584 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1585 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001586 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001587 // In this case we are launching the root activity of the task, but with a
1588 // different intent. We should start a new instance on top.
1589 mAddingToTask = true;
1590 mSourceRecord = intentActivity;
1591 }
1592 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1593 // In this case an activity is being launched in to an existing task, without
1594 // resetting that task. This is typically the situation of launching an activity
1595 // from a notification or shortcut. We want to place the new activity on top of the
1596 // current task.
1597 mAddingToTask = true;
1598 mSourceRecord = intentActivity;
1599 } else if (!intentActivity.task.rootWasReset) {
1600 // In this case we are launching into an existing task that has not yet been started
1601 // from its front door. The current task has been brought to the front. Ideally,
1602 // we'd probably like to place this new task at the bottom of its stack, but that's
1603 // a little hard to do with the current organization of the code so for now we'll
1604 // just drop it.
1605 intentActivity.task.setIntent(mStartActivity);
1606 }
1607 }
1608
1609 private void resumeTargetStackIfNeeded() {
1610 if (mDoResume) {
1611 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1612 if (!mMovedToFront) {
1613 // Make sure to notify Keyguard as well if we are not running an app transition
1614 // later.
1615 mSupervisor.notifyActivityDrawnForKeyguard();
1616 }
1617 } else {
1618 ActivityOptions.abort(mOptions);
1619 }
1620 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1621 }
1622
1623 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1624 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1625 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001626
1627 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001628 final TaskRecord task = mTargetStack.createTaskRecord(
1629 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001630 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1631 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1632 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1633 mStartActivity.setTask(task, taskToAffiliate);
1634 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001635 final int stackId = mTargetStack.mStackId;
1636 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001637 mService.resizeStack(
1638 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001639 } else {
1640 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1641 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001642 }
1643 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1644 "Starting new activity " +
1645 mStartActivity + " in new task " + mStartActivity.task);
1646 } else {
1647 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1648 }
1649 }
1650
1651 private int setTaskFromSourceRecord() {
1652 final TaskRecord sourceTask = mSourceRecord.task;
1653 // We only want to allow changing stack if the target task is not the top one,
1654 // otherwise we would move the launching task to the other side, rather than show
1655 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001656 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1657 if (moveStackAllowed) {
1658 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1659 mOptions);
1660 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001661
1662 if (mTargetStack == null) {
1663 mTargetStack = sourceTask.stack;
1664 } else if (mTargetStack != sourceTask.stack) {
1665 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1666 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1667 }
1668 if (mDoResume) {
1669 mTargetStack.moveToFront("sourceStackToFront");
1670 }
1671 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001672 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001673 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1674 mStartActivity.appTimeTracker, "sourceTaskToFront");
1675 }
1676 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1677 // In this case, we are adding the activity to an existing task, but the caller has
1678 // asked to clear that task if the activity is already running.
1679 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1680 mKeepCurTransition = true;
1681 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001682 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001683 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1684 // For paranoia, make sure we have correctly resumed the top activity.
1685 mTargetStack.mLastPausedActivity = null;
1686 if (mDoResume) {
1687 mSupervisor.resumeFocusedStackTopActivityLocked();
1688 }
1689 ActivityOptions.abort(mOptions);
1690 return START_DELIVERED_TO_TOP;
1691 }
1692 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1693 // In this case, we are launching an activity in our own task that may already be
1694 // running somewhere in the history, and we want to shuffle it to the front of the
1695 // stack if so.
1696 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1697 if (top != null) {
1698 final TaskRecord task = top.task;
1699 task.moveActivityToFrontLocked(top);
1700 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001701 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001702 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1703 mTargetStack.mLastPausedActivity = null;
1704 if (mDoResume) {
1705 mSupervisor.resumeFocusedStackTopActivityLocked();
1706 }
1707 return START_DELIVERED_TO_TOP;
1708 }
1709 }
1710
1711 // An existing activity is starting this new activity, so we want to keep the new one in
1712 // the same task as the one that is starting it.
1713 mStartActivity.setTask(sourceTask, null);
1714 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1715 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1716 return START_SUCCESS;
1717 }
1718
1719 private int setTaskFromInTask() {
1720 if (mLaunchBounds != null) {
1721 mInTask.updateOverrideConfiguration(mLaunchBounds);
1722 int stackId = mInTask.getLaunchStackId();
1723 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001724 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001725 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001726 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001727 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001728 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001729 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001730 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001731 }
1732 mTargetStack = mInTask.stack;
1733 mTargetStack.moveTaskToFrontLocked(
1734 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1735
1736 // Check whether we should actually launch the new activity in to the task,
1737 // or just reuse the current activity on top.
1738 ActivityRecord top = mInTask.getTopActivity();
1739 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1740 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1741 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001742 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001743 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1744 // We don't need to start a new activity, and the client said not to do
1745 // anything if that is the case, so this is it!
1746 return START_RETURN_INTENT_TO_CALLER;
1747 }
1748 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1749 return START_DELIVERED_TO_TOP;
1750 }
1751 }
1752
1753 if (!mAddingToTask) {
1754 // We don't actually want to have this activity added to the task, so just
1755 // stop here but still tell the caller that we consumed the intent.
1756 ActivityOptions.abort(mOptions);
1757 return START_TASK_TO_FRONT;
1758 }
1759
1760 mStartActivity.setTask(mInTask, null);
1761 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1762 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1763
1764 return START_SUCCESS;
1765 }
1766
1767 private void setTaskToCurrentTopOrCreateNewTask() {
1768 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1769 mOptions);
1770 if (mDoResume) {
1771 mTargetStack.moveToFront("addingToTopTask");
1772 }
1773 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001774 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1775 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1776 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001777 mStartActivity.setTask(task, null);
1778 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1779 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1780 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1781 }
1782
1783 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1784 boolean launchSingleTask, int launchFlags) {
1785 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1786 (launchSingleInstance || launchSingleTask)) {
1787 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1788 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1789 "\"singleInstance\" or \"singleTask\"");
1790 launchFlags &=
1791 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1792 } else {
1793 switch (r.info.documentLaunchMode) {
1794 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1795 break;
1796 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1797 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1798 break;
1799 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1800 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1801 break;
1802 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1803 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1804 break;
1805 }
1806 }
1807 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001808 }
1809
1810 final void doPendingActivityLaunchesLocked(boolean doResume) {
1811 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001812 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1813 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001814 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001815 final int result = startActivityUnchecked(
1816 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1817 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001818 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1819 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001820 } catch (Exception e) {
1821 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1822 pal.sendErrorResult(e.getMessage());
1823 }
1824 }
1825 }
1826
1827 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001828 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001829 final TaskRecord task = r.task;
1830 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1831 return mSupervisor.mHomeStack;
1832 }
1833
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001834 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001835 if (stack != null) {
1836 return stack;
1837 }
1838
1839 if (task != null && task.stack != null) {
1840 stack = task.stack;
1841 if (stack.isOnHomeDisplay()) {
1842 if (mSupervisor.mFocusedStack != stack) {
1843 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1844 "computeStackFocus: Setting " + "focused stack to r=" + r
1845 + " task=" + task);
1846 } else {
1847 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1848 "computeStackFocus: Focused stack already="
1849 + mSupervisor.mFocusedStack);
1850 }
1851 }
1852 return stack;
1853 }
1854
1855 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1856 if (container != null) {
1857 // The first time put it on the desired stack, after this put on task stack.
1858 r.mInitialActivityContainer = null;
1859 return container.mStack;
1860 }
1861
1862 // The fullscreen stack can contain any task regardless of if the task is resizeable
1863 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1864 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1865 // we can also put it in the focused stack.
1866 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001867 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1868 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1869 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001870 if (canUseFocusedStack && (!newTask
1871 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1872 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1873 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1874 return mSupervisor.mFocusedStack;
1875 }
1876
1877 // We first try to put the task in the first dynamic stack.
1878 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1879 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1880 stack = homeDisplayStacks.get(stackNdx);
1881 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1882 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1883 "computeStackFocus: Setting focused stack=" + stack);
1884 return stack;
1885 }
1886 }
1887
1888 // If there is no suitable dynamic stack then we figure out which static stack to use.
1889 final int stackId = task != null ? task.getLaunchStackId() :
1890 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1891 FULLSCREEN_WORKSPACE_STACK_ID;
1892 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1893 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1894 + r + " stackId=" + stack.mStackId);
1895 return stack;
1896 }
1897
Wale Ogunwale854809c2015-12-27 16:18:19 -08001898 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001899 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001900
1901 // We are reusing a task, keep the stack!
1902 if (mReuseTask != null) {
1903 return mReuseTask.stack;
1904 }
1905
Wale Ogunwale854809c2015-12-27 16:18:19 -08001906 final int launchStackId =
1907 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1908
1909 if (isValidLaunchStackId(launchStackId, r)) {
1910 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001911 } else if (launchStackId == DOCKED_STACK_ID) {
1912 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1913 // for this activity, so we put the activity in the fullscreen stack.
1914 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001915 }
1916
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001917 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001918 return null;
1919 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001920 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001921
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001922 // The parent activity doesn't want to launch the activity on top of itself, but
1923 // instead tries to put it onto other side in side-by-side mode.
1924 final ActivityStack parentStack = task != null ? task.stack
1925 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1926 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001927
1928 if (parentStack != mSupervisor.mFocusedStack) {
1929 // If task's parent stack is not focused - use it during adjacent launch.
1930 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001931 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001932 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1933 // If task is already on top of focused stack - use it. We don't want to move the
1934 // existing focused task to adjacent stack, just deliver new intent in this case.
1935 return mSupervisor.mFocusedStack;
1936 }
1937
1938 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1939 // If parent was in docked stack, the natural place to launch another activity
1940 // will be fullscreen, so it can appear alongside the docked window.
1941 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1942 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001943 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001944 // If the parent is not in the docked stack, we check if there is docked window
1945 // and if yes, we will launch into that stack. If not, we just put the new
1946 // activity into parent's stack, because we can't find a better place.
1947 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1948 if (dockedStack != null
1949 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1950 // There is a docked stack, but it isn't visible, so we can't launch into that.
1951 return null;
1952 } else {
1953 return dockedStack;
1954 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001955 }
1956 }
1957 }
1958
Wale Ogunwale854809c2015-12-27 16:18:19 -08001959 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1960 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1961 || !StackId.isStaticStack(stackId)) {
1962 return false;
1963 }
1964
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001965 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
1966 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
1967 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001968 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001969
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001970 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1971 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08001972 }
1973
1974 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1975 return false;
1976 }
1977
1978 final boolean supportsPip = mService.mSupportsPictureInPicture
1979 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1980 if (stackId == PINNED_STACK_ID && !supportsPip) {
1981 return false;
1982 }
1983 return true;
1984 }
1985
Wale Ogunwale854809c2015-12-27 16:18:19 -08001986 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1987 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001988 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08001989 if (mSupervisor.canUseActivityOptionsLaunchBounds(
1990 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001991 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08001992 }
1993 }
1994 return newBounds;
1995 }
1996
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001997 void setWindowManager(WindowManagerService wm) {
1998 mWindowManager = wm;
1999 }
2000
2001 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2002 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2003 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2004 if (pal.stack == stack) {
2005 mPendingActivityLaunches.remove(palNdx);
2006 }
2007 }
2008 }
liulvpingb55e42d2016-09-26 20:00:15 +08002009
2010 boolean clearPendingActivityLaunchesLocked(String packageName) {
2011 boolean didSomething = false;
2012
2013 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2014 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2015 ActivityRecord r = pal.r;
2016 if (r != null && r.packageName.equals(packageName)) {
2017 mPendingActivityLaunches.remove(palNdx);
2018 didSomething = true;
2019 }
2020 }
2021 return didSomething;
2022 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002023}