blob: 9f875a1f3efa1d8b105d29378ea1717c75f97481 [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;
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700106import android.os.Process;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.os.RemoteException;
108import android.os.SystemClock;
109import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000110import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800111import android.service.voice.IVoiceInteractionSession;
112import android.util.EventLog;
113import android.util.Slog;
114import android.view.Display;
115
116import com.android.internal.app.HeavyWeightSwitcherActivity;
117import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800118import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
119import com.android.server.wm.WindowManagerService;
120
121import java.util.ArrayList;
122
123/**
124 * Controller for interpreting how and then launching activities.
125 *
126 * This class collects all the logic for determining how an intent and flags should be turned into
127 * an activity and associated task and stack.
128 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800129class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800130 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
131 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
132 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
133 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
134 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
135
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700136 // TODO b/30204367 remove when the platform fully supports ephemeral applications
137 private static final boolean USE_DEFAULT_EPHEMERAL_LAUNCHER = false;
138
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800139 private final ActivityManagerService mService;
140 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000141 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800142 private WindowManagerService mWindowManager;
143
144 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
145
Wale Ogunwale01d66562015-12-29 08:19:19 -0800146 // Share state variable among methods when starting an activity.
147 private ActivityRecord mStartActivity;
Jorim Jaggibe67c902016-04-12 00:53:16 -0700148 private ActivityRecord mReusedActivity;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800149 private Intent mIntent;
150 private int mCallingUid;
151 private ActivityOptions mOptions;
152
153 private boolean mLaunchSingleTop;
154 private boolean mLaunchSingleInstance;
155 private boolean mLaunchSingleTask;
156 private boolean mLaunchTaskBehind;
157 private int mLaunchFlags;
158
159 private Rect mLaunchBounds;
160
161 private ActivityRecord mNotTop;
162 private boolean mDoResume;
163 private int mStartFlags;
164 private ActivityRecord mSourceRecord;
165
166 private TaskRecord mInTask;
167 private boolean mAddingToTask;
168 private TaskRecord mReuseTask;
169
170 private ActivityInfo mNewTaskInfo;
171 private Intent mNewTaskIntent;
172 private ActivityStack mSourceStack;
173 private ActivityStack mTargetStack;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700174 // Indicates that we moved other task and are going to put something on top soon, so
175 // we don't want to show it redundantly or accidentally change what's shown below.
176 private boolean mMovedOtherTask;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800177 private boolean mMovedToFront;
178 private boolean mNoAnimation;
179 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700180 private boolean mAvoidMoveToFront;
Wei Wang98f03f92016-05-18 11:32:52 -0700181 private boolean mPowerHintSent;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800182
183 private IVoiceInteractionSession mVoiceSession;
184 private IVoiceInteractor mVoiceInteractor;
185
186 private void reset() {
187 mStartActivity = null;
188 mIntent = null;
189 mCallingUid = -1;
190 mOptions = null;
191
192 mLaunchSingleTop = false;
193 mLaunchSingleInstance = false;
194 mLaunchSingleTask = false;
195 mLaunchTaskBehind = false;
196 mLaunchFlags = 0;
197
198 mLaunchBounds = null;
199
200 mNotTop = null;
201 mDoResume = false;
202 mStartFlags = 0;
203 mSourceRecord = null;
204
205 mInTask = null;
206 mAddingToTask = false;
207 mReuseTask = null;
208
209 mNewTaskInfo = null;
210 mNewTaskIntent = null;
211 mSourceStack = null;
212
213 mTargetStack = null;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -0700214 mMovedOtherTask = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800215 mMovedToFront = false;
216 mNoAnimation = false;
217 mKeepCurTransition = false;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700218 mAvoidMoveToFront = false;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800219
220 mVoiceSession = null;
221 mVoiceInteractor = null;
222 }
223
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800224 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
225 mService = service;
226 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000227 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800228 }
229
230 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
231 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
232 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
233 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
234 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
235 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
236 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
237 TaskRecord inTask) {
238 int err = ActivityManager.START_SUCCESS;
239
240 ProcessRecord callerApp = null;
241 if (caller != null) {
242 callerApp = mService.getRecordForAppLocked(caller);
243 if (callerApp != null) {
244 callingPid = callerApp.pid;
245 callingUid = callerApp.info.uid;
246 } else {
247 Slog.w(TAG, "Unable to find app for caller " + caller
248 + " (pid=" + callingPid + ") when starting: "
249 + intent.toString());
250 err = ActivityManager.START_PERMISSION_DENIED;
251 }
252 }
253
254 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
255
256 if (err == ActivityManager.START_SUCCESS) {
257 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
258 + "} from uid " + callingUid
259 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
260 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
261 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
262 container.mActivityDisplay.mDisplayId)));
263 }
264
265 ActivityRecord sourceRecord = null;
266 ActivityRecord resultRecord = null;
267 if (resultTo != null) {
268 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
269 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
270 "Will send result to " + resultTo + " " + sourceRecord);
271 if (sourceRecord != null) {
272 if (requestCode >= 0 && !sourceRecord.finishing) {
273 resultRecord = sourceRecord;
274 }
275 }
276 }
277
278 final int launchFlags = intent.getFlags();
279
280 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
281 // Transfer the result target from the source activity to the new
282 // one being started, including any failures.
283 if (requestCode >= 0) {
284 ActivityOptions.abort(options);
285 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
286 }
287 resultRecord = sourceRecord.resultTo;
288 if (resultRecord != null && !resultRecord.isInStackLocked()) {
289 resultRecord = null;
290 }
291 resultWho = sourceRecord.resultWho;
292 requestCode = sourceRecord.requestCode;
293 sourceRecord.resultTo = null;
294 if (resultRecord != null) {
295 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
296 }
297 if (sourceRecord.launchedFromUid == callingUid) {
298 // The new activity is being launched from the same uid as the previous
299 // activity in the flow, and asking to forward its result back to the
300 // previous. In this case the activity is serving as a trampoline between
301 // the two, so we also want to update its launchedFromPackage to be the
302 // same as the previous activity. Note that this is safe, since we know
303 // these two packages come from the same uid; the caller could just as
304 // well have supplied that same package name itself. This specifially
305 // deals with the case of an intent picker/chooser being launched in the app
306 // flow to redirect to an activity picked by the user, where we want the final
307 // activity to consider it to have been launched by the previous app activity.
308 callingPackage = sourceRecord.launchedFromPackage;
309 }
310 }
311
312 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
313 // We couldn't find a class that can handle the given Intent.
314 // That's the end of that!
315 err = ActivityManager.START_INTENT_NOT_RESOLVED;
316 }
317
318 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
319 // We couldn't find the specific class specified in the Intent.
320 // Also the end of the line.
321 err = ActivityManager.START_CLASS_NOT_FOUND;
322 }
323
324 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
325 && sourceRecord.task.voiceSession != null) {
326 // If this activity is being launched as part of a voice session, we need
327 // to ensure that it is safe to do so. If the upcoming activity will also
328 // be part of the voice session, we can only launch it if it has explicitly
329 // said it supports the VOICE category, or it is a part of the calling app.
330 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
331 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
332 try {
333 intent.addCategory(Intent.CATEGORY_VOICE);
334 if (!AppGlobals.getPackageManager().activitySupportsIntent(
335 intent.getComponent(), intent, resolvedType)) {
336 Slog.w(TAG,
337 "Activity being started in current voice task does not support voice: "
338 + intent);
339 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
340 }
341 } catch (RemoteException e) {
342 Slog.w(TAG, "Failure checking voice capabilities", e);
343 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
344 }
345 }
346 }
347
348 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
349 // If the caller is starting a new voice session, just make sure the target
350 // is actually allowing it to run this way.
351 try {
352 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
353 intent, resolvedType)) {
354 Slog.w(TAG,
355 "Activity being started in new voice task does not support: "
356 + intent);
357 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
358 }
359 } catch (RemoteException e) {
360 Slog.w(TAG, "Failure checking voice capabilities", e);
361 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
362 }
363 }
364
365 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
366
Wale Ogunwale01d66562015-12-29 08:19:19 -0800367 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800368 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800369 resultStack.sendActivityResultLocked(
370 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800371 }
372 ActivityOptions.abort(options);
373 return err;
374 }
375
376 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
377 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
Jorim Jaggi2adba072016-03-03 13:43:39 +0100378 resultRecord, resultStack, options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800379 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
380 callingPid, resolvedType, aInfo.applicationInfo);
381
382 if (mService.mController != null) {
383 try {
384 // The Intent we give to the watcher has the extra data
385 // stripped off, since it can contain private information.
386 Intent watchIntent = intent.cloneFilter();
387 abort |= !mService.mController.activityStarting(watchIntent,
388 aInfo.applicationInfo.packageName);
389 } catch (RemoteException e) {
390 mService.mController = null;
391 }
392 }
393
Rubin Xu58d25992016-01-21 17:47:13 +0000394 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Tony Mak853304c2016-04-18 15:17:41 +0100395 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
396 options);
Rubin Xu58d25992016-01-21 17:47:13 +0000397 intent = mInterceptor.mIntent;
398 rInfo = mInterceptor.mRInfo;
399 aInfo = mInterceptor.mAInfo;
400 resolvedType = mInterceptor.mResolvedType;
401 inTask = mInterceptor.mInTask;
402 callingPid = mInterceptor.mCallingPid;
403 callingUid = mInterceptor.mCallingUid;
Tony Mak853304c2016-04-18 15:17:41 +0100404 options = mInterceptor.mActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800405 if (abort) {
406 if (resultRecord != null) {
407 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800408 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800409 }
410 // We pretend to the caller that it was really started, but
411 // they will just get a cancel result.
412 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800413 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800414 }
415
416 // If permissions need a review before any of the app components can run, we
417 // launch the review activity and pass a pending intent to start the activity
418 // we are to launching now after the review is completed.
Svetoslav Ganovac69be52016-06-29 17:31:44 -0700419 if ((mService.mPermissionReviewRequired
420 || Build.PERMISSIONS_REVIEW_REQUIRED) && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800421 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
422 aInfo.packageName, userId)) {
423 IIntentSender target = mService.getIntentSenderLocked(
424 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
425 callingUid, userId, null, null, 0, new Intent[]{intent},
426 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
427 | PendingIntent.FLAG_ONE_SHOT, null);
428
429 final int flags = intent.getFlags();
430 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
431 newIntent.setFlags(flags
432 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
433 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
434 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
435 if (resultRecord != null) {
436 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
437 }
438 intent = newIntent;
439
440 resolvedType = null;
441 callingUid = realCallingUid;
442 callingPid = realCallingPid;
443
444 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
445 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
446 null /*profilerInfo*/);
447
448 if (DEBUG_PERMISSIONS_REVIEW) {
449 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
450 true, false) + "} from uid " + callingUid + " on display "
451 + (container == null ? (mSupervisor.mFocusedStack == null ?
452 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
453 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
454 container.mActivityDisplay.mDisplayId)));
455 }
456 }
457 }
458
459 // If we have an ephemeral app, abort the process of launching the resolved intent.
460 // Instead, launch the ephemeral installer. Once the installer is finished, it
461 // starts either the intent we resolved here [on install error] or the ephemeral
462 // app [on install success].
463 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700464 intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
465 rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
466 userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800467 resolvedType = null;
468 callingUid = realCallingUid;
469 callingPid = realCallingPid;
470
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800471 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
472 }
473
474 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
475 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
476 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
Wale Ogunwale1affbbc2016-05-01 09:03:52 -0700477 options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800478 if (outActivity != null) {
479 outActivity[0] = r;
480 }
481
482 if (r.appTimeTracker == null && sourceRecord != null) {
483 // If the caller didn't specify an explicit time tracker, we want to continue
484 // tracking under any it has.
485 r.appTimeTracker = sourceRecord.appTimeTracker;
486 }
487
488 final ActivityStack stack = mSupervisor.mFocusedStack;
489 if (voiceSession == null && (stack.mResumedActivity == null
490 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
491 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
492 realCallingPid, realCallingUid, "Activity start")) {
493 PendingActivityLaunch pal = new PendingActivityLaunch(r,
494 sourceRecord, startFlags, stack, callerApp);
495 mPendingActivityLaunches.add(pal);
496 ActivityOptions.abort(options);
497 return ActivityManager.START_SWITCHES_CANCELED;
498 }
499 }
500
501 if (mService.mDidAppSwitch) {
502 // This is the second allowed switch since we stopped switches,
503 // so now just generally allow switches. Use case: user presses
504 // home (switches disabled, switch to home, mDidAppSwitch now true);
505 // user taps a home icon (coming from home so allowed, we hit here
506 // and now allow anyone to switch again).
507 mService.mAppSwitchesAllowedTime = 0;
508 } else {
509 mService.mDidAppSwitch = true;
510 }
511
512 doPendingActivityLaunchesLocked(false);
513
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700514 try {
515 mService.mWindowManager.deferSurfaceLayout();
516 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
517 true, options, inTask);
518 } finally {
519 mService.mWindowManager.continueSurfaceLayout();
520 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700521 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800522 return err;
523 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800524
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700525 /**
526 * Builds and returns an intent to launch the ephemeral installer.
527 */
528 private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
529 String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
530 final Intent nonEphemeralIntent = new Intent(origIntent);
531 nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
532 // Intent that is launched if the ephemeral package couldn't be installed
533 // for any reason.
534 final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(
535 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
536 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1,
537 new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType },
538 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
539 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
540
541 final Intent ephemeralIntent;
542 if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
543 // Force the intent to be directed to the ephemeral package
544 ephemeralIntent = new Intent(origIntent);
545 ephemeralIntent.setPackage(ephemeralPackage);
546 } else {
547 // Success intent goes back to the installer
548 // TODO; do we need any extras for the installer?
549 ephemeralIntent = new Intent(launchIntent);
550 ephemeralIntent.setData(null);
551 }
552
553 // Intent that is eventually launched if the ephemeral package was
554 // installed successfully. This will actually be launched by a platform
555 // broadcast receiver.
556 final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
557 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
558 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
559 new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
560 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
561 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
562
563 // Finally build the actual intent to launch the ephemeral installer
564 int flags = launchIntent.getFlags();
565 final Intent intent = new Intent();
566 intent.setFlags(flags
567 | Intent.FLAG_ACTIVITY_NEW_TASK
568 | Intent.FLAG_ACTIVITY_CLEAR_TASK
569 | Intent.FLAG_ACTIVITY_NO_HISTORY
570 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
571 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
572 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
573 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
574 // TODO: Remove when the platform has fully implemented ephemeral apps
575 intent.setData(origIntent.getData());
576 return intent;
577 }
578
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800579 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700580 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
581 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800582
583 if (result < START_SUCCESS) {
584 // If someone asked to have the keyguard dismissed on the next activity start,
585 // but we are not actually doing an activity switch... just dismiss the keyguard now,
586 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800587 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800588 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800589 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800590
Chong Zhang5022da32016-06-21 16:31:37 -0700591 // We're waiting for an activity launch to finish, but that activity simply
592 // brought another activity to front. Let startActivityMayWait() know about
593 // this, so it waits for the new activity to become visible instead.
594 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
595 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
596 }
597
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800598 int startedActivityStackId = INVALID_STACK_ID;
599 if (r.task != null && r.task.stack != null) {
600 startedActivityStackId = r.task.stack.mStackId;
601 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700602 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800603 }
604
Jorim Jaggi352d5842016-05-19 10:20:28 -0700605 // If we launched the activity from a no display activity that was launched from the home
606 // screen, we also need to start recents to un-minimize the docked stack, since the
607 // noDisplay activity will be finished shortly after.
608 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
609 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700610 final boolean noDisplayActivityOverHome = sourceRecord != null
611 && sourceRecord.noDisplay
612 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700613 if (startedActivityStackId == DOCKED_STACK_ID
614 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100615 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
616 final ActivityRecord topActivityHomeStack = homeStack != null
617 ? homeStack.topRunningActivityLocked() : null;
618 if (topActivityHomeStack == null
619 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
620 // We launch an activity while being in home stack, which means either launcher or
621 // recents into docked stack. We don't want the launched activity to be alone in a
622 // docked stack, so we want to immediately launch recents too.
623 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700624 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100625 return;
626 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800627 }
628
629 if (startedActivityStackId == PINNED_STACK_ID
630 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
631 // The activity was already running in the pinned stack so it wasn't started, but either
632 // brought to the front or the new intent was delivered to it since it was already in
633 // front. Notify anyone interested in this piece of information.
634 mService.notifyPinnedActivityRestartAttemptLocked();
635 return;
636 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800637 }
638
639 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
640 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
641 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
642 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
643 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
644 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
645 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700646 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800647 null /*container*/, null /*inTask*/);
648 if (mSupervisor.inResumeTopActivity) {
649 // If we are in resume section already, home activity will be initialized, but not
650 // resumed (to avoid recursive resume) and will stay that way until something pokes it
651 // again. We need to schedule another resume.
652 mSupervisor.scheduleResumeTopActivities();
653 }
654 }
655
Tony Mak853304c2016-04-18 15:17:41 +0100656 void showConfirmDeviceCredential(int userId) {
657 // First, retrieve the stack that we want to resume after credential is confirmed.
658 ActivityStack targetStack;
659 ActivityStack fullscreenStack =
660 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
661 if (fullscreenStack != null &&
662 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
663 // Single window case and the case that the docked stack is shown with fullscreen stack.
664 targetStack = fullscreenStack;
665 } else {
666 // The case that the docked stack is shown with recent.
667 targetStack = mSupervisor.getStack(HOME_STACK_ID);
668 }
669 if (targetStack == null) {
670 return;
671 }
672 final KeyguardManager km = (KeyguardManager) mService.mContext
673 .getSystemService(Context.KEYGUARD_SERVICE);
674 final Intent credential =
675 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100676 // For safety, check null here in case users changed the setting after the checking.
677 if (credential == null) {
678 return;
679 }
Tony Mak853304c2016-04-18 15:17:41 +0100680 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
681 if (activityRecord != null) {
682 final IIntentSender target = mService.getIntentSenderLocked(
683 ActivityManager.INTENT_SENDER_ACTIVITY,
684 activityRecord.launchedFromPackage,
685 activityRecord.launchedFromUid,
686 activityRecord.userId,
687 null, null, 0,
688 new Intent[] { activityRecord.intent },
689 new String[] { activityRecord.resolvedType },
690 PendingIntent.FLAG_CANCEL_CURRENT |
691 PendingIntent.FLAG_ONE_SHOT |
692 PendingIntent.FLAG_IMMUTABLE,
693 null);
694 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
695 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100696 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100697 }
698 }
699
Tony Mak646fe992016-04-21 16:43:08 +0100700 void startConfirmCredentialIntent(Intent intent) {
701 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
702 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
703 FLAG_ACTIVITY_TASK_ON_HOME);
704 final ActivityOptions options = ActivityOptions.makeBasic();
705 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
706 mService.mContext.startActivityAsUser(intent, options.toBundle(),
707 UserHandle.CURRENT);
708 }
Tony Mak853304c2016-04-18 15:17:41 +0100709
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800710 final int startActivityMayWait(IApplicationThread caller, int callingUid,
711 String callingPackage, Intent intent, String resolvedType,
712 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
713 IBinder resultTo, String resultWho, int requestCode, int startFlags,
714 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
715 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
716 IActivityContainer iContainer, TaskRecord inTask) {
717 // Refuse possible leaked file descriptors
718 if (intent != null && intent.hasFileDescriptors()) {
719 throw new IllegalArgumentException("File descriptors passed in Intent");
720 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500721 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800722 boolean componentSpecified = intent.getComponent() != null;
723
724 // Save a copy in case ephemeral needs it
725 final Intent ephemeralIntent = new Intent(intent);
726 // Don't modify the client's object!
727 intent = new Intent(intent);
728
729 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000730 if (rInfo == null) {
731 UserInfo userInfo = mSupervisor.getUserInfo(userId);
732 if (userInfo != null && userInfo.isManagedProfile()) {
733 // Special case for managed profiles, if attempting to launch non-cryto aware
734 // app in a locked managed profile from an unlocked parent allow it to resolve
735 // as user will be sent via confirm credentials to unlock the profile.
736 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700737 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000738 long token = Binder.clearCallingIdentity();
739 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700740 UserInfo parent = userManager.getProfileParent(userId);
741 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
742 && userManager.isUserUnlockingOrUnlocked(parent.id)
743 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000744 } finally {
745 Binder.restoreCallingIdentity(token);
746 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700747 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000748 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600749 PackageManager.MATCH_DIRECT_BOOT_AWARE
750 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000751 }
752 }
753 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800754 // Collect information about the target of the Intent.
755 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
756
757 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
758 ActivityStackSupervisor.ActivityContainer container =
759 (ActivityStackSupervisor.ActivityContainer)iContainer;
760 synchronized (mService) {
761 if (container != null && container.mParentActivity != null &&
762 container.mParentActivity.state != RESUMED) {
763 // Cannot start a child activity if the parent is not resumed.
764 return ActivityManager.START_CANCELED;
765 }
766 final int realCallingPid = Binder.getCallingPid();
767 final int realCallingUid = Binder.getCallingUid();
768 int callingPid;
769 if (callingUid >= 0) {
770 callingPid = -1;
771 } else if (caller == null) {
772 callingPid = realCallingPid;
773 callingUid = realCallingUid;
774 } else {
775 callingPid = callingUid = -1;
776 }
777
778 final ActivityStack stack;
779 if (container == null || container.mStack.isOnHomeDisplay()) {
780 stack = mSupervisor.mFocusedStack;
781 } else {
782 stack = container.mStack;
783 }
784 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
785 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
786 "Starting activity when config will change = " + stack.mConfigWillChange);
787
788 final long origId = Binder.clearCallingIdentity();
789
790 if (aInfo != null &&
791 (aInfo.applicationInfo.privateFlags
792 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
793 // This may be a heavy-weight process! Check to see if we already
794 // have another, different heavy-weight process running.
795 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
796 final ProcessRecord heavy = mService.mHeavyWeightProcess;
797 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
798 || !heavy.processName.equals(aInfo.processName))) {
799 int appCallingUid = callingUid;
800 if (caller != null) {
801 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
802 if (callerApp != null) {
803 appCallingUid = callerApp.info.uid;
804 } else {
805 Slog.w(TAG, "Unable to find app for caller " + caller
806 + " (pid=" + callingPid + ") when starting: "
807 + intent.toString());
808 ActivityOptions.abort(options);
809 return ActivityManager.START_PERMISSION_DENIED;
810 }
811 }
812
813 IIntentSender target = mService.getIntentSenderLocked(
814 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
815 appCallingUid, userId, null, null, 0, new Intent[] { intent },
816 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
817 | PendingIntent.FLAG_ONE_SHOT, null);
818
819 Intent newIntent = new Intent();
820 if (requestCode >= 0) {
821 // Caller is requesting a result.
822 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
823 }
824 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
825 new IntentSender(target));
826 if (heavy.activities.size() > 0) {
827 ActivityRecord hist = heavy.activities.get(0);
828 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
829 hist.packageName);
830 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
831 hist.task.taskId);
832 }
833 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
834 aInfo.packageName);
835 newIntent.setFlags(intent.getFlags());
836 newIntent.setClassName("android",
837 HeavyWeightSwitcherActivity.class.getName());
838 intent = newIntent;
839 resolvedType = null;
840 caller = null;
841 callingUid = Binder.getCallingUid();
842 callingPid = Binder.getCallingPid();
843 componentSpecified = true;
844 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
845 aInfo = rInfo != null ? rInfo.activityInfo : null;
846 if (aInfo != null) {
847 aInfo = mService.getActivityInfoForUser(aInfo, userId);
848 }
849 }
850 }
851 }
852
Jorim Jaggi275561a2016-02-23 10:11:02 -0500853 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800854 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
855 aInfo, rInfo, voiceSession, voiceInteractor,
856 resultTo, resultWho, requestCode, callingPid,
857 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500858 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
859 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800860
861 Binder.restoreCallingIdentity(origId);
862
863 if (stack.mConfigWillChange) {
864 // If the caller also wants to switch to a new configuration,
865 // do so now. This allows a clean switch, as we are waiting
866 // for the current activity to pause (so we will not destroy
867 // it), and have not yet started the next activity.
868 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
869 "updateConfiguration()");
870 stack.mConfigWillChange = false;
871 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
872 "Updating to new configuration after starting activity.");
873 mService.updateConfigurationLocked(config, null, false);
874 }
875
876 if (outResult != null) {
877 outResult.result = res;
878 if (res == ActivityManager.START_SUCCESS) {
879 mSupervisor.mWaitingActivityLaunched.add(outResult);
880 do {
881 try {
882 mService.wait();
883 } catch (InterruptedException e) {
884 }
Chong Zhang5022da32016-06-21 16:31:37 -0700885 } while (outResult.result != START_TASK_TO_FRONT
886 && !outResult.timeout && outResult.who == null);
887 if (outResult.result == START_TASK_TO_FRONT) {
888 res = START_TASK_TO_FRONT;
889 }
890 }
891 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800892 ActivityRecord r = stack.topRunningActivityLocked();
893 if (r.nowVisible && r.state == RESUMED) {
894 outResult.timeout = false;
895 outResult.who = new ComponentName(r.info.packageName, r.info.name);
896 outResult.totalTime = 0;
897 outResult.thisTime = 0;
898 } else {
899 outResult.thisTime = SystemClock.uptimeMillis();
900 mSupervisor.mWaitingActivityVisible.add(outResult);
901 do {
902 try {
903 mService.wait();
904 } catch (InterruptedException e) {
905 }
906 } while (!outResult.timeout && outResult.who == null);
907 }
908 }
909 }
910
Jorim Jaggibe67c902016-04-12 00:53:16 -0700911 final ActivityRecord launchedActivity = mReusedActivity != null
912 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700913 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800914 return res;
915 }
916 }
917
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800918 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
919 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
920 Bundle bOptions, int userId) {
921 if (intents == null) {
922 throw new NullPointerException("intents is null");
923 }
924 if (resolvedTypes == null) {
925 throw new NullPointerException("resolvedTypes is null");
926 }
927 if (intents.length != resolvedTypes.length) {
928 throw new IllegalArgumentException("intents are length different than resolvedTypes");
929 }
930
Makoto Onukid67b1872016-07-21 16:26:36 -0700931 final int realCallingPid = Binder.getCallingPid();
932 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800933
934 int callingPid;
935 if (callingUid >= 0) {
936 callingPid = -1;
937 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700938 callingPid = realCallingPid;
939 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800940 } else {
941 callingPid = callingUid = -1;
942 }
943 final long origId = Binder.clearCallingIdentity();
944 try {
945 synchronized (mService) {
946 ActivityRecord[] outActivity = new ActivityRecord[1];
947 for (int i=0; i<intents.length; i++) {
948 Intent intent = intents[i];
949 if (intent == null) {
950 continue;
951 }
952
953 // Refuse possible leaked file descriptors
954 if (intent != null && intent.hasFileDescriptors()) {
955 throw new IllegalArgumentException("File descriptors passed in Intent");
956 }
957
958 boolean componentSpecified = intent.getComponent() != null;
959
960 // Don't modify the client's object!
961 intent = new Intent(intent);
962
963 // Collect information about the target of the Intent.
964 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
965 null, userId);
966 // TODO: New, check if this is correct
967 aInfo = mService.getActivityInfoForUser(aInfo, userId);
968
969 if (aInfo != null &&
970 (aInfo.applicationInfo.privateFlags
971 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
972 throw new IllegalArgumentException(
973 "FLAG_CANT_SAVE_STATE not supported here");
974 }
975
976 ActivityOptions options = ActivityOptions.fromBundle(
977 i == intents.length - 1 ? bOptions : null);
978 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
979 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700980 callingPid, callingUid, callingPackage,
981 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800982 options, false, componentSpecified, outActivity, null, null);
983 if (res < 0) {
984 return res;
985 }
986
987 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
988 }
989 }
990 } finally {
991 Binder.restoreCallingIdentity(origId);
992 }
993
Wale Ogunwale01d66562015-12-29 08:19:19 -0800994 return START_SUCCESS;
995 }
996
Wei Wang65c7a152016-06-02 18:51:22 -0700997 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
998 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -0700999 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1000 final ActivityRecord curTop = (focusStack == null)
1001 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1002 if ((forceSend || (!mPowerHintSent && curTop != null &&
1003 curTop.task != null && mStartActivity != null &&
1004 curTop.task != mStartActivity.task )) &&
1005 mService.mLocalPowerManager != null) {
Wei Wang65c7a152016-06-02 18:51:22 -07001006 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -07001007 mPowerHintSent = true;
1008 }
1009 }
1010
Wei Wang65c7a152016-06-02 18:51:22 -07001011 void sendPowerHintForLaunchEndIfNeeded() {
1012 // Trigger launch power hint if activity is launched
1013 if (mPowerHintSent && mService.mLocalPowerManager != null) {
1014 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
1015 mPowerHintSent = false;
1016 }
1017 }
1018
Wale Ogunwale01d66562015-12-29 08:19:19 -08001019 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1020 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1021 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1022
1023 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1024 voiceInteractor);
1025
1026 computeLaunchingTaskFlags();
1027
1028 computeSourceStack();
1029
1030 mIntent.setFlags(mLaunchFlags);
1031
Jorim Jaggibe67c902016-04-12 00:53:16 -07001032 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001033
Jorim Jaggi2adba072016-03-03 13:43:39 +01001034 final int preferredLaunchStackId =
1035 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1036
Jorim Jaggibe67c902016-04-12 00:53:16 -07001037 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001038 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1039 // still needs to be a lock task mode violation since the task gets cleared out and
1040 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001041 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001042 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1043 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1044 mSupervisor.showLockTaskToast();
1045 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1046 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1047 }
1048
1049 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001050 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001051 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001052 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001053 // This task was started because of movement of the activity based on affinity...
1054 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001055 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001056 }
1057
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001058 // This code path leads to delivering a new intent, we want to make sure we schedule it
1059 // as the first operation, in case the activity will be resumed as a result of later
1060 // operations.
1061 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001062 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001063 || mLaunchSingleInstance || mLaunchSingleTask) {
1064 // In this situation we want to remove all activities from the task up to the one
1065 // being started. In most cases this means we are resetting the task to its initial
1066 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001067 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001068 mStartActivity, mLaunchFlags);
1069 if (top != null) {
1070 if (top.frontOfTask) {
1071 // Activity aliases may mean we use different intents for the top activity,
1072 // so make sure the task now has the identity of the new intent.
1073 top.task.setIntent(mStartActivity);
1074 }
1075 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1076 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1077 mStartActivity.launchedFromPackage);
1078 }
1079 }
1080
Wei Wang65c7a152016-06-02 18:51:22 -07001081 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001082
Jorim Jaggibe67c902016-04-12 00:53:16 -07001083 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001084
1085 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1086 // We don't need to start a new activity, and the client said not to do anything
1087 // if that is the case, so this is it! And for paranoia, make sure we have
1088 // correctly resumed the top activity.
1089 resumeTargetStackIfNeeded();
1090 return START_RETURN_INTENT_TO_CALLER;
1091 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001092 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001093
1094 if (!mAddingToTask && mReuseTask == null) {
1095 // We didn't do anything... but it was needed (a.k.a., client don't use that
1096 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1097 resumeTargetStackIfNeeded();
1098 return START_TASK_TO_FRONT;
1099 }
1100 }
1101
1102 if (mStartActivity.packageName == null) {
1103 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1104 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1105 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1106 mStartActivity.requestCode, RESULT_CANCELED, null);
1107 }
1108 ActivityOptions.abort(mOptions);
1109 return START_CLASS_NOT_FOUND;
1110 }
1111
1112 // If the activity being launched is the same as the one currently at the top, then
1113 // we need to check if it should only be launched once.
1114 final ActivityStack topStack = mSupervisor.mFocusedStack;
1115 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1116 final boolean dontStart = top != null && mStartActivity.resultTo == null
1117 && top.realActivity.equals(mStartActivity.realActivity)
1118 && top.userId == mStartActivity.userId
1119 && top.app != null && top.app.thread != null
1120 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1121 || mLaunchSingleTop || mLaunchSingleTask);
1122 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001123 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001124 // For paranoia, make sure we have correctly resumed the top activity.
1125 topStack.mLastPausedActivity = null;
1126 if (mDoResume) {
1127 mSupervisor.resumeFocusedStackTopActivityLocked();
1128 }
1129 ActivityOptions.abort(mOptions);
1130 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1131 // We don't need to start a new activity, and the client said not to do
1132 // anything if that is the case, so this is it!
1133 return START_RETURN_INTENT_TO_CALLER;
1134 }
1135 top.deliverNewIntentLocked(
1136 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001137
1138 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1139 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1140 mSupervisor.handleNonResizableTaskIfNeeded(
1141 top.task, preferredLaunchStackId, topStack.mStackId);
1142
Wale Ogunwale01d66562015-12-29 08:19:19 -08001143 return START_DELIVERED_TO_TOP;
1144 }
1145
1146 boolean newTask = false;
1147 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1148 ? mSourceRecord.task : null;
1149
1150 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001151 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001152 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1153 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1154 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001155 result = setTaskFromReuseOrCreateNewTask(
1156 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001157 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001158 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001159 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001160 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001161 } else {
1162 // This not being started from an existing activity, and not part of a new task...
1163 // just put it in the top task, though these days this case should never happen.
1164 setTaskToCurrentTopOrCreateNewTask();
1165 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001166 if (result != START_SUCCESS) {
1167 return result;
1168 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001169
1170 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1171 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1172
1173 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1174 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1175 }
1176 if (newTask) {
1177 EventLog.writeEvent(
1178 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1179 }
1180 ActivityStack.logStartActivity(
1181 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1182 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001183
Wei Wang65c7a152016-06-02 18:51:22 -07001184 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001185
Wale Ogunwale01d66562015-12-29 08:19:19 -08001186 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1187 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001188 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1189 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001190 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1191 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001192 // If the activity is not focusable, we can't resume it, but still would like to
1193 // make sure it becomes visible as it starts (this will also trigger entry
1194 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001195 // Also, we don't want to resume activities in a task that currently has an overlay
1196 // as the starting activity just needs to be in the visible paused state until the
1197 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001198 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001199 // Go ahead and tell window manager to execute app transition for this activity
1200 // since the app transition will not be triggered through the resume channel.
1201 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001202 } else {
1203 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1204 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001205 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001206 } else {
1207 mTargetStack.addRecentActivityLocked(mStartActivity);
1208 }
1209 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1210
Jorim Jaggid53f0922016-04-06 22:16:23 -07001211 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001212 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001213
1214 return START_SUCCESS;
1215 }
1216
1217 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1218 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1219 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1220 reset();
1221
1222 mStartActivity = r;
1223 mIntent = r.intent;
1224 mOptions = options;
1225 mCallingUid = r.launchedFromUid;
1226 mSourceRecord = sourceRecord;
1227 mVoiceSession = voiceSession;
1228 mVoiceInteractor = voiceInteractor;
1229
1230 mLaunchBounds = getOverrideBounds(r, options, inTask);
1231
1232 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1233 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1234 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1235 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1236 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1237 mLaunchTaskBehind = r.mLaunchTaskBehind
1238 && !mLaunchSingleTask && !mLaunchSingleInstance
1239 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1240
1241 sendNewTaskResultRequestIfNeeded();
1242
1243 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1244 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1245 }
1246
1247 // If we are actually going to launch in to a new task, there are some cases where
1248 // we further want to do multiple task.
1249 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1250 if (mLaunchTaskBehind
1251 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1252 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1253 }
1254 }
1255
1256 // We'll invoke onUserLeaving before onPause only if the launching
1257 // activity did not explicitly state that this is an automated launch.
1258 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1259 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1260 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1261
1262 // If the caller has asked not to resume at this point, we make note
1263 // of this in the record so that we can skip it when trying to find
1264 // the top running activity.
1265 mDoResume = doResume;
1266 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1267 r.delayedResume = true;
1268 mDoResume = false;
1269 }
1270
Wale Ogunwale3b232392016-05-13 15:37:13 -07001271 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1272 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001273 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1274 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1275 if (top != null && !top.visible) {
1276
1277 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1278 // it!
1279 mDoResume = false;
1280 mAvoidMoveToFront = true;
1281 }
1282 }
1283
Wale Ogunwale01d66562015-12-29 08:19:19 -08001284 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1285
1286 mInTask = inTask;
1287 // In some flows in to this function, we retrieve the task record and hold on to it
1288 // without a lock before calling back in to here... so the task at this point may
1289 // not actually be in recents. Check for that, and if it isn't in recents just
1290 // consider it invalid.
1291 if (inTask != null && !inTask.inRecents) {
1292 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1293 mInTask = null;
1294 }
1295
1296 mStartFlags = startFlags;
1297 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1298 // is the same as the one making the call... or, as a special case, if we do not know
1299 // the caller then we count the current top activity as the caller.
1300 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1301 ActivityRecord checkedCaller = sourceRecord;
1302 if (checkedCaller == null) {
1303 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1304 mNotTop);
1305 }
1306 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1307 // Caller is not the same as launcher, so always needed.
1308 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1309 }
1310 }
1311
1312 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1313 }
1314
1315 private void sendNewTaskResultRequestIfNeeded() {
1316 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1317 && mStartActivity.resultTo.task.stack != null) {
1318 // For whatever reason this activity is being launched into a new task...
1319 // yet the caller has requested a result back. Well, that is pretty messed up,
1320 // so instead immediately send back a cancel and let the new task continue launched
1321 // as normal without a dependency on its originator.
1322 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1323 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1324 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1325 mStartActivity.resultTo = null;
1326 }
1327 }
1328
1329 private void computeLaunchingTaskFlags() {
1330 // If the caller is not coming from another activity, but has given us an explicit task into
1331 // which they would like us to launch the new activity, then let's see about doing that.
1332 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1333 final Intent baseIntent = mInTask.getBaseIntent();
1334 final ActivityRecord root = mInTask.getRootActivity();
1335 if (baseIntent == null) {
1336 ActivityOptions.abort(mOptions);
1337 throw new IllegalArgumentException("Launching into task without base intent: "
1338 + mInTask);
1339 }
1340
1341 // If this task is empty, then we are adding the first activity -- it
1342 // determines the root, and must be launching as a NEW_TASK.
1343 if (mLaunchSingleInstance || mLaunchSingleTask) {
1344 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1345 ActivityOptions.abort(mOptions);
1346 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1347 + mStartActivity + " into different task " + mInTask);
1348 }
1349 if (root != null) {
1350 ActivityOptions.abort(mOptions);
1351 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1352 + " has root " + root + " but target is singleInstance/Task");
1353 }
1354 }
1355
1356 // If task is empty, then adopt the interesting intent launch flags in to the
1357 // activity being started.
1358 if (root == null) {
1359 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1360 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1361 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1362 | (baseIntent.getFlags() & flagsOfInterest);
1363 mIntent.setFlags(mLaunchFlags);
1364 mInTask.setIntent(mStartActivity);
1365 mAddingToTask = true;
1366
1367 // If the task is not empty and the caller is asking to start it as the root of
1368 // a new task, then we don't actually want to start this on the task. We will
1369 // bring the task to the front, and possibly give it a new intent.
1370 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1371 mAddingToTask = false;
1372
1373 } else {
1374 mAddingToTask = true;
1375 }
1376
1377 mReuseTask = mInTask;
1378 } else {
1379 mInTask = null;
1380 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1381 // when in freeform workspace.
1382 // Also put noDisplay activities in the source task. These by itself can be placed
1383 // in any task/stack, however it could launch other activities like ResolverActivity,
1384 // and we want those to stay in the original task.
1385 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1386 && mSourceRecord.isFreeform()) {
1387 mAddingToTask = true;
1388 }
1389 }
1390
1391 if (mInTask == null) {
1392 if (mSourceRecord == null) {
1393 // This activity is not being started from another... in this
1394 // case we -always- start a new task.
1395 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1396 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1397 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1398 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1399 }
1400 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1401 // The original activity who is starting us is running as a single
1402 // instance... this new activity it is starting must go on its
1403 // own task.
1404 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1405 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1406 // The activity being started is a single instance... it always
1407 // gets launched into its own task.
1408 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1409 }
1410 }
1411 }
1412
1413 private void computeSourceStack() {
1414 if (mSourceRecord == null) {
1415 mSourceStack = null;
1416 return;
1417 }
1418 if (!mSourceRecord.finishing) {
1419 mSourceStack = mSourceRecord.task.stack;
1420 return;
1421 }
1422
1423 // If the source is finishing, we can't further count it as our source. This is because the
1424 // task it is associated with may now be empty and on its way out, so we don't want to
1425 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1426 // a task for it. But save the task information so it can be used when creating the new task.
1427 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1428 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1429 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1430 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1431 mNewTaskInfo = mSourceRecord.info;
1432 mNewTaskIntent = mSourceRecord.task.intent;
1433 }
1434 mSourceRecord = null;
1435 mSourceStack = null;
1436 }
1437
1438 /**
1439 * Decide whether the new activity should be inserted into an existing task. Returns null
1440 * if not or an ActivityRecord with the task into which the new activity should be added.
1441 */
1442 private ActivityRecord getReusableIntentActivity() {
1443 // We may want to try to place the new activity in to an existing task. We always
1444 // do this if the target activity is singleTask or singleInstance; we will also do
1445 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1446 // us to still place it in a new task: multi task, always doc mode, or being asked to
1447 // launch this as a new task behind the current one.
1448 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1449 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1450 || mLaunchSingleInstance || mLaunchSingleTask;
1451 // If bring to front is requested, and no result is requested and we have not been given
1452 // an explicit task to launch in to, and we can find a task that was started with this
1453 // same component, then instead of launching bring that one to the front.
1454 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1455 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001456 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1457 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1458 intentActivity = task != null ? task.getTopActivity() : null;
1459 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001460 if (mLaunchSingleInstance) {
1461 // There can be one and only one instance of single instance activity in the
1462 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001463 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001464 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1465 // For the launch adjacent case we only want to put the activity in an existing
1466 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001467 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1468 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001469 } else {
1470 // Otherwise find the best task to put the activity in.
1471 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1472 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001473 }
1474 return intentActivity;
1475 }
1476
1477 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1478 mTargetStack = intentActivity.task.stack;
1479 mTargetStack.mLastPausedActivity = null;
1480 // If the target task is not in the front, then we need to bring it to the front...
1481 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1482 // the same behavior as if a new instance was being started, which means not bringing it
1483 // to the front if the caller is not itself in the front.
1484 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1485 ActivityRecord curTop = (focusStack == null)
1486 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1487
Jorim Jaggic875ae72016-04-26 22:41:06 -07001488 if (curTop != null
1489 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1490 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001491 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1492 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1493 mSourceStack.topActivity().task == mSourceRecord.task)) {
1494 // We really do want to push this one into the user's face, right now.
1495 if (mLaunchTaskBehind && mSourceRecord != null) {
1496 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1497 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001498 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001499
1500 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1501 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1502 // So no point resuming any of the activities here, it just wastes one extra
1503 // resuming, plus enter AND exit transitions.
1504 // Here we only want to bring the target stack forward. Transition will be applied
1505 // to the new activity that's started after the old ones are gone.
1506 final boolean willClearTask =
1507 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1508 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1509 if (!willClearTask) {
1510 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001511 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001512 if (launchStack == null || launchStack == mTargetStack) {
1513 // We only want to move to the front, if we aren't going to launch on a
1514 // different stack. If we launch on a different stack, we will put the
1515 // task on top there.
1516 mTargetStack.moveTaskToFrontLocked(
1517 intentActivity.task, mNoAnimation, mOptions,
1518 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1519 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001520 } else if (launchStack.mStackId == DOCKED_STACK_ID
1521 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1522 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1523 // If we want to launch adjacent and mTargetStack is not the computed
1524 // launch stack - move task to top of computed stack.
1525 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1526 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1527 ANIMATE);
1528 } else {
1529 // TODO: This should be reevaluated in MW v2.
1530 // We choose to move task to front instead of launching it adjacent
1531 // when specific stack was requested explicitly and it appeared to be
1532 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1533 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1534 mOptions, mStartActivity.appTimeTracker,
1535 "bringToFrontInsteadOfAdjacentLaunch");
1536 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001537 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001538 }
1539 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001540 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001541 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001542 }
1543 }
1544 if (!mMovedToFront && mDoResume) {
1545 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1546 + " from " + intentActivity);
1547 mTargetStack.moveToFront("intentActivityFound");
1548 }
1549
Jorim Jaggid53f0922016-04-06 22:16:23 -07001550 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1551 mTargetStack.mStackId);
1552
Wale Ogunwale01d66562015-12-29 08:19:19 -08001553 // If the caller has requested that the target task be reset, then do so.
1554 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1555 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1556 }
1557 return intentActivity;
1558 }
1559
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001560 private void updateTaskReturnToType(
1561 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
Jiaquan Hee13e9642016-06-15 15:16:13 -07001562 if (focusedStack != null && focusedStack.isHomeStack() &&
1563 focusedStack.topTask().isOnTopLauncher()) {
1564 // Since an on-top launcher will is moved to back when tasks are launched from it,
1565 // those tasks should first try to return to a non-home activity.
1566 // This also makes sure that non-home activities are visible under a transparent
1567 // non-home activity.
1568 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1569 return;
1570 } else if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001571 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1572 // Caller wants to appear on home activity.
1573 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1574 return;
1575 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1576 // Task will be launched over the home stack, so return home.
1577 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1578 return;
1579 }
1580
1581 // Else we are coming from an application stack so return to an application.
1582 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1583 }
1584
Wale Ogunwale01d66562015-12-29 08:19:19 -08001585 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1586 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1587 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1588 // The caller has requested to completely replace any existing task with its new
1589 // activity. Well that should not be too hard...
1590 mReuseTask = intentActivity.task;
1591 mReuseTask.performClearTaskLocked();
1592 mReuseTask.setIntent(mStartActivity);
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001593 // When we clear the task - focus will be adjusted, which will bring another task
1594 // to top before we launch the activity we need. This will temporary swap their
1595 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1596 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001597 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1598 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001599 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1600 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001601 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001602 // A special case: we need to start the activity because it is not currently
1603 // running, and the caller has asked to clear the current task to have this
1604 // activity at the top.
1605 mAddingToTask = true;
1606 // Now pretend like this activity is being started by the top of its task, so it
1607 // is put in the right place.
1608 mSourceRecord = intentActivity;
1609 final TaskRecord task = mSourceRecord.task;
1610 if (task != null && task.stack == null) {
1611 // Target stack got cleared when we all activities were removed above.
1612 // Go ahead and reset it.
1613 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1614 null /* bounds */, mLaunchFlags, mOptions);
1615 mTargetStack.addTask(task,
1616 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1617 }
1618 }
1619 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1620 // In this case the top activity on the task is the same as the one being launched,
1621 // so we take that as a request to bring the task to the foreground. If the top
1622 // activity in the task is the root activity, deliver this new intent to it if it
1623 // desires.
1624 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1625 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001626 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001627 intentActivity.task);
1628 if (intentActivity.frontOfTask) {
1629 intentActivity.task.setIntent(mStartActivity);
1630 }
1631 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1632 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001633 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001634 // In this case we are launching the root activity of the task, but with a
1635 // different intent. We should start a new instance on top.
1636 mAddingToTask = true;
1637 mSourceRecord = intentActivity;
1638 }
1639 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1640 // In this case an activity is being launched in to an existing task, without
1641 // resetting that task. This is typically the situation of launching an activity
1642 // from a notification or shortcut. We want to place the new activity on top of the
1643 // current task.
1644 mAddingToTask = true;
1645 mSourceRecord = intentActivity;
1646 } else if (!intentActivity.task.rootWasReset) {
1647 // In this case we are launching into an existing task that has not yet been started
1648 // from its front door. The current task has been brought to the front. Ideally,
1649 // we'd probably like to place this new task at the bottom of its stack, but that's
1650 // a little hard to do with the current organization of the code so for now we'll
1651 // just drop it.
1652 intentActivity.task.setIntent(mStartActivity);
1653 }
1654 }
1655
1656 private void resumeTargetStackIfNeeded() {
1657 if (mDoResume) {
1658 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1659 if (!mMovedToFront) {
1660 // Make sure to notify Keyguard as well if we are not running an app transition
1661 // later.
1662 mSupervisor.notifyActivityDrawnForKeyguard();
1663 }
1664 } else {
1665 ActivityOptions.abort(mOptions);
1666 }
1667 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1668 }
1669
Chong Zhang6cda19c2016-06-14 19:07:56 -07001670 private int setTaskFromReuseOrCreateNewTask(
1671 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1672 mTargetStack = computeStackFocus(
1673 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1674
1675 // Do no move the target stack to front yet, as we might bail if
1676 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001677
1678 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001679 final TaskRecord task = mTargetStack.createTaskRecord(
1680 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001681 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1682 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1683 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1684 mStartActivity.setTask(task, taskToAffiliate);
1685 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001686 final int stackId = mTargetStack.mStackId;
1687 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001688 mService.resizeStack(
1689 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001690 } else {
1691 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1692 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001693 }
1694 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1695 "Starting new activity " +
1696 mStartActivity + " in new task " + mStartActivity.task);
1697 } else {
1698 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1699 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001700
1701 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1702 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1703 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1704 }
1705
1706 if (!mMovedOtherTask) {
1707 // If stack id is specified in activity options, usually it means that activity is
1708 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1709 // that case we check the target stack.
1710 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1711 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1712 }
1713 if (mDoResume) {
1714 mTargetStack.moveToFront("reuseOrNewTask");
1715 }
1716 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001717 }
1718
1719 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001720 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1721 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1722 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1723 }
1724
Wale Ogunwale01d66562015-12-29 08:19:19 -08001725 final TaskRecord sourceTask = mSourceRecord.task;
1726 // We only want to allow changing stack if the target task is not the top one,
1727 // otherwise we would move the launching task to the other side, rather than show
1728 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001729 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1730 if (moveStackAllowed) {
1731 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1732 mOptions);
1733 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001734
1735 if (mTargetStack == null) {
1736 mTargetStack = sourceTask.stack;
1737 } else if (mTargetStack != sourceTask.stack) {
1738 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1739 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1740 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001741
Wale Ogunwale01d66562015-12-29 08:19:19 -08001742 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001743 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001744 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1745 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001746 } else if (mDoResume) {
1747 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001748 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001749
Wale Ogunwale01d66562015-12-29 08:19:19 -08001750 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1751 // In this case, we are adding the activity to an existing task, but the caller has
1752 // asked to clear that task if the activity is already running.
1753 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1754 mKeepCurTransition = true;
1755 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001756 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001757 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1758 // For paranoia, make sure we have correctly resumed the top activity.
1759 mTargetStack.mLastPausedActivity = null;
1760 if (mDoResume) {
1761 mSupervisor.resumeFocusedStackTopActivityLocked();
1762 }
1763 ActivityOptions.abort(mOptions);
1764 return START_DELIVERED_TO_TOP;
1765 }
1766 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1767 // In this case, we are launching an activity in our own task that may already be
1768 // running somewhere in the history, and we want to shuffle it to the front of the
1769 // stack if so.
1770 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1771 if (top != null) {
1772 final TaskRecord task = top.task;
1773 task.moveActivityToFrontLocked(top);
1774 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001775 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001776 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1777 mTargetStack.mLastPausedActivity = null;
1778 if (mDoResume) {
1779 mSupervisor.resumeFocusedStackTopActivityLocked();
1780 }
1781 return START_DELIVERED_TO_TOP;
1782 }
1783 }
1784
1785 // An existing activity is starting this new activity, so we want to keep the new one in
1786 // the same task as the one that is starting it.
1787 mStartActivity.setTask(sourceTask, null);
1788 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1789 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1790 return START_SUCCESS;
1791 }
1792
1793 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001794 // The caller is asking that the new activity be started in an explicit
1795 // task it has provided to us.
1796 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1797 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1798 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1799 }
1800
Wale Ogunwale01d66562015-12-29 08:19:19 -08001801 if (mLaunchBounds != null) {
1802 mInTask.updateOverrideConfiguration(mLaunchBounds);
1803 int stackId = mInTask.getLaunchStackId();
1804 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001805 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001806 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001807 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001808 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001809 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001810 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001811 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001812 }
1813 mTargetStack = mInTask.stack;
1814 mTargetStack.moveTaskToFrontLocked(
1815 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1816
1817 // Check whether we should actually launch the new activity in to the task,
1818 // or just reuse the current activity on top.
1819 ActivityRecord top = mInTask.getTopActivity();
1820 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1821 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1822 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001823 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001824 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1825 // We don't need to start a new activity, and the client said not to do
1826 // anything if that is the case, so this is it!
1827 return START_RETURN_INTENT_TO_CALLER;
1828 }
1829 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1830 return START_DELIVERED_TO_TOP;
1831 }
1832 }
1833
1834 if (!mAddingToTask) {
1835 // We don't actually want to have this activity added to the task, so just
1836 // stop here but still tell the caller that we consumed the intent.
1837 ActivityOptions.abort(mOptions);
1838 return START_TASK_TO_FRONT;
1839 }
1840
1841 mStartActivity.setTask(mInTask, null);
1842 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1843 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1844
1845 return START_SUCCESS;
1846 }
1847
1848 private void setTaskToCurrentTopOrCreateNewTask() {
1849 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1850 mOptions);
1851 if (mDoResume) {
1852 mTargetStack.moveToFront("addingToTopTask");
1853 }
1854 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001855 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1856 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1857 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001858 mStartActivity.setTask(task, null);
1859 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1860 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1861 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1862 }
1863
1864 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1865 boolean launchSingleTask, int launchFlags) {
1866 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1867 (launchSingleInstance || launchSingleTask)) {
1868 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1869 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1870 "\"singleInstance\" or \"singleTask\"");
1871 launchFlags &=
1872 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1873 } else {
1874 switch (r.info.documentLaunchMode) {
1875 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1876 break;
1877 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1878 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1879 break;
1880 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1881 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1882 break;
1883 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1884 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1885 break;
1886 }
1887 }
1888 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001889 }
1890
1891 final void doPendingActivityLaunchesLocked(boolean doResume) {
1892 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001893 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1894 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001895 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001896 final int result = startActivityUnchecked(
1897 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1898 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001899 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1900 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001901 } catch (Exception e) {
1902 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1903 pal.sendErrorResult(e.getMessage());
1904 }
1905 }
1906 }
1907
1908 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001909 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001910 final TaskRecord task = r.task;
1911 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1912 return mSupervisor.mHomeStack;
1913 }
1914
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001915 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001916 if (stack != null) {
1917 return stack;
1918 }
1919
1920 if (task != null && task.stack != null) {
1921 stack = task.stack;
1922 if (stack.isOnHomeDisplay()) {
1923 if (mSupervisor.mFocusedStack != stack) {
1924 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1925 "computeStackFocus: Setting " + "focused stack to r=" + r
1926 + " task=" + task);
1927 } else {
1928 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1929 "computeStackFocus: Focused stack already="
1930 + mSupervisor.mFocusedStack);
1931 }
1932 }
1933 return stack;
1934 }
1935
1936 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1937 if (container != null) {
1938 // The first time put it on the desired stack, after this put on task stack.
1939 r.mInitialActivityContainer = null;
1940 return container.mStack;
1941 }
1942
1943 // The fullscreen stack can contain any task regardless of if the task is resizeable
1944 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1945 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1946 // we can also put it in the focused stack.
1947 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001948 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1949 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1950 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001951 if (canUseFocusedStack && (!newTask
1952 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1953 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1954 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1955 return mSupervisor.mFocusedStack;
1956 }
1957
1958 // We first try to put the task in the first dynamic stack.
1959 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1960 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1961 stack = homeDisplayStacks.get(stackNdx);
1962 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1963 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1964 "computeStackFocus: Setting focused stack=" + stack);
1965 return stack;
1966 }
1967 }
1968
1969 // If there is no suitable dynamic stack then we figure out which static stack to use.
1970 final int stackId = task != null ? task.getLaunchStackId() :
1971 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1972 FULLSCREEN_WORKSPACE_STACK_ID;
1973 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1974 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1975 + r + " stackId=" + stack.mStackId);
1976 return stack;
1977 }
1978
Wale Ogunwale854809c2015-12-27 16:18:19 -08001979 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001980 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001981
1982 // We are reusing a task, keep the stack!
1983 if (mReuseTask != null) {
1984 return mReuseTask.stack;
1985 }
1986
Wale Ogunwale854809c2015-12-27 16:18:19 -08001987 final int launchStackId =
1988 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1989
1990 if (isValidLaunchStackId(launchStackId, r)) {
1991 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001992 } else if (launchStackId == DOCKED_STACK_ID) {
1993 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1994 // for this activity, so we put the activity in the fullscreen stack.
1995 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001996 }
1997
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001998 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001999 return null;
2000 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002001 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002002
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002003 // The parent activity doesn't want to launch the activity on top of itself, but
2004 // instead tries to put it onto other side in side-by-side mode.
2005 final ActivityStack parentStack = task != null ? task.stack
2006 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2007 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002008
2009 if (parentStack != mSupervisor.mFocusedStack) {
2010 // If task's parent stack is not focused - use it during adjacent launch.
2011 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002012 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002013 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2014 // If task is already on top of focused stack - use it. We don't want to move the
2015 // existing focused task to adjacent stack, just deliver new intent in this case.
2016 return mSupervisor.mFocusedStack;
2017 }
2018
2019 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2020 // If parent was in docked stack, the natural place to launch another activity
2021 // will be fullscreen, so it can appear alongside the docked window.
2022 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2023 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002024 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002025 // If the parent is not in the docked stack, we check if there is docked window
2026 // and if yes, we will launch into that stack. If not, we just put the new
2027 // activity into parent's stack, because we can't find a better place.
2028 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2029 if (dockedStack != null
2030 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2031 // There is a docked stack, but it isn't visible, so we can't launch into that.
2032 return null;
2033 } else {
2034 return dockedStack;
2035 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002036 }
2037 }
2038 }
2039
Wale Ogunwale854809c2015-12-27 16:18:19 -08002040 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2041 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2042 || !StackId.isStaticStack(stackId)) {
2043 return false;
2044 }
2045
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002046 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2047 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2048 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002049 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002050
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002051 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2052 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002053 }
2054
2055 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2056 return false;
2057 }
2058
2059 final boolean supportsPip = mService.mSupportsPictureInPicture
2060 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2061 if (stackId == PINNED_STACK_ID && !supportsPip) {
2062 return false;
2063 }
2064 return true;
2065 }
2066
Wale Ogunwale854809c2015-12-27 16:18:19 -08002067 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2068 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002069 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002070 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2071 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002072 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002073 }
2074 }
2075 return newBounds;
2076 }
2077
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002078 void setWindowManager(WindowManagerService wm) {
2079 mWindowManager = wm;
2080 }
2081
2082 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2083 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2084 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2085 if (pal.stack == stack) {
2086 mPendingActivityLaunches.remove(palNdx);
2087 }
2088 }
2089 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002090
2091 static boolean isDocumentLaunchesIntoExisting(int flags) {
2092 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2093 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2094 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002095}