blob: efa74209afaaf176f6c71c344ea5db3674c64eb5 [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;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080036import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080037import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080038import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080039import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080040import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
41import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080042import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
43import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
44import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
45import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
46import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080047import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale01d66562015-12-29 08:19:19 -080048import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
49import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
50import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080052import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
53import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
54import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
Filip Gruszczynski303210b2016-01-08 16:28:08 -080055import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080056import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
60import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
61import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
64import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
65import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
66import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale673cbd22016-01-30 18:30:55 -080067import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080068import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
69import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
70import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Filip Gruszczynski0e381e22016-01-14 16:31:33 -080071import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080072import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
73import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
74import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080075import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080076import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080077import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080078
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080079import android.app.ActivityManager;
80import android.app.ActivityOptions;
81import android.app.AppGlobals;
82import android.app.IActivityContainer;
83import android.app.IActivityManager;
84import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080085import android.app.PendingIntent;
86import android.app.ProfilerInfo;
87import android.content.ComponentName;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080088import android.content.IIntentSender;
89import android.content.Intent;
90import android.content.IntentSender;
91import android.content.pm.ActivityInfo;
92import android.content.pm.ApplicationInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000093import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000095import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080096import android.content.res.Configuration;
97import android.graphics.Rect;
98import android.os.Binder;
99import android.os.Build;
100import android.os.Bundle;
101import android.os.IBinder;
102import android.os.RemoteException;
103import android.os.SystemClock;
104import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000105import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.service.voice.IVoiceInteractionSession;
107import android.util.EventLog;
108import android.util.Slog;
109import android.view.Display;
110
111import com.android.internal.app.HeavyWeightSwitcherActivity;
112import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800113import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
114import com.android.server.wm.WindowManagerService;
115
116import java.util.ArrayList;
117
118/**
119 * Controller for interpreting how and then launching activities.
120 *
121 * This class collects all the logic for determining how an intent and flags should be turned into
122 * an activity and associated task and stack.
123 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800124class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800125 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
126 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
127 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
128 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
129 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
130
131 private final ActivityManagerService mService;
132 private final ActivityStackSupervisor mSupervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000133 private ActivityStartInterceptor mInterceptor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800134 private WindowManagerService mWindowManager;
135
136 final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
137
Wale Ogunwale01d66562015-12-29 08:19:19 -0800138 // Share state variable among methods when starting an activity.
139 private ActivityRecord mStartActivity;
140 private Intent mIntent;
141 private int mCallingUid;
142 private ActivityOptions mOptions;
143
144 private boolean mLaunchSingleTop;
145 private boolean mLaunchSingleInstance;
146 private boolean mLaunchSingleTask;
147 private boolean mLaunchTaskBehind;
148 private int mLaunchFlags;
149
150 private Rect mLaunchBounds;
151
152 private ActivityRecord mNotTop;
153 private boolean mDoResume;
154 private int mStartFlags;
155 private ActivityRecord mSourceRecord;
156
157 private TaskRecord mInTask;
158 private boolean mAddingToTask;
159 private TaskRecord mReuseTask;
160
161 private ActivityInfo mNewTaskInfo;
162 private Intent mNewTaskIntent;
163 private ActivityStack mSourceStack;
164 private ActivityStack mTargetStack;
165 // TODO: Is the mMoveHome flag really needed?
166 private boolean mMovedHome;
167 private boolean mMovedToFront;
168 private boolean mNoAnimation;
169 private boolean mKeepCurTransition;
170
171 private IVoiceInteractionSession mVoiceSession;
172 private IVoiceInteractor mVoiceInteractor;
173
174 private void reset() {
175 mStartActivity = null;
176 mIntent = null;
177 mCallingUid = -1;
178 mOptions = null;
179
180 mLaunchSingleTop = false;
181 mLaunchSingleInstance = false;
182 mLaunchSingleTask = false;
183 mLaunchTaskBehind = false;
184 mLaunchFlags = 0;
185
186 mLaunchBounds = null;
187
188 mNotTop = null;
189 mDoResume = false;
190 mStartFlags = 0;
191 mSourceRecord = null;
192
193 mInTask = null;
194 mAddingToTask = false;
195 mReuseTask = null;
196
197 mNewTaskInfo = null;
198 mNewTaskIntent = null;
199 mSourceStack = null;
200
201 mTargetStack = null;
202 mMovedHome = false;
203 mMovedToFront = false;
204 mNoAnimation = false;
205 mKeepCurTransition = false;
206
207 mVoiceSession = null;
208 mVoiceInteractor = null;
209 }
210
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800211 ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
212 mService = service;
213 mSupervisor = supervisor;
Rubin Xu58d25992016-01-21 17:47:13 +0000214 mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800215 }
216
217 final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
218 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
219 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
220 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
221 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
222 ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
223 ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
224 TaskRecord inTask) {
225 int err = ActivityManager.START_SUCCESS;
226
227 ProcessRecord callerApp = null;
228 if (caller != null) {
229 callerApp = mService.getRecordForAppLocked(caller);
230 if (callerApp != null) {
231 callingPid = callerApp.pid;
232 callingUid = callerApp.info.uid;
233 } else {
234 Slog.w(TAG, "Unable to find app for caller " + caller
235 + " (pid=" + callingPid + ") when starting: "
236 + intent.toString());
237 err = ActivityManager.START_PERMISSION_DENIED;
238 }
239 }
240
241 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
242
243 if (err == ActivityManager.START_SUCCESS) {
244 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
245 + "} from uid " + callingUid
246 + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ?
247 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
248 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
249 container.mActivityDisplay.mDisplayId)));
250 }
251
252 ActivityRecord sourceRecord = null;
253 ActivityRecord resultRecord = null;
254 if (resultTo != null) {
255 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
256 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
257 "Will send result to " + resultTo + " " + sourceRecord);
258 if (sourceRecord != null) {
259 if (requestCode >= 0 && !sourceRecord.finishing) {
260 resultRecord = sourceRecord;
261 }
262 }
263 }
264
265 final int launchFlags = intent.getFlags();
266
267 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
268 // Transfer the result target from the source activity to the new
269 // one being started, including any failures.
270 if (requestCode >= 0) {
271 ActivityOptions.abort(options);
272 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
273 }
274 resultRecord = sourceRecord.resultTo;
275 if (resultRecord != null && !resultRecord.isInStackLocked()) {
276 resultRecord = null;
277 }
278 resultWho = sourceRecord.resultWho;
279 requestCode = sourceRecord.requestCode;
280 sourceRecord.resultTo = null;
281 if (resultRecord != null) {
282 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
283 }
284 if (sourceRecord.launchedFromUid == callingUid) {
285 // The new activity is being launched from the same uid as the previous
286 // activity in the flow, and asking to forward its result back to the
287 // previous. In this case the activity is serving as a trampoline between
288 // the two, so we also want to update its launchedFromPackage to be the
289 // same as the previous activity. Note that this is safe, since we know
290 // these two packages come from the same uid; the caller could just as
291 // well have supplied that same package name itself. This specifially
292 // deals with the case of an intent picker/chooser being launched in the app
293 // flow to redirect to an activity picked by the user, where we want the final
294 // activity to consider it to have been launched by the previous app activity.
295 callingPackage = sourceRecord.launchedFromPackage;
296 }
297 }
298
299 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
300 // We couldn't find a class that can handle the given Intent.
301 // That's the end of that!
302 err = ActivityManager.START_INTENT_NOT_RESOLVED;
303 }
304
305 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
306 // We couldn't find the specific class specified in the Intent.
307 // Also the end of the line.
308 err = ActivityManager.START_CLASS_NOT_FOUND;
309 }
310
311 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
312 && sourceRecord.task.voiceSession != null) {
313 // If this activity is being launched as part of a voice session, we need
314 // to ensure that it is safe to do so. If the upcoming activity will also
315 // be part of the voice session, we can only launch it if it has explicitly
316 // said it supports the VOICE category, or it is a part of the calling app.
317 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
318 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
319 try {
320 intent.addCategory(Intent.CATEGORY_VOICE);
321 if (!AppGlobals.getPackageManager().activitySupportsIntent(
322 intent.getComponent(), intent, resolvedType)) {
323 Slog.w(TAG,
324 "Activity being started in current voice task does not support voice: "
325 + intent);
326 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
327 }
328 } catch (RemoteException e) {
329 Slog.w(TAG, "Failure checking voice capabilities", e);
330 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
331 }
332 }
333 }
334
335 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
336 // If the caller is starting a new voice session, just make sure the target
337 // is actually allowing it to run this way.
338 try {
339 if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
340 intent, resolvedType)) {
341 Slog.w(TAG,
342 "Activity being started in new voice task does not support: "
343 + intent);
344 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
345 }
346 } catch (RemoteException e) {
347 Slog.w(TAG, "Failure checking voice capabilities", e);
348 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
349 }
350 }
351
352 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
353
Wale Ogunwale01d66562015-12-29 08:19:19 -0800354 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800355 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800356 resultStack.sendActivityResultLocked(
357 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800358 }
359 ActivityOptions.abort(options);
360 return err;
361 }
362
363 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
364 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
365 resultRecord, resultStack);
366 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
367 callingPid, resolvedType, aInfo.applicationInfo);
368
369 if (mService.mController != null) {
370 try {
371 // The Intent we give to the watcher has the extra data
372 // stripped off, since it can contain private information.
373 Intent watchIntent = intent.cloneFilter();
374 abort |= !mService.mController.activityStarting(watchIntent,
375 aInfo.applicationInfo.packageName);
376 } catch (RemoteException e) {
377 mService.mController = null;
378 }
379 }
380
Rubin Xu58d25992016-01-21 17:47:13 +0000381 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
382 mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid);
383 intent = mInterceptor.mIntent;
384 rInfo = mInterceptor.mRInfo;
385 aInfo = mInterceptor.mAInfo;
386 resolvedType = mInterceptor.mResolvedType;
387 inTask = mInterceptor.mInTask;
388 callingPid = mInterceptor.mCallingPid;
389 callingUid = mInterceptor.mCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800390
391 if (abort) {
392 if (resultRecord != null) {
393 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800394 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800395 }
396 // We pretend to the caller that it was really started, but
397 // they will just get a cancel result.
398 ActivityOptions.abort(options);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800399 return START_SUCCESS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800400 }
401
402 // If permissions need a review before any of the app components can run, we
403 // launch the review activity and pass a pending intent to start the activity
404 // we are to launching now after the review is completed.
405 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
406 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
407 aInfo.packageName, userId)) {
408 IIntentSender target = mService.getIntentSenderLocked(
409 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
410 callingUid, userId, null, null, 0, new Intent[]{intent},
411 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
412 | PendingIntent.FLAG_ONE_SHOT, null);
413
414 final int flags = intent.getFlags();
415 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
416 newIntent.setFlags(flags
417 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
418 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
419 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
420 if (resultRecord != null) {
421 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
422 }
423 intent = newIntent;
424
425 resolvedType = null;
426 callingUid = realCallingUid;
427 callingPid = realCallingPid;
428
429 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
430 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
431 null /*profilerInfo*/);
432
433 if (DEBUG_PERMISSIONS_REVIEW) {
434 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
435 true, false) + "} from uid " + callingUid + " on display "
436 + (container == null ? (mSupervisor.mFocusedStack == null ?
437 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
438 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
439 container.mActivityDisplay.mDisplayId)));
440 }
441 }
442 }
443
444 // If we have an ephemeral app, abort the process of launching the resolved intent.
445 // Instead, launch the ephemeral installer. Once the installer is finished, it
446 // starts either the intent we resolved here [on install error] or the ephemeral
447 // app [on install success].
448 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
449 // Create a pending intent to start the intent resolved here.
450 final IIntentSender failureTarget = mService.getIntentSenderLocked(
451 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
452 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
453 new String[]{ resolvedType },
454 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
455 | PendingIntent.FLAG_IMMUTABLE, null);
456
457 // Create a pending intent to start the ephemeral application; force it to be
458 // directed to the ephemeral package.
459 ephemeralIntent.setPackage(rInfo.ephemeralResolveInfo.getPackageName());
460 final IIntentSender ephemeralTarget = mService.getIntentSenderLocked(
461 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
462 Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ ephemeralIntent },
463 new String[]{ resolvedType },
464 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
465 | PendingIntent.FLAG_IMMUTABLE, null);
466
467 int flags = intent.getFlags();
468 intent = new Intent();
469 intent.setFlags(flags
470 | Intent.FLAG_ACTIVITY_NEW_TASK
471 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
472 intent.putExtra(Intent.EXTRA_PACKAGE_NAME,
473 rInfo.ephemeralResolveInfo.getPackageName());
474 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureTarget));
475 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(ephemeralTarget));
476
477 resolvedType = null;
478 callingUid = realCallingUid;
479 callingPid = realCallingPid;
480
481 rInfo = rInfo.ephemeralInstaller;
482 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
483 }
484
485 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
486 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
487 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
488 options);
489 if (outActivity != null) {
490 outActivity[0] = r;
491 }
492
493 if (r.appTimeTracker == null && sourceRecord != null) {
494 // If the caller didn't specify an explicit time tracker, we want to continue
495 // tracking under any it has.
496 r.appTimeTracker = sourceRecord.appTimeTracker;
497 }
498
499 final ActivityStack stack = mSupervisor.mFocusedStack;
500 if (voiceSession == null && (stack.mResumedActivity == null
501 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
502 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
503 realCallingPid, realCallingUid, "Activity start")) {
504 PendingActivityLaunch pal = new PendingActivityLaunch(r,
505 sourceRecord, startFlags, stack, callerApp);
506 mPendingActivityLaunches.add(pal);
507 ActivityOptions.abort(options);
508 return ActivityManager.START_SWITCHES_CANCELED;
509 }
510 }
511
512 if (mService.mDidAppSwitch) {
513 // This is the second allowed switch since we stopped switches,
514 // so now just generally allow switches. Use case: user presses
515 // home (switches disabled, switch to home, mDidAppSwitch now true);
516 // user taps a home icon (coming from home so allowed, we hit here
517 // and now allow anyone to switch again).
518 mService.mAppSwitchesAllowedTime = 0;
519 } else {
520 mService.mDidAppSwitch = true;
521 }
522
523 doPendingActivityLaunchesLocked(false);
524
Wale Ogunwale01d66562015-12-29 08:19:19 -0800525 err = startActivityUnchecked(
526 r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800527 postStartActivityUncheckedProcessing(r, err, stack.mStackId);
528 return err;
529 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800530
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800531 void postStartActivityUncheckedProcessing(
532 ActivityRecord r, int result, int prevFocusedStackId) {
533
534 if (result < START_SUCCESS) {
535 // If someone asked to have the keyguard dismissed on the next activity start,
536 // but we are not actually doing an activity switch... just dismiss the keyguard now,
537 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800538 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800539 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800540 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800541
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800542 int startedActivityStackId = INVALID_STACK_ID;
543 if (r.task != null && r.task.stack != null) {
544 startedActivityStackId = r.task.stack.mStackId;
545 } else if (mTargetStack != null) {
546 startedActivityStackId = mTargetStack.mStackId;
547 }
548
549 if (startedActivityStackId == DOCKED_STACK_ID && prevFocusedStackId == HOME_STACK_ID) {
550 // We launch an activity while being in home stack, which means either launcher or
551 // recents into docked stack. We don't want the launched activity to be alone in a
552 // docked stack, so we want to immediately launch recents too.
553 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
554 mWindowManager.showRecentApps();
555 return;
556 }
557
558 if (startedActivityStackId == PINNED_STACK_ID
559 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
560 // The activity was already running in the pinned stack so it wasn't started, but either
561 // brought to the front or the new intent was delivered to it since it was already in
562 // front. Notify anyone interested in this piece of information.
563 mService.notifyPinnedActivityRestartAttemptLocked();
564 return;
565 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800566 }
567
568 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
569 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
570 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
571 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
572 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
573 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
574 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
575 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
576 null /*container*/, null /*inTask*/);
577 if (mSupervisor.inResumeTopActivity) {
578 // If we are in resume section already, home activity will be initialized, but not
579 // resumed (to avoid recursive resume) and will stay that way until something pokes it
580 // again. We need to schedule another resume.
581 mSupervisor.scheduleResumeTopActivities();
582 }
583 }
584
585 final int startActivityMayWait(IApplicationThread caller, int callingUid,
586 String callingPackage, Intent intent, String resolvedType,
587 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
588 IBinder resultTo, String resultWho, int requestCode, int startFlags,
589 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
590 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
591 IActivityContainer iContainer, TaskRecord inTask) {
592 // Refuse possible leaked file descriptors
593 if (intent != null && intent.hasFileDescriptors()) {
594 throw new IllegalArgumentException("File descriptors passed in Intent");
595 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500596 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800597 boolean componentSpecified = intent.getComponent() != null;
598
599 // Save a copy in case ephemeral needs it
600 final Intent ephemeralIntent = new Intent(intent);
601 // Don't modify the client's object!
602 intent = new Intent(intent);
603
604 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000605 if (rInfo == null) {
606 UserInfo userInfo = mSupervisor.getUserInfo(userId);
607 if (userInfo != null && userInfo.isManagedProfile()) {
608 // Special case for managed profiles, if attempting to launch non-cryto aware
609 // app in a locked managed profile from an unlocked parent allow it to resolve
610 // as user will be sent via confirm credentials to unlock the profile.
611 UserManager userManager = UserManager.get(mService.mContext);
Tony Mak13436452016-02-24 11:08:38 +0000612 UserInfo parent = null;
613 long token = Binder.clearCallingIdentity();
614 try {
615 parent = userManager.getProfileParent(userId);
616 } finally {
617 Binder.restoreCallingIdentity(token);
618 }
Kenny Guyb1b30262016-02-09 16:02:35 +0000619 if (parent != null
620 && userManager.isUserUnlocked(parent.getUserHandle())
621 && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
622 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600623 PackageManager.MATCH_DIRECT_BOOT_AWARE
624 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000625 }
626 }
627 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800628 // Collect information about the target of the Intent.
629 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
630
631 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
632 ActivityStackSupervisor.ActivityContainer container =
633 (ActivityStackSupervisor.ActivityContainer)iContainer;
634 synchronized (mService) {
635 if (container != null && container.mParentActivity != null &&
636 container.mParentActivity.state != RESUMED) {
637 // Cannot start a child activity if the parent is not resumed.
638 return ActivityManager.START_CANCELED;
639 }
640 final int realCallingPid = Binder.getCallingPid();
641 final int realCallingUid = Binder.getCallingUid();
642 int callingPid;
643 if (callingUid >= 0) {
644 callingPid = -1;
645 } else if (caller == null) {
646 callingPid = realCallingPid;
647 callingUid = realCallingUid;
648 } else {
649 callingPid = callingUid = -1;
650 }
651
652 final ActivityStack stack;
653 if (container == null || container.mStack.isOnHomeDisplay()) {
654 stack = mSupervisor.mFocusedStack;
655 } else {
656 stack = container.mStack;
657 }
658 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
659 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
660 "Starting activity when config will change = " + stack.mConfigWillChange);
661
662 final long origId = Binder.clearCallingIdentity();
663
664 if (aInfo != null &&
665 (aInfo.applicationInfo.privateFlags
666 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
667 // This may be a heavy-weight process! Check to see if we already
668 // have another, different heavy-weight process running.
669 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
670 final ProcessRecord heavy = mService.mHeavyWeightProcess;
671 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
672 || !heavy.processName.equals(aInfo.processName))) {
673 int appCallingUid = callingUid;
674 if (caller != null) {
675 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
676 if (callerApp != null) {
677 appCallingUid = callerApp.info.uid;
678 } else {
679 Slog.w(TAG, "Unable to find app for caller " + caller
680 + " (pid=" + callingPid + ") when starting: "
681 + intent.toString());
682 ActivityOptions.abort(options);
683 return ActivityManager.START_PERMISSION_DENIED;
684 }
685 }
686
687 IIntentSender target = mService.getIntentSenderLocked(
688 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
689 appCallingUid, userId, null, null, 0, new Intent[] { intent },
690 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
691 | PendingIntent.FLAG_ONE_SHOT, null);
692
693 Intent newIntent = new Intent();
694 if (requestCode >= 0) {
695 // Caller is requesting a result.
696 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
697 }
698 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
699 new IntentSender(target));
700 if (heavy.activities.size() > 0) {
701 ActivityRecord hist = heavy.activities.get(0);
702 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
703 hist.packageName);
704 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
705 hist.task.taskId);
706 }
707 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
708 aInfo.packageName);
709 newIntent.setFlags(intent.getFlags());
710 newIntent.setClassName("android",
711 HeavyWeightSwitcherActivity.class.getName());
712 intent = newIntent;
713 resolvedType = null;
714 caller = null;
715 callingUid = Binder.getCallingUid();
716 callingPid = Binder.getCallingPid();
717 componentSpecified = true;
718 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
719 aInfo = rInfo != null ? rInfo.activityInfo : null;
720 if (aInfo != null) {
721 aInfo = mService.getActivityInfoForUser(aInfo, userId);
722 }
723 }
724 }
725 }
726
Jorim Jaggi275561a2016-02-23 10:11:02 -0500727 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800728 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
729 aInfo, rInfo, voiceSession, voiceInteractor,
730 resultTo, resultWho, requestCode, callingPid,
731 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500732 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
733 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800734
735 Binder.restoreCallingIdentity(origId);
736
737 if (stack.mConfigWillChange) {
738 // If the caller also wants to switch to a new configuration,
739 // do so now. This allows a clean switch, as we are waiting
740 // for the current activity to pause (so we will not destroy
741 // it), and have not yet started the next activity.
742 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
743 "updateConfiguration()");
744 stack.mConfigWillChange = false;
745 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
746 "Updating to new configuration after starting activity.");
747 mService.updateConfigurationLocked(config, null, false);
748 }
749
750 if (outResult != null) {
751 outResult.result = res;
752 if (res == ActivityManager.START_SUCCESS) {
753 mSupervisor.mWaitingActivityLaunched.add(outResult);
754 do {
755 try {
756 mService.wait();
757 } catch (InterruptedException e) {
758 }
759 } while (!outResult.timeout && outResult.who == null);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800760 } else if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800761 ActivityRecord r = stack.topRunningActivityLocked();
762 if (r.nowVisible && r.state == RESUMED) {
763 outResult.timeout = false;
764 outResult.who = new ComponentName(r.info.packageName, r.info.name);
765 outResult.totalTime = 0;
766 outResult.thisTime = 0;
767 } else {
768 outResult.thisTime = SystemClock.uptimeMillis();
769 mSupervisor.mWaitingActivityVisible.add(outResult);
770 do {
771 try {
772 mService.wait();
773 } catch (InterruptedException e) {
774 }
775 } while (!outResult.timeout && outResult.who == null);
776 }
777 }
778 }
779
Jorim Jaggi275561a2016-02-23 10:11:02 -0500780 final String componentName = outRecord[0] != null ? outRecord[0].shortComponentName
781 : null;
782 final boolean processRunning = outRecord[0] != null &&
783 mService.mProcessNames.get(outRecord[0].processName,
784 outRecord[0].appInfo.uid) != null;
785 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, componentName,
786 processRunning);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800787 return res;
788 }
789 }
790
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800791 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
792 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
793 Bundle bOptions, int userId) {
794 if (intents == null) {
795 throw new NullPointerException("intents is null");
796 }
797 if (resolvedTypes == null) {
798 throw new NullPointerException("resolvedTypes is null");
799 }
800 if (intents.length != resolvedTypes.length) {
801 throw new IllegalArgumentException("intents are length different than resolvedTypes");
802 }
803
804
805 int callingPid;
806 if (callingUid >= 0) {
807 callingPid = -1;
808 } else if (caller == null) {
809 callingPid = Binder.getCallingPid();
810 callingUid = Binder.getCallingUid();
811 } else {
812 callingPid = callingUid = -1;
813 }
814 final long origId = Binder.clearCallingIdentity();
815 try {
816 synchronized (mService) {
817 ActivityRecord[] outActivity = new ActivityRecord[1];
818 for (int i=0; i<intents.length; i++) {
819 Intent intent = intents[i];
820 if (intent == null) {
821 continue;
822 }
823
824 // Refuse possible leaked file descriptors
825 if (intent != null && intent.hasFileDescriptors()) {
826 throw new IllegalArgumentException("File descriptors passed in Intent");
827 }
828
829 boolean componentSpecified = intent.getComponent() != null;
830
831 // Don't modify the client's object!
832 intent = new Intent(intent);
833
834 // Collect information about the target of the Intent.
835 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
836 null, userId);
837 // TODO: New, check if this is correct
838 aInfo = mService.getActivityInfoForUser(aInfo, userId);
839
840 if (aInfo != null &&
841 (aInfo.applicationInfo.privateFlags
842 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
843 throw new IllegalArgumentException(
844 "FLAG_CANT_SAVE_STATE not supported here");
845 }
846
847 ActivityOptions options = ActivityOptions.fromBundle(
848 i == intents.length - 1 ? bOptions : null);
849 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
850 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
851 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
852 options, false, componentSpecified, outActivity, null, null);
853 if (res < 0) {
854 return res;
855 }
856
857 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
858 }
859 }
860 } finally {
861 Binder.restoreCallingIdentity(origId);
862 }
863
Wale Ogunwale01d66562015-12-29 08:19:19 -0800864 return START_SUCCESS;
865 }
866
867 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
868 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
869 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
870
871 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
872 voiceInteractor);
873
874 computeLaunchingTaskFlags();
875
876 computeSourceStack();
877
878 mIntent.setFlags(mLaunchFlags);
879
880 ActivityRecord intentActivity = getReusableIntentActivity();
881
882 if (intentActivity != null) {
883 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
884 // still needs to be a lock task mode violation since the task gets cleared out and
885 // the device would otherwise leave the locked task.
886 if (mSupervisor.isLockTaskModeViolation(intentActivity.task,
887 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
888 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
889 mSupervisor.showLockTaskToast();
890 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
891 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
892 }
893
894 if (mStartActivity.task == null) {
895 mStartActivity.task = intentActivity.task;
896 }
897 if (intentActivity.task.intent == null) {
898 // This task was started because of movement of the activity based on affinity...
899 // Now that we are actually launching it, we can assign the base intent.
900 intentActivity.task.setIntent(mStartActivity);
901 }
902
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800903 // This code path leads to delivering a new intent, we want to make sure we schedule it
904 // as the first operation, in case the activity will be resumed as a result of later
905 // operations.
906 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
907 || mLaunchSingleInstance || mLaunchSingleTask) {
908 // In this situation we want to remove all activities from the task up to the one
909 // being started. In most cases this means we are resetting the task to its initial
910 // state.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800911 final ActivityRecord top = intentActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800912 mStartActivity, mLaunchFlags);
913 if (top != null) {
914 if (top.frontOfTask) {
915 // Activity aliases may mean we use different intents for the top activity,
916 // so make sure the task now has the identity of the new intent.
917 top.task.setIntent(mStartActivity);
918 }
919 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
920 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
921 mStartActivity.launchedFromPackage);
922 }
923 }
924
Wale Ogunwale01d66562015-12-29 08:19:19 -0800925 intentActivity = setTargetStackAndMoveToFrontIfNeeded(intentActivity);
926
927 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
928 // We don't need to start a new activity, and the client said not to do anything
929 // if that is the case, so this is it! And for paranoia, make sure we have
930 // correctly resumed the top activity.
931 resumeTargetStackIfNeeded();
932 return START_RETURN_INTENT_TO_CALLER;
933 }
934
935 setTaskFromIntentActivity(intentActivity);
936
937 if (!mAddingToTask && mReuseTask == null) {
938 // We didn't do anything... but it was needed (a.k.a., client don't use that
939 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
940 resumeTargetStackIfNeeded();
941 return START_TASK_TO_FRONT;
942 }
943 }
944
945 if (mStartActivity.packageName == null) {
946 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
947 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
948 -1, mStartActivity.resultTo, mStartActivity.resultWho,
949 mStartActivity.requestCode, RESULT_CANCELED, null);
950 }
951 ActivityOptions.abort(mOptions);
952 return START_CLASS_NOT_FOUND;
953 }
954
955 // If the activity being launched is the same as the one currently at the top, then
956 // we need to check if it should only be launched once.
957 final ActivityStack topStack = mSupervisor.mFocusedStack;
958 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
959 final boolean dontStart = top != null && mStartActivity.resultTo == null
960 && top.realActivity.equals(mStartActivity.realActivity)
961 && top.userId == mStartActivity.userId
962 && top.app != null && top.app.thread != null
963 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
964 || mLaunchSingleTop || mLaunchSingleTask);
965 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -0800966 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800967 // For paranoia, make sure we have correctly resumed the top activity.
968 topStack.mLastPausedActivity = null;
969 if (mDoResume) {
970 mSupervisor.resumeFocusedStackTopActivityLocked();
971 }
972 ActivityOptions.abort(mOptions);
973 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
974 // We don't need to start a new activity, and the client said not to do
975 // anything if that is the case, so this is it!
976 return START_RETURN_INTENT_TO_CALLER;
977 }
978 top.deliverNewIntentLocked(
979 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
980 return START_DELIVERED_TO_TOP;
981 }
982
983 boolean newTask = false;
984 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
985 ? mSourceRecord.task : null;
986
987 // Should this be considered a new task?
988 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
989 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
990 newTask = true;
991 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
992
993 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
994 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
995 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
996 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -0800997 if (!mMovedHome) {
998 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800999 }
1000 } else if (mSourceRecord != null) {
1001 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1002 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1003 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1004 }
1005
1006 final int result = setTaskFromSourceRecord();
1007 if (result != START_SUCCESS) {
1008 return result;
1009 }
1010 } else if (mInTask != null) {
1011 // The caller is asking that the new activity be started in an explicit
1012 // task it has provided to us.
1013 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1014 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1015 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1016 }
1017
1018 final int result = setTaskFromInTask();
1019 if (result != START_SUCCESS) {
1020 return result;
1021 }
1022 } else {
1023 // This not being started from an existing activity, and not part of a new task...
1024 // just put it in the top task, though these days this case should never happen.
1025 setTaskToCurrentTopOrCreateNewTask();
1026 }
1027
1028 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1029 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1030
1031 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1032 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1033 }
1034 if (newTask) {
1035 EventLog.writeEvent(
1036 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1037 }
1038 ActivityStack.logStartActivity(
1039 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1040 mTargetStack.mLastPausedActivity = null;
1041 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1042 if (mDoResume) {
1043 if (!mLaunchTaskBehind) {
1044 // TODO(b/26381750): Remove this code after verification that all the decision
1045 // points above moved targetStack to the front which will also set the focus
1046 // activity.
1047 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1048 }
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001049 if (mTargetStack.isFocusable()) {
1050 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1051 mOptions);
1052 } else {
1053 // If the activity is not focusable, we can't resume it, but still would like to
1054 // make sure it becomes visible as it starts (this will also trigger entry
1055 // animation). An example of this are PIP activities.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001056 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001057 // Go ahead and tell window manager to execute app transition for this activity
1058 // since the app transition will not be triggered through the resume channel.
1059 mWindowManager.executeAppTransition();
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001060 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001061 } else {
1062 mTargetStack.addRecentActivityLocked(mStartActivity);
1063 }
1064 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1065
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001066 final int preferredLaunchStackId =
1067 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1068 mSupervisor.showNonResizeableDockToastIfNeeded(
1069 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001070
1071 return START_SUCCESS;
1072 }
1073
1074 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1075 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1076 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1077 reset();
1078
1079 mStartActivity = r;
1080 mIntent = r.intent;
1081 mOptions = options;
1082 mCallingUid = r.launchedFromUid;
1083 mSourceRecord = sourceRecord;
1084 mVoiceSession = voiceSession;
1085 mVoiceInteractor = voiceInteractor;
1086
1087 mLaunchBounds = getOverrideBounds(r, options, inTask);
1088
1089 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1090 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1091 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1092 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1093 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1094 mLaunchTaskBehind = r.mLaunchTaskBehind
1095 && !mLaunchSingleTask && !mLaunchSingleInstance
1096 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1097
1098 sendNewTaskResultRequestIfNeeded();
1099
1100 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1101 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1102 }
1103
1104 // If we are actually going to launch in to a new task, there are some cases where
1105 // we further want to do multiple task.
1106 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1107 if (mLaunchTaskBehind
1108 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1109 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1110 }
1111 }
1112
1113 // We'll invoke onUserLeaving before onPause only if the launching
1114 // activity did not explicitly state that this is an automated launch.
1115 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1116 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1117 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1118
1119 // If the caller has asked not to resume at this point, we make note
1120 // of this in the record so that we can skip it when trying to find
1121 // the top running activity.
1122 mDoResume = doResume;
1123 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1124 r.delayedResume = true;
1125 mDoResume = false;
1126 }
1127
1128 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1129
1130 mInTask = inTask;
1131 // In some flows in to this function, we retrieve the task record and hold on to it
1132 // without a lock before calling back in to here... so the task at this point may
1133 // not actually be in recents. Check for that, and if it isn't in recents just
1134 // consider it invalid.
1135 if (inTask != null && !inTask.inRecents) {
1136 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1137 mInTask = null;
1138 }
1139
1140 mStartFlags = startFlags;
1141 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1142 // is the same as the one making the call... or, as a special case, if we do not know
1143 // the caller then we count the current top activity as the caller.
1144 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1145 ActivityRecord checkedCaller = sourceRecord;
1146 if (checkedCaller == null) {
1147 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1148 mNotTop);
1149 }
1150 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1151 // Caller is not the same as launcher, so always needed.
1152 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1153 }
1154 }
1155
1156 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1157 }
1158
1159 private void sendNewTaskResultRequestIfNeeded() {
1160 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1161 && mStartActivity.resultTo.task.stack != null) {
1162 // For whatever reason this activity is being launched into a new task...
1163 // yet the caller has requested a result back. Well, that is pretty messed up,
1164 // so instead immediately send back a cancel and let the new task continue launched
1165 // as normal without a dependency on its originator.
1166 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1167 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1168 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1169 mStartActivity.resultTo = null;
1170 }
1171 }
1172
1173 private void computeLaunchingTaskFlags() {
1174 // If the caller is not coming from another activity, but has given us an explicit task into
1175 // which they would like us to launch the new activity, then let's see about doing that.
1176 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1177 final Intent baseIntent = mInTask.getBaseIntent();
1178 final ActivityRecord root = mInTask.getRootActivity();
1179 if (baseIntent == null) {
1180 ActivityOptions.abort(mOptions);
1181 throw new IllegalArgumentException("Launching into task without base intent: "
1182 + mInTask);
1183 }
1184
1185 // If this task is empty, then we are adding the first activity -- it
1186 // determines the root, and must be launching as a NEW_TASK.
1187 if (mLaunchSingleInstance || mLaunchSingleTask) {
1188 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1189 ActivityOptions.abort(mOptions);
1190 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1191 + mStartActivity + " into different task " + mInTask);
1192 }
1193 if (root != null) {
1194 ActivityOptions.abort(mOptions);
1195 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1196 + " has root " + root + " but target is singleInstance/Task");
1197 }
1198 }
1199
1200 // If task is empty, then adopt the interesting intent launch flags in to the
1201 // activity being started.
1202 if (root == null) {
1203 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1204 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1205 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1206 | (baseIntent.getFlags() & flagsOfInterest);
1207 mIntent.setFlags(mLaunchFlags);
1208 mInTask.setIntent(mStartActivity);
1209 mAddingToTask = true;
1210
1211 // If the task is not empty and the caller is asking to start it as the root of
1212 // a new task, then we don't actually want to start this on the task. We will
1213 // bring the task to the front, and possibly give it a new intent.
1214 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1215 mAddingToTask = false;
1216
1217 } else {
1218 mAddingToTask = true;
1219 }
1220
1221 mReuseTask = mInTask;
1222 } else {
1223 mInTask = null;
1224 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1225 // when in freeform workspace.
1226 // Also put noDisplay activities in the source task. These by itself can be placed
1227 // in any task/stack, however it could launch other activities like ResolverActivity,
1228 // and we want those to stay in the original task.
1229 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1230 && mSourceRecord.isFreeform()) {
1231 mAddingToTask = true;
1232 }
1233 }
1234
1235 if (mInTask == null) {
1236 if (mSourceRecord == null) {
1237 // This activity is not being started from another... in this
1238 // case we -always- start a new task.
1239 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1240 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1241 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1242 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1243 }
1244 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1245 // The original activity who is starting us is running as a single
1246 // instance... this new activity it is starting must go on its
1247 // own task.
1248 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1249 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1250 // The activity being started is a single instance... it always
1251 // gets launched into its own task.
1252 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1253 }
1254 }
1255 }
1256
1257 private void computeSourceStack() {
1258 if (mSourceRecord == null) {
1259 mSourceStack = null;
1260 return;
1261 }
1262 if (!mSourceRecord.finishing) {
1263 mSourceStack = mSourceRecord.task.stack;
1264 return;
1265 }
1266
1267 // If the source is finishing, we can't further count it as our source. This is because the
1268 // task it is associated with may now be empty and on its way out, so we don't want to
1269 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1270 // a task for it. But save the task information so it can be used when creating the new task.
1271 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1272 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1273 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1274 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1275 mNewTaskInfo = mSourceRecord.info;
1276 mNewTaskIntent = mSourceRecord.task.intent;
1277 }
1278 mSourceRecord = null;
1279 mSourceStack = null;
1280 }
1281
1282 /**
1283 * Decide whether the new activity should be inserted into an existing task. Returns null
1284 * if not or an ActivityRecord with the task into which the new activity should be added.
1285 */
1286 private ActivityRecord getReusableIntentActivity() {
1287 // We may want to try to place the new activity in to an existing task. We always
1288 // do this if the target activity is singleTask or singleInstance; we will also do
1289 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1290 // us to still place it in a new task: multi task, always doc mode, or being asked to
1291 // launch this as a new task behind the current one.
1292 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1293 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1294 || mLaunchSingleInstance || mLaunchSingleTask;
1295 // If bring to front is requested, and no result is requested and we have not been given
1296 // an explicit task to launch in to, and we can find a task that was started with this
1297 // same component, then instead of launching bring that one to the front.
1298 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1299 ActivityRecord intentActivity = null;
1300 if (putIntoExistingTask) {
1301 // See if there is a task to bring to the front. If this is a SINGLE_INSTANCE
1302 // activity, there can be one and only one instance of it in the history, and it is
1303 // always in its own unique task, so we do a special search.
1304 intentActivity = mLaunchSingleInstance ? mSupervisor.findActivityLocked(mIntent, mStartActivity.info)
1305 : mSupervisor.findTaskLocked(mStartActivity);
1306 }
1307 return intentActivity;
1308 }
1309
1310 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1311 mTargetStack = intentActivity.task.stack;
1312 mTargetStack.mLastPausedActivity = null;
1313 // If the target task is not in the front, then we need to bring it to the front...
1314 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1315 // the same behavior as if a new instance was being started, which means not bringing it
1316 // to the front if the caller is not itself in the front.
1317 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1318 ActivityRecord curTop = (focusStack == null)
1319 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1320
1321 if (curTop != null && (curTop.task != intentActivity.task ||
1322 curTop.task != focusStack.topTask())) {
1323 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1324 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1325 mSourceStack.topActivity().task == mSourceRecord.task)) {
1326 // We really do want to push this one into the user's face, right now.
1327 if (mLaunchTaskBehind && mSourceRecord != null) {
1328 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1329 }
1330 mMovedHome = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001331
1332 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1333 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1334 // So no point resuming any of the activities here, it just wastes one extra
1335 // resuming, plus enter AND exit transitions.
1336 // Here we only want to bring the target stack forward. Transition will be applied
1337 // to the new activity that's started after the old ones are gone.
1338 final boolean willClearTask =
1339 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1340 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1341 if (!willClearTask) {
1342 final ActivityStack launchStack = getLaunchStack(
1343 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, true);
1344 if (launchStack == null || launchStack == mTargetStack) {
1345 // We only want to move to the front, if we aren't going to launch on a
1346 // different stack. If we launch on a different stack, we will put the
1347 // task on top there.
1348 mTargetStack.moveTaskToFrontLocked(
1349 intentActivity.task, mNoAnimation, mOptions,
1350 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1351 mMovedToFront = true;
1352 }
1353 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001354 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001355 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001356 }
1357 }
1358 if (!mMovedToFront && mDoResume) {
1359 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1360 + " from " + intentActivity);
1361 mTargetStack.moveToFront("intentActivityFound");
1362 }
1363
1364 // If the caller has requested that the target task be reset, then do so.
1365 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1366 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1367 }
1368 return intentActivity;
1369 }
1370
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001371 private void updateTaskReturnToType(
1372 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1373 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1374 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1375 // Caller wants to appear on home activity.
1376 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1377 return;
1378 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1379 // Task will be launched over the home stack, so return home.
1380 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1381 return;
1382 }
1383
1384 // Else we are coming from an application stack so return to an application.
1385 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1386 }
1387
Wale Ogunwale01d66562015-12-29 08:19:19 -08001388 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1389 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1390 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1391 // The caller has requested to completely replace any existing task with its new
1392 // activity. Well that should not be too hard...
1393 mReuseTask = intentActivity.task;
1394 mReuseTask.performClearTaskLocked();
1395 mReuseTask.setIntent(mStartActivity);
1396 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1397 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001398 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1399 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001400 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001401 // A special case: we need to start the activity because it is not currently
1402 // running, and the caller has asked to clear the current task to have this
1403 // activity at the top.
1404 mAddingToTask = true;
1405 // Now pretend like this activity is being started by the top of its task, so it
1406 // is put in the right place.
1407 mSourceRecord = intentActivity;
1408 final TaskRecord task = mSourceRecord.task;
1409 if (task != null && task.stack == null) {
1410 // Target stack got cleared when we all activities were removed above.
1411 // Go ahead and reset it.
1412 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1413 null /* bounds */, mLaunchFlags, mOptions);
1414 mTargetStack.addTask(task,
1415 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1416 }
1417 }
1418 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1419 // In this case the top activity on the task is the same as the one being launched,
1420 // so we take that as a request to bring the task to the foreground. If the top
1421 // activity in the task is the root activity, deliver this new intent to it if it
1422 // desires.
1423 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1424 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001425 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001426 intentActivity.task);
1427 if (intentActivity.frontOfTask) {
1428 intentActivity.task.setIntent(mStartActivity);
1429 }
1430 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1431 mStartActivity.launchedFromPackage);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -08001432 } else if (!intentActivity.task.isSameIntentResolution(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001433 // In this case we are launching the root activity of the task, but with a
1434 // different intent. We should start a new instance on top.
1435 mAddingToTask = true;
1436 mSourceRecord = intentActivity;
1437 }
1438 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1439 // In this case an activity is being launched in to an existing task, without
1440 // resetting that task. This is typically the situation of launching an activity
1441 // from a notification or shortcut. We want to place the new activity on top of the
1442 // current task.
1443 mAddingToTask = true;
1444 mSourceRecord = intentActivity;
1445 } else if (!intentActivity.task.rootWasReset) {
1446 // In this case we are launching into an existing task that has not yet been started
1447 // from its front door. The current task has been brought to the front. Ideally,
1448 // we'd probably like to place this new task at the bottom of its stack, but that's
1449 // a little hard to do with the current organization of the code so for now we'll
1450 // just drop it.
1451 intentActivity.task.setIntent(mStartActivity);
1452 }
1453 }
1454
1455 private void resumeTargetStackIfNeeded() {
1456 if (mDoResume) {
1457 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1458 if (!mMovedToFront) {
1459 // Make sure to notify Keyguard as well if we are not running an app transition
1460 // later.
1461 mSupervisor.notifyActivityDrawnForKeyguard();
1462 }
1463 } else {
1464 ActivityOptions.abort(mOptions);
1465 }
1466 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1467 }
1468
1469 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1470 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1471 mOptions);
1472 if (mDoResume) {
1473 mTargetStack.moveToFront("startingNewTask");
1474 }
1475
1476 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001477 final TaskRecord task = mTargetStack.createTaskRecord(
1478 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001479 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1480 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1481 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1482 mStartActivity.setTask(task, taskToAffiliate);
1483 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001484 final int stackId = mTargetStack.mStackId;
1485 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Filip Gruszczynski47dae582016-02-02 11:52:13 -08001486 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001487 } else {
1488 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1489 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001490 }
1491 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1492 "Starting new activity " +
1493 mStartActivity + " in new task " + mStartActivity.task);
1494 } else {
1495 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1496 }
1497 }
1498
1499 private int setTaskFromSourceRecord() {
1500 final TaskRecord sourceTask = mSourceRecord.task;
1501 // We only want to allow changing stack if the target task is not the top one,
1502 // otherwise we would move the launching task to the other side, rather than show
1503 // two side by side.
1504 final boolean launchToSideAllowed = sourceTask.stack.topTask() != sourceTask;
1505 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, launchToSideAllowed);
1506
1507 if (mTargetStack == null) {
1508 mTargetStack = sourceTask.stack;
1509 } else if (mTargetStack != sourceTask.stack) {
1510 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1511 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1512 }
1513 if (mDoResume) {
1514 mTargetStack.moveToFront("sourceStackToFront");
1515 }
1516 final TaskRecord topTask = mTargetStack.topTask();
1517 if (topTask != sourceTask) {
1518 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1519 mStartActivity.appTimeTracker, "sourceTaskToFront");
1520 }
1521 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1522 // In this case, we are adding the activity to an existing task, but the caller has
1523 // asked to clear that task if the activity is already running.
1524 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1525 mKeepCurTransition = true;
1526 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001527 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001528 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1529 // For paranoia, make sure we have correctly resumed the top activity.
1530 mTargetStack.mLastPausedActivity = null;
1531 if (mDoResume) {
1532 mSupervisor.resumeFocusedStackTopActivityLocked();
1533 }
1534 ActivityOptions.abort(mOptions);
1535 return START_DELIVERED_TO_TOP;
1536 }
1537 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1538 // In this case, we are launching an activity in our own task that may already be
1539 // running somewhere in the history, and we want to shuffle it to the front of the
1540 // stack if so.
1541 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1542 if (top != null) {
1543 final TaskRecord task = top.task;
1544 task.moveActivityToFrontLocked(top);
1545 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001546 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001547 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1548 mTargetStack.mLastPausedActivity = null;
1549 if (mDoResume) {
1550 mSupervisor.resumeFocusedStackTopActivityLocked();
1551 }
1552 return START_DELIVERED_TO_TOP;
1553 }
1554 }
1555
1556 // An existing activity is starting this new activity, so we want to keep the new one in
1557 // the same task as the one that is starting it.
1558 mStartActivity.setTask(sourceTask, null);
1559 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1560 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1561 return START_SUCCESS;
1562 }
1563
1564 private int setTaskFromInTask() {
1565 if (mLaunchBounds != null) {
1566 mInTask.updateOverrideConfiguration(mLaunchBounds);
1567 int stackId = mInTask.getLaunchStackId();
1568 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001569 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001570 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001571 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001572 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001573 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Filip Gruszczynski47dae582016-02-02 11:52:13 -08001574 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001575 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001576 }
1577 mTargetStack = mInTask.stack;
1578 mTargetStack.moveTaskToFrontLocked(
1579 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1580
1581 // Check whether we should actually launch the new activity in to the task,
1582 // or just reuse the current activity on top.
1583 ActivityRecord top = mInTask.getTopActivity();
1584 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1585 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1586 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001587 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001588 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1589 // We don't need to start a new activity, and the client said not to do
1590 // anything if that is the case, so this is it!
1591 return START_RETURN_INTENT_TO_CALLER;
1592 }
1593 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1594 return START_DELIVERED_TO_TOP;
1595 }
1596 }
1597
1598 if (!mAddingToTask) {
1599 // We don't actually want to have this activity added to the task, so just
1600 // stop here but still tell the caller that we consumed the intent.
1601 ActivityOptions.abort(mOptions);
1602 return START_TASK_TO_FRONT;
1603 }
1604
1605 mStartActivity.setTask(mInTask, null);
1606 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1607 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1608
1609 return START_SUCCESS;
1610 }
1611
1612 private void setTaskToCurrentTopOrCreateNewTask() {
1613 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1614 mOptions);
1615 if (mDoResume) {
1616 mTargetStack.moveToFront("addingToTopTask");
1617 }
1618 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001619 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1620 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1621 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001622 mStartActivity.setTask(task, null);
1623 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1624 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1625 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1626 }
1627
1628 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1629 boolean launchSingleTask, int launchFlags) {
1630 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1631 (launchSingleInstance || launchSingleTask)) {
1632 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1633 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1634 "\"singleInstance\" or \"singleTask\"");
1635 launchFlags &=
1636 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1637 } else {
1638 switch (r.info.documentLaunchMode) {
1639 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1640 break;
1641 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1642 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1643 break;
1644 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1645 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1646 break;
1647 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1648 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1649 break;
1650 }
1651 }
1652 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001653 }
1654
1655 final void doPendingActivityLaunchesLocked(boolean doResume) {
1656 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001657 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1658 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001659 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001660 final int result = startActivityUnchecked(
1661 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1662 postStartActivityUncheckedProcessing(
1663 pal.r, result, mSupervisor.mFocusedStack.mStackId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001664 } catch (Exception e) {
1665 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1666 pal.sendErrorResult(e.getMessage());
1667 }
1668 }
1669 }
1670
1671 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001672 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001673 final TaskRecord task = r.task;
1674 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1675 return mSupervisor.mHomeStack;
1676 }
1677
Wale Ogunwale854809c2015-12-27 16:18:19 -08001678 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions, true);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001679 if (stack != null) {
1680 return stack;
1681 }
1682
1683 if (task != null && task.stack != null) {
1684 stack = task.stack;
1685 if (stack.isOnHomeDisplay()) {
1686 if (mSupervisor.mFocusedStack != stack) {
1687 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1688 "computeStackFocus: Setting " + "focused stack to r=" + r
1689 + " task=" + task);
1690 } else {
1691 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1692 "computeStackFocus: Focused stack already="
1693 + mSupervisor.mFocusedStack);
1694 }
1695 }
1696 return stack;
1697 }
1698
1699 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1700 if (container != null) {
1701 // The first time put it on the desired stack, after this put on task stack.
1702 r.mInitialActivityContainer = null;
1703 return container.mStack;
1704 }
1705
1706 // The fullscreen stack can contain any task regardless of if the task is resizeable
1707 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1708 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1709 // we can also put it in the focused stack.
1710 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001711 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1712 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1713 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001714 if (canUseFocusedStack && (!newTask
1715 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1716 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1717 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1718 return mSupervisor.mFocusedStack;
1719 }
1720
1721 // We first try to put the task in the first dynamic stack.
1722 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1723 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1724 stack = homeDisplayStacks.get(stackNdx);
1725 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1726 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1727 "computeStackFocus: Setting focused stack=" + stack);
1728 return stack;
1729 }
1730 }
1731
1732 // If there is no suitable dynamic stack then we figure out which static stack to use.
1733 final int stackId = task != null ? task.getLaunchStackId() :
1734 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1735 FULLSCREEN_WORKSPACE_STACK_ID;
1736 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1737 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1738 + r + " stackId=" + stack.mStackId);
1739 return stack;
1740 }
1741
Wale Ogunwale854809c2015-12-27 16:18:19 -08001742 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
1743 ActivityOptions aOptions, boolean launchToSideAllowed) {
1744 final int launchStackId =
1745 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1746
1747 if (isValidLaunchStackId(launchStackId, r)) {
1748 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001749 } else if (launchStackId == DOCKED_STACK_ID) {
1750 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1751 // for this activity, so we put the activity in the fullscreen stack.
1752 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001753 }
1754
Wale Ogunwale2a25a622016-01-30 11:27:21 -08001755 if (!launchToSideAllowed || (launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001756 return null;
1757 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001758
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001759 // The parent activity doesn't want to launch the activity on top of itself, but
1760 // instead tries to put it onto other side in side-by-side mode.
1761 final ActivityStack parentStack = task != null ? task.stack
1762 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1763 : mSupervisor.mFocusedStack;
1764 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
1765 // If parent was in docked stack, the natural place to launch another activity
1766 // will be fullscreen, so it can appear alongside the docked window.
1767 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
1768 } else {
1769 // If the parent is not in the docked stack, we check if there is docked window
1770 // and if yes, we will launch into that stack. If not, we just put the new
1771 // activity into parent's stack, because we can't find a better place.
1772 final ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
Wale Ogunwale8051c5c2016-03-04 10:27:32 -08001773 if (stack != null && stack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001774 // There is a docked stack, but it isn't visible, so we can't launch into that.
1775 return null;
1776 } else {
1777 return stack;
1778 }
1779 }
1780 }
1781
Wale Ogunwale854809c2015-12-27 16:18:19 -08001782 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
1783 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
1784 || !StackId.isStaticStack(stackId)) {
1785 return false;
1786 }
1787
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001788 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
1789 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
1790 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001791 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08001792
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08001793 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
1794 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08001795 }
1796
1797 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
1798 return false;
1799 }
1800
1801 final boolean supportsPip = mService.mSupportsPictureInPicture
1802 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
1803 if (stackId == PINNED_STACK_ID && !supportsPip) {
1804 return false;
1805 }
1806 return true;
1807 }
1808
Wale Ogunwale854809c2015-12-27 16:18:19 -08001809 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
1810 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001811 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08001812 if (mSupervisor.canUseActivityOptionsLaunchBounds(
1813 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001814 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08001815 }
1816 }
1817 return newBounds;
1818 }
1819
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001820 void setWindowManager(WindowManagerService wm) {
1821 mWindowManager = wm;
1822 }
1823
1824 void removePendingActivityLaunchesLocked(ActivityStack stack) {
1825 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
1826 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
1827 if (pal.stack == stack) {
1828 mPendingActivityLaunches.remove(palNdx);
1829 }
1830 }
1831 }
1832}