blob: 2ee6de2e8c38a5085db78618a712f8f88aeba2e0 [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.
419 if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
420 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
421 aInfo.packageName, userId)) {
422 IIntentSender target = mService.getIntentSenderLocked(
423 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
424 callingUid, userId, null, null, 0, new Intent[]{intent},
425 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
426 | PendingIntent.FLAG_ONE_SHOT, null);
427
428 final int flags = intent.getFlags();
429 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
430 newIntent.setFlags(flags
431 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
432 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
433 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
434 if (resultRecord != null) {
435 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
436 }
437 intent = newIntent;
438
439 resolvedType = null;
440 callingUid = realCallingUid;
441 callingPid = realCallingPid;
442
443 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
444 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
445 null /*profilerInfo*/);
446
447 if (DEBUG_PERMISSIONS_REVIEW) {
448 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
449 true, false) + "} from uid " + callingUid + " on display "
450 + (container == null ? (mSupervisor.mFocusedStack == null ?
451 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
452 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
453 container.mActivityDisplay.mDisplayId)));
454 }
455 }
456 }
457
458 // If we have an ephemeral app, abort the process of launching the resolved intent.
459 // Instead, launch the ephemeral installer. Once the installer is finished, it
460 // starts either the intent we resolved here [on install error] or the ephemeral
461 // app [on install success].
462 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700463 intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
464 rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
465 userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800466 resolvedType = null;
467 callingUid = realCallingUid;
468 callingPid = realCallingPid;
469
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800470 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
471 }
472
473 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
474 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
475 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
Wale Ogunwale1affbbc2016-05-01 09:03:52 -0700476 options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800477 if (outActivity != null) {
478 outActivity[0] = r;
479 }
480
481 if (r.appTimeTracker == null && sourceRecord != null) {
482 // If the caller didn't specify an explicit time tracker, we want to continue
483 // tracking under any it has.
484 r.appTimeTracker = sourceRecord.appTimeTracker;
485 }
486
487 final ActivityStack stack = mSupervisor.mFocusedStack;
488 if (voiceSession == null && (stack.mResumedActivity == null
489 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
490 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
491 realCallingPid, realCallingUid, "Activity start")) {
492 PendingActivityLaunch pal = new PendingActivityLaunch(r,
493 sourceRecord, startFlags, stack, callerApp);
494 mPendingActivityLaunches.add(pal);
495 ActivityOptions.abort(options);
496 return ActivityManager.START_SWITCHES_CANCELED;
497 }
498 }
499
500 if (mService.mDidAppSwitch) {
501 // This is the second allowed switch since we stopped switches,
502 // so now just generally allow switches. Use case: user presses
503 // home (switches disabled, switch to home, mDidAppSwitch now true);
504 // user taps a home icon (coming from home so allowed, we hit here
505 // and now allow anyone to switch again).
506 mService.mAppSwitchesAllowedTime = 0;
507 } else {
508 mService.mDidAppSwitch = true;
509 }
510
511 doPendingActivityLaunchesLocked(false);
512
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700513 try {
514 mService.mWindowManager.deferSurfaceLayout();
515 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
516 true, options, inTask);
517 } finally {
518 mService.mWindowManager.continueSurfaceLayout();
519 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700520 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800521 return err;
522 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800523
Todd Kennedy8e2d9d12016-06-28 14:09:55 -0700524 /**
525 * Builds and returns an intent to launch the ephemeral installer.
526 */
527 private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
528 String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
529 final Intent nonEphemeralIntent = new Intent(origIntent);
530 nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
531 // Intent that is launched if the ephemeral package couldn't be installed
532 // for any reason.
533 final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(
534 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
535 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1,
536 new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType },
537 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
538 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
539
540 final Intent ephemeralIntent;
541 if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
542 // Force the intent to be directed to the ephemeral package
543 ephemeralIntent = new Intent(origIntent);
544 ephemeralIntent.setPackage(ephemeralPackage);
545 } else {
546 // Success intent goes back to the installer
547 // TODO; do we need any extras for the installer?
548 ephemeralIntent = new Intent(launchIntent);
549 ephemeralIntent.setData(null);
550 }
551
552 // Intent that is eventually launched if the ephemeral package was
553 // installed successfully. This will actually be launched by a platform
554 // broadcast receiver.
555 final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
556 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
557 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
558 new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
559 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
560 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
561
562 // Finally build the actual intent to launch the ephemeral installer
563 int flags = launchIntent.getFlags();
564 final Intent intent = new Intent();
565 intent.setFlags(flags
566 | Intent.FLAG_ACTIVITY_NEW_TASK
567 | Intent.FLAG_ACTIVITY_CLEAR_TASK
568 | Intent.FLAG_ACTIVITY_NO_HISTORY
569 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
570 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
571 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
572 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
573 // TODO: Remove when the platform has fully implemented ephemeral apps
574 intent.setData(origIntent.getData());
575 return intent;
576 }
577
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800578 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700579 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
580 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800581
582 if (result < START_SUCCESS) {
583 // If someone asked to have the keyguard dismissed on the next activity start,
584 // but we are not actually doing an activity switch... just dismiss the keyguard now,
585 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800586 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800587 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800588 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800589
Chong Zhang5022da32016-06-21 16:31:37 -0700590 // We're waiting for an activity launch to finish, but that activity simply
591 // brought another activity to front. Let startActivityMayWait() know about
592 // this, so it waits for the new activity to become visible instead.
593 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
594 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
595 }
596
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800597 int startedActivityStackId = INVALID_STACK_ID;
598 if (r.task != null && r.task.stack != null) {
599 startedActivityStackId = r.task.stack.mStackId;
600 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700601 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800602 }
603
Jorim Jaggi352d5842016-05-19 10:20:28 -0700604 // If we launched the activity from a no display activity that was launched from the home
605 // screen, we also need to start recents to un-minimize the docked stack, since the
606 // noDisplay activity will be finished shortly after.
607 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
608 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700609 final boolean noDisplayActivityOverHome = sourceRecord != null
610 && sourceRecord.noDisplay
611 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700612 if (startedActivityStackId == DOCKED_STACK_ID
613 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100614 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
615 final ActivityRecord topActivityHomeStack = homeStack != null
616 ? homeStack.topRunningActivityLocked() : null;
617 if (topActivityHomeStack == null
618 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
619 // We launch an activity while being in home stack, which means either launcher or
620 // recents into docked stack. We don't want the launched activity to be alone in a
621 // docked stack, so we want to immediately launch recents too.
622 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700623 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100624 return;
625 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800626 }
627
628 if (startedActivityStackId == PINNED_STACK_ID
629 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
630 // The activity was already running in the pinned stack so it wasn't started, but either
631 // brought to the front or the new intent was delivered to it since it was already in
632 // front. Notify anyone interested in this piece of information.
633 mService.notifyPinnedActivityRestartAttemptLocked();
634 return;
635 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800636 }
637
638 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
639 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
640 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
641 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
642 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
643 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
644 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700645 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800646 null /*container*/, null /*inTask*/);
647 if (mSupervisor.inResumeTopActivity) {
648 // If we are in resume section already, home activity will be initialized, but not
649 // resumed (to avoid recursive resume) and will stay that way until something pokes it
650 // again. We need to schedule another resume.
651 mSupervisor.scheduleResumeTopActivities();
652 }
653 }
654
Tony Mak853304c2016-04-18 15:17:41 +0100655 void showConfirmDeviceCredential(int userId) {
656 // First, retrieve the stack that we want to resume after credential is confirmed.
657 ActivityStack targetStack;
658 ActivityStack fullscreenStack =
659 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
660 if (fullscreenStack != null &&
661 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
662 // Single window case and the case that the docked stack is shown with fullscreen stack.
663 targetStack = fullscreenStack;
664 } else {
665 // The case that the docked stack is shown with recent.
666 targetStack = mSupervisor.getStack(HOME_STACK_ID);
667 }
668 if (targetStack == null) {
669 return;
670 }
671 final KeyguardManager km = (KeyguardManager) mService.mContext
672 .getSystemService(Context.KEYGUARD_SERVICE);
673 final Intent credential =
674 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100675 // For safety, check null here in case users changed the setting after the checking.
676 if (credential == null) {
677 return;
678 }
Tony Mak853304c2016-04-18 15:17:41 +0100679 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
680 if (activityRecord != null) {
681 final IIntentSender target = mService.getIntentSenderLocked(
682 ActivityManager.INTENT_SENDER_ACTIVITY,
683 activityRecord.launchedFromPackage,
684 activityRecord.launchedFromUid,
685 activityRecord.userId,
686 null, null, 0,
687 new Intent[] { activityRecord.intent },
688 new String[] { activityRecord.resolvedType },
689 PendingIntent.FLAG_CANCEL_CURRENT |
690 PendingIntent.FLAG_ONE_SHOT |
691 PendingIntent.FLAG_IMMUTABLE,
692 null);
693 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
694 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100695 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100696 }
697 }
698
Tony Mak646fe992016-04-21 16:43:08 +0100699 void startConfirmCredentialIntent(Intent intent) {
700 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
701 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
702 FLAG_ACTIVITY_TASK_ON_HOME);
703 final ActivityOptions options = ActivityOptions.makeBasic();
704 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
705 mService.mContext.startActivityAsUser(intent, options.toBundle(),
706 UserHandle.CURRENT);
707 }
Tony Mak853304c2016-04-18 15:17:41 +0100708
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800709 final int startActivityMayWait(IApplicationThread caller, int callingUid,
710 String callingPackage, Intent intent, String resolvedType,
711 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
712 IBinder resultTo, String resultWho, int requestCode, int startFlags,
713 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
714 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
715 IActivityContainer iContainer, TaskRecord inTask) {
716 // Refuse possible leaked file descriptors
717 if (intent != null && intent.hasFileDescriptors()) {
718 throw new IllegalArgumentException("File descriptors passed in Intent");
719 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500720 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800721 boolean componentSpecified = intent.getComponent() != null;
722
723 // Save a copy in case ephemeral needs it
724 final Intent ephemeralIntent = new Intent(intent);
725 // Don't modify the client's object!
726 intent = new Intent(intent);
727
728 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000729 if (rInfo == null) {
730 UserInfo userInfo = mSupervisor.getUserInfo(userId);
731 if (userInfo != null && userInfo.isManagedProfile()) {
732 // Special case for managed profiles, if attempting to launch non-cryto aware
733 // app in a locked managed profile from an unlocked parent allow it to resolve
734 // as user will be sent via confirm credentials to unlock the profile.
735 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700736 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000737 long token = Binder.clearCallingIdentity();
738 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700739 UserInfo parent = userManager.getProfileParent(userId);
740 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
741 && userManager.isUserUnlockingOrUnlocked(parent.id)
742 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000743 } finally {
744 Binder.restoreCallingIdentity(token);
745 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700746 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000747 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600748 PackageManager.MATCH_DIRECT_BOOT_AWARE
749 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000750 }
751 }
752 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800753 // Collect information about the target of the Intent.
754 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
755
756 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
757 ActivityStackSupervisor.ActivityContainer container =
758 (ActivityStackSupervisor.ActivityContainer)iContainer;
759 synchronized (mService) {
760 if (container != null && container.mParentActivity != null &&
761 container.mParentActivity.state != RESUMED) {
762 // Cannot start a child activity if the parent is not resumed.
763 return ActivityManager.START_CANCELED;
764 }
765 final int realCallingPid = Binder.getCallingPid();
766 final int realCallingUid = Binder.getCallingUid();
767 int callingPid;
768 if (callingUid >= 0) {
769 callingPid = -1;
770 } else if (caller == null) {
771 callingPid = realCallingPid;
772 callingUid = realCallingUid;
773 } else {
774 callingPid = callingUid = -1;
775 }
776
777 final ActivityStack stack;
778 if (container == null || container.mStack.isOnHomeDisplay()) {
779 stack = mSupervisor.mFocusedStack;
780 } else {
781 stack = container.mStack;
782 }
783 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
784 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
785 "Starting activity when config will change = " + stack.mConfigWillChange);
786
787 final long origId = Binder.clearCallingIdentity();
788
789 if (aInfo != null &&
790 (aInfo.applicationInfo.privateFlags
791 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
792 // This may be a heavy-weight process! Check to see if we already
793 // have another, different heavy-weight process running.
794 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
795 final ProcessRecord heavy = mService.mHeavyWeightProcess;
796 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
797 || !heavy.processName.equals(aInfo.processName))) {
798 int appCallingUid = callingUid;
799 if (caller != null) {
800 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
801 if (callerApp != null) {
802 appCallingUid = callerApp.info.uid;
803 } else {
804 Slog.w(TAG, "Unable to find app for caller " + caller
805 + " (pid=" + callingPid + ") when starting: "
806 + intent.toString());
807 ActivityOptions.abort(options);
808 return ActivityManager.START_PERMISSION_DENIED;
809 }
810 }
811
812 IIntentSender target = mService.getIntentSenderLocked(
813 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
814 appCallingUid, userId, null, null, 0, new Intent[] { intent },
815 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
816 | PendingIntent.FLAG_ONE_SHOT, null);
817
818 Intent newIntent = new Intent();
819 if (requestCode >= 0) {
820 // Caller is requesting a result.
821 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
822 }
823 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
824 new IntentSender(target));
825 if (heavy.activities.size() > 0) {
826 ActivityRecord hist = heavy.activities.get(0);
827 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
828 hist.packageName);
829 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
830 hist.task.taskId);
831 }
832 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
833 aInfo.packageName);
834 newIntent.setFlags(intent.getFlags());
835 newIntent.setClassName("android",
836 HeavyWeightSwitcherActivity.class.getName());
837 intent = newIntent;
838 resolvedType = null;
839 caller = null;
840 callingUid = Binder.getCallingUid();
841 callingPid = Binder.getCallingPid();
842 componentSpecified = true;
843 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
844 aInfo = rInfo != null ? rInfo.activityInfo : null;
845 if (aInfo != null) {
846 aInfo = mService.getActivityInfoForUser(aInfo, userId);
847 }
848 }
849 }
850 }
851
Jorim Jaggi275561a2016-02-23 10:11:02 -0500852 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800853 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
854 aInfo, rInfo, voiceSession, voiceInteractor,
855 resultTo, resultWho, requestCode, callingPid,
856 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500857 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
858 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800859
860 Binder.restoreCallingIdentity(origId);
861
862 if (stack.mConfigWillChange) {
863 // If the caller also wants to switch to a new configuration,
864 // do so now. This allows a clean switch, as we are waiting
865 // for the current activity to pause (so we will not destroy
866 // it), and have not yet started the next activity.
867 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
868 "updateConfiguration()");
869 stack.mConfigWillChange = false;
870 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
871 "Updating to new configuration after starting activity.");
872 mService.updateConfigurationLocked(config, null, false);
873 }
874
875 if (outResult != null) {
876 outResult.result = res;
877 if (res == ActivityManager.START_SUCCESS) {
878 mSupervisor.mWaitingActivityLaunched.add(outResult);
879 do {
880 try {
881 mService.wait();
882 } catch (InterruptedException e) {
883 }
Chong Zhang5022da32016-06-21 16:31:37 -0700884 } while (outResult.result != START_TASK_TO_FRONT
885 && !outResult.timeout && outResult.who == null);
886 if (outResult.result == START_TASK_TO_FRONT) {
887 res = START_TASK_TO_FRONT;
888 }
889 }
890 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800891 ActivityRecord r = stack.topRunningActivityLocked();
892 if (r.nowVisible && r.state == RESUMED) {
893 outResult.timeout = false;
894 outResult.who = new ComponentName(r.info.packageName, r.info.name);
895 outResult.totalTime = 0;
896 outResult.thisTime = 0;
897 } else {
898 outResult.thisTime = SystemClock.uptimeMillis();
899 mSupervisor.mWaitingActivityVisible.add(outResult);
900 do {
901 try {
902 mService.wait();
903 } catch (InterruptedException e) {
904 }
905 } while (!outResult.timeout && outResult.who == null);
906 }
907 }
908 }
909
Jorim Jaggibe67c902016-04-12 00:53:16 -0700910 final ActivityRecord launchedActivity = mReusedActivity != null
911 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700912 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800913 return res;
914 }
915 }
916
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800917 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
918 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
919 Bundle bOptions, int userId) {
920 if (intents == null) {
921 throw new NullPointerException("intents is null");
922 }
923 if (resolvedTypes == null) {
924 throw new NullPointerException("resolvedTypes is null");
925 }
926 if (intents.length != resolvedTypes.length) {
927 throw new IllegalArgumentException("intents are length different than resolvedTypes");
928 }
929
930
931 int callingPid;
932 if (callingUid >= 0) {
933 callingPid = -1;
934 } else if (caller == null) {
935 callingPid = Binder.getCallingPid();
936 callingUid = Binder.getCallingUid();
937 } else {
938 callingPid = callingUid = -1;
939 }
940 final long origId = Binder.clearCallingIdentity();
941 try {
942 synchronized (mService) {
943 ActivityRecord[] outActivity = new ActivityRecord[1];
944 for (int i=0; i<intents.length; i++) {
945 Intent intent = intents[i];
946 if (intent == null) {
947 continue;
948 }
949
950 // Refuse possible leaked file descriptors
951 if (intent != null && intent.hasFileDescriptors()) {
952 throw new IllegalArgumentException("File descriptors passed in Intent");
953 }
954
955 boolean componentSpecified = intent.getComponent() != null;
956
957 // Don't modify the client's object!
958 intent = new Intent(intent);
959
960 // Collect information about the target of the Intent.
961 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
962 null, userId);
963 // TODO: New, check if this is correct
964 aInfo = mService.getActivityInfoForUser(aInfo, userId);
965
966 if (aInfo != null &&
967 (aInfo.applicationInfo.privateFlags
968 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
969 throw new IllegalArgumentException(
970 "FLAG_CANT_SAVE_STATE not supported here");
971 }
972
973 ActivityOptions options = ActivityOptions.fromBundle(
974 i == intents.length - 1 ? bOptions : null);
975 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
976 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
977 callingPid, callingUid, callingPackage, callingPid, callingUid, 0,
978 options, false, componentSpecified, outActivity, null, null);
979 if (res < 0) {
980 return res;
981 }
982
983 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
984 }
985 }
986 } finally {
987 Binder.restoreCallingIdentity(origId);
988 }
989
Wale Ogunwale01d66562015-12-29 08:19:19 -0800990 return START_SUCCESS;
991 }
992
Wei Wang65c7a152016-06-02 18:51:22 -0700993 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
994 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -0700995 final ActivityStack focusStack = mSupervisor.getFocusedStack();
996 final ActivityRecord curTop = (focusStack == null)
997 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
998 if ((forceSend || (!mPowerHintSent && curTop != null &&
999 curTop.task != null && mStartActivity != null &&
1000 curTop.task != mStartActivity.task )) &&
1001 mService.mLocalPowerManager != null) {
Wei Wang65c7a152016-06-02 18:51:22 -07001002 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -07001003 mPowerHintSent = true;
1004 }
1005 }
1006
Wei Wang65c7a152016-06-02 18:51:22 -07001007 void sendPowerHintForLaunchEndIfNeeded() {
1008 // Trigger launch power hint if activity is launched
1009 if (mPowerHintSent && mService.mLocalPowerManager != null) {
1010 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
1011 mPowerHintSent = false;
1012 }
1013 }
1014
Wale Ogunwale01d66562015-12-29 08:19:19 -08001015 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1016 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1017 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1018
1019 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1020 voiceInteractor);
1021
1022 computeLaunchingTaskFlags();
1023
1024 computeSourceStack();
1025
1026 mIntent.setFlags(mLaunchFlags);
1027
Jorim Jaggibe67c902016-04-12 00:53:16 -07001028 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001029
Jorim Jaggi2adba072016-03-03 13:43:39 +01001030 final int preferredLaunchStackId =
1031 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1032
Jorim Jaggibe67c902016-04-12 00:53:16 -07001033 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001034 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1035 // still needs to be a lock task mode violation since the task gets cleared out and
1036 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001037 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001038 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1039 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1040 mSupervisor.showLockTaskToast();
1041 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1042 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1043 }
1044
1045 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001046 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001047 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001048 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001049 // This task was started because of movement of the activity based on affinity...
1050 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001051 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001052 }
1053
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001054 // This code path leads to delivering a new intent, we want to make sure we schedule it
1055 // as the first operation, in case the activity will be resumed as a result of later
1056 // operations.
1057 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001058 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001059 || mLaunchSingleInstance || mLaunchSingleTask) {
1060 // In this situation we want to remove all activities from the task up to the one
1061 // being started. In most cases this means we are resetting the task to its initial
1062 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001063 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001064 mStartActivity, mLaunchFlags);
1065 if (top != null) {
1066 if (top.frontOfTask) {
1067 // Activity aliases may mean we use different intents for the top activity,
1068 // so make sure the task now has the identity of the new intent.
1069 top.task.setIntent(mStartActivity);
1070 }
1071 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
1072 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1073 mStartActivity.launchedFromPackage);
1074 }
1075 }
1076
Wei Wang65c7a152016-06-02 18:51:22 -07001077 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001078
Jorim Jaggibe67c902016-04-12 00:53:16 -07001079 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001080
1081 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1082 // We don't need to start a new activity, and the client said not to do anything
1083 // if that is the case, so this is it! And for paranoia, make sure we have
1084 // correctly resumed the top activity.
1085 resumeTargetStackIfNeeded();
1086 return START_RETURN_INTENT_TO_CALLER;
1087 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001088 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001089
1090 if (!mAddingToTask && mReuseTask == null) {
1091 // We didn't do anything... but it was needed (a.k.a., client don't use that
1092 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1093 resumeTargetStackIfNeeded();
1094 return START_TASK_TO_FRONT;
1095 }
1096 }
1097
1098 if (mStartActivity.packageName == null) {
1099 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1100 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1101 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1102 mStartActivity.requestCode, RESULT_CANCELED, null);
1103 }
1104 ActivityOptions.abort(mOptions);
1105 return START_CLASS_NOT_FOUND;
1106 }
1107
1108 // If the activity being launched is the same as the one currently at the top, then
1109 // we need to check if it should only be launched once.
1110 final ActivityStack topStack = mSupervisor.mFocusedStack;
1111 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1112 final boolean dontStart = top != null && mStartActivity.resultTo == null
1113 && top.realActivity.equals(mStartActivity.realActivity)
1114 && top.userId == mStartActivity.userId
1115 && top.app != null && top.app.thread != null
1116 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1117 || mLaunchSingleTop || mLaunchSingleTask);
1118 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001119 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001120 // For paranoia, make sure we have correctly resumed the top activity.
1121 topStack.mLastPausedActivity = null;
1122 if (mDoResume) {
1123 mSupervisor.resumeFocusedStackTopActivityLocked();
1124 }
1125 ActivityOptions.abort(mOptions);
1126 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1127 // We don't need to start a new activity, and the client said not to do
1128 // anything if that is the case, so this is it!
1129 return START_RETURN_INTENT_TO_CALLER;
1130 }
1131 top.deliverNewIntentLocked(
1132 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001133
1134 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1135 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1136 mSupervisor.handleNonResizableTaskIfNeeded(
1137 top.task, preferredLaunchStackId, topStack.mStackId);
1138
Wale Ogunwale01d66562015-12-29 08:19:19 -08001139 return START_DELIVERED_TO_TOP;
1140 }
1141
1142 boolean newTask = false;
1143 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1144 ? mSourceRecord.task : null;
1145
1146 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001147 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001148 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1149 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1150 newTask = true;
Chong Zhang6cda19c2016-06-14 19:07:56 -07001151 result = setTaskFromReuseOrCreateNewTask(
1152 taskToAffiliate, preferredLaunchStackId, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001153 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001154 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001155 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001156 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001157 } else {
1158 // This not being started from an existing activity, and not part of a new task...
1159 // just put it in the top task, though these days this case should never happen.
1160 setTaskToCurrentTopOrCreateNewTask();
1161 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001162 if (result != START_SUCCESS) {
1163 return result;
1164 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001165
1166 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1167 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1168
1169 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1170 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1171 }
1172 if (newTask) {
1173 EventLog.writeEvent(
1174 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1175 }
1176 ActivityStack.logStartActivity(
1177 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1178 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001179
Wei Wang65c7a152016-06-02 18:51:22 -07001180 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001181
Wale Ogunwale01d66562015-12-29 08:19:19 -08001182 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1183 if (mDoResume) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001184 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1185 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001186 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1187 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001188 // If the activity is not focusable, we can't resume it, but still would like to
1189 // make sure it becomes visible as it starts (this will also trigger entry
1190 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001191 // Also, we don't want to resume activities in a task that currently has an overlay
1192 // as the starting activity just needs to be in the visible paused state until the
1193 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001194 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001195 // Go ahead and tell window manager to execute app transition for this activity
1196 // since the app transition will not be triggered through the resume channel.
1197 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001198 } else {
1199 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1200 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001201 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001202 } else {
1203 mTargetStack.addRecentActivityLocked(mStartActivity);
1204 }
1205 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1206
Jorim Jaggid53f0922016-04-06 22:16:23 -07001207 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001208 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001209
1210 return START_SUCCESS;
1211 }
1212
1213 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1214 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1215 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1216 reset();
1217
1218 mStartActivity = r;
1219 mIntent = r.intent;
1220 mOptions = options;
1221 mCallingUid = r.launchedFromUid;
1222 mSourceRecord = sourceRecord;
1223 mVoiceSession = voiceSession;
1224 mVoiceInteractor = voiceInteractor;
1225
1226 mLaunchBounds = getOverrideBounds(r, options, inTask);
1227
1228 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1229 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1230 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1231 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1232 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1233 mLaunchTaskBehind = r.mLaunchTaskBehind
1234 && !mLaunchSingleTask && !mLaunchSingleInstance
1235 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1236
1237 sendNewTaskResultRequestIfNeeded();
1238
1239 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1240 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1241 }
1242
1243 // If we are actually going to launch in to a new task, there are some cases where
1244 // we further want to do multiple task.
1245 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1246 if (mLaunchTaskBehind
1247 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1248 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1249 }
1250 }
1251
1252 // We'll invoke onUserLeaving before onPause only if the launching
1253 // activity did not explicitly state that this is an automated launch.
1254 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1255 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1256 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1257
1258 // If the caller has asked not to resume at this point, we make note
1259 // of this in the record so that we can skip it when trying to find
1260 // the top running activity.
1261 mDoResume = doResume;
1262 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1263 r.delayedResume = true;
1264 mDoResume = false;
1265 }
1266
Wale Ogunwale3b232392016-05-13 15:37:13 -07001267 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1268 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001269 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1270 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1271 if (top != null && !top.visible) {
1272
1273 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1274 // it!
1275 mDoResume = false;
1276 mAvoidMoveToFront = true;
1277 }
1278 }
1279
Wale Ogunwale01d66562015-12-29 08:19:19 -08001280 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1281
1282 mInTask = inTask;
1283 // In some flows in to this function, we retrieve the task record and hold on to it
1284 // without a lock before calling back in to here... so the task at this point may
1285 // not actually be in recents. Check for that, and if it isn't in recents just
1286 // consider it invalid.
1287 if (inTask != null && !inTask.inRecents) {
1288 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1289 mInTask = null;
1290 }
1291
1292 mStartFlags = startFlags;
1293 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1294 // is the same as the one making the call... or, as a special case, if we do not know
1295 // the caller then we count the current top activity as the caller.
1296 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1297 ActivityRecord checkedCaller = sourceRecord;
1298 if (checkedCaller == null) {
1299 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1300 mNotTop);
1301 }
1302 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1303 // Caller is not the same as launcher, so always needed.
1304 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1305 }
1306 }
1307
1308 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1309 }
1310
1311 private void sendNewTaskResultRequestIfNeeded() {
1312 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1313 && mStartActivity.resultTo.task.stack != null) {
1314 // For whatever reason this activity is being launched into a new task...
1315 // yet the caller has requested a result back. Well, that is pretty messed up,
1316 // so instead immediately send back a cancel and let the new task continue launched
1317 // as normal without a dependency on its originator.
1318 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1319 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1320 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1321 mStartActivity.resultTo = null;
1322 }
1323 }
1324
1325 private void computeLaunchingTaskFlags() {
1326 // If the caller is not coming from another activity, but has given us an explicit task into
1327 // which they would like us to launch the new activity, then let's see about doing that.
1328 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1329 final Intent baseIntent = mInTask.getBaseIntent();
1330 final ActivityRecord root = mInTask.getRootActivity();
1331 if (baseIntent == null) {
1332 ActivityOptions.abort(mOptions);
1333 throw new IllegalArgumentException("Launching into task without base intent: "
1334 + mInTask);
1335 }
1336
1337 // If this task is empty, then we are adding the first activity -- it
1338 // determines the root, and must be launching as a NEW_TASK.
1339 if (mLaunchSingleInstance || mLaunchSingleTask) {
1340 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1341 ActivityOptions.abort(mOptions);
1342 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1343 + mStartActivity + " into different task " + mInTask);
1344 }
1345 if (root != null) {
1346 ActivityOptions.abort(mOptions);
1347 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1348 + " has root " + root + " but target is singleInstance/Task");
1349 }
1350 }
1351
1352 // If task is empty, then adopt the interesting intent launch flags in to the
1353 // activity being started.
1354 if (root == null) {
1355 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1356 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1357 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1358 | (baseIntent.getFlags() & flagsOfInterest);
1359 mIntent.setFlags(mLaunchFlags);
1360 mInTask.setIntent(mStartActivity);
1361 mAddingToTask = true;
1362
1363 // If the task is not empty and the caller is asking to start it as the root of
1364 // a new task, then we don't actually want to start this on the task. We will
1365 // bring the task to the front, and possibly give it a new intent.
1366 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1367 mAddingToTask = false;
1368
1369 } else {
1370 mAddingToTask = true;
1371 }
1372
1373 mReuseTask = mInTask;
1374 } else {
1375 mInTask = null;
1376 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1377 // when in freeform workspace.
1378 // Also put noDisplay activities in the source task. These by itself can be placed
1379 // in any task/stack, however it could launch other activities like ResolverActivity,
1380 // and we want those to stay in the original task.
1381 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1382 && mSourceRecord.isFreeform()) {
1383 mAddingToTask = true;
1384 }
1385 }
1386
1387 if (mInTask == null) {
1388 if (mSourceRecord == null) {
1389 // This activity is not being started from another... in this
1390 // case we -always- start a new task.
1391 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1392 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1393 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1394 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1395 }
1396 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1397 // The original activity who is starting us is running as a single
1398 // instance... this new activity it is starting must go on its
1399 // own task.
1400 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1401 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1402 // The activity being started is a single instance... it always
1403 // gets launched into its own task.
1404 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1405 }
1406 }
1407 }
1408
1409 private void computeSourceStack() {
1410 if (mSourceRecord == null) {
1411 mSourceStack = null;
1412 return;
1413 }
1414 if (!mSourceRecord.finishing) {
1415 mSourceStack = mSourceRecord.task.stack;
1416 return;
1417 }
1418
1419 // If the source is finishing, we can't further count it as our source. This is because the
1420 // task it is associated with may now be empty and on its way out, so we don't want to
1421 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1422 // a task for it. But save the task information so it can be used when creating the new task.
1423 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1424 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1425 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1426 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1427 mNewTaskInfo = mSourceRecord.info;
1428 mNewTaskIntent = mSourceRecord.task.intent;
1429 }
1430 mSourceRecord = null;
1431 mSourceStack = null;
1432 }
1433
1434 /**
1435 * Decide whether the new activity should be inserted into an existing task. Returns null
1436 * if not or an ActivityRecord with the task into which the new activity should be added.
1437 */
1438 private ActivityRecord getReusableIntentActivity() {
1439 // We may want to try to place the new activity in to an existing task. We always
1440 // do this if the target activity is singleTask or singleInstance; we will also do
1441 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1442 // us to still place it in a new task: multi task, always doc mode, or being asked to
1443 // launch this as a new task behind the current one.
1444 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1445 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1446 || mLaunchSingleInstance || mLaunchSingleTask;
1447 // If bring to front is requested, and no result is requested and we have not been given
1448 // an explicit task to launch in to, and we can find a task that was started with this
1449 // same component, then instead of launching bring that one to the front.
1450 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1451 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001452 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1453 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1454 intentActivity = task != null ? task.getTopActivity() : null;
1455 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001456 if (mLaunchSingleInstance) {
1457 // There can be one and only one instance of single instance activity in the
1458 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001459 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001460 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1461 // For the launch adjacent case we only want to put the activity in an existing
1462 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001463 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1464 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001465 } else {
1466 // Otherwise find the best task to put the activity in.
1467 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1468 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001469 }
1470 return intentActivity;
1471 }
1472
1473 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1474 mTargetStack = intentActivity.task.stack;
1475 mTargetStack.mLastPausedActivity = null;
1476 // If the target task is not in the front, then we need to bring it to the front...
1477 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1478 // the same behavior as if a new instance was being started, which means not bringing it
1479 // to the front if the caller is not itself in the front.
1480 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1481 ActivityRecord curTop = (focusStack == null)
1482 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1483
Jorim Jaggic875ae72016-04-26 22:41:06 -07001484 if (curTop != null
1485 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1486 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001487 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1488 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1489 mSourceStack.topActivity().task == mSourceRecord.task)) {
1490 // We really do want to push this one into the user's face, right now.
1491 if (mLaunchTaskBehind && mSourceRecord != null) {
1492 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1493 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001494 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001495
1496 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1497 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1498 // So no point resuming any of the activities here, it just wastes one extra
1499 // resuming, plus enter AND exit transitions.
1500 // Here we only want to bring the target stack forward. Transition will be applied
1501 // to the new activity that's started after the old ones are gone.
1502 final boolean willClearTask =
1503 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1504 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1505 if (!willClearTask) {
1506 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001507 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001508 if (launchStack == null || launchStack == mTargetStack) {
1509 // We only want to move to the front, if we aren't going to launch on a
1510 // different stack. If we launch on a different stack, we will put the
1511 // task on top there.
1512 mTargetStack.moveTaskToFrontLocked(
1513 intentActivity.task, mNoAnimation, mOptions,
1514 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1515 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001516 } else if (launchStack.mStackId == DOCKED_STACK_ID
1517 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1518 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1519 // If we want to launch adjacent and mTargetStack is not the computed
1520 // launch stack - move task to top of computed stack.
1521 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1522 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1523 ANIMATE);
1524 } else {
1525 // TODO: This should be reevaluated in MW v2.
1526 // We choose to move task to front instead of launching it adjacent
1527 // when specific stack was requested explicitly and it appeared to be
1528 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1529 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1530 mOptions, mStartActivity.appTimeTracker,
1531 "bringToFrontInsteadOfAdjacentLaunch");
1532 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001533 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001534 }
1535 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001536 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001537 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001538 }
1539 }
1540 if (!mMovedToFront && mDoResume) {
1541 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1542 + " from " + intentActivity);
1543 mTargetStack.moveToFront("intentActivityFound");
1544 }
1545
Jorim Jaggid53f0922016-04-06 22:16:23 -07001546 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1547 mTargetStack.mStackId);
1548
Wale Ogunwale01d66562015-12-29 08:19:19 -08001549 // If the caller has requested that the target task be reset, then do so.
1550 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1551 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1552 }
1553 return intentActivity;
1554 }
1555
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001556 private void updateTaskReturnToType(
1557 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1558 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1559 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1560 // Caller wants to appear on home activity.
1561 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1562 return;
1563 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1564 // Task will be launched over the home stack, so return home.
1565 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1566 return;
1567 }
1568
1569 // Else we are coming from an application stack so return to an application.
1570 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1571 }
1572
Wale Ogunwale01d66562015-12-29 08:19:19 -08001573 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1574 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1575 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1576 // The caller has requested to completely replace any existing task with its new
1577 // activity. Well that should not be too hard...
1578 mReuseTask = intentActivity.task;
1579 mReuseTask.performClearTaskLocked();
1580 mReuseTask.setIntent(mStartActivity);
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001581 // When we clear the task - focus will be adjusted, which will bring another task
1582 // to top before we launch the activity we need. This will temporary swap their
1583 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1584 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001585 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1586 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001587 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1588 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001589 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001590 // A special case: we need to start the activity because it is not currently
1591 // running, and the caller has asked to clear the current task to have this
1592 // activity at the top.
1593 mAddingToTask = true;
1594 // Now pretend like this activity is being started by the top of its task, so it
1595 // is put in the right place.
1596 mSourceRecord = intentActivity;
1597 final TaskRecord task = mSourceRecord.task;
1598 if (task != null && task.stack == null) {
1599 // Target stack got cleared when we all activities were removed above.
1600 // Go ahead and reset it.
1601 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1602 null /* bounds */, mLaunchFlags, mOptions);
1603 mTargetStack.addTask(task,
1604 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1605 }
1606 }
1607 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1608 // In this case the top activity on the task is the same as the one being launched,
1609 // so we take that as a request to bring the task to the foreground. If the top
1610 // activity in the task is the root activity, deliver this new intent to it if it
1611 // desires.
1612 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1613 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001614 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001615 intentActivity.task);
1616 if (intentActivity.frontOfTask) {
1617 intentActivity.task.setIntent(mStartActivity);
1618 }
1619 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1620 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001621 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001622 // In this case we are launching the root activity of the task, but with a
1623 // different intent. We should start a new instance on top.
1624 mAddingToTask = true;
1625 mSourceRecord = intentActivity;
1626 }
1627 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1628 // In this case an activity is being launched in to an existing task, without
1629 // resetting that task. This is typically the situation of launching an activity
1630 // from a notification or shortcut. We want to place the new activity on top of the
1631 // current task.
1632 mAddingToTask = true;
1633 mSourceRecord = intentActivity;
1634 } else if (!intentActivity.task.rootWasReset) {
1635 // In this case we are launching into an existing task that has not yet been started
1636 // from its front door. The current task has been brought to the front. Ideally,
1637 // we'd probably like to place this new task at the bottom of its stack, but that's
1638 // a little hard to do with the current organization of the code so for now we'll
1639 // just drop it.
1640 intentActivity.task.setIntent(mStartActivity);
1641 }
1642 }
1643
1644 private void resumeTargetStackIfNeeded() {
1645 if (mDoResume) {
1646 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1647 if (!mMovedToFront) {
1648 // Make sure to notify Keyguard as well if we are not running an app transition
1649 // later.
1650 mSupervisor.notifyActivityDrawnForKeyguard();
1651 }
1652 } else {
1653 ActivityOptions.abort(mOptions);
1654 }
1655 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1656 }
1657
Chong Zhang6cda19c2016-06-14 19:07:56 -07001658 private int setTaskFromReuseOrCreateNewTask(
1659 TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
1660 mTargetStack = computeStackFocus(
1661 mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
1662
1663 // Do no move the target stack to front yet, as we might bail if
1664 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001665
1666 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001667 final TaskRecord task = mTargetStack.createTaskRecord(
1668 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001669 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1670 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1671 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1672 mStartActivity.setTask(task, taskToAffiliate);
1673 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001674 final int stackId = mTargetStack.mStackId;
1675 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001676 mService.resizeStack(
1677 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001678 } else {
1679 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1680 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001681 }
1682 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1683 "Starting new activity " +
1684 mStartActivity + " in new task " + mStartActivity.task);
1685 } else {
1686 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1687 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001688
1689 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1690 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1691 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1692 }
1693
1694 if (!mMovedOtherTask) {
1695 // If stack id is specified in activity options, usually it means that activity is
1696 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1697 // that case we check the target stack.
1698 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1699 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
1700 }
1701 if (mDoResume) {
1702 mTargetStack.moveToFront("reuseOrNewTask");
1703 }
1704 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001705 }
1706
1707 private int setTaskFromSourceRecord() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001708 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1709 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1710 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1711 }
1712
Wale Ogunwale01d66562015-12-29 08:19:19 -08001713 final TaskRecord sourceTask = mSourceRecord.task;
1714 // We only want to allow changing stack if the target task is not the top one,
1715 // otherwise we would move the launching task to the other side, rather than show
1716 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001717 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1718 if (moveStackAllowed) {
1719 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1720 mOptions);
1721 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001722
1723 if (mTargetStack == null) {
1724 mTargetStack = sourceTask.stack;
1725 } else if (mTargetStack != sourceTask.stack) {
1726 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1727 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1728 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001729
Wale Ogunwale01d66562015-12-29 08:19:19 -08001730 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001731 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001732 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1733 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07001734 } else if (mDoResume) {
1735 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08001736 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001737
Wale Ogunwale01d66562015-12-29 08:19:19 -08001738 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1739 // In this case, we are adding the activity to an existing task, but the caller has
1740 // asked to clear that task if the activity is already running.
1741 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1742 mKeepCurTransition = true;
1743 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001744 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001745 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1746 // For paranoia, make sure we have correctly resumed the top activity.
1747 mTargetStack.mLastPausedActivity = null;
1748 if (mDoResume) {
1749 mSupervisor.resumeFocusedStackTopActivityLocked();
1750 }
1751 ActivityOptions.abort(mOptions);
1752 return START_DELIVERED_TO_TOP;
1753 }
1754 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1755 // In this case, we are launching an activity in our own task that may already be
1756 // running somewhere in the history, and we want to shuffle it to the front of the
1757 // stack if so.
1758 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1759 if (top != null) {
1760 final TaskRecord task = top.task;
1761 task.moveActivityToFrontLocked(top);
1762 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001763 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001764 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1765 mTargetStack.mLastPausedActivity = null;
1766 if (mDoResume) {
1767 mSupervisor.resumeFocusedStackTopActivityLocked();
1768 }
1769 return START_DELIVERED_TO_TOP;
1770 }
1771 }
1772
1773 // An existing activity is starting this new activity, so we want to keep the new one in
1774 // the same task as the one that is starting it.
1775 mStartActivity.setTask(sourceTask, null);
1776 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1777 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1778 return START_SUCCESS;
1779 }
1780
1781 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001782 // The caller is asking that the new activity be started in an explicit
1783 // task it has provided to us.
1784 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1785 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1786 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1787 }
1788
Wale Ogunwale01d66562015-12-29 08:19:19 -08001789 if (mLaunchBounds != null) {
1790 mInTask.updateOverrideConfiguration(mLaunchBounds);
1791 int stackId = mInTask.getLaunchStackId();
1792 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001793 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001794 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001795 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001796 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001797 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001798 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001799 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001800 }
1801 mTargetStack = mInTask.stack;
1802 mTargetStack.moveTaskToFrontLocked(
1803 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1804
1805 // Check whether we should actually launch the new activity in to the task,
1806 // or just reuse the current activity on top.
1807 ActivityRecord top = mInTask.getTopActivity();
1808 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1809 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1810 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001811 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001812 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1813 // We don't need to start a new activity, and the client said not to do
1814 // anything if that is the case, so this is it!
1815 return START_RETURN_INTENT_TO_CALLER;
1816 }
1817 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1818 return START_DELIVERED_TO_TOP;
1819 }
1820 }
1821
1822 if (!mAddingToTask) {
1823 // We don't actually want to have this activity added to the task, so just
1824 // stop here but still tell the caller that we consumed the intent.
1825 ActivityOptions.abort(mOptions);
1826 return START_TASK_TO_FRONT;
1827 }
1828
1829 mStartActivity.setTask(mInTask, null);
1830 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1831 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1832
1833 return START_SUCCESS;
1834 }
1835
1836 private void setTaskToCurrentTopOrCreateNewTask() {
1837 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1838 mOptions);
1839 if (mDoResume) {
1840 mTargetStack.moveToFront("addingToTopTask");
1841 }
1842 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001843 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1844 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1845 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001846 mStartActivity.setTask(task, null);
1847 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1848 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1849 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1850 }
1851
1852 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1853 boolean launchSingleTask, int launchFlags) {
1854 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1855 (launchSingleInstance || launchSingleTask)) {
1856 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1857 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1858 "\"singleInstance\" or \"singleTask\"");
1859 launchFlags &=
1860 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1861 } else {
1862 switch (r.info.documentLaunchMode) {
1863 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1864 break;
1865 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1866 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1867 break;
1868 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1869 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1870 break;
1871 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1872 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1873 break;
1874 }
1875 }
1876 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001877 }
1878
1879 final void doPendingActivityLaunchesLocked(boolean doResume) {
1880 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001881 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1882 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001883 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001884 final int result = startActivityUnchecked(
1885 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1886 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001887 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1888 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001889 } catch (Exception e) {
1890 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1891 pal.sendErrorResult(e.getMessage());
1892 }
1893 }
1894 }
1895
1896 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001897 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001898 final TaskRecord task = r.task;
1899 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1900 return mSupervisor.mHomeStack;
1901 }
1902
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001903 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001904 if (stack != null) {
1905 return stack;
1906 }
1907
1908 if (task != null && task.stack != null) {
1909 stack = task.stack;
1910 if (stack.isOnHomeDisplay()) {
1911 if (mSupervisor.mFocusedStack != stack) {
1912 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1913 "computeStackFocus: Setting " + "focused stack to r=" + r
1914 + " task=" + task);
1915 } else {
1916 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1917 "computeStackFocus: Focused stack already="
1918 + mSupervisor.mFocusedStack);
1919 }
1920 }
1921 return stack;
1922 }
1923
1924 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1925 if (container != null) {
1926 // The first time put it on the desired stack, after this put on task stack.
1927 r.mInitialActivityContainer = null;
1928 return container.mStack;
1929 }
1930
1931 // The fullscreen stack can contain any task regardless of if the task is resizeable
1932 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1933 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1934 // we can also put it in the focused stack.
1935 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001936 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1937 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1938 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001939 if (canUseFocusedStack && (!newTask
1940 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1941 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1942 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1943 return mSupervisor.mFocusedStack;
1944 }
1945
1946 // We first try to put the task in the first dynamic stack.
1947 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1948 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1949 stack = homeDisplayStacks.get(stackNdx);
1950 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1951 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1952 "computeStackFocus: Setting focused stack=" + stack);
1953 return stack;
1954 }
1955 }
1956
1957 // If there is no suitable dynamic stack then we figure out which static stack to use.
1958 final int stackId = task != null ? task.getLaunchStackId() :
1959 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1960 FULLSCREEN_WORKSPACE_STACK_ID;
1961 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1962 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1963 + r + " stackId=" + stack.mStackId);
1964 return stack;
1965 }
1966
Wale Ogunwale854809c2015-12-27 16:18:19 -08001967 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001968 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001969
1970 // We are reusing a task, keep the stack!
1971 if (mReuseTask != null) {
1972 return mReuseTask.stack;
1973 }
1974
Wale Ogunwale854809c2015-12-27 16:18:19 -08001975 final int launchStackId =
1976 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1977
1978 if (isValidLaunchStackId(launchStackId, r)) {
1979 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001980 } else if (launchStackId == DOCKED_STACK_ID) {
1981 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1982 // for this activity, so we put the activity in the fullscreen stack.
1983 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001984 }
1985
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001986 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001987 return null;
1988 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001989 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08001990
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001991 // The parent activity doesn't want to launch the activity on top of itself, but
1992 // instead tries to put it onto other side in side-by-side mode.
1993 final ActivityStack parentStack = task != null ? task.stack
1994 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
1995 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001996
1997 if (parentStack != mSupervisor.mFocusedStack) {
1998 // If task's parent stack is not focused - use it during adjacent launch.
1999 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002000 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002001 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2002 // If task is already on top of focused stack - use it. We don't want to move the
2003 // existing focused task to adjacent stack, just deliver new intent in this case.
2004 return mSupervisor.mFocusedStack;
2005 }
2006
2007 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2008 // If parent was in docked stack, the natural place to launch another activity
2009 // will be fullscreen, so it can appear alongside the docked window.
2010 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2011 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002012 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002013 // If the parent is not in the docked stack, we check if there is docked window
2014 // and if yes, we will launch into that stack. If not, we just put the new
2015 // activity into parent's stack, because we can't find a better place.
2016 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2017 if (dockedStack != null
2018 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2019 // There is a docked stack, but it isn't visible, so we can't launch into that.
2020 return null;
2021 } else {
2022 return dockedStack;
2023 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002024 }
2025 }
2026 }
2027
Wale Ogunwale854809c2015-12-27 16:18:19 -08002028 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2029 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2030 || !StackId.isStaticStack(stackId)) {
2031 return false;
2032 }
2033
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002034 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2035 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2036 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002037 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002038
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002039 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2040 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002041 }
2042
2043 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2044 return false;
2045 }
2046
2047 final boolean supportsPip = mService.mSupportsPictureInPicture
2048 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2049 if (stackId == PINNED_STACK_ID && !supportsPip) {
2050 return false;
2051 }
2052 return true;
2053 }
2054
Wale Ogunwale854809c2015-12-27 16:18:19 -08002055 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2056 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002057 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002058 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2059 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002060 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002061 }
2062 }
2063 return newBounds;
2064 }
2065
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002066 void setWindowManager(WindowManagerService wm) {
2067 mWindowManager = wm;
2068 }
2069
2070 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2071 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2072 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2073 if (pal.stack == stack) {
2074 mPendingActivityLaunches.remove(palNdx);
2075 }
2076 }
2077 }
Daichi Hirono15a02992016-04-27 18:47:01 +09002078
2079 static boolean isDocumentLaunchesIntoExisting(int flags) {
2080 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2081 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2082 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002083}