blob: 52524469908256a81a1c37ee660e1b7f2d63e770 [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;
Wei Wang98f03f92016-05-18 11:32:52 -0700105import android.os.PowerManagerInternal;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.os.RemoteException;
107import android.os.SystemClock;
108import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000109import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import android.service.voice.IVoiceInteractionSession;
111import android.util.EventLog;
112import android.util.Slog;
113import android.view.Display;
114
115import com.android.internal.app.HeavyWeightSwitcherActivity;
116import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800117import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
118import com.android.server.wm.WindowManagerService;
119
120import java.util.ArrayList;
121
122/**
123 * Controller for interpreting how and then launching activities.
124 *
125 * This class collects all the logic for determining how an intent and flags should be turned into
126 * an activity and associated task and stack.
127 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800128class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800129 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
130 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
131 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
132 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
133 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
134
135 private final ActivityManagerService mService;
136 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000137 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800138 private WindowManagerService mWindowManager;
139
140 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
141
Wale Ogunwale01d66562015-12-29 08:19:19 -0800142 // Share state variable among methods when starting an activity.
143 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700144 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800145 private Intent mIntent;
146 private int mCallingUid;
147 private ActivityOptions mOptions;
148
149 private boolean mLaunchSingleTop;
150 private boolean mLaunchSingleInstance;
151 private boolean mLaunchSingleTask;
152 private boolean mLaunchTaskBehind;
153 private int mLaunchFlags;
154
155 private Rect mLaunchBounds;
156
157 private ActivityRecord mNotTop;
158 private boolean mDoResume;
159 private int mStartFlags;
160 private ActivityRecord mSourceRecord;
161
162 private TaskRecord mInTask;
163 private boolean mAddingToTask;
164 private TaskRecord mReuseTask;
165
166 private ActivityInfo mNewTaskInfo;
167 private Intent mNewTaskIntent;
168 private ActivityStack mSourceStack;
169 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700170 // Indicates that we moved other task and are going to put something on top soon, so
171 // we don't want to show it redundantly or accidentally change what's shown below.
172 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800173 private boolean mMovedToFront;
174 private boolean mNoAnimation;
175 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700176 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700177 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800178
179 private IVoiceInteractionSession mVoiceSession;
180 private IVoiceInteractor mVoiceInteractor;
181
182 private void reset() {
183 mStartActivity = null;
184 mIntent = null;
185 mCallingUid = -1;
186 mOptions = null;
187
188 mLaunchSingleTop = false;
189 mLaunchSingleInstance = false;
190 mLaunchSingleTask = false;
191 mLaunchTaskBehind = false;
192 mLaunchFlags = 0;
193
194 mLaunchBounds = null;
195
196 mNotTop = null;
197 mDoResume = false;
198 mStartFlags = 0;
199 mSourceRecord = null;
200
201 mInTask = null;
202 mAddingToTask = false;
203 mReuseTask = null;
204
205 mNewTaskInfo = null;
206 mNewTaskIntent = null;
207 mSourceStack = null;
208
209 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700210 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800211 mMovedToFront = false;
212 mNoAnimation = false;
213 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700214 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800215
216 mVoiceSession = null;
217 mVoiceInteractor = null;
218 }
219
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800220 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
221 mService = service;
222 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000223 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800224 }
225
226 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
227 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
228 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
229 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
230 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
231 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
232 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
233 TaskRecord inTask) {
234 int err = ActivityManager.START_SUCCESS;
235
236 ProcessRecord callerApp = null;
237 if (caller != null) {
238 callerApp = mService.getRecordForAppLocked(caller);
239 if (callerApp != null) {
240 callingPid = callerApp.pid;
241 callingUid = callerApp.info.uid;
242 } else {
243 Slog.w(TAG, "Unable to find app for caller " + caller
244 + " (pid=" + callingPid + ") when starting: "
245 + intent.toString());
246 err = ActivityManager.START_PERMISSION_DENIED;
247 }
248 }
249
250 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
251
252 if (err == ActivityManager.START_SUCCESS) {
253 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
254 + "} from uid " + callingUid
255 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
256 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
257 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
258 container.mActivityDisplay.mDisplayId)));
259 }
260
261 ActivityRecord sourceRecord = null;
262 ActivityRecord resultRecord = null;
263 if (resultTo != null) {
264 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
265 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
266 "Will send result to " + resultTo + " " + sourceRecord);
267 if (sourceRecord != null) {
268 if (requestCode >= 0 && !sourceRecord.finishing) {
269 resultRecord = sourceRecord;
270 }
271 }
272 }
273
274 final int launchFlags = intent.getFlags();
275
276 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
277 // Transfer the result target from the source activity to the new
278 // one being started, including any failures.
279 if (requestCode >= 0) {
280 ActivityOptions.abort(options);
281 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
282 }
283 resultRecord = sourceRecord.resultTo;
284 if (resultRecord != null && !resultRecord.isInStackLocked()) {
285 resultRecord = null;
286 }
287 resultWho = sourceRecord.resultWho;
288 requestCode = sourceRecord.requestCode;
289 sourceRecord.resultTo = null;
290 if (resultRecord != null) {
291 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
292 }
293 if (sourceRecord.launchedFromUid == callingUid) {
294 // The new activity is being launched from the same uid as the previous
295 // activity in the flow, and asking to forward its result back to the
296 // previous. In this case the activity is serving as a trampoline between
297 // the two, so we also want to update its launchedFromPackage to be the
298 // same as the previous activity. Note that this is safe, since we know
299 // these two packages come from the same uid; the caller could just as
300 // well have supplied that same package name itself. This specifially
301 // deals with the case of an intent picker/chooser being launched in the app
302 // flow to redirect to an activity picked by the user, where we want the final
303 // activity to consider it to have been launched by the previous app activity.
304 callingPackage = sourceRecord.launchedFromPackage;
305 }
306 }
307
308 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
309 // We couldn't find a class that can handle the given Intent.
310 // That's the end of that!
311 err = ActivityManager.START_INTENT_NOT_RESOLVED;
312 }
313
314 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
315 // We couldn't find the specific class specified in the Intent.
316 // Also the end of the line.
317 err = ActivityManager.START_CLASS_NOT_FOUND;
318 }
319
320 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
321 && sourceRecord.task.voiceSession != null) {
322 // If this activity is being launched as part of a voice session, we need
323 // to ensure that it is safe to do so. If the upcoming activity will also
324 // be part of the voice session, we can only launch it if it has explicitly
325 // said it supports the VOICE category, or it is a part of the calling app.
326 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
327 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
328 try {
329 intent.addCategory(Intent.CATEGORY_VOICE);
330 if (!AppGlobals.getPackageManager().activitySupportsIntent(
331 intent.getComponent(), intent, resolvedType)) {
332 Slog.w(TAG,
333 "Activity being started in current voice task does not support voice: "
334 + intent);
335 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
336 }
337 } catch (RemoteException e) {
338 Slog.w(TAG, "Failure checking voice capabilities", e);
339 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
340 }
341 }
342 }
343
344 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
345 // If the caller is starting a new voice session, just make sure the target
346 // is actually allowing it to run this way.
347 try {
348 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
349 intent, resolvedType)) {
350 Slog.w(TAG,
351 "Activity being started in new voice task does not support: "
352 + intent);
353 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
354 }
355 } catch (RemoteException e) {
356 Slog.w(TAG, "Failure checking voice capabilities", e);
357 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
358 }
359 }
360
361 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
362
Wale Ogunwale01d66562015-12-29 08:19:19 -0800363 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800364 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800365 resultStack.sendActivityResultLocked(
366 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800367 }
368 ActivityOptions.abort(options);
369 return err;
370 }
371
372 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
373 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100374 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800375 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
376 callingPid, resolvedType, aInfo.applicationInfo);
377
378 if (mService.mController != null) {
379 try {
380 // The Intent we give to the watcher has the extra data
381 // stripped off, since it can contain private information.
382 Intent watchIntent = intent.cloneFilter();
383 abort |= !mService.mController.activityStarting(watchIntent,
384 aInfo.applicationInfo.packageName);
385 } catch (RemoteException e) {
386 mService.mController = null;
387 }
388 }
389
Rubin Xu58d25992016-01-21 17:47:13 +0000390 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100391 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
392 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000393 intent = mInterceptor.mIntent;
394 rInfo = mInterceptor.mRInfo;
395 aInfo = mInterceptor.mAInfo;
396 resolvedType = mInterceptor.mResolvedType;
397 inTask = mInterceptor.mInTask;
398 callingPid = mInterceptor.mCallingPid;
399 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100400 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800401 if (abort) {
402 if (resultRecord != null) {
403 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800404 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800405 }
406 // We pretend to the caller that it was really started, but
407 // they will just get a cancel result.
408 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800409 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800410 }
411
412 // If permissions need a review before any of the app components can run, we
413 // launch the review activity and pass a pending intent to start the activity
414 // we are to launching now after the review is completed.
415 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
416 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
417 aInfo.packageName, userId)) {
418 IIntentSender target = mService.getIntentSenderLocked(
419 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
420 callingUid, userId, null, null, 0, new Intent[]{intent},
421 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
422 | PendingIntent.FLAG_ONE_SHOT, null);
423
424 final int flags = intent.getFlags();
425 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
426 newIntent.setFlags(flags
427 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
428 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
429 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
430 if (resultRecord != null) {
431 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
432 }
433 intent = newIntent;
434
435 resolvedType = null;
436 callingUid = realCallingUid;
437 callingPid = realCallingPid;
438
439 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
440 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
441 null /*profilerInfo*/);
442
443 if (DEBUG_PERMISSIONS_REVIEW) {
444 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
445 true, false) + "} from uid " + callingUid + " on display "
446 + (container == null ? (mSupervisor.mFocusedStack == null ?
447 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
448 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
449 container.mActivityDisplay.mDisplayId)));
450 }
451 }
452 }
453
454 // If we have an ephemeral app, abort the process of launching the resolved intent.
455 // Instead, launch the ephemeral installer. Once the installer is finished, it
456 // starts either the intent we resolved here [on install error] or the ephemeral
457 // app [on install success].
458 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
459 // Create a pending intent to start the intent resolved here.
460 final IIntentSender failureTarget = mService.getIntentSenderLocked(
461 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
462 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
463 new String[]{ resolvedType },
464 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
465 | PendingIntent.FLAG_IMMUTABLE, null);
466
467 // Create a pending intent to start the ephemeral application; force it to be
468 // directed to the ephemeral package.
469 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
470 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
471 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
472 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
473 new String[]{ resolvedType },
474 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
475 | PendingIntent.FLAG_IMMUTABLE, null);
476
477 int flags = intent.getFlags();
478 intent = new Intent();
479 intent.setFlags(flags
480 | Intent.FLAG_ACTIVITY_NEW_TASK
481 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
482 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
483 rInfo.ephemeralResolveInfo.getPackageName());
484 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
485 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
486
487 resolvedType = null;
488 callingUid = realCallingUid;
489 callingPid = realCallingPid;
490
491 rInfo = rInfo.ephemeralInstaller;
492 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
493 }
494
495 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
496 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
497 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
Wale Ogunwale1affbbc2016-05-01 09:03:52 -0700498 options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800499 if (outActivity != null) {
500 outActivity[0] = r;
501 }
502
503 if (r.appTimeTracker == null && sourceRecord != null) {
504 // If the caller didn't specify an explicit time tracker, we want to continue
505 // tracking under any it has.
506 r.appTimeTracker = sourceRecord.appTimeTracker;
507 }
508
509 final ActivityStack stack = mSupervisor.mFocusedStack;
510 if (voiceSession == null && (stack.mResumedActivity == null
511 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
512 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
513 realCallingPid, realCallingUid, "Activity start")) {
514 PendingActivityLaunch pal = new PendingActivityLaunch(r,
515 sourceRecord, startFlags, stack, callerApp);
516 mPendingActivityLaunches.add(pal);
517 ActivityOptions.abort(options);
518 return ActivityManager.START_SWITCHES_CANCELED;
519 }
520 }
521
522 if (mService.mDidAppSwitch) {
523 // This is the second allowed switch since we stopped switches,
524 // so now just generally allow switches. Use case: user presses
525 // home (switches disabled, switch to home, mDidAppSwitch now true);
526 // user taps a home icon (coming from home so allowed, we hit here
527 // and now allow anyone to switch again).
528 mService.mAppSwitchesAllowedTime = 0;
529 } else {
530 mService.mDidAppSwitch = true;
531 }
532
533 doPendingActivityLaunchesLocked(false);
534
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700535 try {
536 mService.mWindowManager.deferSurfaceLayout();
537 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
538 true, options, inTask);
539 } finally {
540 mService.mWindowManager.continueSurfaceLayout();
541 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700542 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800543 return err;
544 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800545
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800546 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700547 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
548 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800549
550 if (result < START_SUCCESS) {
551 // If someone asked to have the keyguard dismissed on the next activity start,
552 // but we are not actually doing an activity switch... just dismiss the keyguard now,
553 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800554 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800555 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800556 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800557
Chong Zhang5022da32016-06-21 16:31:37 -0700558 // We're waiting for an activity launch to finish, but that activity simply
559 // brought another activity to front. Let startActivityMayWait() know about
560 // this, so it waits for the new activity to become visible instead.
561 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
562 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
563 }
564
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800565 int startedActivityStackId = INVALID_STACK_ID;
566 if (r.task != null && r.task.stack != null) {
567 startedActivityStackId = r.task.stack.mStackId;
568 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700569 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800570 }
571
Jorim Jaggi352d5842016-05-19 10:20:28 -0700572 // If we launched the activity from a no display activity that was launched from the home
573 // screen, we also need to start recents to un-minimize the docked stack, since the
574 // noDisplay activity will be finished shortly after.
575 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
576 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700577 final boolean noDisplayActivityOverHome = sourceRecord != null
578 && sourceRecord.noDisplay
579 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700580 if (startedActivityStackId == DOCKED_STACK_ID
581 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100582 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
583 final ActivityRecord topActivityHomeStack = homeStack != null
584 ? homeStack.topRunningActivityLocked() : null;
585 if (topActivityHomeStack == null
586 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
587 // We launch an activity while being in home stack, which means either launcher or
588 // recents into docked stack. We don't want the launched activity to be alone in a
589 // docked stack, so we want to immediately launch recents too.
590 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700591 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100592 return;
593 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800594 }
595
596 if (startedActivityStackId == PINNED_STACK_ID
597 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
598 // The activity was already running in the pinned stack so it wasn't started, but either
599 // brought to the front or the new intent was delivered to it since it was already in
600 // front. Notify anyone interested in this piece of information.
601 mService.notifyPinnedActivityRestartAttemptLocked();
602 return;
603 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800604 }
605
606 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
607 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
608 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
609 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
610 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
611 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
612 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700613 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800614 null /*container*/, null /*inTask*/);
615 if (mSupervisor.inResumeTopActivity) {
616 // If we are in resume section already, home activity will be initialized, but not
617 // resumed (to avoid recursive resume) and will stay that way until something pokes it
618 // again. We need to schedule another resume.
619 mSupervisor.scheduleResumeTopActivities();
620 }
621 }
622
Tony Mak853304c2016-04-18 15:17:41 +0100623 void showConfirmDeviceCredential(int userId) {
624 // First, retrieve the stack that we want to resume after credential is confirmed.
625 ActivityStack targetStack;
626 ActivityStack fullscreenStack =
627 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
628 if (fullscreenStack != null &&
629 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
630 // Single window case and the case that the docked stack is shown with fullscreen stack.
631 targetStack = fullscreenStack;
632 } else {
633 // The case that the docked stack is shown with recent.
634 targetStack = mSupervisor.getStack(HOME_STACK_ID);
635 }
636 if (targetStack == null) {
637 return;
638 }
639 final KeyguardManager km = (KeyguardManager) mService.mContext
640 .getSystemService(Context.KEYGUARD_SERVICE);
641 final Intent credential =
642 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100643 // For safety, check null here in case users changed the setting after the checking.
644 if (credential == null) {
645 return;
646 }
Tony Mak853304c2016-04-18 15:17:41 +0100647 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
648 if (activityRecord != null) {
649 final IIntentSender target = mService.getIntentSenderLocked(
650 ActivityManager.INTENT_SENDER_ACTIVITY,
651 activityRecord.launchedFromPackage,
652 activityRecord.launchedFromUid,
653 activityRecord.userId,
654 null, null, 0,
655 new Intent[] { activityRecord.intent },
656 new String[] { activityRecord.resolvedType },
657 PendingIntent.FLAG_CANCEL_CURRENT |
658 PendingIntent.FLAG_ONE_SHOT |
659 PendingIntent.FLAG_IMMUTABLE,
660 null);
661 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
662 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100663 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100664 }
665 }
666
Tony Mak646fe992016-04-21 16:43:08 +0100667 void startConfirmCredentialIntent(Intent intent) {
668 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
669 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
670 FLAG_ACTIVITY_TASK_ON_HOME);
671 final ActivityOptions options = ActivityOptions.makeBasic();
672 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
673 mService.mContext.startActivityAsUser(intent, options.toBundle(),
674 UserHandle.CURRENT);
675 }
Tony Mak853304c2016-04-18 15:17:41 +0100676
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800677 final int startActivityMayWait(IApplicationThread caller, int callingUid,
678 String callingPackage, Intent intent, String resolvedType,
679 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
680 IBinder resultTo, String resultWho, int requestCode, int startFlags,
681 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
682 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
683 IActivityContainer iContainer, TaskRecord inTask) {
684 // Refuse possible leaked file descriptors
685 if (intent != null && intent.hasFileDescriptors()) {
686 throw new IllegalArgumentException("File descriptors passed in Intent");
687 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500688 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800689 boolean componentSpecified = intent.getComponent() != null;
690
691 // Save a copy in case ephemeral needs it
692 final Intent ephemeralIntent = new Intent(intent);
693 // Don't modify the client's object!
694 intent = new Intent(intent);
695
696 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000697 if (rInfo == null) {
698 UserInfo userInfo = mSupervisor.getUserInfo(userId);
699 if (userInfo != null && userInfo.isManagedProfile()) {
700 // Special case for managed profiles, if attempting to launch non-cryto aware
701 // app in a locked managed profile from an unlocked parent allow it to resolve
702 // as user will be sent via confirm credentials to unlock the profile.
703 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700704 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000705 long token = Binder.clearCallingIdentity();
706 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700707 UserInfo parent = userManager.getProfileParent(userId);
708 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
709 && userManager.isUserUnlockingOrUnlocked(parent.id)
710 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000711 } finally {
712 Binder.restoreCallingIdentity(token);
713 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700714 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000715 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600716 PackageManager.MATCH_DIRECT_BOOT_AWARE
717 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000718 }
719 }
720 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800721 // Collect information about the target of the Intent.
722 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
723
724 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
725 ActivityStackSupervisor.ActivityContainer container =
726 (ActivityStackSupervisor.ActivityContainer)iContainer;
727 synchronized (mService) {
728 if (container != null && container.mParentActivity != null &&
729 container.mParentActivity.state != RESUMED) {
730 // Cannot start a child activity if the parent is not resumed.
731 return ActivityManager.START_CANCELED;
732 }
733 final int realCallingPid = Binder.getCallingPid();
734 final int realCallingUid = Binder.getCallingUid();
735 int callingPid;
736 if (callingUid >= 0) {
737 callingPid = -1;
738 } else if (caller == null) {
739 callingPid = realCallingPid;
740 callingUid = realCallingUid;
741 } else {
742 callingPid = callingUid = -1;
743 }
744
745 final ActivityStack stack;
746 if (container == null || container.mStack.isOnHomeDisplay()) {
747 stack = mSupervisor.mFocusedStack;
748 } else {
749 stack = container.mStack;
750 }
751 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
752 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
753 "Starting activity when config will change = " + stack.mConfigWillChange);
754
755 final long origId = Binder.clearCallingIdentity();
756
757 if (aInfo != null &&
758 (aInfo.applicationInfo.privateFlags
759 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
760 // This may be a heavy-weight process! Check to see if we already
761 // have another, different heavy-weight process running.
762 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
763 final ProcessRecord heavy = mService.mHeavyWeightProcess;
764 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
765 || !heavy.processName.equals(aInfo.processName))) {
766 int appCallingUid = callingUid;
767 if (caller != null) {
768 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
769 if (callerApp != null) {
770 appCallingUid = callerApp.info.uid;
771 } else {
772 Slog.w(TAG, "Unable to find app for caller " + caller
773 + " (pid=" + callingPid + ") when starting: "
774 + intent.toString());
775 ActivityOptions.abort(options);
776 return ActivityManager.START_PERMISSION_DENIED;
777 }
778 }
779
780 IIntentSender target = mService.getIntentSenderLocked(
781 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
782 appCallingUid, userId, null, null, 0, new Intent[] { intent },
783 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
784 | PendingIntent.FLAG_ONE_SHOT, null);
785
786 Intent newIntent = new Intent();
787 if (requestCode >= 0) {
788 // Caller is requesting a result.
789 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
790 }
791 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
792 new IntentSender(target));
793 if (heavy.activities.size() > 0) {
794 ActivityRecord hist = heavy.activities.get(0);
795 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
796 hist.packageName);
797 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
798 hist.task.taskId);
799 }
800 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
801 aInfo.packageName);
802 newIntent.setFlags(intent.getFlags());
803 newIntent.setClassName("android",
804 HeavyWeightSwitcherActivity.class.getName());
805 intent = newIntent;
806 resolvedType = null;
807 caller = null;
808 callingUid = Binder.getCallingUid();
809 callingPid = Binder.getCallingPid();
810 componentSpecified = true;
811 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
812 aInfo = rInfo != null ? rInfo.activityInfo : null;
813 if (aInfo != null) {
814 aInfo = mService.getActivityInfoForUser(aInfo, userId);
815 }
816 }
817 }
818 }
819
Jorim Jaggi275561a2016-02-23 10:11:02 -0500820 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800821 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
822 aInfo, rInfo, voiceSession, voiceInteractor,
823 resultTo, resultWho, requestCode, callingPid,
824 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500825 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
826 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800827
828 Binder.restoreCallingIdentity(origId);
829
830 if (stack.mConfigWillChange) {
831 // If the caller also wants to switch to a new configuration,
832 // do so now. This allows a clean switch, as we are waiting
833 // for the current activity to pause (so we will not destroy
834 // it), and have not yet started the next activity.
835 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
836 "updateConfiguration()");
837 stack.mConfigWillChange = false;
838 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
839 "Updating to new configuration after starting activity.");
840 mService.updateConfigurationLocked(config, null, false);
841 }
842
843 if (outResult != null) {
844 outResult.result = res;
845 if (res == ActivityManager.START_SUCCESS) {
846 mSupervisor.mWaitingActivityLaunched.add(outResult);
847 do {
848 try {
849 mService.wait();
850 } catch (InterruptedException e) {
851 }
Chong Zhang5022da32016-06-21 16:31:37 -0700852 } while (outResult.result != START_TASK_TO_FRONT
853 && !outResult.timeout && outResult.who == null);
854 if (outResult.result == START_TASK_TO_FRONT) {
855 res = START_TASK_TO_FRONT;
856 }
857 }
858 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800859 ActivityRecord r = stack.topRunningActivityLocked();
860 if (r.nowVisible && r.state == RESUMED) {
861 outResult.timeout = false;
862 outResult.who = new ComponentName(r.info.packageName, r.info.name);
863 outResult.totalTime = 0;
864 outResult.thisTime = 0;
865 } else {
866 outResult.thisTime = SystemClock.uptimeMillis();
867 mSupervisor.mWaitingActivityVisible.add(outResult);
868 do {
869 try {
870 mService.wait();
871 } catch (InterruptedException e) {
872 }
873 } while (!outResult.timeout && outResult.who == null);
874 }
875 }
876 }
877
Jorim Jaggibe67c902016-04-12 00:53:16 -0700878 final ActivityRecord launchedActivity = mReusedActivity != null
879 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700880 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800881 return res;
882 }
883 }
884
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800885 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
886 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
887 Bundle bOptions, int userId) {
888 if (intents == null) {
889 throw new NullPointerException("intents is null");
890 }
891 if (resolvedTypes == null) {
892 throw new NullPointerException("resolvedTypes is null");
893 }
894 if (intents.length != resolvedTypes.length) {
895 throw new IllegalArgumentException("intents are length different than resolvedTypes");
896 }
897
Makoto Onukid67b1872016-07-21 16:26:36 -0700898 final int realCallingPid = Binder.getCallingPid();
899 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800900
901 int callingPid;
902 if (callingUid >= 0) {
903 callingPid = -1;
904 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700905 callingPid = realCallingPid;
906 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800907 } else {
908 callingPid = callingUid = -1;
909 }
910 final long origId = Binder.clearCallingIdentity();
911 try {
912 synchronized (mService) {
913 ActivityRecord[] outActivity = new ActivityRecord[1];
914 for (int i=0; i<intents.length; i++) {
915 Intent intent = intents[i];
916 if (intent == null) {
917 continue;
918 }
919
920 // Refuse possible leaked file descriptors
921 if (intent != null && intent.hasFileDescriptors()) {
922 throw new IllegalArgumentException("File descriptors passed in Intent");
923 }
924
925 boolean componentSpecified = intent.getComponent() != null;
926
927 // Don't modify the client's object!
928 intent = new Intent(intent);
929
930 // Collect information about the target of the Intent.
931 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
932 null, userId);
933 // TODO: New, check if this is correct
934 aInfo = mService.getActivityInfoForUser(aInfo, userId);
935
936 if (aInfo != null &&
937 (aInfo.applicationInfo.privateFlags
938 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
939 throw new IllegalArgumentException(
940 "FLAG_CANT_SAVE_STATE not supported here");
941 }
942
943 ActivityOptions options = ActivityOptions.fromBundle(
944 i == intents.length - 1 ? bOptions : null);
945 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
946 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700947 callingPid, callingUid, callingPackage,
948 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800949 options, false, componentSpecified, outActivity, null, null);
950 if (res < 0) {
951 return res;
952 }
953
954 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
955 }
956 }
957 } finally {
958 Binder.restoreCallingIdentity(origId);
959 }
960
Wale Ogunwale01d66562015-12-29 08:19:19 -0800961 return START_SUCCESS;
962 }
963
Wei Wang65c7a152016-06-02 18:51:22 -0700964 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
965 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -0700966 final ActivityStack focusStack = mSupervisor.getFocusedStack();
967 final ActivityRecord curTop = (focusStack == null)
968 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
969 if ((forceSend || (!mPowerHintSent && curTop != null &&
970 curTop.task != null && mStartActivity != null &&
971 curTop.task != mStartActivity.task )) &&
972 mService.mLocalPowerManager != null) {
Wei Wang65c7a152016-06-02 18:51:22 -0700973 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -0700974 mPowerHintSent = true;
975 }
976 }
977
Wei Wang65c7a152016-06-02 18:51:22 -0700978 void sendPowerHintForLaunchEndIfNeeded() {
979 // Trigger launch power hint if activity is launched
980 if (mPowerHintSent && mService.mLocalPowerManager != null) {
981 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
982 mPowerHintSent = false;
983 }
984 }
985
Wale Ogunwale01d66562015-12-29 08:19:19 -0800986 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
987 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
988 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
989
990 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
991 voiceInteractor);
992
993 computeLaunchingTaskFlags();
994
995 computeSourceStack();
996
997 mIntent.setFlags(mLaunchFlags);
998
Jorim Jaggibe67c902016-04-12 00:53:16 -0700999 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001000
Jorim Jaggi2adba072016-03-03 13:43:39 +01001001 final int preferredLaunchStackId =
1002 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1003
Jorim Jaggibe67c902016-04-12 00:53:16 -07001004 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001005 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1006 // still needs to be a lock task mode violation since the task gets cleared out and
1007 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001008 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001009 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1010 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1011 mSupervisor.showLockTaskToast();
1012 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1013 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1014 }
1015
1016 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001017 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001018 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001019 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001020 // This task was started because of movement of the activity based on affinity...
1021 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001022 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001023 }
1024
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001025 // This code path leads to delivering a new intent, we want to make sure we schedule it
1026 // as the first operation, in case the activity will be resumed as a result of later
1027 // operations.
1028 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1029 || mLaunchSingleInstance || mLaunchSingleTask) {
1030 // In this situation we want to remove all activities from the task up to the one
1031 // being started. In most cases this means we are resetting the task to its initial
1032 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001033 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001034 mStartActivity, mLaunchFlags);
1035 if (top != null) {
1036 if (top.frontOfTask) {
1037 // Activity aliases may mean we use different intents for the top activity,
1038 // so make sure the task now has the identity of the new intent.
1039 top.task.setIntent(mStartActivity);
1040 }
1041 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1042 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1043 mStartActivity.launchedFromPackage);
1044 }
1045 }
1046
Wei Wang65c7a152016-06-02 18:51:22 -07001047 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001048
Jorim Jaggibe67c902016-04-12 00:53:16 -07001049 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001050
1051 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1052 // We don't need to start a new activity, and the client said not to do anything
1053 // if that is the case, so this is it! And for paranoia, make sure we have
1054 // correctly resumed the top activity.
1055 resumeTargetStackIfNeeded();
1056 return START_RETURN_INTENT_TO_CALLER;
1057 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001058 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001059
1060 if (!mAddingToTask && mReuseTask == null) {
1061 // We didn't do anything... but it was needed (a.k.a., client don't use that
1062 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1063 resumeTargetStackIfNeeded();
1064 return START_TASK_TO_FRONT;
1065 }
1066 }
1067
1068 if (mStartActivity.packageName == null) {
1069 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1070 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1071 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1072 mStartActivity.requestCode, RESULT_CANCELED, null);
1073 }
1074 ActivityOptions.abort(mOptions);
1075 return START_CLASS_NOT_FOUND;
1076 }
1077
1078 // If the activity being launched is the same as the one currently at the top, then
1079 // we need to check if it should only be launched once.
1080 final ActivityStack topStack = mSupervisor.mFocusedStack;
1081 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1082 final boolean dontStart = top != null && mStartActivity.resultTo == null
1083 && top.realActivity.equals(mStartActivity.realActivity)
1084 && top.userId == mStartActivity.userId
1085 && top.app != null && top.app.thread != null
1086 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1087 || mLaunchSingleTop || mLaunchSingleTask);
1088 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001089 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001090 // For paranoia, make sure we have correctly resumed the top activity.
1091 topStack.mLastPausedActivity = null;
1092 if (mDoResume) {
1093 mSupervisor.resumeFocusedStackTopActivityLocked();
1094 }
1095 ActivityOptions.abort(mOptions);
1096 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1097 // We don't need to start a new activity, and the client said not to do
1098 // anything if that is the case, so this is it!
1099 return START_RETURN_INTENT_TO_CALLER;
1100 }
1101 top.deliverNewIntentLocked(
1102 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001103
1104 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1105 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1106 mSupervisor.handleNonResizableTaskIfNeeded(
1107 top.task, preferredLaunchStackId, topStack.mStackId);
1108
Wale Ogunwale01d66562015-12-29 08:19:19 -08001109 return START_DELIVERED_TO_TOP;
1110 }
1111
1112 boolean newTask = false;
1113 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1114 ? mSourceRecord.task : null;
1115
1116 // Should this be considered a new task?
1117 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1118 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1119 newTask = true;
1120 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1121
1122 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1123 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1124 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1125 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001126 if (!mMovedOtherTask) {
Andrii Kuliandc0f8932016-06-28 16:34:02 -07001127 // If stack id is specified in activity options, usually it means that activity is
1128 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1129 // that case we check the target stack.
1130 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1131 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001132 }
1133 } else if (mSourceRecord != null) {
1134 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1135 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1136 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1137 }
1138
1139 final int result = setTaskFromSourceRecord();
1140 if (result != START_SUCCESS) {
1141 return result;
1142 }
1143 } else if (mInTask != null) {
1144 // The caller is asking that the new activity be started in an explicit
1145 // task it has provided to us.
1146 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1147 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1148 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1149 }
1150
1151 final int result = setTaskFromInTask();
1152 if (result != START_SUCCESS) {
1153 return result;
1154 }
1155 } else {
1156 // This not being started from an existing activity, and not part of a new task...
1157 // just put it in the top task, though these days this case should never happen.
1158 setTaskToCurrentTopOrCreateNewTask();
1159 }
1160
1161 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1162 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1163
1164 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1165 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1166 }
1167 if (newTask) {
1168 EventLog.writeEvent(
1169 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1170 }
1171 ActivityStack.logStartActivity(
1172 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1173 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001174
Wei Wang65c7a152016-06-02 18:51:22 -07001175 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001176
Wale Ogunwale01d66562015-12-29 08:19:19 -08001177 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1178 if (mDoResume) {
1179 if (!mLaunchTaskBehind) {
1180 // TODO(b/26381750): Remove this code after verification that all the decision
1181 // points above moved targetStack to the front which will also set the focus
1182 // activity.
1183 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1184 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001185 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1186 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001187 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1188 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001189 // If the activity is not focusable, we can't resume it, but still would like to
1190 // make sure it becomes visible as it starts (this will also trigger entry
1191 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001192 // Also, we don't want to resume activities in a task that currently has an overlay
1193 // as the starting activity just needs to be in the visible paused state until the
1194 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001195 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001196 // Go ahead and tell window manager to execute app transition for this activity
1197 // since the app transition will not be triggered through the resume channel.
1198 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001199 } else {
1200 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1201 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001202 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001203 } else {
1204 mTargetStack.addRecentActivityLocked(mStartActivity);
1205 }
1206 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1207
Jorim Jaggid53f0922016-04-06 22:16:23 -07001208 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001209 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001210
1211 return START_SUCCESS;
1212 }
1213
1214 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1215 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1216 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1217 reset();
1218
1219 mStartActivity = r;
1220 mIntent = r.intent;
1221 mOptions = options;
1222 mCallingUid = r.launchedFromUid;
1223 mSourceRecord = sourceRecord;
1224 mVoiceSession = voiceSession;
1225 mVoiceInteractor = voiceInteractor;
1226
1227 mLaunchBounds = getOverrideBounds(r, options, inTask);
1228
1229 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1230 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1231 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1232 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1233 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1234 mLaunchTaskBehind = r.mLaunchTaskBehind
1235 && !mLaunchSingleTask && !mLaunchSingleInstance
1236 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1237
1238 sendNewTaskResultRequestIfNeeded();
1239
1240 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1241 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1242 }
1243
1244 // If we are actually going to launch in to a new task, there are some cases where
1245 // we further want to do multiple task.
1246 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1247 if (mLaunchTaskBehind
1248 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1249 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1250 }
1251 }
1252
1253 // We'll invoke onUserLeaving before onPause only if the launching
1254 // activity did not explicitly state that this is an automated launch.
1255 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1256 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1257 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1258
1259 // If the caller has asked not to resume at this point, we make note
1260 // of this in the record so that we can skip it when trying to find
1261 // the top running activity.
1262 mDoResume = doResume;
1263 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1264 r.delayedResume = true;
1265 mDoResume = false;
1266 }
1267
Wale Ogunwale3b232392016-05-13 15:37:13 -07001268 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1269 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001270 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1271 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1272 if (top != null && !top.visible) {
1273
1274 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1275 // it!
1276 mDoResume = false;
1277 mAvoidMoveToFront = true;
1278 }
1279 }
1280
Wale Ogunwale01d66562015-12-29 08:19:19 -08001281 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1282
1283 mInTask = inTask;
1284 // In some flows in to this function, we retrieve the task record and hold on to it
1285 // without a lock before calling back in to here... so the task at this point may
1286 // not actually be in recents. Check for that, and if it isn't in recents just
1287 // consider it invalid.
1288 if (inTask != null && !inTask.inRecents) {
1289 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1290 mInTask = null;
1291 }
1292
1293 mStartFlags = startFlags;
1294 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1295 // is the same as the one making the call... or, as a special case, if we do not know
1296 // the caller then we count the current top activity as the caller.
1297 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1298 ActivityRecord checkedCaller = sourceRecord;
1299 if (checkedCaller == null) {
1300 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1301 mNotTop);
1302 }
1303 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1304 // Caller is not the same as launcher, so always needed.
1305 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1306 }
1307 }
1308
1309 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1310 }
1311
1312 private void sendNewTaskResultRequestIfNeeded() {
1313 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1314 && mStartActivity.resultTo.task.stack != null) {
1315 // For whatever reason this activity is being launched into a new task...
1316 // yet the caller has requested a result back. Well, that is pretty messed up,
1317 // so instead immediately send back a cancel and let the new task continue launched
1318 // as normal without a dependency on its originator.
1319 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1320 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1321 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1322 mStartActivity.resultTo = null;
1323 }
1324 }
1325
1326 private void computeLaunchingTaskFlags() {
1327 // If the caller is not coming from another activity, but has given us an explicit task into
1328 // which they would like us to launch the new activity, then let's see about doing that.
1329 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1330 final Intent baseIntent = mInTask.getBaseIntent();
1331 final ActivityRecord root = mInTask.getRootActivity();
1332 if (baseIntent == null) {
1333 ActivityOptions.abort(mOptions);
1334 throw new IllegalArgumentException("Launching into task without base intent: "
1335 + mInTask);
1336 }
1337
1338 // If this task is empty, then we are adding the first activity -- it
1339 // determines the root, and must be launching as a NEW_TASK.
1340 if (mLaunchSingleInstance || mLaunchSingleTask) {
1341 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1342 ActivityOptions.abort(mOptions);
1343 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1344 + mStartActivity + " into different task " + mInTask);
1345 }
1346 if (root != null) {
1347 ActivityOptions.abort(mOptions);
1348 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1349 + " has root " + root + " but target is singleInstance/Task");
1350 }
1351 }
1352
1353 // If task is empty, then adopt the interesting intent launch flags in to the
1354 // activity being started.
1355 if (root == null) {
1356 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1357 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1358 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1359 | (baseIntent.getFlags() & flagsOfInterest);
1360 mIntent.setFlags(mLaunchFlags);
1361 mInTask.setIntent(mStartActivity);
1362 mAddingToTask = true;
1363
1364 // If the task is not empty and the caller is asking to start it as the root of
1365 // a new task, then we don't actually want to start this on the task. We will
1366 // bring the task to the front, and possibly give it a new intent.
1367 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1368 mAddingToTask = false;
1369
1370 } else {
1371 mAddingToTask = true;
1372 }
1373
1374 mReuseTask = mInTask;
1375 } else {
1376 mInTask = null;
1377 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1378 // when in freeform workspace.
1379 // Also put noDisplay activities in the source task. These by itself can be placed
1380 // in any task/stack, however it could launch other activities like ResolverActivity,
1381 // and we want those to stay in the original task.
1382 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1383 && mSourceRecord.isFreeform()) {
1384 mAddingToTask = true;
1385 }
1386 }
1387
1388 if (mInTask == null) {
1389 if (mSourceRecord == null) {
1390 // This activity is not being started from another... in this
1391 // case we -always- start a new task.
1392 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1393 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1394 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1395 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1396 }
1397 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1398 // The original activity who is starting us is running as a single
1399 // instance... this new activity it is starting must go on its
1400 // own task.
1401 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1402 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1403 // The activity being started is a single instance... it always
1404 // gets launched into its own task.
1405 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1406 }
1407 }
1408 }
1409
1410 private void computeSourceStack() {
1411 if (mSourceRecord == null) {
1412 mSourceStack = null;
1413 return;
1414 }
1415 if (!mSourceRecord.finishing) {
1416 mSourceStack = mSourceRecord.task.stack;
1417 return;
1418 }
1419
1420 // If the source is finishing, we can't further count it as our source. This is because the
1421 // task it is associated with may now be empty and on its way out, so we don't want to
1422 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1423 // a task for it. But save the task information so it can be used when creating the new task.
1424 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1425 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1426 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1427 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1428 mNewTaskInfo = mSourceRecord.info;
1429 mNewTaskIntent = mSourceRecord.task.intent;
1430 }
1431 mSourceRecord = null;
1432 mSourceStack = null;
1433 }
1434
1435 /**
1436 * Decide whether the new activity should be inserted into an existing task. Returns null
1437 * if not or an ActivityRecord with the task into which the new activity should be added.
1438 */
1439 private ActivityRecord getReusableIntentActivity() {
1440 // We may want to try to place the new activity in to an existing task. We always
1441 // do this if the target activity is singleTask or singleInstance; we will also do
1442 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1443 // us to still place it in a new task: multi task, always doc mode, or being asked to
1444 // launch this as a new task behind the current one.
1445 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1446 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1447 || mLaunchSingleInstance || mLaunchSingleTask;
1448 // If bring to front is requested, and no result is requested and we have not been given
1449 // an explicit task to launch in to, and we can find a task that was started with this
1450 // same component, then instead of launching bring that one to the front.
1451 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1452 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001453 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1454 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1455 intentActivity = task != null ? task.getTopActivity() : null;
1456 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001457 if (mLaunchSingleInstance) {
1458 // There can be one and only one instance of single instance activity in the
1459 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001460 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001461 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1462 // For the launch adjacent case we only want to put the activity in an existing
1463 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001464 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1465 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001466 } else {
1467 // Otherwise find the best task to put the activity in.
1468 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1469 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001470 }
1471 return intentActivity;
1472 }
1473
1474 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1475 mTargetStack = intentActivity.task.stack;
1476 mTargetStack.mLastPausedActivity = null;
1477 // If the target task is not in the front, then we need to bring it to the front...
1478 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1479 // the same behavior as if a new instance was being started, which means not bringing it
1480 // to the front if the caller is not itself in the front.
1481 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1482 ActivityRecord curTop = (focusStack == null)
1483 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1484
Jorim Jaggic875ae72016-04-26 22:41:06 -07001485 if (curTop != null
1486 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1487 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001488 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1489 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1490 mSourceStack.topActivity().task == mSourceRecord.task)) {
1491 // We really do want to push this one into the user's face, right now.
1492 if (mLaunchTaskBehind && mSourceRecord != null) {
1493 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1494 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001495 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001496
1497 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1498 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1499 // So no point resuming any of the activities here, it just wastes one extra
1500 // resuming, plus enter AND exit transitions.
1501 // Here we only want to bring the target stack forward. Transition will be applied
1502 // to the new activity that's started after the old ones are gone.
1503 final boolean willClearTask =
1504 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1505 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1506 if (!willClearTask) {
1507 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001508 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001509 if (launchStack == null || launchStack == mTargetStack) {
1510 // We only want to move to the front, if we aren't going to launch on a
1511 // different stack. If we launch on a different stack, we will put the
1512 // task on top there.
1513 mTargetStack.moveTaskToFrontLocked(
1514 intentActivity.task, mNoAnimation, mOptions,
1515 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1516 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001517 } else if (launchStack.mStackId == DOCKED_STACK_ID
1518 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1519 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1520 // If we want to launch adjacent and mTargetStack is not the computed
1521 // launch stack - move task to top of computed stack.
1522 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1523 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1524 ANIMATE);
1525 } else {
1526 // TODO: This should be reevaluated in MW v2.
1527 // We choose to move task to front instead of launching it adjacent
1528 // when specific stack was requested explicitly and it appeared to be
1529 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1530 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1531 mOptions, mStartActivity.appTimeTracker,
1532 "bringToFrontInsteadOfAdjacentLaunch");
1533 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001534 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001535 }
1536 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001537 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001538 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001539 }
1540 }
1541 if (!mMovedToFront && mDoResume) {
1542 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1543 + " from " + intentActivity);
1544 mTargetStack.moveToFront("intentActivityFound");
1545 }
1546
Jorim Jaggid53f0922016-04-06 22:16:23 -07001547 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1548 mTargetStack.mStackId);
1549
Wale Ogunwale01d66562015-12-29 08:19:19 -08001550 // If the caller has requested that the target task be reset, then do so.
1551 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1552 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1553 }
1554 return intentActivity;
1555 }
1556
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001557 private void updateTaskReturnToType(
1558 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1559 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1560 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1561 // Caller wants to appear on home activity.
1562 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1563 return;
1564 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1565 // Task will be launched over the home stack, so return home.
1566 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1567 return;
1568 }
1569
1570 // Else we are coming from an application stack so return to an application.
1571 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1572 }
1573
Wale Ogunwale01d66562015-12-29 08:19:19 -08001574 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1575 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1576 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1577 // The caller has requested to completely replace any existing task with its new
1578 // activity. Well that should not be too hard...
1579 mReuseTask = intentActivity.task;
1580 mReuseTask.performClearTaskLocked();
1581 mReuseTask.setIntent(mStartActivity);
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001582 // When we clear the task - focus will be adjusted, which will bring another task
1583 // to top before we launch the activity we need. This will temporary swap their
1584 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1585 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001586 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1587 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001588 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1589 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001590 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001591 // A special case: we need to start the activity because it is not currently
1592 // running, and the caller has asked to clear the current task to have this
1593 // activity at the top.
1594 mAddingToTask = true;
1595 // Now pretend like this activity is being started by the top of its task, so it
1596 // is put in the right place.
1597 mSourceRecord = intentActivity;
1598 final TaskRecord task = mSourceRecord.task;
1599 if (task != null && task.stack == null) {
1600 // Target stack got cleared when we all activities were removed above.
1601 // Go ahead and reset it.
1602 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1603 null /* bounds */, mLaunchFlags, mOptions);
1604 mTargetStack.addTask(task,
1605 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1606 }
1607 }
1608 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1609 // In this case the top activity on the task is the same as the one being launched,
1610 // so we take that as a request to bring the task to the foreground. If the top
1611 // activity in the task is the root activity, deliver this new intent to it if it
1612 // desires.
1613 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1614 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001615 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001616 intentActivity.task);
1617 if (intentActivity.frontOfTask) {
1618 intentActivity.task.setIntent(mStartActivity);
1619 }
1620 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1621 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001622 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001623 // In this case we are launching the root activity of the task, but with a
1624 // different intent. We should start a new instance on top.
1625 mAddingToTask = true;
1626 mSourceRecord = intentActivity;
1627 }
1628 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1629 // In this case an activity is being launched in to an existing task, without
1630 // resetting that task. This is typically the situation of launching an activity
1631 // from a notification or shortcut. We want to place the new activity on top of the
1632 // current task.
1633 mAddingToTask = true;
1634 mSourceRecord = intentActivity;
1635 } else if (!intentActivity.task.rootWasReset) {
1636 // In this case we are launching into an existing task that has not yet been started
1637 // from its front door. The current task has been brought to the front. Ideally,
1638 // we'd probably like to place this new task at the bottom of its stack, but that's
1639 // a little hard to do with the current organization of the code so for now we'll
1640 // just drop it.
1641 intentActivity.task.setIntent(mStartActivity);
1642 }
1643 }
1644
1645 private void resumeTargetStackIfNeeded() {
1646 if (mDoResume) {
1647 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1648 if (!mMovedToFront) {
1649 // Make sure to notify Keyguard as well if we are not running an app transition
1650 // later.
1651 mSupervisor.notifyActivityDrawnForKeyguard();
1652 }
1653 } else {
1654 ActivityOptions.abort(mOptions);
1655 }
1656 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1657 }
1658
1659 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1660 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1661 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001662
1663 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001664 final TaskRecord task = mTargetStack.createTaskRecord(
1665 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001666 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1667 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1668 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1669 mStartActivity.setTask(task, taskToAffiliate);
1670 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001671 final int stackId = mTargetStack.mStackId;
1672 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001673 mService.resizeStack(
1674 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001675 } else {
1676 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1677 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001678 }
1679 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1680 "Starting new activity " +
1681 mStartActivity + " in new task " + mStartActivity.task);
1682 } else {
1683 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1684 }
1685 }
1686
1687 private int setTaskFromSourceRecord() {
1688 final TaskRecord sourceTask = mSourceRecord.task;
1689 // We only want to allow changing stack if the target task is not the top one,
1690 // otherwise we would move the launching task to the other side, rather than show
1691 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001692 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1693 if (moveStackAllowed) {
1694 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1695 mOptions);
1696 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001697
1698 if (mTargetStack == null) {
1699 mTargetStack = sourceTask.stack;
1700 } else if (mTargetStack != sourceTask.stack) {
1701 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1702 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1703 }
1704 if (mDoResume) {
1705 mTargetStack.moveToFront("sourceStackToFront");
1706 }
1707 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001708 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001709 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1710 mStartActivity.appTimeTracker, "sourceTaskToFront");
1711 }
1712 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1713 // In this case, we are adding the activity to an existing task, but the caller has
1714 // asked to clear that task if the activity is already running.
1715 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1716 mKeepCurTransition = true;
1717 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001718 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001719 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1720 // For paranoia, make sure we have correctly resumed the top activity.
1721 mTargetStack.mLastPausedActivity = null;
1722 if (mDoResume) {
1723 mSupervisor.resumeFocusedStackTopActivityLocked();
1724 }
1725 ActivityOptions.abort(mOptions);
1726 return START_DELIVERED_TO_TOP;
1727 }
1728 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1729 // In this case, we are launching an activity in our own task that may already be
1730 // running somewhere in the history, and we want to shuffle it to the front of the
1731 // stack if so.
1732 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1733 if (top != null) {
1734 final TaskRecord task = top.task;
1735 task.moveActivityToFrontLocked(top);
1736 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001737 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001738 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1739 mTargetStack.mLastPausedActivity = null;
1740 if (mDoResume) {
1741 mSupervisor.resumeFocusedStackTopActivityLocked();
1742 }
1743 return START_DELIVERED_TO_TOP;
1744 }
1745 }
1746
1747 // An existing activity is starting this new activity, so we want to keep the new one in
1748 // the same task as the one that is starting it.
1749 mStartActivity.setTask(sourceTask, null);
1750 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1751 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1752 return START_SUCCESS;
1753 }
1754
1755 private int setTaskFromInTask() {
1756 if (mLaunchBounds != null) {
1757 mInTask.updateOverrideConfiguration(mLaunchBounds);
1758 int stackId = mInTask.getLaunchStackId();
1759 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001760 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001761 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001762 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001763 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001764 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001765 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001766 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001767 }
1768 mTargetStack = mInTask.stack;
1769 mTargetStack.moveTaskToFrontLocked(
1770 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1771
1772 // Check whether we should actually launch the new activity in to the task,
1773 // or just reuse the current activity on top.
1774 ActivityRecord top = mInTask.getTopActivity();
1775 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1776 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1777 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001778 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001779 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1780 // We don't need to start a new activity, and the client said not to do
1781 // anything if that is the case, so this is it!
1782 return START_RETURN_INTENT_TO_CALLER;
1783 }
1784 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1785 return START_DELIVERED_TO_TOP;
1786 }
1787 }
1788
1789 if (!mAddingToTask) {
1790 // We don't actually want to have this activity added to the task, so just
1791 // stop here but still tell the caller that we consumed the intent.
1792 ActivityOptions.abort(mOptions);
1793 return START_TASK_TO_FRONT;
1794 }
1795
1796 mStartActivity.setTask(mInTask, null);
1797 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1798 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1799
1800 return START_SUCCESS;
1801 }
1802
1803 private void setTaskToCurrentTopOrCreateNewTask() {
1804 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1805 mOptions);
1806 if (mDoResume) {
1807 mTargetStack.moveToFront("addingToTopTask");
1808 }
1809 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001810 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1811 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1812 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001813 mStartActivity.setTask(task, null);
1814 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1815 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1816 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1817 }
1818
1819 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1820 boolean launchSingleTask, int launchFlags) {
1821 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1822 (launchSingleInstance || launchSingleTask)) {
1823 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1824 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1825 "\"singleInstance\" or \"singleTask\"");
1826 launchFlags &=
1827 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1828 } else {
1829 switch (r.info.documentLaunchMode) {
1830 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1831 break;
1832 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1833 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1834 break;
1835 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1836 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1837 break;
1838 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1839 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1840 break;
1841 }
1842 }
1843 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001844 }
1845
1846 final void doPendingActivityLaunchesLocked(boolean doResume) {
1847 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001848 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1849 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001850 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001851 final int result = startActivityUnchecked(
1852 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1853 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001854 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1855 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001856 } catch (Exception e) {
1857 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1858 pal.sendErrorResult(e.getMessage());
1859 }
1860 }
1861 }
1862
1863 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001864 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001865 final TaskRecord task = r.task;
1866 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1867 return mSupervisor.mHomeStack;
1868 }
1869
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001870 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001871 if (stack != null) {
1872 return stack;
1873 }
1874
1875 if (task != null && task.stack != null) {
1876 stack = task.stack;
1877 if (stack.isOnHomeDisplay()) {
1878 if (mSupervisor.mFocusedStack != stack) {
1879 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1880 "computeStackFocus: Setting " + "focused stack to r=" + r
1881 + " task=" + task);
1882 } else {
1883 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1884 "computeStackFocus: Focused stack already="
1885 + mSupervisor.mFocusedStack);
1886 }
1887 }
1888 return stack;
1889 }
1890
1891 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1892 if (container != null) {
1893 // The first time put it on the desired stack, after this put on task stack.
1894 r.mInitialActivityContainer = null;
1895 return container.mStack;
1896 }
1897
1898 // The fullscreen stack can contain any task regardless of if the task is resizeable
1899 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1900 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1901 // we can also put it in the focused stack.
1902 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001903 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1904 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1905 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001906 if (canUseFocusedStack && (!newTask
1907 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1908 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1909 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1910 return mSupervisor.mFocusedStack;
1911 }
1912
1913 // We first try to put the task in the first dynamic stack.
1914 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1915 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1916 stack = homeDisplayStacks.get(stackNdx);
1917 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1918 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1919 "computeStackFocus: Setting focused stack=" + stack);
1920 return stack;
1921 }
1922 }
1923
1924 // If there is no suitable dynamic stack then we figure out which static stack to use.
1925 final int stackId = task != null ? task.getLaunchStackId() :
1926 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1927 FULLSCREEN_WORKSPACE_STACK_ID;
1928 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1929 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1930 + r + " stackId=" + stack.mStackId);
1931 return stack;
1932 }
1933
Wale Ogunwale854809c2015-12-27 16:18:19 -08001934 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001935 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001936
1937 // We are reusing a task, keep the stack!
1938 if (mReuseTask != null) {
1939 return mReuseTask.stack;
1940 }
1941
Wale Ogunwale854809c2015-12-27 16:18:19 -08001942 final int launchStackId =
1943 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1944
1945 if (isValidLaunchStackId(launchStackId, r)) {
1946 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001947 } else if (launchStackId == DOCKED_STACK_ID) {
1948 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1949 // for this activity, so we put the activity in the fullscreen stack.
1950 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001951 }
1952
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001953 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001954 return null;
1955 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001956 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001957
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001958 // The parent activity doesn't want to launch the activity on top of itself, but
1959 // instead tries to put it onto other side in side-by-side mode.
1960 final ActivityStack parentStack = task != null ? task.stack
1961 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1962 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001963
1964 if (parentStack != mSupervisor.mFocusedStack) {
1965 // If task's parent stack is not focused - use it during adjacent launch.
1966 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001967 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001968 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
1969 // If task is already on top of focused stack - use it. We don't want to move the
1970 // existing focused task to adjacent stack, just deliver new intent in this case.
1971 return mSupervisor.mFocusedStack;
1972 }
1973
1974 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1975 // If parent was in docked stack, the natural place to launch another activity
1976 // will be fullscreen, so it can appear alongside the docked window.
1977 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
1978 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001979 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001980 // If the parent is not in the docked stack, we check if there is docked window
1981 // and if yes, we will launch into that stack. If not, we just put the new
1982 // activity into parent's stack, because we can't find a better place.
1983 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
1984 if (dockedStack != null
1985 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
1986 // There is a docked stack, but it isn't visible, so we can't launch into that.
1987 return null;
1988 } else {
1989 return dockedStack;
1990 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001991 }
1992 }
1993 }
1994
Wale Ogunwale854809c2015-12-27 16:18:19 -08001995 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1996 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1997 || !StackId.isStaticStack(stackId)) {
1998 return false;
1999 }
2000
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002001 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2002 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2003 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002004 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002005
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002006 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2007 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002008 }
2009
2010 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2011 return false;
2012 }
2013
2014 final boolean supportsPip = mService.mSupportsPictureInPicture
2015 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2016 if (stackId == PINNED_STACK_ID && !supportsPip) {
2017 return false;
2018 }
2019 return true;
2020 }
2021
Wale Ogunwale854809c2015-12-27 16:18:19 -08002022 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2023 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002024 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002025 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2026 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002027 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002028 }
2029 }
2030 return newBounds;
2031 }
2032
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002033 void setWindowManager(WindowManagerService wm) {
2034 mWindowManager = wm;
2035 }
2036
2037 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2038 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2039 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2040 if (pal.stack == stack) {
2041 mPendingActivityLaunches.remove(palNdx);
2042 }
2043 }
2044 }
2045}