blob: bebfc0bdad1732c27580d007da054ada49dc23f7 [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 Kennedyfea1b772016-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 Kennedyfea1b772016-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.
Ivan Podogov44608392016-12-13 20:36:04 +0000419 if ((mService.mPermissionReviewRequired
420 || Build.PERMISSIONS_REVIEW_REQUIRED) && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800421 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
422 aInfo.packageName, userId)) {
423 IIntentSender target = mService.getIntentSenderLocked(
424 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
425 callingUid, userId, null, null, 0, new Intent[]{intent},
426 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
427 | PendingIntent.FLAG_ONE_SHOT, null);
428
429 final int flags = intent.getFlags();
430 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
431 newIntent.setFlags(flags
432 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
433 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
434 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
435 if (resultRecord != null) {
436 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
437 }
438 intent = newIntent;
439
440 resolvedType = null;
441 callingUid = realCallingUid;
442 callingPid = realCallingPid;
443
444 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
445 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
446 null /*profilerInfo*/);
447
448 if (DEBUG_PERMISSIONS_REVIEW) {
449 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
450 true, false) + "} from uid " + callingUid + " on display "
451 + (container == null ? (mSupervisor.mFocusedStack == null ?
452 Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) :
453 (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
454 container.mActivityDisplay.mDisplayId)));
455 }
456 }
457 }
458
459 // If we have an ephemeral app, abort the process of launching the resolved intent.
460 // Instead, launch the ephemeral installer. Once the installer is finished, it
461 // starts either the intent we resolved here [on install error] or the ephemeral
462 // app [on install success].
463 if (rInfo != null && rInfo.ephemeralResolveInfo != null) {
Todd Kennedyfea1b772016-06-28 14:09:55 -0700464 intent = buildEphemeralInstallerIntent(intent, ephemeralIntent,
465 rInfo.ephemeralResolveInfo.getPackageName(), callingPackage, resolvedType,
466 userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800467 resolvedType = null;
468 callingUid = realCallingUid;
469 callingPid = realCallingPid;
470
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800471 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
472 }
473
474 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
475 intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
476 requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
Wale Ogunwale1affbbc2016-05-01 09:03:52 -0700477 options, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800478 if (outActivity != null) {
479 outActivity[0] = r;
480 }
481
482 if (r.appTimeTracker == null && sourceRecord != null) {
483 // If the caller didn't specify an explicit time tracker, we want to continue
484 // tracking under any it has.
485 r.appTimeTracker = sourceRecord.appTimeTracker;
486 }
487
488 final ActivityStack stack = mSupervisor.mFocusedStack;
489 if (voiceSession == null && (stack.mResumedActivity == null
490 || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
491 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
492 realCallingPid, realCallingUid, "Activity start")) {
493 PendingActivityLaunch pal = new PendingActivityLaunch(r,
494 sourceRecord, startFlags, stack, callerApp);
495 mPendingActivityLaunches.add(pal);
496 ActivityOptions.abort(options);
497 return ActivityManager.START_SWITCHES_CANCELED;
498 }
499 }
500
501 if (mService.mDidAppSwitch) {
502 // This is the second allowed switch since we stopped switches,
503 // so now just generally allow switches. Use case: user presses
504 // home (switches disabled, switch to home, mDidAppSwitch now true);
505 // user taps a home icon (coming from home so allowed, we hit here
506 // and now allow anyone to switch again).
507 mService.mAppSwitchesAllowedTime = 0;
508 } else {
509 mService.mDidAppSwitch = true;
510 }
511
512 doPendingActivityLaunchesLocked(false);
513
Jorim Jaggi4ccfc302016-04-20 20:37:45 -0700514 try {
515 mService.mWindowManager.deferSurfaceLayout();
516 err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
517 true, options, inTask);
518 } finally {
519 mService.mWindowManager.continueSurfaceLayout();
520 }
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700521 postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800522 return err;
523 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800524
Todd Kennedyfea1b772016-06-28 14:09:55 -0700525 /**
526 * Builds and returns an intent to launch the ephemeral installer.
527 */
528 private Intent buildEphemeralInstallerIntent(Intent launchIntent, Intent origIntent,
529 String ephemeralPackage, String callingPackage, String resolvedType, int userId) {
530 final Intent nonEphemeralIntent = new Intent(origIntent);
531 nonEphemeralIntent.setFlags(nonEphemeralIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
532 // Intent that is launched if the ephemeral package couldn't be installed
533 // for any reason.
534 final IIntentSender failureIntentTarget = mService.getIntentSenderLocked(
535 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
536 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 1,
537 new Intent[]{ nonEphemeralIntent }, new String[]{ resolvedType },
538 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
539 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
540
541 final Intent ephemeralIntent;
542 if (USE_DEFAULT_EPHEMERAL_LAUNCHER) {
543 // Force the intent to be directed to the ephemeral package
544 ephemeralIntent = new Intent(origIntent);
545 ephemeralIntent.setPackage(ephemeralPackage);
546 } else {
547 // Success intent goes back to the installer
Todd Kennedyfea1b772016-06-28 14:09:55 -0700548 ephemeralIntent = new Intent(launchIntent);
Todd Kennedyfea1b772016-06-28 14:09:55 -0700549 }
550
551 // Intent that is eventually launched if the ephemeral package was
552 // installed successfully. This will actually be launched by a platform
553 // broadcast receiver.
554 final IIntentSender successIntentTarget = mService.getIntentSenderLocked(
555 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
556 Binder.getCallingUid(), userId, null /*token*/, null /*resultWho*/, 0,
557 new Intent[]{ ephemeralIntent }, new String[]{ resolvedType },
558 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
559 | PendingIntent.FLAG_IMMUTABLE, null /*bOptions*/);
560
561 // Finally build the actual intent to launch the ephemeral installer
562 int flags = launchIntent.getFlags();
563 final Intent intent = new Intent();
564 intent.setFlags(flags
565 | Intent.FLAG_ACTIVITY_NEW_TASK
566 | Intent.FLAG_ACTIVITY_CLEAR_TASK
567 | Intent.FLAG_ACTIVITY_NO_HISTORY
568 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
569 intent.putExtra(Intent.EXTRA_PACKAGE_NAME, ephemeralPackage);
570 intent.putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, new IntentSender(failureIntentTarget));
571 intent.putExtra(Intent.EXTRA_EPHEMERAL_SUCCESS, new IntentSender(successIntentTarget));
572 // TODO: Remove when the platform has fully implemented ephemeral apps
Todd Kennedy52f179f2016-09-21 15:53:50 -0700573 intent.setData(origIntent.getData().buildUpon().clearQuery().build());
Todd Kennedyfea1b772016-06-28 14:09:55 -0700574 return intent;
575 }
576
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800577 void postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700578 ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
579 ActivityStack targetStack) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800580
581 if (result < START_SUCCESS) {
582 // If someone asked to have the keyguard dismissed on the next activity start,
583 // but we are not actually doing an activity switch... just dismiss the keyguard now,
584 // because we probably want to see whatever is behind it.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800585 mSupervisor.notifyActivityDrawnForKeyguard();
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800586 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800587 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800588
Chong Zhang5022da32016-06-21 16:31:37 -0700589 // We're waiting for an activity launch to finish, but that activity simply
590 // brought another activity to front. Let startActivityMayWait() know about
591 // this, so it waits for the new activity to become visible instead.
592 if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
593 mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
594 }
595
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800596 int startedActivityStackId = INVALID_STACK_ID;
597 if (r.task != null && r.task.stack != null) {
598 startedActivityStackId = r.task.stack.mStackId;
599 } else if (mTargetStack != null) {
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700600 startedActivityStackId = targetStack.mStackId;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800601 }
602
Jorim Jaggi352d5842016-05-19 10:20:28 -0700603 // If we launched the activity from a no display activity that was launched from the home
604 // screen, we also need to start recents to un-minimize the docked stack, since the
605 // noDisplay activity will be finished shortly after.
Jorim Jaggi936aaeb2016-08-26 19:02:11 -0700606 // Note that some apps have trampoline activities without noDisplay being set. In that case,
607 // we have another heuristic in DockedStackDividerController.notifyAppTransitionStarting
608 // that tries to detect that case.
Jorim Jaggi352d5842016-05-19 10:20:28 -0700609 // TODO: We should prevent noDisplay activities from affecting task/stack ordering and
610 // visibility instead of using this flag.
Jorim Jaggi6afd1562016-06-01 18:57:54 -0700611 final boolean noDisplayActivityOverHome = sourceRecord != null
612 && sourceRecord.noDisplay
613 && sourceRecord.task.getTaskToReturnTo() == HOME_ACTIVITY_TYPE;
Jorim Jaggi352d5842016-05-19 10:20:28 -0700614 if (startedActivityStackId == DOCKED_STACK_ID
615 && (prevFocusedStackId == HOME_STACK_ID || noDisplayActivityOverHome)) {
Jorim Jaggic69bd222016-03-15 14:38:37 +0100616 final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
617 final ActivityRecord topActivityHomeStack = homeStack != null
618 ? homeStack.topRunningActivityLocked() : null;
619 if (topActivityHomeStack == null
620 || topActivityHomeStack.mActivityType != RECENTS_ACTIVITY_TYPE) {
621 // We launch an activity while being in home stack, which means either launcher or
622 // recents into docked stack. We don't want the launched activity to be alone in a
623 // docked stack, so we want to immediately launch recents too.
624 if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
Jorim Jaggi681fc7b2016-04-14 22:02:39 -0700625 mWindowManager.showRecentApps(true /* fromHome */);
Jorim Jaggic69bd222016-03-15 14:38:37 +0100626 return;
627 }
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800628 }
629
630 if (startedActivityStackId == PINNED_STACK_ID
631 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP)) {
632 // The activity was already running in the pinned stack so it wasn't started, but either
633 // brought to the front or the new intent was delivered to it since it was already in
634 // front. Notify anyone interested in this piece of information.
635 mService.notifyPinnedActivityRestartAttemptLocked();
636 return;
637 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800638 }
639
640 void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
641 mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
642 startActivityLocked(null /*caller*/, intent, null /*ephemeralIntent*/,
643 null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/,
644 null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/,
645 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/,
646 0 /*realCallingPid*/, 0 /*realCallingUid*/, 0 /*startFlags*/, null /*options*/,
Jorim Jaggi4ad98562016-04-19 20:30:47 -0700647 false /*ignoreTargetSecurity*/, false /*componentSpecified*/, null /*outActivity*/,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800648 null /*container*/, null /*inTask*/);
649 if (mSupervisor.inResumeTopActivity) {
650 // If we are in resume section already, home activity will be initialized, but not
651 // resumed (to avoid recursive resume) and will stay that way until something pokes it
652 // again. We need to schedule another resume.
653 mSupervisor.scheduleResumeTopActivities();
654 }
655 }
656
Tony Mak853304c2016-04-18 15:17:41 +0100657 void showConfirmDeviceCredential(int userId) {
658 // First, retrieve the stack that we want to resume after credential is confirmed.
659 ActivityStack targetStack;
660 ActivityStack fullscreenStack =
661 mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID);
Robin Lee0737c2b2016-08-08 14:48:43 +0100662 ActivityStack freeformStack =
663 mSupervisor.getStack(FREEFORM_WORKSPACE_STACK_ID);
Tony Mak853304c2016-04-18 15:17:41 +0100664 if (fullscreenStack != null &&
665 fullscreenStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
666 // Single window case and the case that the docked stack is shown with fullscreen stack.
667 targetStack = fullscreenStack;
Robin Lee0737c2b2016-08-08 14:48:43 +0100668 } else if (freeformStack != null &&
669 freeformStack.getStackVisibilityLocked(null) != ActivityStack.STACK_INVISIBLE) {
670 targetStack = freeformStack;
Tony Mak853304c2016-04-18 15:17:41 +0100671 } else {
672 // The case that the docked stack is shown with recent.
673 targetStack = mSupervisor.getStack(HOME_STACK_ID);
674 }
675 if (targetStack == null) {
676 return;
677 }
678 final KeyguardManager km = (KeyguardManager) mService.mContext
679 .getSystemService(Context.KEYGUARD_SERVICE);
680 final Intent credential =
681 km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makae13e182016-05-17 16:36:14 +0100682 // For safety, check null here in case users changed the setting after the checking.
683 if (credential == null) {
684 return;
685 }
Tony Mak853304c2016-04-18 15:17:41 +0100686 final ActivityRecord activityRecord = targetStack.topRunningActivityLocked();
687 if (activityRecord != null) {
688 final IIntentSender target = mService.getIntentSenderLocked(
689 ActivityManager.INTENT_SENDER_ACTIVITY,
690 activityRecord.launchedFromPackage,
691 activityRecord.launchedFromUid,
692 activityRecord.userId,
693 null, null, 0,
694 new Intent[] { activityRecord.intent },
695 new String[] { activityRecord.resolvedType },
696 PendingIntent.FLAG_CANCEL_CURRENT |
697 PendingIntent.FLAG_ONE_SHOT |
698 PendingIntent.FLAG_IMMUTABLE,
699 null);
700 credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
701 // Show confirm credentials activity.
Tony Mak646fe992016-04-21 16:43:08 +0100702 startConfirmCredentialIntent(credential);
Tony Mak853304c2016-04-18 15:17:41 +0100703 }
704 }
705
Tony Mak646fe992016-04-21 16:43:08 +0100706 void startConfirmCredentialIntent(Intent intent) {
707 intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
708 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
709 FLAG_ACTIVITY_TASK_ON_HOME);
710 final ActivityOptions options = ActivityOptions.makeBasic();
711 options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
712 mService.mContext.startActivityAsUser(intent, options.toBundle(),
713 UserHandle.CURRENT);
714 }
Tony Mak853304c2016-04-18 15:17:41 +0100715
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800716 final int startActivityMayWait(IApplicationThread caller, int callingUid,
717 String callingPackage, Intent intent, String resolvedType,
718 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
719 IBinder resultTo, String resultWho, int requestCode, int startFlags,
720 ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
721 Bundle bOptions, boolean ignoreTargetSecurity, int userId,
722 IActivityContainer iContainer, TaskRecord inTask) {
723 // Refuse possible leaked file descriptors
724 if (intent != null && intent.hasFileDescriptors()) {
725 throw new IllegalArgumentException("File descriptors passed in Intent");
726 }
Jorim Jaggi275561a2016-02-23 10:11:02 -0500727 mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800728 boolean componentSpecified = intent.getComponent() != null;
729
730 // Save a copy in case ephemeral needs it
731 final Intent ephemeralIntent = new Intent(intent);
732 // Don't modify the client's object!
733 intent = new Intent(intent);
734
735 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000736 if (rInfo == null) {
737 UserInfo userInfo = mSupervisor.getUserInfo(userId);
738 if (userInfo != null && userInfo.isManagedProfile()) {
739 // Special case for managed profiles, if attempting to launch non-cryto aware
740 // app in a locked managed profile from an unlocked parent allow it to resolve
741 // as user will be sent via confirm credentials to unlock the profile.
742 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700743 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000744 long token = Binder.clearCallingIdentity();
745 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700746 UserInfo parent = userManager.getProfileParent(userId);
747 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
748 && userManager.isUserUnlockingOrUnlocked(parent.id)
749 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000750 } finally {
751 Binder.restoreCallingIdentity(token);
752 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700753 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000754 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600755 PackageManager.MATCH_DIRECT_BOOT_AWARE
756 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000757 }
758 }
759 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800760 // Collect information about the target of the Intent.
761 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
762
763 ActivityOptions options = ActivityOptions.fromBundle(bOptions);
764 ActivityStackSupervisor.ActivityContainer container =
765 (ActivityStackSupervisor.ActivityContainer)iContainer;
766 synchronized (mService) {
767 if (container != null && container.mParentActivity != null &&
768 container.mParentActivity.state != RESUMED) {
769 // Cannot start a child activity if the parent is not resumed.
770 return ActivityManager.START_CANCELED;
771 }
772 final int realCallingPid = Binder.getCallingPid();
773 final int realCallingUid = Binder.getCallingUid();
774 int callingPid;
775 if (callingUid >= 0) {
776 callingPid = -1;
777 } else if (caller == null) {
778 callingPid = realCallingPid;
779 callingUid = realCallingUid;
780 } else {
781 callingPid = callingUid = -1;
782 }
783
784 final ActivityStack stack;
785 if (container == null || container.mStack.isOnHomeDisplay()) {
786 stack = mSupervisor.mFocusedStack;
787 } else {
788 stack = container.mStack;
789 }
790 stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
791 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
792 "Starting activity when config will change = " + stack.mConfigWillChange);
793
794 final long origId = Binder.clearCallingIdentity();
795
796 if (aInfo != null &&
797 (aInfo.applicationInfo.privateFlags
798 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
799 // This may be a heavy-weight process! Check to see if we already
800 // have another, different heavy-weight process running.
801 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
802 final ProcessRecord heavy = mService.mHeavyWeightProcess;
803 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
804 || !heavy.processName.equals(aInfo.processName))) {
805 int appCallingUid = callingUid;
806 if (caller != null) {
807 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
808 if (callerApp != null) {
809 appCallingUid = callerApp.info.uid;
810 } else {
811 Slog.w(TAG, "Unable to find app for caller " + caller
812 + " (pid=" + callingPid + ") when starting: "
813 + intent.toString());
814 ActivityOptions.abort(options);
815 return ActivityManager.START_PERMISSION_DENIED;
816 }
817 }
818
819 IIntentSender target = mService.getIntentSenderLocked(
820 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
821 appCallingUid, userId, null, null, 0, new Intent[] { intent },
822 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
823 | PendingIntent.FLAG_ONE_SHOT, null);
824
825 Intent newIntent = new Intent();
826 if (requestCode >= 0) {
827 // Caller is requesting a result.
828 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
829 }
830 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
831 new IntentSender(target));
832 if (heavy.activities.size() > 0) {
833 ActivityRecord hist = heavy.activities.get(0);
834 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
835 hist.packageName);
836 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
837 hist.task.taskId);
838 }
839 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
840 aInfo.packageName);
841 newIntent.setFlags(intent.getFlags());
842 newIntent.setClassName("android",
843 HeavyWeightSwitcherActivity.class.getName());
844 intent = newIntent;
845 resolvedType = null;
846 caller = null;
847 callingUid = Binder.getCallingUid();
848 callingPid = Binder.getCallingPid();
849 componentSpecified = true;
850 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
851 aInfo = rInfo != null ? rInfo.activityInfo : null;
852 if (aInfo != null) {
853 aInfo = mService.getActivityInfoForUser(aInfo, userId);
854 }
855 }
856 }
857 }
858
Jorim Jaggi275561a2016-02-23 10:11:02 -0500859 final ActivityRecord[] outRecord = new ActivityRecord[1];
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800860 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
861 aInfo, rInfo, voiceSession, voiceInteractor,
862 resultTo, resultWho, requestCode, callingPid,
863 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
Jorim Jaggi275561a2016-02-23 10:11:02 -0500864 options, ignoreTargetSecurity, componentSpecified, outRecord, container,
865 inTask);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800866
867 Binder.restoreCallingIdentity(origId);
868
869 if (stack.mConfigWillChange) {
870 // If the caller also wants to switch to a new configuration,
871 // do so now. This allows a clean switch, as we are waiting
872 // for the current activity to pause (so we will not destroy
873 // it), and have not yet started the next activity.
874 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
875 "updateConfiguration()");
876 stack.mConfigWillChange = false;
877 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
878 "Updating to new configuration after starting activity.");
879 mService.updateConfigurationLocked(config, null, false);
880 }
881
882 if (outResult != null) {
883 outResult.result = res;
884 if (res == ActivityManager.START_SUCCESS) {
885 mSupervisor.mWaitingActivityLaunched.add(outResult);
886 do {
887 try {
888 mService.wait();
889 } catch (InterruptedException e) {
890 }
Chong Zhang5022da32016-06-21 16:31:37 -0700891 } while (outResult.result != START_TASK_TO_FRONT
892 && !outResult.timeout && outResult.who == null);
893 if (outResult.result == START_TASK_TO_FRONT) {
894 res = START_TASK_TO_FRONT;
895 }
896 }
897 if (res == START_TASK_TO_FRONT) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800898 ActivityRecord r = stack.topRunningActivityLocked();
899 if (r.nowVisible && r.state == RESUMED) {
900 outResult.timeout = false;
901 outResult.who = new ComponentName(r.info.packageName, r.info.name);
902 outResult.totalTime = 0;
903 outResult.thisTime = 0;
904 } else {
905 outResult.thisTime = SystemClock.uptimeMillis();
906 mSupervisor.mWaitingActivityVisible.add(outResult);
907 do {
908 try {
909 mService.wait();
910 } catch (InterruptedException e) {
911 }
912 } while (!outResult.timeout && outResult.who == null);
913 }
914 }
915 }
916
Jorim Jaggibe67c902016-04-12 00:53:16 -0700917 final ActivityRecord launchedActivity = mReusedActivity != null
918 ? mReusedActivity : outRecord[0];
Jorim Jaggi1e630c02016-05-16 12:13:13 -0700919 mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800920 return res;
921 }
922 }
923
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800924 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
925 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
926 Bundle bOptions, int userId) {
927 if (intents == null) {
928 throw new NullPointerException("intents is null");
929 }
930 if (resolvedTypes == null) {
931 throw new NullPointerException("resolvedTypes is null");
932 }
933 if (intents.length != resolvedTypes.length) {
934 throw new IllegalArgumentException("intents are length different than resolvedTypes");
935 }
936
Makoto Onukid67b1872016-07-21 16:26:36 -0700937 final int realCallingPid = Binder.getCallingPid();
938 final int realCallingUid = Binder.getCallingUid();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800939
940 int callingPid;
941 if (callingUid >= 0) {
942 callingPid = -1;
943 } else if (caller == null) {
Makoto Onukid67b1872016-07-21 16:26:36 -0700944 callingPid = realCallingPid;
945 callingUid = realCallingUid;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800946 } else {
947 callingPid = callingUid = -1;
948 }
949 final long origId = Binder.clearCallingIdentity();
950 try {
951 synchronized (mService) {
952 ActivityRecord[] outActivity = new ActivityRecord[1];
953 for (int i=0; i<intents.length; i++) {
954 Intent intent = intents[i];
955 if (intent == null) {
956 continue;
957 }
958
959 // Refuse possible leaked file descriptors
960 if (intent != null && intent.hasFileDescriptors()) {
961 throw new IllegalArgumentException("File descriptors passed in Intent");
962 }
963
964 boolean componentSpecified = intent.getComponent() != null;
965
966 // Don't modify the client's object!
967 intent = new Intent(intent);
968
969 // Collect information about the target of the Intent.
970 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
971 null, userId);
972 // TODO: New, check if this is correct
973 aInfo = mService.getActivityInfoForUser(aInfo, userId);
974
975 if (aInfo != null &&
976 (aInfo.applicationInfo.privateFlags
977 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
978 throw new IllegalArgumentException(
979 "FLAG_CANT_SAVE_STATE not supported here");
980 }
981
982 ActivityOptions options = ActivityOptions.fromBundle(
983 i == intents.length - 1 ? bOptions : null);
984 int res = startActivityLocked(caller, intent, null /*ephemeralIntent*/,
985 resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
Makoto Onukid67b1872016-07-21 16:26:36 -0700986 callingPid, callingUid, callingPackage,
987 realCallingPid, realCallingUid, 0,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800988 options, false, componentSpecified, outActivity, null, null);
989 if (res < 0) {
990 return res;
991 }
992
993 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
994 }
995 }
996 } finally {
997 Binder.restoreCallingIdentity(origId);
998 }
999
Wale Ogunwale01d66562015-12-29 08:19:19 -08001000 return START_SUCCESS;
1001 }
1002
Wei Wang65c7a152016-06-02 18:51:22 -07001003 void sendPowerHintForLaunchStartIfNeeded(boolean forceSend) {
1004 // Trigger launch power hint if activity being launched is not in the current task
Wei Wang98f03f92016-05-18 11:32:52 -07001005 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1006 final ActivityRecord curTop = (focusStack == null)
1007 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1008 if ((forceSend || (!mPowerHintSent && curTop != null &&
1009 curTop.task != null && mStartActivity != null &&
1010 curTop.task != mStartActivity.task )) &&
1011 mService.mLocalPowerManager != null) {
Wei Wang65c7a152016-06-02 18:51:22 -07001012 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 1);
Wei Wang98f03f92016-05-18 11:32:52 -07001013 mPowerHintSent = true;
1014 }
1015 }
1016
Wei Wang65c7a152016-06-02 18:51:22 -07001017 void sendPowerHintForLaunchEndIfNeeded() {
1018 // Trigger launch power hint if activity is launched
1019 if (mPowerHintSent && mService.mLocalPowerManager != null) {
1020 mService.mLocalPowerManager.powerHint(PowerManagerInternal.POWER_HINT_LAUNCH, 0);
1021 mPowerHintSent = false;
1022 }
1023 }
1024
Wale Ogunwale01d66562015-12-29 08:19:19 -08001025 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1026 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1027 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
1028
1029 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1030 voiceInteractor);
1031
1032 computeLaunchingTaskFlags();
1033
1034 computeSourceStack();
1035
1036 mIntent.setFlags(mLaunchFlags);
1037
Jorim Jaggibe67c902016-04-12 00:53:16 -07001038 mReusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001039
Jorim Jaggi2adba072016-03-03 13:43:39 +01001040 final int preferredLaunchStackId =
1041 (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
1042
Jorim Jaggibe67c902016-04-12 00:53:16 -07001043 if (mReusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001044 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1045 // still needs to be a lock task mode violation since the task gets cleared out and
1046 // the device would otherwise leave the locked task.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001047 if (mSupervisor.isLockTaskModeViolation(mReusedActivity.task,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001048 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1049 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1050 mSupervisor.showLockTaskToast();
1051 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1052 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1053 }
1054
1055 if (mStartActivity.task == null) {
Jorim Jaggibe67c902016-04-12 00:53:16 -07001056 mStartActivity.task = mReusedActivity.task;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001057 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001058 if (mReusedActivity.task.intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001059 // This task was started because of movement of the activity based on affinity...
1060 // Now that we are actually launching it, we can assign the base intent.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001061 mReusedActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001062 }
1063
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001064 // This code path leads to delivering a new intent, we want to make sure we schedule it
1065 // as the first operation, in case the activity will be resumed as a result of later
1066 // operations.
1067 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1068 || mLaunchSingleInstance || mLaunchSingleTask) {
1069 // In this situation we want to remove all activities from the task up to the one
1070 // being started. In most cases this means we are resetting the task to its initial
1071 // state.
Jorim Jaggibe67c902016-04-12 00:53:16 -07001072 final ActivityRecord top = mReusedActivity.task.performClearTaskForReuseLocked(
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001073 mStartActivity, mLaunchFlags);
1074 if (top != null) {
1075 if (top.frontOfTask) {
1076 // Activity aliases may mean we use different intents for the top activity,
1077 // so make sure the task now has the identity of the new intent.
1078 top.task.setIntent(mStartActivity);
1079 }
1080 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Anthony Hughf73d0852016-11-22 15:13:35 -08001081
1082 if (shouldActivityBeBroughtToFront(mReusedActivity)) {
1083 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1084 }
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001085 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1086 mStartActivity.launchedFromPackage);
1087 }
1088 }
1089
Wei Wang65c7a152016-06-02 18:51:22 -07001090 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001091
Jorim Jaggibe67c902016-04-12 00:53:16 -07001092 mReusedActivity = setTargetStackAndMoveToFrontIfNeeded(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001093
1094 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1095 // We don't need to start a new activity, and the client said not to do anything
1096 // if that is the case, so this is it! And for paranoia, make sure we have
1097 // correctly resumed the top activity.
1098 resumeTargetStackIfNeeded();
1099 return START_RETURN_INTENT_TO_CALLER;
1100 }
Jorim Jaggibe67c902016-04-12 00:53:16 -07001101 setTaskFromIntentActivity(mReusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001102
1103 if (!mAddingToTask && mReuseTask == null) {
1104 // We didn't do anything... but it was needed (a.k.a., client don't use that
1105 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1106 resumeTargetStackIfNeeded();
1107 return START_TASK_TO_FRONT;
1108 }
1109 }
1110
1111 if (mStartActivity.packageName == null) {
1112 if (mStartActivity.resultTo != null && mStartActivity.resultTo.task.stack != null) {
1113 mStartActivity.resultTo.task.stack.sendActivityResultLocked(
1114 -1, mStartActivity.resultTo, mStartActivity.resultWho,
1115 mStartActivity.requestCode, RESULT_CANCELED, null);
1116 }
1117 ActivityOptions.abort(mOptions);
1118 return START_CLASS_NOT_FOUND;
1119 }
1120
1121 // If the activity being launched is the same as the one currently at the top, then
1122 // we need to check if it should only be launched once.
1123 final ActivityStack topStack = mSupervisor.mFocusedStack;
1124 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1125 final boolean dontStart = top != null && mStartActivity.resultTo == null
1126 && top.realActivity.equals(mStartActivity.realActivity)
1127 && top.userId == mStartActivity.userId
1128 && top.app != null && top.app.thread != null
1129 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1130 || mLaunchSingleTop || mLaunchSingleTask);
1131 if (dontStart) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001132 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001133 // For paranoia, make sure we have correctly resumed the top activity.
1134 topStack.mLastPausedActivity = null;
1135 if (mDoResume) {
1136 mSupervisor.resumeFocusedStackTopActivityLocked();
1137 }
1138 ActivityOptions.abort(mOptions);
1139 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1140 // We don't need to start a new activity, and the client said not to do
1141 // anything if that is the case, so this is it!
1142 return START_RETURN_INTENT_TO_CALLER;
1143 }
1144 top.deliverNewIntentLocked(
1145 mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
Chong Zhangd44063c2016-04-08 11:52:30 -07001146
1147 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1148 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1149 mSupervisor.handleNonResizableTaskIfNeeded(
1150 top.task, preferredLaunchStackId, topStack.mStackId);
1151
Wale Ogunwale01d66562015-12-29 08:19:19 -08001152 return START_DELIVERED_TO_TOP;
1153 }
1154
1155 boolean newTask = false;
1156 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1157 ? mSourceRecord.task : null;
1158
1159 // Should this be considered a new task?
1160 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1161 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1162 newTask = true;
1163 setTaskFromReuseOrCreateNewTask(taskToAffiliate);
1164
1165 if (mSupervisor.isLockTaskModeViolation(mStartActivity.task)) {
1166 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1167 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1168 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001169 if (!mMovedOtherTask) {
Andrii Kuliandc0f8932016-06-28 16:34:02 -07001170 // If stack id is specified in activity options, usually it means that activity is
1171 // launched not from currently focused stack (e.g. from SysUI or from shell) - in
1172 // that case we check the target stack.
1173 updateTaskReturnToType(mStartActivity.task, mLaunchFlags,
1174 preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001175 }
1176 } else if (mSourceRecord != null) {
1177 if (mSupervisor.isLockTaskModeViolation(mSourceRecord.task)) {
1178 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1179 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1180 }
1181
1182 final int result = setTaskFromSourceRecord();
1183 if (result != START_SUCCESS) {
1184 return result;
1185 }
1186 } else if (mInTask != null) {
1187 // The caller is asking that the new activity be started in an explicit
1188 // task it has provided to us.
1189 if (mSupervisor.isLockTaskModeViolation(mInTask)) {
1190 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1191 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1192 }
1193
1194 final int result = setTaskFromInTask();
1195 if (result != START_SUCCESS) {
1196 return result;
1197 }
1198 } else {
1199 // This not being started from an existing activity, and not part of a new task...
1200 // just put it in the top task, though these days this case should never happen.
1201 setTaskToCurrentTopOrCreateNewTask();
1202 }
1203
1204 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1205 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1206
1207 if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
1208 mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
1209 }
1210 if (newTask) {
1211 EventLog.writeEvent(
1212 EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.task.taskId);
1213 }
1214 ActivityStack.logStartActivity(
1215 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.task);
1216 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001217
Wei Wang65c7a152016-06-02 18:51:22 -07001218 sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
Wei Wang98f03f92016-05-18 11:32:52 -07001219
Wale Ogunwale01d66562015-12-29 08:19:19 -08001220 mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
1221 if (mDoResume) {
1222 if (!mLaunchTaskBehind) {
1223 // TODO(b/26381750): Remove this code after verification that all the decision
1224 // points above moved targetStack to the front which will also set the focus
1225 // activity.
1226 mService.setFocusedActivityLocked(mStartActivity, "startedActivity");
1227 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001228 final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked();
1229 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001230 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1231 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001232 // If the activity is not focusable, we can't resume it, but still would like to
1233 // make sure it becomes visible as it starts (this will also trigger entry
1234 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001235 // Also, we don't want to resume activities in a task that currently has an overlay
1236 // as the starting activity just needs to be in the visible paused state until the
1237 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001238 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001239 // Go ahead and tell window manager to execute app transition for this activity
1240 // since the app transition will not be triggered through the resume channel.
1241 mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001242 } else {
1243 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1244 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001245 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001246 } else {
1247 mTargetStack.addRecentActivityLocked(mStartActivity);
1248 }
1249 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1250
Jorim Jaggid53f0922016-04-06 22:16:23 -07001251 mSupervisor.handleNonResizableTaskIfNeeded(
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08001252 mStartActivity.task, preferredLaunchStackId, mTargetStack.mStackId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001253
1254 return START_SUCCESS;
1255 }
1256
1257 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1258 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1259 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1260 reset();
1261
1262 mStartActivity = r;
1263 mIntent = r.intent;
1264 mOptions = options;
1265 mCallingUid = r.launchedFromUid;
1266 mSourceRecord = sourceRecord;
1267 mVoiceSession = voiceSession;
1268 mVoiceInteractor = voiceInteractor;
1269
1270 mLaunchBounds = getOverrideBounds(r, options, inTask);
1271
1272 mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
1273 mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
1274 mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
1275 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1276 r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
1277 mLaunchTaskBehind = r.mLaunchTaskBehind
1278 && !mLaunchSingleTask && !mLaunchSingleInstance
1279 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1280
1281 sendNewTaskResultRequestIfNeeded();
1282
1283 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1284 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1285 }
1286
1287 // If we are actually going to launch in to a new task, there are some cases where
1288 // we further want to do multiple task.
1289 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1290 if (mLaunchTaskBehind
1291 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1292 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1293 }
1294 }
1295
1296 // We'll invoke onUserLeaving before onPause only if the launching
1297 // activity did not explicitly state that this is an automated launch.
1298 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1299 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1300 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1301
1302 // If the caller has asked not to resume at this point, we make note
1303 // of this in the record so that we can skip it when trying to find
1304 // the top running activity.
1305 mDoResume = doResume;
1306 if (!doResume || !mSupervisor.okToShowLocked(r)) {
1307 r.delayedResume = true;
1308 mDoResume = false;
1309 }
1310
Wale Ogunwale3b232392016-05-13 15:37:13 -07001311 if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1312 r.mTaskOverlay = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001313 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1314 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1315 if (top != null && !top.visible) {
1316
1317 // The caller specifies that we'd like to be avoided to be moved to the front, so be
1318 // it!
1319 mDoResume = false;
1320 mAvoidMoveToFront = true;
1321 }
1322 }
1323
Wale Ogunwale01d66562015-12-29 08:19:19 -08001324 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1325
1326 mInTask = inTask;
1327 // In some flows in to this function, we retrieve the task record and hold on to it
1328 // without a lock before calling back in to here... so the task at this point may
1329 // not actually be in recents. Check for that, and if it isn't in recents just
1330 // consider it invalid.
1331 if (inTask != null && !inTask.inRecents) {
1332 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1333 mInTask = null;
1334 }
1335
1336 mStartFlags = startFlags;
1337 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1338 // is the same as the one making the call... or, as a special case, if we do not know
1339 // the caller then we count the current top activity as the caller.
1340 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1341 ActivityRecord checkedCaller = sourceRecord;
1342 if (checkedCaller == null) {
1343 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1344 mNotTop);
1345 }
1346 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1347 // Caller is not the same as launcher, so always needed.
1348 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1349 }
1350 }
1351
1352 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1353 }
1354
1355 private void sendNewTaskResultRequestIfNeeded() {
1356 if (mStartActivity.resultTo != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0
1357 && mStartActivity.resultTo.task.stack != null) {
1358 // For whatever reason this activity is being launched into a new task...
1359 // yet the caller has requested a result back. Well, that is pretty messed up,
1360 // so instead immediately send back a cancel and let the new task continue launched
1361 // as normal without a dependency on its originator.
1362 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1363 mStartActivity.resultTo.task.stack.sendActivityResultLocked(-1, mStartActivity.resultTo,
1364 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null);
1365 mStartActivity.resultTo = null;
1366 }
1367 }
1368
1369 private void computeLaunchingTaskFlags() {
1370 // If the caller is not coming from another activity, but has given us an explicit task into
1371 // which they would like us to launch the new activity, then let's see about doing that.
1372 if (mSourceRecord == null && mInTask != null && mInTask.stack != null) {
1373 final Intent baseIntent = mInTask.getBaseIntent();
1374 final ActivityRecord root = mInTask.getRootActivity();
1375 if (baseIntent == null) {
1376 ActivityOptions.abort(mOptions);
1377 throw new IllegalArgumentException("Launching into task without base intent: "
1378 + mInTask);
1379 }
1380
1381 // If this task is empty, then we are adding the first activity -- it
1382 // determines the root, and must be launching as a NEW_TASK.
1383 if (mLaunchSingleInstance || mLaunchSingleTask) {
1384 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1385 ActivityOptions.abort(mOptions);
1386 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1387 + mStartActivity + " into different task " + mInTask);
1388 }
1389 if (root != null) {
1390 ActivityOptions.abort(mOptions);
1391 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1392 + " has root " + root + " but target is singleInstance/Task");
1393 }
1394 }
1395
1396 // If task is empty, then adopt the interesting intent launch flags in to the
1397 // activity being started.
1398 if (root == null) {
1399 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1400 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1401 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1402 | (baseIntent.getFlags() & flagsOfInterest);
1403 mIntent.setFlags(mLaunchFlags);
1404 mInTask.setIntent(mStartActivity);
1405 mAddingToTask = true;
1406
1407 // If the task is not empty and the caller is asking to start it as the root of
1408 // a new task, then we don't actually want to start this on the task. We will
1409 // bring the task to the front, and possibly give it a new intent.
1410 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1411 mAddingToTask = false;
1412
1413 } else {
1414 mAddingToTask = true;
1415 }
1416
1417 mReuseTask = mInTask;
1418 } else {
1419 mInTask = null;
1420 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1421 // when in freeform workspace.
1422 // Also put noDisplay activities in the source task. These by itself can be placed
1423 // in any task/stack, however it could launch other activities like ResolverActivity,
1424 // and we want those to stay in the original task.
1425 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1426 && mSourceRecord.isFreeform()) {
1427 mAddingToTask = true;
1428 }
1429 }
1430
1431 if (mInTask == null) {
1432 if (mSourceRecord == null) {
1433 // This activity is not being started from another... in this
1434 // case we -always- start a new task.
1435 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1436 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1437 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1438 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1439 }
1440 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1441 // The original activity who is starting us is running as a single
1442 // instance... this new activity it is starting must go on its
1443 // own task.
1444 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1445 } else if (mLaunchSingleInstance || mLaunchSingleTask) {
1446 // The activity being started is a single instance... it always
1447 // gets launched into its own task.
1448 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1449 }
1450 }
1451 }
1452
1453 private void computeSourceStack() {
1454 if (mSourceRecord == null) {
1455 mSourceStack = null;
1456 return;
1457 }
1458 if (!mSourceRecord.finishing) {
1459 mSourceStack = mSourceRecord.task.stack;
1460 return;
1461 }
1462
1463 // If the source is finishing, we can't further count it as our source. This is because the
1464 // task it is associated with may now be empty and on its way out, so we don't want to
1465 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1466 // a task for it. But save the task information so it can be used when creating the new task.
1467 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1468 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1469 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1470 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1471 mNewTaskInfo = mSourceRecord.info;
1472 mNewTaskIntent = mSourceRecord.task.intent;
1473 }
1474 mSourceRecord = null;
1475 mSourceStack = null;
1476 }
1477
1478 /**
1479 * Decide whether the new activity should be inserted into an existing task. Returns null
1480 * if not or an ActivityRecord with the task into which the new activity should be added.
1481 */
1482 private ActivityRecord getReusableIntentActivity() {
1483 // We may want to try to place the new activity in to an existing task. We always
1484 // do this if the target activity is singleTask or singleInstance; we will also do
1485 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1486 // us to still place it in a new task: multi task, always doc mode, or being asked to
1487 // launch this as a new task behind the current one.
1488 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1489 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1490 || mLaunchSingleInstance || mLaunchSingleTask;
1491 // If bring to front is requested, and no result is requested and we have not been given
1492 // an explicit task to launch in to, and we can find a task that was started with this
1493 // same component, then instead of launching bring that one to the front.
1494 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1495 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001496 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1497 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1498 intentActivity = task != null ? task.getTopActivity() : null;
1499 } else if (putIntoExistingTask) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001500 if (mLaunchSingleInstance) {
1501 // There can be one and only one instance of single instance activity in the
1502 // history, and it is always in its own unique task, so we do a special search.
Andrii Kuliand3bbb132016-06-16 16:00:20 -07001503 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001504 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1505 // For the launch adjacent case we only want to put the activity in an existing
1506 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001507 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1508 !mLaunchSingleTask);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001509 } else {
1510 // Otherwise find the best task to put the activity in.
1511 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
1512 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001513 }
1514 return intentActivity;
1515 }
1516
Anthony Hughf73d0852016-11-22 15:13:35 -08001517 private boolean shouldActivityBeBroughtToFront(ActivityRecord intentActivity) {
1518 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1519 ActivityRecord curTop = (focusStack == null)
1520 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1521
1522 return curTop != null
1523 && (curTop.task != intentActivity.task || curTop.task != focusStack.topTask())
1524 && !mAvoidMoveToFront;
1525 }
1526
Wale Ogunwale01d66562015-12-29 08:19:19 -08001527 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1528 mTargetStack = intentActivity.task.stack;
1529 mTargetStack.mLastPausedActivity = null;
1530 // If the target task is not in the front, then we need to bring it to the front...
1531 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1532 // the same behavior as if a new instance was being started, which means not bringing it
1533 // to the front if the caller is not itself in the front.
1534 final ActivityStack focusStack = mSupervisor.getFocusedStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001535
Anthony Hughf73d0852016-11-22 15:13:35 -08001536 if (shouldActivityBeBroughtToFront(intentActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001537 if (mSourceRecord == null || (mSourceStack.topActivity() != null &&
1538 mSourceStack.topActivity().task == mSourceRecord.task)) {
1539 // We really do want to push this one into the user's face, right now.
1540 if (mLaunchTaskBehind && mSourceRecord != null) {
1541 intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
1542 }
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001543 mMovedOtherTask = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001544
1545 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1546 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1547 // So no point resuming any of the activities here, it just wastes one extra
1548 // resuming, plus enter AND exit transitions.
1549 // Here we only want to bring the target stack forward. Transition will be applied
1550 // to the new activity that's started after the old ones are gone.
1551 final boolean willClearTask =
1552 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1553 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1554 if (!willClearTask) {
1555 final ActivityStack launchStack = getLaunchStack(
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001556 mStartActivity, mLaunchFlags, mStartActivity.task, mOptions);
Chong Zhangdea4bd92016-03-15 12:50:03 -07001557 if (launchStack == null || launchStack == mTargetStack) {
1558 // We only want to move to the front, if we aren't going to launch on a
1559 // different stack. If we launch on a different stack, we will put the
1560 // task on top there.
1561 mTargetStack.moveTaskToFrontLocked(
1562 intentActivity.task, mNoAnimation, mOptions,
1563 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1564 mMovedToFront = true;
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001565 } else if (launchStack.mStackId == DOCKED_STACK_ID
1566 || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
1567 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1568 // If we want to launch adjacent and mTargetStack is not the computed
1569 // launch stack - move task to top of computed stack.
1570 mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
1571 launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
1572 ANIMATE);
1573 } else {
1574 // TODO: This should be reevaluated in MW v2.
1575 // We choose to move task to front instead of launching it adjacent
1576 // when specific stack was requested explicitly and it appeared to be
1577 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1578 mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
1579 mOptions, mStartActivity.appTimeTracker,
1580 "bringToFrontInsteadOfAdjacentLaunch");
1581 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001582 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001583 }
1584 mOptions = null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001585 }
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001586 updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001587 }
1588 }
1589 if (!mMovedToFront && mDoResume) {
1590 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1591 + " from " + intentActivity);
1592 mTargetStack.moveToFront("intentActivityFound");
1593 }
1594
Jorim Jaggid53f0922016-04-06 22:16:23 -07001595 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.task, INVALID_STACK_ID,
1596 mTargetStack.mStackId);
1597
Wale Ogunwale01d66562015-12-29 08:19:19 -08001598 // If the caller has requested that the target task be reset, then do so.
1599 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1600 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1601 }
1602 return intentActivity;
1603 }
1604
Wale Ogunwale673cbd22016-01-30 18:30:55 -08001605 private void updateTaskReturnToType(
1606 TaskRecord task, int launchFlags, ActivityStack focusedStack) {
1607 if ((launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1608 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1609 // Caller wants to appear on home activity.
1610 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1611 return;
1612 } else if (focusedStack == null || focusedStack.mStackId == HOME_STACK_ID) {
1613 // Task will be launched over the home stack, so return home.
1614 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1615 return;
1616 }
1617
1618 // Else we are coming from an application stack so return to an application.
1619 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1620 }
1621
Wale Ogunwale01d66562015-12-29 08:19:19 -08001622 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1623 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1624 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1625 // The caller has requested to completely replace any existing task with its new
1626 // activity. Well that should not be too hard...
Shigeki Yokomichi0bd28e22016-10-12 18:35:17 +09001627 intentActivity.task.performClearTaskLocked();
1628 intentActivity.task.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001629 mReuseTask = intentActivity.task;
Andrii Kulian4b7f2d42016-06-08 17:20:44 -07001630 // When we clear the task - focus will be adjusted, which will bring another task
1631 // to top before we launch the activity we need. This will temporary swap their
1632 // mTaskToReturnTo values and we don't want to overwrite them accidentally.
1633 mMovedOtherTask = true;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001634 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1635 || mLaunchSingleInstance || mLaunchSingleTask) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001636 ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
1637 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001638 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001639 // A special case: we need to start the activity because it is not currently
1640 // running, and the caller has asked to clear the current task to have this
1641 // activity at the top.
1642 mAddingToTask = true;
1643 // Now pretend like this activity is being started by the top of its task, so it
1644 // is put in the right place.
1645 mSourceRecord = intentActivity;
1646 final TaskRecord task = mSourceRecord.task;
1647 if (task != null && task.stack == null) {
1648 // Target stack got cleared when we all activities were removed above.
1649 // Go ahead and reset it.
1650 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
1651 null /* bounds */, mLaunchFlags, mOptions);
1652 mTargetStack.addTask(task,
1653 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1654 }
1655 }
1656 } else if (mStartActivity.realActivity.equals(intentActivity.task.realActivity)) {
1657 // In this case the top activity on the task is the same as the one being launched,
1658 // so we take that as a request to bring the task to the foreground. If the top
1659 // activity in the task is the root activity, deliver this new intent to it if it
1660 // desires.
1661 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
1662 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001663 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001664 intentActivity.task);
1665 if (intentActivity.frontOfTask) {
1666 intentActivity.task.setIntent(mStartActivity);
1667 }
1668 intentActivity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
1669 mStartActivity.launchedFromPackage);
Andrii Kulian206b9fa2016-06-02 13:18:01 -07001670 } else if (!intentActivity.task.isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001671 // In this case we are launching the root activity of the task, but with a
1672 // different intent. We should start a new instance on top.
1673 mAddingToTask = true;
1674 mSourceRecord = intentActivity;
1675 }
1676 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1677 // In this case an activity is being launched in to an existing task, without
1678 // resetting that task. This is typically the situation of launching an activity
1679 // from a notification or shortcut. We want to place the new activity on top of the
1680 // current task.
1681 mAddingToTask = true;
1682 mSourceRecord = intentActivity;
1683 } else if (!intentActivity.task.rootWasReset) {
1684 // In this case we are launching into an existing task that has not yet been started
1685 // from its front door. The current task has been brought to the front. Ideally,
1686 // we'd probably like to place this new task at the bottom of its stack, but that's
1687 // a little hard to do with the current organization of the code so for now we'll
1688 // just drop it.
1689 intentActivity.task.setIntent(mStartActivity);
1690 }
1691 }
1692
1693 private void resumeTargetStackIfNeeded() {
1694 if (mDoResume) {
1695 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
1696 if (!mMovedToFront) {
1697 // Make sure to notify Keyguard as well if we are not running an app transition
1698 // later.
1699 mSupervisor.notifyActivityDrawnForKeyguard();
1700 }
1701 } else {
1702 ActivityOptions.abort(mOptions);
1703 }
1704 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1705 }
1706
1707 private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
1708 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
1709 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001710
1711 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001712 final TaskRecord task = mTargetStack.createTaskRecord(
1713 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001714 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
1715 mNewTaskIntent != null ? mNewTaskIntent : mIntent,
1716 mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
1717 mStartActivity.setTask(task, taskToAffiliate);
1718 if (mLaunchBounds != null) {
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001719 final int stackId = mTargetStack.mStackId;
1720 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001721 mService.resizeStack(
1722 stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001723 } else {
1724 mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
1725 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001726 }
1727 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1728 "Starting new activity " +
1729 mStartActivity + " in new task " + mStartActivity.task);
1730 } else {
1731 mStartActivity.setTask(mReuseTask, taskToAffiliate);
1732 }
1733 }
1734
1735 private int setTaskFromSourceRecord() {
1736 final TaskRecord sourceTask = mSourceRecord.task;
1737 // We only want to allow changing stack if the target task is not the top one,
1738 // otherwise we would move the launching task to the other side, rather than show
1739 // two side by side.
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001740 final boolean moveStackAllowed = sourceTask.stack.topTask() != sourceTask;
1741 if (moveStackAllowed) {
1742 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task,
1743 mOptions);
1744 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001745
1746 if (mTargetStack == null) {
1747 mTargetStack = sourceTask.stack;
1748 } else if (mTargetStack != sourceTask.stack) {
1749 mSupervisor.moveTaskToStackLocked(sourceTask.taskId, mTargetStack.mStackId,
1750 ON_TOP, FORCE_FOCUS, "launchToSide", !ANIMATE);
1751 }
1752 if (mDoResume) {
1753 mTargetStack.moveToFront("sourceStackToFront");
1754 }
1755 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07001756 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001757 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
1758 mStartActivity.appTimeTracker, "sourceTaskToFront");
1759 }
1760 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1761 // In this case, we are adding the activity to an existing task, but the caller has
1762 // asked to clear that task if the activity is already running.
1763 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
1764 mKeepCurTransition = true;
1765 if (top != null) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001766 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001767 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1768 // For paranoia, make sure we have correctly resumed the top activity.
1769 mTargetStack.mLastPausedActivity = null;
1770 if (mDoResume) {
1771 mSupervisor.resumeFocusedStackTopActivityLocked();
1772 }
1773 ActivityOptions.abort(mOptions);
1774 return START_DELIVERED_TO_TOP;
1775 }
1776 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1777 // In this case, we are launching an activity in our own task that may already be
1778 // running somewhere in the history, and we want to shuffle it to the front of the
1779 // stack if so.
1780 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
1781 if (top != null) {
1782 final TaskRecord task = top.task;
1783 task.moveActivityToFrontLocked(top);
1784 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001785 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001786 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1787 mTargetStack.mLastPausedActivity = null;
1788 if (mDoResume) {
1789 mSupervisor.resumeFocusedStackTopActivityLocked();
1790 }
1791 return START_DELIVERED_TO_TOP;
1792 }
1793 }
1794
1795 // An existing activity is starting this new activity, so we want to keep the new one in
1796 // the same task as the one that is starting it.
1797 mStartActivity.setTask(sourceTask, null);
1798 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
1799 + " in existing task " + mStartActivity.task + " from source " + mSourceRecord);
1800 return START_SUCCESS;
1801 }
1802
1803 private int setTaskFromInTask() {
1804 if (mLaunchBounds != null) {
1805 mInTask.updateOverrideConfiguration(mLaunchBounds);
1806 int stackId = mInTask.getLaunchStackId();
1807 if (stackId != mInTask.stack.mStackId) {
Wale Ogunwale513346d2016-01-27 10:55:01 -08001808 final ActivityStack stack = mSupervisor.moveTaskToStackUncheckedLocked(
Wale Ogunwale01d66562015-12-29 08:19:19 -08001809 mInTask, stackId, ON_TOP, !FORCE_FOCUS, "inTaskToFront");
Wale Ogunwale513346d2016-01-27 10:55:01 -08001810 stackId = stack.mStackId;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001811 }
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001812 if (StackId.resizeStackWithLaunchBounds(stackId)) {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001813 mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Wale Ogunwalecacfaa22016-01-15 11:26:08 -08001814 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001815 }
1816 mTargetStack = mInTask.stack;
1817 mTargetStack.moveTaskToFrontLocked(
1818 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
1819
1820 // Check whether we should actually launch the new activity in to the task,
1821 // or just reuse the current activity on top.
1822 ActivityRecord top = mInTask.getTopActivity();
1823 if (top != null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId) {
1824 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1825 || mLaunchSingleTop || mLaunchSingleTask) {
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001826 ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.task);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001827 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1828 // We don't need to start a new activity, and the client said not to do
1829 // anything if that is the case, so this is it!
1830 return START_RETURN_INTENT_TO_CALLER;
1831 }
1832 top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
1833 return START_DELIVERED_TO_TOP;
1834 }
1835 }
1836
1837 if (!mAddingToTask) {
1838 // We don't actually want to have this activity added to the task, so just
1839 // stop here but still tell the caller that we consumed the intent.
1840 ActivityOptions.abort(mOptions);
1841 return START_TASK_TO_FRONT;
1842 }
1843
1844 mStartActivity.setTask(mInTask, null);
1845 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1846 "Starting new activity " + mStartActivity + " in explicit task " + mStartActivity.task);
1847
1848 return START_SUCCESS;
1849 }
1850
1851 private void setTaskToCurrentTopOrCreateNewTask() {
1852 mTargetStack = computeStackFocus(mStartActivity, false, null /* bounds */, mLaunchFlags,
1853 mOptions);
1854 if (mDoResume) {
1855 mTargetStack.moveToFront("addingToTopTask");
1856 }
1857 final ActivityRecord prev = mTargetStack.topActivity();
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001858 final TaskRecord task = (prev != null) ? prev.task : mTargetStack.createTaskRecord(
1859 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
1860 mStartActivity.info, mIntent, null, null, true);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001861 mStartActivity.setTask(task, null);
1862 mWindowManager.moveTaskToTop(mStartActivity.task.taskId);
1863 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1864 "Starting new activity " + mStartActivity + " in new guessed " + mStartActivity.task);
1865 }
1866
1867 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
1868 boolean launchSingleTask, int launchFlags) {
1869 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
1870 (launchSingleInstance || launchSingleTask)) {
1871 // We have a conflict between the Intent and the Activity manifest, manifest wins.
1872 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
1873 "\"singleInstance\" or \"singleTask\"");
1874 launchFlags &=
1875 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
1876 } else {
1877 switch (r.info.documentLaunchMode) {
1878 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1879 break;
1880 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1881 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1882 break;
1883 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1884 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
1885 break;
1886 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
1887 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
1888 break;
1889 }
1890 }
1891 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001892 }
1893
1894 final void doPendingActivityLaunchesLocked(boolean doResume) {
1895 while (!mPendingActivityLaunches.isEmpty()) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001896 final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
1897 final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001898 try {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -08001899 final int result = startActivityUnchecked(
1900 pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
1901 postStartActivityUncheckedProcessing(
Jorim Jaggi6afd1562016-06-01 18:57:54 -07001902 pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
1903 mTargetStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001904 } catch (Exception e) {
1905 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
1906 pal.sendErrorResult(e.getMessage());
1907 }
1908 }
1909 }
1910
1911 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
Wale Ogunwale854809c2015-12-27 16:18:19 -08001912 int launchFlags, ActivityOptions aOptions) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001913 final TaskRecord task = r.task;
1914 if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
1915 return mSupervisor.mHomeStack;
1916 }
1917
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001918 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001919 if (stack != null) {
1920 return stack;
1921 }
1922
1923 if (task != null && task.stack != null) {
1924 stack = task.stack;
1925 if (stack.isOnHomeDisplay()) {
1926 if (mSupervisor.mFocusedStack != stack) {
1927 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1928 "computeStackFocus: Setting " + "focused stack to r=" + r
1929 + " task=" + task);
1930 } else {
1931 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1932 "computeStackFocus: Focused stack already="
1933 + mSupervisor.mFocusedStack);
1934 }
1935 }
1936 return stack;
1937 }
1938
1939 final ActivityStackSupervisor.ActivityContainer container = r.mInitialActivityContainer;
1940 if (container != null) {
1941 // The first time put it on the desired stack, after this put on task stack.
1942 r.mInitialActivityContainer = null;
1943 return container.mStack;
1944 }
1945
1946 // The fullscreen stack can contain any task regardless of if the task is resizeable
1947 // or not. So, we let the task go in the fullscreen task if it is the focus stack.
1948 // If the freeform or docked stack has focus, and the activity to be launched is resizeable,
1949 // we can also put it in the focused stack.
1950 final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
Wale Ogunwale513346d2016-01-27 10:55:01 -08001951 final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
1952 || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
1953 || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001954 if (canUseFocusedStack && (!newTask
1955 || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
1956 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1957 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
1958 return mSupervisor.mFocusedStack;
1959 }
1960
1961 // We first try to put the task in the first dynamic stack.
1962 final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
1963 for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1964 stack = homeDisplayStacks.get(stackNdx);
1965 if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {
1966 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
1967 "computeStackFocus: Setting focused stack=" + stack);
1968 return stack;
1969 }
1970 }
1971
1972 // If there is no suitable dynamic stack then we figure out which static stack to use.
1973 final int stackId = task != null ? task.getLaunchStackId() :
1974 bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
1975 FULLSCREEN_WORKSPACE_STACK_ID;
1976 stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
1977 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
1978 + r + " stackId=" + stack.mStackId);
1979 return stack;
1980 }
1981
Wale Ogunwale854809c2015-12-27 16:18:19 -08001982 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07001983 ActivityOptions aOptions) {
Jorim Jaggib8c58762016-04-20 17:58:29 -07001984
1985 // We are reusing a task, keep the stack!
1986 if (mReuseTask != null) {
1987 return mReuseTask.stack;
1988 }
1989
Wale Ogunwale854809c2015-12-27 16:18:19 -08001990 final int launchStackId =
1991 (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
1992
1993 if (isValidLaunchStackId(launchStackId, r)) {
1994 return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001995 } else if (launchStackId == DOCKED_STACK_ID) {
1996 // The preferred launch stack is the docked stack, but it isn't a valid launch stack
1997 // for this activity, so we put the activity in the fullscreen stack.
1998 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
Wale Ogunwale854809c2015-12-27 16:18:19 -08001999 }
2000
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002001 if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002002 return null;
2003 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002004 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002005
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002006 // The parent activity doesn't want to launch the activity on top of itself, but
2007 // instead tries to put it onto other side in side-by-side mode.
2008 final ActivityStack parentStack = task != null ? task.stack
2009 : r.mInitialActivityContainer != null ? r.mInitialActivityContainer.mStack
2010 : mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002011
2012 if (parentStack != mSupervisor.mFocusedStack) {
2013 // If task's parent stack is not focused - use it during adjacent launch.
2014 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002015 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002016 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2017 // If task is already on top of focused stack - use it. We don't want to move the
2018 // existing focused task to adjacent stack, just deliver new intent in this case.
2019 return mSupervisor.mFocusedStack;
2020 }
2021
2022 if (parentStack != null && parentStack.mStackId == DOCKED_STACK_ID) {
2023 // If parent was in docked stack, the natural place to launch another activity
2024 // will be fullscreen, so it can appear alongside the docked window.
2025 return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
2026 ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002027 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002028 // If the parent is not in the docked stack, we check if there is docked window
2029 // and if yes, we will launch into that stack. If not, we just put the new
2030 // activity into parent's stack, because we can't find a better place.
2031 final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
2032 if (dockedStack != null
2033 && dockedStack.getStackVisibilityLocked(r) == STACK_INVISIBLE) {
2034 // There is a docked stack, but it isn't visible, so we can't launch into that.
2035 return null;
2036 } else {
2037 return dockedStack;
2038 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002039 }
2040 }
2041 }
2042
Wale Ogunwale854809c2015-12-27 16:18:19 -08002043 private boolean isValidLaunchStackId(int stackId, ActivityRecord r) {
2044 if (stackId == INVALID_STACK_ID || stackId == HOME_STACK_ID
2045 || !StackId.isStaticStack(stackId)) {
2046 return false;
2047 }
2048
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002049 if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
2050 && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
2051 return false;
Wale Ogunwale513346d2016-01-27 10:55:01 -08002052 }
Wale Ogunwale854809c2015-12-27 16:18:19 -08002053
Wale Ogunwalefb1c8642016-03-02 08:28:08 -08002054 if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
2055 return true;
Wale Ogunwale854809c2015-12-27 16:18:19 -08002056 }
2057
2058 if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
2059 return false;
2060 }
2061
2062 final boolean supportsPip = mService.mSupportsPictureInPicture
2063 && (r.supportsPictureInPicture() || mService.mForceResizableActivities);
2064 if (stackId == PINNED_STACK_ID && !supportsPip) {
2065 return false;
2066 }
2067 return true;
2068 }
2069
Wale Ogunwale854809c2015-12-27 16:18:19 -08002070 Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
2071 Rect newBounds = null;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002072 if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
Wale Ogunwale854809c2015-12-27 16:18:19 -08002073 if (mSupervisor.canUseActivityOptionsLaunchBounds(
2074 options, options.getLaunchStackId())) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002075 newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
Wale Ogunwale854809c2015-12-27 16:18:19 -08002076 }
2077 }
2078 return newBounds;
2079 }
2080
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002081 void setWindowManager(WindowManagerService wm) {
2082 mWindowManager = wm;
2083 }
2084
2085 void removePendingActivityLaunchesLocked(ActivityStack stack) {
2086 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2087 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2088 if (pal.stack == stack) {
2089 mPendingActivityLaunches.remove(palNdx);
2090 }
2091 }
2092 }
liulvpingb55e42d2016-09-26 20:00:15 +08002093
2094 boolean clearPendingActivityLaunchesLocked(String packageName) {
2095 boolean didSomething = false;
2096
2097 for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
2098 PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
2099 ActivityRecord r = pal.r;
2100 if (r != null && r.packageName.equals(packageName)) {
2101 mPendingActivityLaunches.remove(palNdx);
2102 didSomething = true;
2103 }
2104 }
2105 return didSomething;
2106 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002107}