blob: 182a3f60d211a3cc9ccad73648a3133a60e6107d [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;
Bryce Leef9d49542017-06-26 16:27:32 -070020import static android.app.ActivityManager.START_ABORTED;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080021import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080022import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27import static android.app.ActivityManager.START_SUCCESS;
28import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale68278562017-09-23 17:13:55 -070029import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070031import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
32import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale0568aed2017-09-08 13:29:37 -070033import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Patrick Baumann577d4022018-01-31 16:55:10 +000034import static android.content.Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080035import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
36import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
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;
48import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
Bryce Leef65ee7e2018-03-26 16:03:47 -070049import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
Wale Ogunwale01d66562015-12-29 08:19:19 -080050import 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;
David Stevensc6b91c62017-02-08 14:23:58 -080053import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070054import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080055import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
56import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
61import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
66import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
67import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
68import static com.android.server.am.ActivityManagerService.ANIMATE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080069import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Winson Chung74666102017-02-22 17:49:24 -080070import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080071import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080072import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080073import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080074import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080075import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
76import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
77
Todd Kennedye9910222017-02-21 16:00:11 -080078import android.annotation.NonNull;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +010079import android.annotation.Nullable;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080080import android.app.ActivityManager;
81import android.app.ActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080082import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080083import android.app.PendingIntent;
84import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070085import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080086import android.content.IIntentSender;
87import android.content.Intent;
88import android.content.IntentSender;
89import android.content.pm.ActivityInfo;
90import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -080091import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000092import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080093import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000094import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080095import android.content.res.Configuration;
96import android.graphics.Rect;
97import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080098import android.os.Bundle;
99import android.os.IBinder;
100import android.os.RemoteException;
101import android.os.SystemClock;
102import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000103import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800104import android.service.voice.IVoiceInteractionSession;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700105import android.text.TextUtils;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800106import android.util.EventLog;
Bryce Leedaa91e42017-12-06 14:13:01 -0800107import android.util.Pools.SynchronizedPool;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800108import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800109
Bryce Leed3624e12017-11-30 08:51:45 -0800110import com.android.internal.annotations.VisibleForTesting;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800111import com.android.internal.app.HeavyWeightSwitcherActivity;
112import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800113import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Bryce Leeec55eb02017-12-05 20:51:27 -0800114import com.android.server.am.LaunchParamsController.LaunchParams;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800115import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800116
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700117import java.io.PrintWriter;
118import java.text.DateFormat;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700119import java.util.Date;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800120
121/**
Bryce Leed3624e12017-11-30 08:51:45 -0800122 * Controller for interpreting how and then launching an activity.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800123 *
124 * This class collects all the logic for determining how an intent and flags should be turned into
125 * an activity and associated task and stack.
126 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800127class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800128 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
129 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
130 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
131 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
132 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
Bryce Lee7daee392017-10-12 13:46:18 -0700133 private static final int INVALID_LAUNCH_MODE = -1;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800134
135 private final ActivityManagerService mService;
136 private final ActivityStackSupervisor mSupervisor;
Benjamin Franz563707b2017-06-29 15:06:13 +0100137 private final ActivityStartInterceptor mInterceptor;
Bryce Leed3624e12017-11-30 08:51:45 -0800138 private final ActivityStartController mController;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800139
Wale Ogunwale01d66562015-12-29 08:19:19 -0800140 // Share state variable among methods when starting an activity.
141 private ActivityRecord mStartActivity;
142 private Intent mIntent;
143 private int mCallingUid;
144 private ActivityOptions mOptions;
145
Bryce Lee7daee392017-10-12 13:46:18 -0700146 private int mLaunchMode;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800147 private boolean mLaunchTaskBehind;
148 private int mLaunchFlags;
149
Bryce Leeec55eb02017-12-05 20:51:27 -0800150 private LaunchParams mLaunchParams = new LaunchParams();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800151
152 private ActivityRecord mNotTop;
153 private boolean mDoResume;
154 private int mStartFlags;
155 private ActivityRecord mSourceRecord;
Bryce Lee7daee392017-10-12 13:46:18 -0700156
David Stevense5a7b642017-05-22 13:18:23 -0700157 // The display to launch the activity onto, barring any strong reason to do otherwise.
158 private int mPreferredDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800159
160 private TaskRecord mInTask;
161 private boolean mAddingToTask;
162 private TaskRecord mReuseTask;
163
164 private ActivityInfo mNewTaskInfo;
165 private Intent mNewTaskIntent;
166 private ActivityStack mSourceStack;
167 private ActivityStack mTargetStack;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800168 private boolean mMovedToFront;
169 private boolean mNoAnimation;
170 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700171 private boolean mAvoidMoveToFront;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800172
Bryce Lee325e09682017-10-05 17:20:25 -0700173 // We must track when we deliver the new intent since multiple code paths invoke
174 // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
175 // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
176 // delivered at most once.
177 private boolean mIntentDelivered;
178
Wale Ogunwale01d66562015-12-29 08:19:19 -0800179 private IVoiceInteractionSession mVoiceSession;
180 private IVoiceInteractor mVoiceInteractor;
181
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700182 // Last activity record we attempted to start
183 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
184 // The result of the last activity we attempted to start.
185 private int mLastStartActivityResult;
186 // Time in milli seconds we attempted to start the last activity.
187 private long mLastStartActivityTimeMs;
188 // The reason we were trying to start the last activity
189 private String mLastStartReason;
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700190
Bryce Lee4c9a5972017-12-01 22:14:24 -0800191 /*
192 * Request details provided through setter methods. Should be reset after {@link #execute()}
193 * to avoid unnecessarily retaining parameters. Note that the request is ignored when
194 * {@link #startResolvedActivity} is invoked directly.
195 */
196 private Request mRequest = new Request();
197
Bryce Leed3624e12017-11-30 08:51:45 -0800198 /**
199 * An interface that to provide {@link ActivityStarter} instances to the controller. This is
200 * used by tests to inject their own starter implementations for verification purposes.
201 */
202 @VisibleForTesting
203 interface Factory {
204 /**
Bryce Lee4c9a5972017-12-01 22:14:24 -0800205 * Sets the {@link ActivityStartController} to be passed to {@link ActivityStarter}.
206 */
207 void setController(ActivityStartController controller);
208
209 /**
Bryce Leed3624e12017-11-30 08:51:45 -0800210 * Generates an {@link ActivityStarter} that is ready to handle a new start request.
211 * @param controller The {@link ActivityStartController} which the starter who will own
212 * this instance.
213 * @return an {@link ActivityStarter}
214 */
Bryce Leedaa91e42017-12-06 14:13:01 -0800215 ActivityStarter obtain();
216
217 /**
218 * Recycles a starter for reuse.
219 */
220 void recycle(ActivityStarter starter);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800221 }
222
Bryce Leed3624e12017-11-30 08:51:45 -0800223 /**
224 * Default implementation of {@link StarterFactory}.
225 */
226 static class DefaultFactory implements Factory {
Bryce Leedaa91e42017-12-06 14:13:01 -0800227 /**
228 * The maximum count of starters that should be active at one time:
229 * 1. last ran starter (for logging and post activity processing)
230 * 2. current running starter
231 * 3. starter from re-entry in (2)
232 */
233 private final int MAX_STARTER_COUNT = 3;
234
Bryce Lee4c9a5972017-12-01 22:14:24 -0800235 private ActivityStartController mController;
236 private ActivityManagerService mService;
237 private ActivityStackSupervisor mSupervisor;
238 private ActivityStartInterceptor mInterceptor;
239
Bryce Leedaa91e42017-12-06 14:13:01 -0800240 private SynchronizedPool<ActivityStarter> mStarterPool =
241 new SynchronizedPool<>(MAX_STARTER_COUNT);
242
Bryce Lee4c9a5972017-12-01 22:14:24 -0800243 DefaultFactory(ActivityManagerService service,
244 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
245 mService = service;
246 mSupervisor = supervisor;
247 mInterceptor = interceptor;
Bryce Leed3624e12017-11-30 08:51:45 -0800248 }
Bryce Lee4c9a5972017-12-01 22:14:24 -0800249
250 @Override
251 public void setController(ActivityStartController controller) {
252 mController = controller;
253 }
254
255 @Override
Bryce Leedaa91e42017-12-06 14:13:01 -0800256 public ActivityStarter obtain() {
257 ActivityStarter starter = mStarterPool.acquire();
258
259 if (starter == null) {
260 starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
261 }
262
263 return starter;
264 }
265
266 @Override
267 public void recycle(ActivityStarter starter) {
268 starter.reset(true /* clearRequest*/);
269 mStarterPool.release(starter);
Bryce Lee4c9a5972017-12-01 22:14:24 -0800270 }
271 }
272
273 /**
274 * Container for capturing initial start request details. This information is NOT reset until
275 * the {@link ActivityStarter} is recycled, allowing for multiple invocations with the same
276 * parameters.
277 *
278 * TODO(b/64750076): Investigate consolidating member variables of {@link ActivityStarter} with
279 * the request object. Note that some member variables are referenced in
280 * {@link #dump(PrintWriter, String)} and therefore cannot be cleared immediately after
281 * execution.
282 */
283 private static class Request {
284 private static final int DEFAULT_CALLING_UID = -1;
285 private static final int DEFAULT_CALLING_PID = 0;
286
287 IApplicationThread caller;
288 Intent intent;
289 Intent ephemeralIntent;
290 String resolvedType;
291 ActivityInfo activityInfo;
292 ResolveInfo resolveInfo;
293 IVoiceInteractionSession voiceSession;
294 IVoiceInteractor voiceInteractor;
295 IBinder resultTo;
296 String resultWho;
297 int requestCode;
298 int callingPid = DEFAULT_CALLING_UID;
299 int callingUid = DEFAULT_CALLING_PID;
300 String callingPackage;
301 int realCallingPid;
302 int realCallingUid;
303 int startFlags;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100304 SafeActivityOptions activityOptions;
Bryce Lee4c9a5972017-12-01 22:14:24 -0800305 boolean ignoreTargetSecurity;
306 boolean componentSpecified;
Winson Chunge2d72172018-01-25 17:46:20 +0000307 boolean avoidMoveToFront;
Bryce Lee4c9a5972017-12-01 22:14:24 -0800308 ActivityRecord[] outActivity;
309 TaskRecord inTask;
310 String reason;
311 ProfilerInfo profilerInfo;
312 Configuration globalConfig;
Bryce Lee4c9a5972017-12-01 22:14:24 -0800313 int userId;
314 WaitResult waitResult;
315
316 /**
317 * Indicates that we should wait for the result of the start request. This flag is set when
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100318 * {@link ActivityStarter#setMayWait(int)} is called.
Bryce Lee4c9a5972017-12-01 22:14:24 -0800319 * {@see ActivityStarter#startActivityMayWait}.
320 */
321 boolean mayWait;
Bryce Leedaa91e42017-12-06 14:13:01 -0800322
323 /**
Bryce Leea3cd8e02018-01-09 15:44:24 -0800324 * Ensure constructed request matches reset instance.
325 */
326 Request() {
327 reset();
328 }
329
330 /**
Bryce Leedaa91e42017-12-06 14:13:01 -0800331 * Sets values back to the initial state, clearing any held references.
332 */
333 void reset() {
334 caller = null;
335 intent = null;
336 ephemeralIntent = null;
337 resolvedType = null;
338 activityInfo = null;
339 resolveInfo = null;
340 voiceSession = null;
341 voiceInteractor = null;
342 resultTo = null;
343 resultWho = null;
344 requestCode = 0;
Bryce Leea3cd8e02018-01-09 15:44:24 -0800345 callingPid = DEFAULT_CALLING_PID;
346 callingUid = DEFAULT_CALLING_UID;
Bryce Leedaa91e42017-12-06 14:13:01 -0800347 callingPackage = null;
348 realCallingPid = 0;
349 realCallingUid = 0;
350 startFlags = 0;
351 activityOptions = null;
352 ignoreTargetSecurity = false;
353 componentSpecified = false;
354 outActivity = null;
355 inTask = null;
356 reason = null;
357 profilerInfo = null;
358 globalConfig = null;
Bryce Leedaa91e42017-12-06 14:13:01 -0800359 userId = 0;
360 waitResult = null;
361 mayWait = false;
Winson Chunge2d72172018-01-25 17:46:20 +0000362 avoidMoveToFront = false;
Bryce Leedaa91e42017-12-06 14:13:01 -0800363 }
364
365 /**
366 * Adopts all values from passed in request.
367 */
368 void set(Request request) {
369 caller = request.caller;
370 intent = request.intent;
371 ephemeralIntent = request.ephemeralIntent;
372 resolvedType = request.resolvedType;
373 activityInfo = request.activityInfo;
374 resolveInfo = request.resolveInfo;
375 voiceSession = request.voiceSession;
376 voiceInteractor = request.voiceInteractor;
377 resultTo = request.resultTo;
378 resultWho = request.resultWho;
379 requestCode = request.requestCode;
380 callingPid = request.callingPid;
381 callingUid = request.callingUid;
382 callingPackage = request.callingPackage;
383 realCallingPid = request.realCallingPid;
384 realCallingUid = request.realCallingUid;
385 startFlags = request.startFlags;
386 activityOptions = request.activityOptions;
387 ignoreTargetSecurity = request.ignoreTargetSecurity;
388 componentSpecified = request.componentSpecified;
389 outActivity = request.outActivity;
390 inTask = request.inTask;
391 reason = request.reason;
392 profilerInfo = request.profilerInfo;
393 globalConfig = request.globalConfig;
Bryce Leedaa91e42017-12-06 14:13:01 -0800394 userId = request.userId;
395 waitResult = request.waitResult;
396 mayWait = request.mayWait;
Winson Chunge2d72172018-01-25 17:46:20 +0000397 avoidMoveToFront = request.avoidMoveToFront;
Bryce Leedaa91e42017-12-06 14:13:01 -0800398 }
Bryce Leed3624e12017-11-30 08:51:45 -0800399 }
400
401 ActivityStarter(ActivityStartController controller, ActivityManagerService service,
402 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
403 mController = controller;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800404 mService = service;
Bryce Leed3624e12017-11-30 08:51:45 -0800405 mSupervisor = supervisor;
406 mInterceptor = interceptor;
Bryce Leedaa91e42017-12-06 14:13:01 -0800407 reset(true);
408 }
409
410 /**
411 * Effectively duplicates the starter passed in. All state and request values will be
412 * mirrored.
413 * @param starter
414 */
415 void set(ActivityStarter starter) {
416 mStartActivity = starter.mStartActivity;
417 mIntent = starter.mIntent;
418 mCallingUid = starter.mCallingUid;
419 mOptions = starter.mOptions;
420
421 mLaunchTaskBehind = starter.mLaunchTaskBehind;
422 mLaunchFlags = starter.mLaunchFlags;
423 mLaunchMode = starter.mLaunchMode;
424
Bryce Leeec55eb02017-12-05 20:51:27 -0800425 mLaunchParams.set(starter.mLaunchParams);
Bryce Leedaa91e42017-12-06 14:13:01 -0800426
427 mNotTop = starter.mNotTop;
428 mDoResume = starter.mDoResume;
429 mStartFlags = starter.mStartFlags;
430 mSourceRecord = starter.mSourceRecord;
431 mPreferredDisplayId = starter.mPreferredDisplayId;
432
433 mInTask = starter.mInTask;
434 mAddingToTask = starter.mAddingToTask;
435 mReuseTask = starter.mReuseTask;
436
437 mNewTaskInfo = starter.mNewTaskInfo;
438 mNewTaskIntent = starter.mNewTaskIntent;
439 mSourceStack = starter.mSourceStack;
440
441 mTargetStack = starter.mTargetStack;
442 mMovedToFront = starter.mMovedToFront;
443 mNoAnimation = starter.mNoAnimation;
444 mKeepCurTransition = starter.mKeepCurTransition;
445 mAvoidMoveToFront = starter.mAvoidMoveToFront;
446
447 mVoiceSession = starter.mVoiceSession;
448 mVoiceInteractor = starter.mVoiceInteractor;
449
450 mIntentDelivered = starter.mIntentDelivered;
451
452 mRequest.set(starter.mRequest);
Bryce Leed3624e12017-11-30 08:51:45 -0800453 }
454
Bryce Lee4c9a5972017-12-01 22:14:24 -0800455 ActivityRecord getStartActivity() {
456 return mStartActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800457 }
458
Bryce Lee4c9a5972017-12-01 22:14:24 -0800459 boolean relatedToPackage(String packageName) {
460 return (mLastStartActivityRecord[0] != null
461 && packageName.equals(mLastStartActivityRecord[0].packageName))
462 || (mStartActivity != null && packageName.equals(mStartActivity.packageName));
463 }
464
465 /**
466 * Starts an activity based on the request parameters provided earlier.
467 * @return The starter result.
468 */
469 int execute() {
Bryce Leedaa91e42017-12-06 14:13:01 -0800470 try {
471 // TODO(b/64750076): Look into passing request directly to these methods to allow
472 // for transactional diffs and preprocessing.
473 if (mRequest.mayWait) {
474 return startActivityMayWait(mRequest.caller, mRequest.callingUid,
475 mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
476 mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
477 mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
478 mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100479 mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
Bryce Leedaa91e42017-12-06 14:13:01 -0800480 mRequest.inTask, mRequest.reason);
481 } else {
482 return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
483 mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
484 mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
485 mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
486 mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
487 mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
488 mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
489 mRequest.outActivity, mRequest.inTask, mRequest.reason);
490 }
491 } finally {
492 onExecutionComplete();
493 }
494 }
495
496 /**
497 * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
498 * Note that this method is called internally as well as part of {@link #startActivity}.
499 *
500 * @return The start result.
501 */
502 int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
503 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
504 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
505 ActivityRecord[] outActivity) {
506 try {
507 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
508 doResume, options, inTask, outActivity);
509 } finally {
510 onExecutionComplete();
Bryce Lee4c9a5972017-12-01 22:14:24 -0800511 }
512 }
513
514 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700515 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
516 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
517 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
518 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100519 SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700520 ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700521
522 if (TextUtils.isEmpty(reason)) {
523 throw new IllegalArgumentException("Need to specify a reason.");
524 }
525 mLastStartReason = reason;
526 mLastStartActivityTimeMs = System.currentTimeMillis();
527 mLastStartActivityRecord[0] = null;
528
529 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
530 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
531 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
532 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700533 inTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700534
535 if (outActivity != null) {
536 // mLastStartActivityRecord[0] is set in the call to startActivity above.
537 outActivity[0] = mLastStartActivityRecord[0];
538 }
Bryce Leef9d49542017-06-26 16:27:32 -0700539
Bryce Lee93e7f792017-10-25 15:54:55 -0700540 return getExternalResult(mLastStartActivityResult);
541 }
542
Bryce Leed3624e12017-11-30 08:51:45 -0800543 static int getExternalResult(int result) {
Bryce Leef9d49542017-06-26 16:27:32 -0700544 // Aborted results are treated as successes externally, but we must track them internally.
Bryce Lee93e7f792017-10-25 15:54:55 -0700545 return result != START_ABORTED ? result : START_SUCCESS;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700546 }
547
Bryce Leedaa91e42017-12-06 14:13:01 -0800548 /**
549 * Called when execution is complete. Sets state indicating completion and proceeds with
550 * recycling if appropriate.
551 */
552 private void onExecutionComplete() {
553 mController.onExecutionComplete(this);
554 }
555
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700556 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800557 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
558 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
559 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
560 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100561 SafeActivityOptions options,
562 boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
563 TaskRecord inTask) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800564 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700565 // Pull the optional Ephemeral Installer-only bundle out of the options early.
566 final Bundle verificationBundle
567 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800568
569 ProcessRecord callerApp = null;
570 if (caller != null) {
571 callerApp = mService.getRecordForAppLocked(caller);
572 if (callerApp != null) {
573 callingPid = callerApp.pid;
574 callingUid = callerApp.info.uid;
575 } else {
576 Slog.w(TAG, "Unable to find app for caller " + caller
577 + " (pid=" + callingPid + ") when starting: "
578 + intent.toString());
579 err = ActivityManager.START_PERMISSION_DENIED;
580 }
581 }
582
Bryce Lee93e7f792017-10-25 15:54:55 -0700583 final int userId = aInfo != null && aInfo.applicationInfo != null
584 ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800585
586 if (err == ActivityManager.START_SUCCESS) {
587 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800588 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800589 }
590
591 ActivityRecord sourceRecord = null;
592 ActivityRecord resultRecord = null;
593 if (resultTo != null) {
594 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
595 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
596 "Will send result to " + resultTo + " " + sourceRecord);
597 if (sourceRecord != null) {
598 if (requestCode >= 0 && !sourceRecord.finishing) {
599 resultRecord = sourceRecord;
600 }
601 }
602 }
603
604 final int launchFlags = intent.getFlags();
605
606 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
607 // Transfer the result target from the source activity to the new
608 // one being started, including any failures.
609 if (requestCode >= 0) {
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100610 SafeActivityOptions.abort(options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800611 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
612 }
613 resultRecord = sourceRecord.resultTo;
614 if (resultRecord != null && !resultRecord.isInStackLocked()) {
615 resultRecord = null;
616 }
617 resultWho = sourceRecord.resultWho;
618 requestCode = sourceRecord.requestCode;
619 sourceRecord.resultTo = null;
620 if (resultRecord != null) {
621 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
622 }
623 if (sourceRecord.launchedFromUid == callingUid) {
624 // The new activity is being launched from the same uid as the previous
625 // activity in the flow, and asking to forward its result back to the
626 // previous. In this case the activity is serving as a trampoline between
627 // the two, so we also want to update its launchedFromPackage to be the
628 // same as the previous activity. Note that this is safe, since we know
629 // these two packages come from the same uid; the caller could just as
630 // well have supplied that same package name itself. This specifially
631 // deals with the case of an intent picker/chooser being launched in the app
632 // flow to redirect to an activity picked by the user, where we want the final
633 // activity to consider it to have been launched by the previous app activity.
634 callingPackage = sourceRecord.launchedFromPackage;
635 }
636 }
637
638 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
639 // We couldn't find a class that can handle the given Intent.
640 // That's the end of that!
641 err = ActivityManager.START_INTENT_NOT_RESOLVED;
642 }
643
644 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
645 // We couldn't find the specific class specified in the Intent.
646 // Also the end of the line.
647 err = ActivityManager.START_CLASS_NOT_FOUND;
648 }
649
650 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700651 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800652 // If this activity is being launched as part of a voice session, we need
653 // to ensure that it is safe to do so. If the upcoming activity will also
654 // be part of the voice session, we can only launch it if it has explicitly
655 // said it supports the VOICE category, or it is a part of the calling app.
656 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
657 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
658 try {
659 intent.addCategory(Intent.CATEGORY_VOICE);
Bryce Leeba8f4422017-11-20 12:35:57 -0800660 if (!mService.getPackageManager().activitySupportsIntent(
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800661 intent.getComponent(), intent, resolvedType)) {
662 Slog.w(TAG,
663 "Activity being started in current voice task does not support voice: "
664 + intent);
665 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
666 }
667 } catch (RemoteException e) {
668 Slog.w(TAG, "Failure checking voice capabilities", e);
669 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
670 }
671 }
672 }
673
674 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
675 // If the caller is starting a new voice session, just make sure the target
676 // is actually allowing it to run this way.
677 try {
Bryce Leeba8f4422017-11-20 12:35:57 -0800678 if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800679 intent, resolvedType)) {
680 Slog.w(TAG,
681 "Activity being started in new voice task does not support: "
682 + intent);
683 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
684 }
685 } catch (RemoteException e) {
686 Slog.w(TAG, "Failure checking voice capabilities", e);
687 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
688 }
689 }
690
Andrii Kulian02b7a832016-10-06 23:11:56 -0700691 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800692
Wale Ogunwale01d66562015-12-29 08:19:19 -0800693 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800694 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800695 resultStack.sendActivityResultLocked(
696 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800697 }
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100698 SafeActivityOptions.abort(options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800699 return err;
700 }
701
702 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100703 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
704 callerApp, resultRecord, resultStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800705 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
706 callingPid, resolvedType, aInfo.applicationInfo);
707
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100708 // Merge the two options bundles, while realCallerOptions takes precedence.
709 ActivityOptions checkedOptions = options != null
710 ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
711 : null;
Jorim Jaggi04dc5962018-01-29 18:54:13 +0100712 checkedOptions = mService.getActivityStartController().getPendingRemoteAnimationRegistry()
713 .overrideOptionsIfNeeded(callingPackage, checkedOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800714 if (mService.mController != null) {
715 try {
716 // The Intent we give to the watcher has the extra data
717 // stripped off, since it can contain private information.
718 Intent watchIntent = intent.cloneFilter();
719 abort |= !mService.mController.activityStarting(watchIntent,
720 aInfo.applicationInfo.packageName);
721 } catch (RemoteException e) {
722 mService.mController = null;
723 }
724 }
725
Rubin Xu58d25992016-01-21 17:47:13 +0000726 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Benjamin Franz563707b2017-06-29 15:06:13 +0100727 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100728 callingUid, checkedOptions)) {
Benjamin Franz563707b2017-06-29 15:06:13 +0100729 // activity start was intercepted, e.g. because the target user is currently in quiet
730 // mode (turn off work) or the target application is suspended
731 intent = mInterceptor.mIntent;
732 rInfo = mInterceptor.mRInfo;
733 aInfo = mInterceptor.mAInfo;
734 resolvedType = mInterceptor.mResolvedType;
735 inTask = mInterceptor.mInTask;
736 callingPid = mInterceptor.mCallingPid;
737 callingUid = mInterceptor.mCallingUid;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100738 checkedOptions = mInterceptor.mActivityOptions;
Benjamin Franz563707b2017-06-29 15:06:13 +0100739 }
740
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800741 if (abort) {
742 if (resultRecord != null) {
743 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800744 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800745 }
746 // We pretend to the caller that it was really started, but
747 // they will just get a cancel result.
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100748 ActivityOptions.abort(checkedOptions);
Bryce Leef9d49542017-06-26 16:27:32 -0700749 return START_ABORTED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800750 }
751
752 // If permissions need a review before any of the app components can run, we
753 // launch the review activity and pass a pending intent to start the activity
754 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700755 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800756 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
757 aInfo.packageName, userId)) {
758 IIntentSender target = mService.getIntentSenderLocked(
759 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
760 callingUid, userId, null, null, 0, new Intent[]{intent},
761 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
762 | PendingIntent.FLAG_ONE_SHOT, null);
763
764 final int flags = intent.getFlags();
765 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
766 newIntent.setFlags(flags
767 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
768 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
769 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
770 if (resultRecord != null) {
771 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
772 }
773 intent = newIntent;
774
775 resolvedType = null;
776 callingUid = realCallingUid;
777 callingPid = realCallingPid;
778
779 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
780 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
781 null /*profilerInfo*/);
782
783 if (DEBUG_PERMISSIONS_REVIEW) {
784 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
785 true, false) + "} from uid " + callingUid + " on display "
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700786 + (mSupervisor.mFocusedStack == null
787 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800788 }
789 }
790 }
791
792 // If we have an ephemeral app, abort the process of launching the resolved intent.
793 // Instead, launch the ephemeral installer. Once the installer is finished, it
794 // starts either the intent we resolved here [on install error] or the ephemeral
795 // app [on install success].
Patrick Baumanna89a1722018-02-07 15:26:52 -0800796 if (rInfo != null && rInfo.auxiliaryInfo != null) {
Todd Kennedye9910222017-02-21 16:00:11 -0800797 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700798 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800799 resolvedType = null;
800 callingUid = realCallingUid;
801 callingPid = realCallingPid;
802
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800803 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
804 }
805
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800806 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
807 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
808 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100809 mSupervisor, checkedOptions, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800810 if (outActivity != null) {
811 outActivity[0] = r;
812 }
813
814 if (r.appTimeTracker == null && sourceRecord != null) {
815 // If the caller didn't specify an explicit time tracker, we want to continue
816 // tracking under any it has.
817 r.appTimeTracker = sourceRecord.appTimeTracker;
818 }
819
820 final ActivityStack stack = mSupervisor.mFocusedStack;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100821
822 // If we are starting an activity that is not from the same uid as the currently resumed
823 // one, check whether app switches are allowed.
Bryce Leec4ab62a2018-03-05 14:19:26 -0800824 if (voiceSession == null && (stack.getResumedActivity() == null
825 || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800826 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
827 realCallingPid, realCallingUid, "Activity start")) {
Bryce Leed3624e12017-11-30 08:51:45 -0800828 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
829 sourceRecord, startFlags, stack, callerApp));
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100830 ActivityOptions.abort(checkedOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800831 return ActivityManager.START_SWITCHES_CANCELED;
832 }
833 }
834
835 if (mService.mDidAppSwitch) {
836 // This is the second allowed switch since we stopped switches,
837 // so now just generally allow switches. Use case: user presses
838 // home (switches disabled, switch to home, mDidAppSwitch now true);
839 // user taps a home icon (coming from home so allowed, we hit here
840 // and now allow anyone to switch again).
841 mService.mAppSwitchesAllowedTime = 0;
842 } else {
843 mService.mDidAppSwitch = true;
844 }
845
Bryce Leed3624e12017-11-30 08:51:45 -0800846 mController.doPendingActivityLaunches(false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800847
Bryce Leedaa91e42017-12-06 14:13:01 -0800848 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100849 true /* doResume */, checkedOptions, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800850 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800851
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100852
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800853 /**
854 * Creates a launch intent for the given auxiliary resolution data.
855 */
Patrick Baumann577d4022018-01-31 16:55:10 +0000856 private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700857 Intent originalIntent, String callingPackage, Bundle verificationBundle,
858 String resolvedType, int userId) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000859 if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
Todd Kennedye9910222017-02-21 16:00:11 -0800860 // request phase two resolution
861 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700862 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
863 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800864 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700865 return InstantAppResolver.buildEphemeralInstallerIntent(
Patrick Baumann577d4022018-01-31 16:55:10 +0000866 originalIntent,
867 InstantAppResolver.sanitizeIntent(originalIntent),
868 auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent,
869 callingPackage,
870 verificationBundle,
871 resolvedType,
872 userId,
873 auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity,
874 auxiliaryResponse == null ? null : auxiliaryResponse.token,
875 auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo,
876 auxiliaryResponse == null ? null : auxiliaryResponse.filters);
Todd Kennedye9910222017-02-21 16:00:11 -0800877 }
878
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700879 void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
Bryce Lee7f936862017-05-09 15:33:18 -0700880 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800881 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800882 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800883
Chong Zhang5022da32016-06-21 16:31:37 -0700884 // We're waiting for an activity launch to finish, but that activity simply
Bryce Lee5f0e28f2018-01-30 16:00:03 -0800885 // brought another activity to front. We must also handle the case where the task is already
886 // in the front as a result of the trampoline activity being in the same task (it will be
887 // considered focused as the trampoline will be finished). Let startActivityMayWait() know
888 // about this, so it waits for the new activity to become visible instead.
889 mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);
Chong Zhang5022da32016-06-21 16:31:37 -0700890
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700891 ActivityStack startedActivityStack = null;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700892 final ActivityStack currentStack = r.getStack();
893 if (currentStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700894 startedActivityStack = currentStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800895 } else if (mTargetStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700896 startedActivityStack = targetStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800897 }
898
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700899 if (startedActivityStack == null) {
900 return;
901 }
902
Wale Ogunwaleac36e4d2017-11-29 13:30:26 -0800903 final int clearTaskFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK;
904 boolean clearedTask = (mLaunchFlags & clearTaskFlags) == clearTaskFlags
905 && mReuseTask != null;
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700906 if (startedActivityStack.inPinnedWindowingMode()
907 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
908 || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800909 // The activity was already running in the pinned stack so it wasn't started, but either
910 // brought to the front or the new intent was delivered to it since it was already in
911 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700912 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
913 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800914 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800915 }
916
Bryce Lee4c9a5972017-12-01 22:14:24 -0800917 private int startActivityMayWait(IApplicationThread caller, int callingUid,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800918 String callingPackage, Intent intent, String resolvedType,
919 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
920 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700921 ProfilerInfo profilerInfo, WaitResult outResult,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100922 Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
923 int userId, TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800924 // Refuse possible leaked file descriptors
925 if (intent != null && intent.hasFileDescriptors()) {
926 throw new IllegalArgumentException("File descriptors passed in Intent");
927 }
Bryce Lee2a3cc462017-10-27 10:57:35 -0700928 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800929 boolean componentSpecified = intent.getComponent() != null;
930
931 // Save a copy in case ephemeral needs it
932 final Intent ephemeralIntent = new Intent(intent);
933 // Don't modify the client's object!
934 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700935 if (componentSpecified
Patrick Baumann531db462018-02-13 13:01:47 -0800936 && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
Patrick Baumann577d4022018-01-31 16:55:10 +0000937 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
938 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700939 && mService.getPackageManagerInternalLocked()
940 .isInstantAppInstallerComponent(intent.getComponent())) {
941 // intercept intents targeted directly to the ephemeral installer the
Patrick Baumann577d4022018-01-31 16:55:10 +0000942 // ephemeral installer should never be started with a raw Intent; instead
Todd Kennedyb21be122017-03-24 14:10:01 -0700943 // adjust the intent so it looks like a "normal" instant app launch
944 intent.setComponent(null /*component*/);
945 componentSpecified = false;
946 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800947
948 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000949 if (rInfo == null) {
950 UserInfo userInfo = mSupervisor.getUserInfo(userId);
951 if (userInfo != null && userInfo.isManagedProfile()) {
952 // Special case for managed profiles, if attempting to launch non-cryto aware
953 // app in a locked managed profile from an unlocked parent allow it to resolve
954 // as user will be sent via confirm credentials to unlock the profile.
955 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700956 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000957 long token = Binder.clearCallingIdentity();
958 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700959 UserInfo parent = userManager.getProfileParent(userId);
960 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
961 && userManager.isUserUnlockingOrUnlocked(parent.id)
962 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000963 } finally {
964 Binder.restoreCallingIdentity(token);
965 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700966 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000967 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600968 PackageManager.MATCH_DIRECT_BOOT_AWARE
969 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000970 }
971 }
972 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800973 // Collect information about the target of the Intent.
974 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
975
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800976 synchronized (mService) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800977 final int realCallingPid = Binder.getCallingPid();
978 final int realCallingUid = Binder.getCallingUid();
979 int callingPid;
980 if (callingUid >= 0) {
981 callingPid = -1;
982 } else if (caller == null) {
983 callingPid = realCallingPid;
984 callingUid = realCallingUid;
985 } else {
986 callingPid = callingUid = -1;
987 }
988
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700989 final ActivityStack stack = mSupervisor.mFocusedStack;
Andrii Kulian8072d112016-09-16 11:11:01 -0700990 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700991 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800992 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
993 "Starting activity when config will change = " + stack.mConfigWillChange);
994
995 final long origId = Binder.clearCallingIdentity();
996
997 if (aInfo != null &&
998 (aInfo.applicationInfo.privateFlags
999 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
1000 // This may be a heavy-weight process! Check to see if we already
1001 // have another, different heavy-weight process running.
1002 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
1003 final ProcessRecord heavy = mService.mHeavyWeightProcess;
1004 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
1005 || !heavy.processName.equals(aInfo.processName))) {
1006 int appCallingUid = callingUid;
1007 if (caller != null) {
1008 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
1009 if (callerApp != null) {
1010 appCallingUid = callerApp.info.uid;
1011 } else {
1012 Slog.w(TAG, "Unable to find app for caller " + caller
1013 + " (pid=" + callingPid + ") when starting: "
1014 + intent.toString());
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01001015 SafeActivityOptions.abort(options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001016 return ActivityManager.START_PERMISSION_DENIED;
1017 }
1018 }
1019
1020 IIntentSender target = mService.getIntentSenderLocked(
1021 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
1022 appCallingUid, userId, null, null, 0, new Intent[] { intent },
1023 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
1024 | PendingIntent.FLAG_ONE_SHOT, null);
1025
1026 Intent newIntent = new Intent();
1027 if (requestCode >= 0) {
1028 // Caller is requesting a result.
1029 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
1030 }
1031 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
1032 new IntentSender(target));
1033 if (heavy.activities.size() > 0) {
1034 ActivityRecord hist = heavy.activities.get(0);
1035 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
1036 hist.packageName);
1037 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -07001038 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001039 }
1040 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
1041 aInfo.packageName);
1042 newIntent.setFlags(intent.getFlags());
1043 newIntent.setClassName("android",
1044 HeavyWeightSwitcherActivity.class.getName());
1045 intent = newIntent;
1046 resolvedType = null;
1047 caller = null;
1048 callingUid = Binder.getCallingUid();
1049 callingPid = Binder.getCallingPid();
1050 componentSpecified = true;
1051 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
1052 aInfo = rInfo != null ? rInfo.activityInfo : null;
1053 if (aInfo != null) {
1054 aInfo = mService.getActivityInfoForUser(aInfo, userId);
1055 }
1056 }
1057 }
1058 }
1059
Jorim Jaggi275561a2016-02-23 10:11:02 -05001060 final ActivityRecord[] outRecord = new ActivityRecord[1];
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01001061 int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
1062 voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
1063 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
1064 ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001065
1066 Binder.restoreCallingIdentity(origId);
1067
1068 if (stack.mConfigWillChange) {
1069 // If the caller also wants to switch to a new configuration,
1070 // do so now. This allows a clean switch, as we are waiting
1071 // for the current activity to pause (so we will not destroy
1072 // it), and have not yet started the next activity.
1073 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
1074 "updateConfiguration()");
1075 stack.mConfigWillChange = false;
1076 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1077 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -07001078 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001079 }
1080
1081 if (outResult != null) {
1082 outResult.result = res;
Bryce Lee4a194382017-04-04 14:32:48 -07001083
Bryce Lee5f0e28f2018-01-30 16:00:03 -08001084 final ActivityRecord r = outRecord[0];
1085
1086 switch(res) {
1087 case START_SUCCESS: {
1088 mSupervisor.mWaitingActivityLaunched.add(outResult);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001089 do {
1090 try {
1091 mService.wait();
1092 } catch (InterruptedException e) {
1093 }
Bryce Lee5f0e28f2018-01-30 16:00:03 -08001094 } while (outResult.result != START_TASK_TO_FRONT
1095 && !outResult.timeout && outResult.who == null);
1096 if (outResult.result == START_TASK_TO_FRONT) {
1097 res = START_TASK_TO_FRONT;
1098 }
1099 break;
1100 }
1101 case START_DELIVERED_TO_TOP: {
1102 outResult.timeout = false;
1103 outResult.who = r.realActivity;
1104 outResult.totalTime = 0;
1105 outResult.thisTime = 0;
1106 break;
1107 }
1108 case START_TASK_TO_FRONT: {
1109 // ActivityRecord may represent a different activity, but it should not be
1110 // in the resumed state.
Bryce Lee7ace3952018-02-16 14:34:32 -08001111 if (r.nowVisible && r.isState(RESUMED)) {
Bryce Lee5f0e28f2018-01-30 16:00:03 -08001112 outResult.timeout = false;
1113 outResult.who = r.realActivity;
1114 outResult.totalTime = 0;
1115 outResult.thisTime = 0;
1116 } else {
1117 outResult.thisTime = SystemClock.uptimeMillis();
1118 mSupervisor.waitActivityVisible(r.realActivity, outResult);
1119 // Note: the timeout variable is not currently not ever set.
1120 do {
1121 try {
1122 mService.wait();
1123 } catch (InterruptedException e) {
1124 }
1125 } while (!outResult.timeout && outResult.who == null);
1126 }
1127 break;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001128 }
1129 }
1130 }
1131
Bryce Lee2a3cc462017-10-27 10:57:35 -07001132 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001133 return res;
1134 }
1135 }
1136
Bryce Leedaa91e42017-12-06 14:13:01 -08001137 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
1138 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1139 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1140 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001141 int result = START_CANCELED;
1142 try {
1143 mService.mWindowManager.deferSurfaceLayout();
1144 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001145 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001146 } finally {
1147 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1148 // activity in an incomplete state can lead to issues, such as performing operations
1149 // without a window container.
Bryce Lee2b8e0372018-04-05 17:01:37 -07001150 final ActivityStack stack = mStartActivity.getStack();
1151 if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
1152 stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
1153 null /* intentResultData */, "startActivity", true /* oomAdj */);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001154 }
1155 mService.mWindowManager.continueSurfaceLayout();
1156 }
1157
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001158 postStartActivityProcessing(r, result, mTargetStack);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001159
1160 return result;
1161 }
1162
1163 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001164 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1165 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001166 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1167 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001168
1169 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1170 voiceInteractor);
1171
1172 computeLaunchingTaskFlags();
1173
1174 computeSourceStack();
1175
1176 mIntent.setFlags(mLaunchFlags);
1177
Bryce Lee4a194382017-04-04 14:32:48 -07001178 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001179
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001180 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1181 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1182 if (mOptions != null) {
1183 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1184 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1185 }
Jorim Jaggi2adba072016-03-03 13:43:39 +01001186
Bryce Leeec55eb02017-12-05 20:51:27 -08001187 // windowing mode and preferred launch display values from {@link LaunchParams} take
1188 // priority over those specified in {@link ActivityOptions}.
1189 if (!mLaunchParams.isEmpty()) {
1190 if (mLaunchParams.hasPreferredDisplay()) {
1191 preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
1192 }
1193
1194 if (mLaunchParams.hasWindowingMode()) {
1195 preferredWindowingMode = mLaunchParams.mWindowingMode;
1196 }
1197 }
1198
Bryce Lee4a194382017-04-04 14:32:48 -07001199 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001200 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1201 // still needs to be a lock task mode violation since the task gets cleared out and
1202 // the device would otherwise leave the locked task.
Bryce Lee2b8e0372018-04-05 17:01:37 -07001203 if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001204 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1205 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001206 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1207 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1208 }
1209
Bryce Leef65ee7e2018-03-26 16:03:47 -07001210 // True if we are clearing top and resetting of a standard (default) launch mode
1211 // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
1212 final boolean clearTopAndResetStandardLaunchMode =
1213 (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
1214 == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
1215 && mLaunchMode == LAUNCH_MULTIPLE;
1216
1217 // If mStartActivity does not have a task associated with it, associate it with the
1218 // reused activity's task. Do not do so if we're clearing top and resetting for a
1219 // standard launchMode activity.
1220 if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
Bryce Lee4a194382017-04-04 14:32:48 -07001221 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001222 }
Bryce Leef65ee7e2018-03-26 16:03:47 -07001223
Bryce Lee4a194382017-04-04 14:32:48 -07001224 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001225 // This task was started because of movement of the activity based on affinity...
1226 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001227 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001228 }
1229
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001230 // This code path leads to delivering a new intent, we want to make sure we schedule it
1231 // as the first operation, in case the activity will be resumed as a result of later
1232 // operations.
1233 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001234 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Bryce Lee7daee392017-10-12 13:46:18 -07001235 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Lee4a194382017-04-04 14:32:48 -07001236 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001237
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001238 // In this situation we want to remove all activities from the task up to the one
1239 // being started. In most cases this means we are resetting the task to its initial
1240 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001241 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1242 mLaunchFlags);
1243
Bryce Lee4a194382017-04-04 14:32:48 -07001244 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001245 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1246 // task reference is needed in the call below to
1247 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001248 if (reusedActivity.getTask() == null) {
1249 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001250 }
1251
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001252 if (top != null) {
1253 if (top.frontOfTask) {
1254 // Activity aliases may mean we use different intents for the top activity,
1255 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001256 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001257 }
Bryce Lee325e09682017-10-05 17:20:25 -07001258 deliverNewIntent(top);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001259 }
1260 }
1261
Bryce Leed3624e12017-11-30 08:51:45 -08001262 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001263
Bryce Lee4a194382017-04-04 14:32:48 -07001264 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001265
Bryce Lee89cd19a2017-05-17 15:18:35 -07001266 final ActivityRecord outResult =
1267 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1268
1269 // When there is a reused activity and the current result is a trampoline activity,
1270 // set the reused activity as the result.
1271 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1272 outActivity[0] = reusedActivity;
1273 }
1274
Wale Ogunwale01d66562015-12-29 08:19:19 -08001275 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1276 // We don't need to start a new activity, and the client said not to do anything
1277 // if that is the case, so this is it! And for paranoia, make sure we have
1278 // correctly resumed the top activity.
1279 resumeTargetStackIfNeeded();
1280 return START_RETURN_INTENT_TO_CALLER;
1281 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001282
Bryce Leef65ee7e2018-03-26 16:03:47 -07001283 if (reusedActivity != null) {
1284 setTaskFromIntentActivity(reusedActivity);
1285
1286 if (!mAddingToTask && mReuseTask == null) {
1287 // We didn't do anything... but it was needed (a.k.a., client don't use that
1288 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1289
1290 resumeTargetStackIfNeeded();
1291 if (outActivity != null && outActivity.length > 0) {
1292 outActivity[0] = reusedActivity;
1293 }
1294
1295 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001296 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001297 }
1298 }
1299
1300 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001301 final ActivityStack sourceStack = mStartActivity.resultTo != null
1302 ? mStartActivity.resultTo.getStack() : null;
1303 if (sourceStack != null) {
1304 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1305 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1306 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001307 }
1308 ActivityOptions.abort(mOptions);
1309 return START_CLASS_NOT_FOUND;
1310 }
1311
1312 // If the activity being launched is the same as the one currently at the top, then
1313 // we need to check if it should only be launched once.
1314 final ActivityStack topStack = mSupervisor.mFocusedStack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001315 final ActivityRecord topFocused = topStack.getTopActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001316 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1317 final boolean dontStart = top != null && mStartActivity.resultTo == null
1318 && top.realActivity.equals(mStartActivity.realActivity)
1319 && top.userId == mStartActivity.userId
1320 && top.app != null && top.app.thread != null
1321 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001322 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001323 if (dontStart) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001324 // For paranoia, make sure we have correctly resumed the top activity.
1325 topStack.mLastPausedActivity = null;
1326 if (mDoResume) {
1327 mSupervisor.resumeFocusedStackTopActivityLocked();
1328 }
1329 ActivityOptions.abort(mOptions);
1330 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1331 // We don't need to start a new activity, and the client said not to do
1332 // anything if that is the case, so this is it!
1333 return START_RETURN_INTENT_TO_CALLER;
1334 }
Bryce Lee325e09682017-10-05 17:20:25 -07001335
1336 deliverNewIntent(top);
Chong Zhangd44063c2016-04-08 11:52:30 -07001337
1338 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1339 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001340 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001341 preferredLaunchDisplayId, topStack);
Chong Zhangd44063c2016-04-08 11:52:30 -07001342
Wale Ogunwale01d66562015-12-29 08:19:19 -08001343 return START_DELIVERED_TO_TOP;
1344 }
1345
1346 boolean newTask = false;
1347 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001348 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001349
1350 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001351 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001352 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1353 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1354 newTask = true;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001355 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001356 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001357 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001358 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001359 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001360 } else {
1361 // This not being started from an existing activity, and not part of a new task...
1362 // just put it in the top task, though these days this case should never happen.
1363 setTaskToCurrentTopOrCreateNewTask();
1364 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001365 if (result != START_SUCCESS) {
1366 return result;
1367 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001368
1369 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1370 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001371 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1372 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001373 if (newTask) {
Wale Ogunwale66e16852017-10-19 13:35:52 -07001374 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
Bryce Leeaf691c02017-03-20 14:20:22 -07001375 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001376 }
1377 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001378 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001379 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001380
Bryce Leed3624e12017-11-30 08:51:45 -08001381 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001382
Winson Chungb5c41b72016-12-07 15:00:47 -08001383 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1384 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001385 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001386 final ActivityRecord topTaskActivity =
1387 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001388 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001389 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1390 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001391 // If the activity is not focusable, we can't resume it, but still would like to
1392 // make sure it becomes visible as it starts (this will also trigger entry
1393 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001394 // Also, we don't want to resume activities in a task that currently has an overlay
1395 // as the starting activity just needs to be in the visible paused state until the
1396 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001397 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001398 // Go ahead and tell window manager to execute app transition for this activity
1399 // since the app transition will not be triggered through the resume channel.
Bryce Lee7daee392017-10-12 13:46:18 -07001400 mService.mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001401 } else {
Winson Chung32066032016-11-04 11:55:21 -07001402 // If the target stack was not previously focusable (previous top running activity
1403 // on that stack was not visible) then any prior calls to move the stack to the
1404 // will not update the focused stack. If starting the new activity now allows the
1405 // task stack to be focusable, then ensure that we now update the focused stack
1406 // accordingly.
1407 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1408 mTargetStack.moveToFront("startActivityUnchecked");
1409 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001410 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1411 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001412 }
Winson Chung1dbc8112017-09-28 18:05:31 -07001413 } else if (mStartActivity != null) {
1414 mSupervisor.mRecentTasks.add(mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001415 }
1416 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1417
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001418 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001419 preferredLaunchDisplayId, mTargetStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001420
1421 return START_SUCCESS;
1422 }
1423
Bryce Leedaa91e42017-12-06 14:13:01 -08001424 /**
1425 * Resets the {@link ActivityStarter} state.
1426 * @param clearRequest whether the request should be reset to default values.
1427 */
1428 void reset(boolean clearRequest) {
1429 mStartActivity = null;
1430 mIntent = null;
1431 mCallingUid = -1;
1432 mOptions = null;
1433
1434 mLaunchTaskBehind = false;
1435 mLaunchFlags = 0;
1436 mLaunchMode = INVALID_LAUNCH_MODE;
1437
Bryce Leeec55eb02017-12-05 20:51:27 -08001438 mLaunchParams.reset();
Bryce Leedaa91e42017-12-06 14:13:01 -08001439
1440 mNotTop = null;
1441 mDoResume = false;
1442 mStartFlags = 0;
1443 mSourceRecord = null;
1444 mPreferredDisplayId = INVALID_DISPLAY;
1445
1446 mInTask = null;
1447 mAddingToTask = false;
1448 mReuseTask = null;
1449
1450 mNewTaskInfo = null;
1451 mNewTaskIntent = null;
1452 mSourceStack = null;
1453
1454 mTargetStack = null;
1455 mMovedToFront = false;
1456 mNoAnimation = false;
1457 mKeepCurTransition = false;
1458 mAvoidMoveToFront = false;
1459
1460 mVoiceSession = null;
1461 mVoiceInteractor = null;
1462
1463 mIntentDelivered = false;
1464
1465 if (clearRequest) {
1466 mRequest.reset();
1467 }
1468 }
1469
Wale Ogunwale01d66562015-12-29 08:19:19 -08001470 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1471 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1472 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
Bryce Leedaa91e42017-12-06 14:13:01 -08001473 reset(false /* clearRequest */);
1474
Wale Ogunwale01d66562015-12-29 08:19:19 -08001475 mStartActivity = r;
1476 mIntent = r.intent;
1477 mOptions = options;
1478 mCallingUid = r.launchedFromUid;
1479 mSourceRecord = sourceRecord;
1480 mVoiceSession = voiceSession;
1481 mVoiceInteractor = voiceInteractor;
1482
David Stevense5a7b642017-05-22 13:18:23 -07001483 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
David Stevensc6b91c62017-02-08 14:23:58 -08001484
Bryce Leeec55eb02017-12-05 20:51:27 -08001485 mLaunchParams.reset();
Bryce Leedacefc42017-10-10 12:56:02 -07001486
Bryce Leeec55eb02017-12-05 20:51:27 -08001487 mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
1488 options, mLaunchParams);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001489
Bryce Lee7daee392017-10-12 13:46:18 -07001490 mLaunchMode = r.launchMode;
1491
Wale Ogunwale01d66562015-12-29 08:19:19 -08001492 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
Bryce Lee7daee392017-10-12 13:46:18 -07001493 r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1494 LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001495 mLaunchTaskBehind = r.mLaunchTaskBehind
Bryce Lee7daee392017-10-12 13:46:18 -07001496 && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001497 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1498
1499 sendNewTaskResultRequestIfNeeded();
1500
1501 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1502 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1503 }
1504
1505 // If we are actually going to launch in to a new task, there are some cases where
1506 // we further want to do multiple task.
1507 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1508 if (mLaunchTaskBehind
1509 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1510 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1511 }
1512 }
1513
1514 // We'll invoke onUserLeaving before onPause only if the launching
1515 // activity did not explicitly state that this is an automated launch.
1516 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1517 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1518 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1519
1520 // If the caller has asked not to resume at this point, we make note
1521 // of this in the record so that we can skip it when trying to find
1522 // the top running activity.
1523 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001524 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001525 r.delayedResume = true;
1526 mDoResume = false;
1527 }
1528
Winson Chunge2d72172018-01-25 17:46:20 +00001529 if (mOptions != null) {
1530 if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1531 r.mTaskOverlay = true;
1532 if (!mOptions.canTaskOverlayResume()) {
1533 final TaskRecord task = mSupervisor.anyTaskForIdLocked(
1534 mOptions.getLaunchTaskId());
1535 final ActivityRecord top = task != null ? task.getTopActivity() : null;
Bryce Lee7ace3952018-02-16 14:34:32 -08001536 if (top != null && !top.isState(RESUMED)) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001537
Winson Chunge2d72172018-01-25 17:46:20 +00001538 // The caller specifies that we'd like to be avoided to be moved to the
1539 // front, so be it!
1540 mDoResume = false;
1541 mAvoidMoveToFront = true;
1542 }
Winson Chungcbcadc92017-01-12 15:54:12 -08001543 }
Winson Chunge2d72172018-01-25 17:46:20 +00001544 } else if (mOptions.getAvoidMoveToFront()) {
1545 mAvoidMoveToFront = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001546 }
1547 }
1548
Wale Ogunwale01d66562015-12-29 08:19:19 -08001549 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1550
1551 mInTask = inTask;
1552 // In some flows in to this function, we retrieve the task record and hold on to it
1553 // without a lock before calling back in to here... so the task at this point may
1554 // not actually be in recents. Check for that, and if it isn't in recents just
1555 // consider it invalid.
1556 if (inTask != null && !inTask.inRecents) {
1557 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1558 mInTask = null;
1559 }
1560
1561 mStartFlags = startFlags;
1562 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1563 // is the same as the one making the call... or, as a special case, if we do not know
1564 // the caller then we count the current top activity as the caller.
1565 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1566 ActivityRecord checkedCaller = sourceRecord;
1567 if (checkedCaller == null) {
1568 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1569 mNotTop);
1570 }
1571 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1572 // Caller is not the same as launcher, so always needed.
1573 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1574 }
1575 }
1576
1577 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1578 }
1579
1580 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001581 final ActivityStack sourceStack = mStartActivity.resultTo != null
1582 ? mStartActivity.resultTo.getStack() : null;
1583 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001584 // For whatever reason this activity is being launched into a new task...
1585 // yet the caller has requested a result back. Well, that is pretty messed up,
1586 // so instead immediately send back a cancel and let the new task continue launched
1587 // as normal without a dependency on its originator.
1588 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001589 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1590 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1591 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001592 mStartActivity.resultTo = null;
1593 }
1594 }
1595
1596 private void computeLaunchingTaskFlags() {
1597 // If the caller is not coming from another activity, but has given us an explicit task into
1598 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001599 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001600 final Intent baseIntent = mInTask.getBaseIntent();
1601 final ActivityRecord root = mInTask.getRootActivity();
1602 if (baseIntent == null) {
1603 ActivityOptions.abort(mOptions);
1604 throw new IllegalArgumentException("Launching into task without base intent: "
1605 + mInTask);
1606 }
1607
1608 // If this task is empty, then we are adding the first activity -- it
1609 // determines the root, and must be launching as a NEW_TASK.
Bryce Lee7daee392017-10-12 13:46:18 -07001610 if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001611 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1612 ActivityOptions.abort(mOptions);
1613 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1614 + mStartActivity + " into different task " + mInTask);
1615 }
1616 if (root != null) {
1617 ActivityOptions.abort(mOptions);
1618 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1619 + " has root " + root + " but target is singleInstance/Task");
1620 }
1621 }
1622
1623 // If task is empty, then adopt the interesting intent launch flags in to the
1624 // activity being started.
1625 if (root == null) {
1626 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1627 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1628 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1629 | (baseIntent.getFlags() & flagsOfInterest);
1630 mIntent.setFlags(mLaunchFlags);
1631 mInTask.setIntent(mStartActivity);
1632 mAddingToTask = true;
1633
1634 // If the task is not empty and the caller is asking to start it as the root of
1635 // a new task, then we don't actually want to start this on the task. We will
1636 // bring the task to the front, and possibly give it a new intent.
1637 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1638 mAddingToTask = false;
1639
1640 } else {
1641 mAddingToTask = true;
1642 }
1643
1644 mReuseTask = mInTask;
1645 } else {
1646 mInTask = null;
1647 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1648 // when in freeform workspace.
1649 // Also put noDisplay activities in the source task. These by itself can be placed
1650 // in any task/stack, however it could launch other activities like ResolverActivity,
1651 // and we want those to stay in the original task.
1652 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001653 && mSourceRecord.inFreeformWindowingMode()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001654 mAddingToTask = true;
1655 }
1656 }
1657
1658 if (mInTask == null) {
1659 if (mSourceRecord == null) {
1660 // This activity is not being started from another... in this
1661 // case we -always- start a new task.
1662 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1663 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1664 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1665 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1666 }
1667 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1668 // The original activity who is starting us is running as a single
1669 // instance... this new activity it is starting must go on its
1670 // own task.
1671 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
Bryce Lee7daee392017-10-12 13:46:18 -07001672 } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001673 // The activity being started is a single instance... it always
1674 // gets launched into its own task.
1675 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1676 }
1677 }
1678 }
1679
1680 private void computeSourceStack() {
1681 if (mSourceRecord == null) {
1682 mSourceStack = null;
1683 return;
1684 }
1685 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001686 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001687 return;
1688 }
1689
1690 // If the source is finishing, we can't further count it as our source. This is because the
1691 // task it is associated with may now be empty and on its way out, so we don't want to
1692 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1693 // a task for it. But save the task information so it can be used when creating the new task.
1694 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1695 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1696 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1697 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1698 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001699
1700 // It is not guaranteed that the source record will have a task associated with it. For,
1701 // example, if this method is being called for processing a pending activity launch, it
1702 // is possible that the activity has been removed from the task after the launch was
1703 // enqueued.
1704 final TaskRecord sourceTask = mSourceRecord.getTask();
1705 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001706 }
1707 mSourceRecord = null;
1708 mSourceStack = null;
1709 }
1710
1711 /**
1712 * Decide whether the new activity should be inserted into an existing task. Returns null
1713 * if not or an ActivityRecord with the task into which the new activity should be added.
1714 */
1715 private ActivityRecord getReusableIntentActivity() {
1716 // We may want to try to place the new activity in to an existing task. We always
1717 // do this if the target activity is singleTask or singleInstance; we will also do
1718 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1719 // us to still place it in a new task: multi task, always doc mode, or being asked to
1720 // launch this as a new task behind the current one.
1721 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1722 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
Bryce Lee7daee392017-10-12 13:46:18 -07001723 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001724 // If bring to front is requested, and no result is requested and we have not been given
1725 // an explicit task to launch in to, and we can find a task that was started with this
1726 // same component, then instead of launching bring that one to the front.
1727 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1728 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001729 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1730 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1731 intentActivity = task != null ? task.getTopActivity() : null;
1732 } else if (putIntoExistingTask) {
Bryce Lee7daee392017-10-12 13:46:18 -07001733 if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001734 // There can be one and only one instance of single instance activity in the
1735 // history, and it is always in its own unique task, so we do a special search.
Bryce Lee28d80422017-07-21 13:25:13 -07001736 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001737 mStartActivity.isActivityTypeHome());
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001738 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1739 // For the launch adjacent case we only want to put the activity in an existing
1740 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001741 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Bryce Lee7daee392017-10-12 13:46:18 -07001742 !(LAUNCH_SINGLE_TASK == mLaunchMode));
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001743 } else {
1744 // Otherwise find the best task to put the activity in.
David Stevense5a7b642017-05-22 13:18:23 -07001745 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001746 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001747 }
1748 return intentActivity;
1749 }
1750
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001751 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001752 * Returns the ID of the display to use for a new activity. If the device is in VR mode,
David Stevense5a7b642017-05-22 13:18:23 -07001753 * then return the Vr mode's virtual display ID. If not, if the activity was started with
1754 * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1755 * set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001756 */
David Stevense5a7b642017-05-22 13:18:23 -07001757 private int getPreferedDisplayId(
1758 ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001759 // Check if the Activity is a VR activity. If so, the activity should be launched in
1760 // main display.
1761 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1762 return DEFAULT_DISPLAY;
1763 }
1764
1765 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001766 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001767 if (displayId != INVALID_DISPLAY) {
1768 if (DEBUG_STACK) {
1769 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1770 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001771 return displayId;
1772 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001773
David Stevense5a7b642017-05-22 13:18:23 -07001774 // If the caller requested a display, prefer that display.
1775 final int launchDisplayId =
1776 (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1777 if (launchDisplayId != INVALID_DISPLAY) {
1778 return launchDisplayId;
1779 }
1780
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001781 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1782 // If the activity has a displayId set explicitly, launch it on the same displayId.
1783 if (displayId != INVALID_DISPLAY) {
1784 return displayId;
1785 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001786 return DEFAULT_DISPLAY;
1787 }
1788
1789 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001790 * Figure out which task and activity to bring to front when we have found an existing matching
1791 * activity record in history. May also clear the task if needed.
1792 * @param intentActivity Existing matching activity.
1793 * @return {@link ActivityRecord} brought to front.
1794 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001795 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001796 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001797 mTargetStack.mLastPausedActivity = null;
1798 // If the target task is not in the front, then we need to bring it to the front...
1799 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1800 // the same behavior as if a new instance was being started, which means not bringing it
1801 // to the front if the caller is not itself in the front.
1802 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1803 ActivityRecord curTop = (focusStack == null)
1804 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1805
Bryce Leeaf691c02017-03-20 14:20:22 -07001806 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1807 if (topTask != null
1808 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001809 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001810 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001811 if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1812 mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001813 // We really do want to push this one into the user's face, right now.
1814 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001815 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001816 }
Chong Zhangdea4bd92016-03-15 12:50:03 -07001817
1818 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1819 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1820 // So no point resuming any of the activities here, it just wastes one extra
1821 // resuming, plus enter AND exit transitions.
1822 // Here we only want to bring the target stack forward. Transition will be applied
1823 // to the new activity that's started after the old ones are gone.
1824 final boolean willClearTask =
1825 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1826 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1827 if (!willClearTask) {
1828 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001829 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1830 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001831 if (launchStack == null || launchStack == mTargetStack) {
1832 // We only want to move to the front, if we aren't going to launch on a
1833 // different stack. If we launch on a different stack, we will put the
1834 // task on top there.
chaviw0d562bf2018-03-15 14:24:14 -07001835 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1836 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
Chong Zhangdea4bd92016-03-15 12:50:03 -07001837 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001838 } else if (launchStack.inSplitScreenWindowingMode()) {
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001839 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1840 // If we want to launch adjacent and mTargetStack is not the computed
1841 // launch stack - move task to top of computed stack.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001842 intentTask.reparent(launchStack, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001843 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1844 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001845 } else {
1846 // TODO: This should be reevaluated in MW v2.
1847 // We choose to move task to front instead of launching it adjacent
1848 // when specific stack was requested explicitly and it appeared to be
1849 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
chaviw0d562bf2018-03-15 14:24:14 -07001850 mTargetStack.moveTaskToFrontLocked(intentTask,
Bryce Leeaf691c02017-03-20 14:20:22 -07001851 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001852 "bringToFrontInsteadOfAdjacentLaunch");
1853 }
Bryce Lee32e09ef2018-03-19 15:29:49 -07001854 mMovedToFront = launchStack != launchStack.getDisplay()
1855 .getTopStackInWindowingMode(launchStack.getWindowingMode());
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001856 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1857 // Target and computed stacks are on different displays and we've
1858 // found a matching task - move the existing instance to that display and
1859 // move it to front.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001860 intentActivity.getTask().reparent(launchStack, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001861 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1862 "reparentToDisplay");
1863 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001864 } else if (launchStack.isActivityTypeHome()
1865 && !mTargetStack.isActivityTypeHome()) {
Bryce Lee4ff7da92017-07-17 10:39:24 -07001866 // It is possible for the home activity to be in another stack initially.
1867 // For example, the activity may have been initially started with an intent
1868 // which placed it in the fullscreen stack. To ensure the proper handling of
1869 // the activity based on home stack assumptions, we must move it over.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001870 intentActivity.getTask().reparent(launchStack, ON_TOP,
Bryce Lee4ff7da92017-07-17 10:39:24 -07001871 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1872 "reparentingHome");
1873 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001874 }
1875 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001876
1877 // We are moving a task to the front, use starting window to hide initial drawn
1878 // delay.
1879 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1880 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001881 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001882 }
1883 }
Andrii Kulianb850ea52017-12-12 23:49:10 -08001884 // Need to update mTargetStack because if task was moved out of it, the original stack may
1885 // be destroyed.
1886 mTargetStack = intentActivity.getStack();
Winson Chunge2d72172018-01-25 17:46:20 +00001887 if (!mAvoidMoveToFront && !mMovedToFront && mDoResume) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001888 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1889 + " from " + intentActivity);
1890 mTargetStack.moveToFront("intentActivityFound");
1891 }
1892
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001893 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001894 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001895
Wale Ogunwale01d66562015-12-29 08:19:19 -08001896 // If the caller has requested that the target task be reset, then do so.
1897 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1898 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1899 }
1900 return intentActivity;
1901 }
1902
1903 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1904 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1905 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1906 // The caller has requested to completely replace any existing task with its new
1907 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001908 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1909 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001910 // of history or if it is finished immediately), thus disassociating the task. Also note
1911 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1912 // launching another activity.
1913 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1914 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001915 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001916 task.performClearTaskLocked();
1917 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001918 mReuseTask.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001919 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001920 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001921 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001922 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001923 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001924 // A special case: we need to start the activity because it is not currently
1925 // running, and the caller has asked to clear the current task to have this
1926 // activity at the top.
1927 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001928
1929 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001930 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001931 // Now pretend like this activity is being started by the top of its task, so it
1932 // is put in the right place.
1933 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001934 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001935 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001936 // Target stack got cleared when we all activities were removed above.
1937 // Go ahead and reset it.
1938 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
Bryce Leedacefc42017-10-10 12:56:02 -07001939 mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001940 mTargetStack.addTask(task,
1941 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1942 }
1943 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001944 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001945 // In this case the top activity on the task is the same as the one being launched,
1946 // so we take that as a request to bring the task to the foreground. If the top
1947 // activity in the task is the root activity, deliver this new intent to it if it
1948 // desires.
Bryce Lee7daee392017-10-12 13:46:18 -07001949 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1950 || LAUNCH_SINGLE_TOP == mLaunchMode)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001951 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001952 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001953 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001954 }
Bryce Lee325e09682017-10-05 17:20:25 -07001955 deliverNewIntent(intentActivity);
Bryce Leeaf691c02017-03-20 14:20:22 -07001956 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001957 // In this case we are launching the root activity of the task, but with a
1958 // different intent. We should start a new instance on top.
1959 mAddingToTask = true;
1960 mSourceRecord = intentActivity;
1961 }
1962 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1963 // In this case an activity is being launched in to an existing task, without
1964 // resetting that task. This is typically the situation of launching an activity
1965 // from a notification or shortcut. We want to place the new activity on top of the
1966 // current task.
1967 mAddingToTask = true;
1968 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001969 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001970 // In this case we are launching into an existing task that has not yet been started
1971 // from its front door. The current task has been brought to the front. Ideally,
1972 // we'd probably like to place this new task at the bottom of its stack, but that's
1973 // a little hard to do with the current organization of the code so for now we'll
1974 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001975 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001976 }
1977 }
1978
1979 private void resumeTargetStackIfNeeded() {
1980 if (mDoResume) {
1981 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001982 } else {
1983 ActivityOptions.abort(mOptions);
1984 }
1985 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1986 }
1987
Chong Zhang6cda19c2016-06-14 19:07:56 -07001988 private int setTaskFromReuseOrCreateNewTask(
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001989 TaskRecord taskToAffiliate, ActivityStack topStack) {
Bryce Leedacefc42017-10-10 12:56:02 -07001990 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
Chong Zhang6cda19c2016-06-14 19:07:56 -07001991
1992 // Do no move the target stack to front yet, as we might bail if
1993 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001994
1995 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001996 final TaskRecord task = mTargetStack.createTaskRecord(
1997 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001998 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001999 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
Bryce Leeb802ea12017-11-15 21:25:03 -08002000 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
2001 mOptions);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002002 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Bryce Leeec55eb02017-12-05 20:51:27 -08002003 updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002004
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002005 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002006 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08002007 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002008 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
2009 }
2010
2011 if (taskToAffiliate != null) {
2012 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002013 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002014
Bryce Lee2b8e0372018-04-05 17:01:37 -07002015 if (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002016 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2017 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2018 }
2019
Chong Zhang6cda19c2016-06-14 19:07:56 -07002020 if (mDoResume) {
2021 mTargetStack.moveToFront("reuseOrNewTask");
2022 }
2023 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08002024 }
2025
Bryce Lee325e09682017-10-05 17:20:25 -07002026 private void deliverNewIntent(ActivityRecord activity) {
2027 if (mIntentDelivered) {
2028 return;
2029 }
2030
2031 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
2032 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
2033 mStartActivity.launchedFromPackage);
2034 mIntentDelivered = true;
2035 }
2036
Wale Ogunwale01d66562015-12-29 08:19:19 -08002037 private int setTaskFromSourceRecord() {
Bryce Lee2b8e0372018-04-05 17:01:37 -07002038 if (mService.getLockTaskController().isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002039 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2040 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2041 }
2042
Bryce Leeaf691c02017-03-20 14:20:22 -07002043 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002044 final ActivityStack sourceStack = mSourceRecord.getStack();
Andrii Kulian02689a72017-07-06 14:28:59 -07002045 // We only want to allow changing stack in two cases:
2046 // 1. If the target task is not the top one. Otherwise we would move the launching task to
2047 // the other side, rather than show two side by side.
2048 // 2. If activity is not allowed on target display.
2049 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
2050 : sourceStack.mDisplayId;
2051 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
2052 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002053 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002054 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002055 mOptions);
Andrii Kulian02689a72017-07-06 14:28:59 -07002056 // If target stack is not found now - we can't just rely on the source stack, as it may
2057 // be not suitable. Let's check other displays.
2058 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
2059 // Can't use target display, lets find a stack on the source display.
2060 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
2061 sourceStack.mDisplayId, mStartActivity);
2062 }
2063 if (mTargetStack == null) {
2064 // There are no suitable stacks on the target and source display(s). Look on all
2065 // displays.
2066 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
2067 mStartActivity, -1 /* currentFocus */);
2068 }
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002069 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002070
2071 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002072 mTargetStack = sourceStack;
2073 } else if (mTargetStack != sourceStack) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002074 sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
2075 DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002076 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002077
Wale Ogunwale01d66562015-12-29 08:19:19 -08002078 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07002079 if (topTask != sourceTask && !mAvoidMoveToFront) {
chaviw0d562bf2018-03-15 14:24:14 -07002080 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
Wale Ogunwale01d66562015-12-29 08:19:19 -08002081 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07002082 } else if (mDoResume) {
2083 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002084 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002085
Wale Ogunwale01d66562015-12-29 08:19:19 -08002086 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2087 // In this case, we are adding the activity to an existing task, but the caller has
2088 // asked to clear that task if the activity is already running.
2089 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
2090 mKeepCurTransition = true;
2091 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002092 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Bryce Lee325e09682017-10-05 17:20:25 -07002093 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002094 // For paranoia, make sure we have correctly resumed the top activity.
2095 mTargetStack.mLastPausedActivity = null;
2096 if (mDoResume) {
2097 mSupervisor.resumeFocusedStackTopActivityLocked();
2098 }
2099 ActivityOptions.abort(mOptions);
2100 return START_DELIVERED_TO_TOP;
2101 }
2102 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
2103 // In this case, we are launching an activity in our own task that may already be
2104 // running somewhere in the history, and we want to shuffle it to the front of the
2105 // stack if so.
2106 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
2107 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002108 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08002109 task.moveActivityToFrontLocked(top);
2110 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08002111 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Bryce Lee325e09682017-10-05 17:20:25 -07002112 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002113 mTargetStack.mLastPausedActivity = null;
2114 if (mDoResume) {
2115 mSupervisor.resumeFocusedStackTopActivityLocked();
2116 }
2117 return START_DELIVERED_TO_TOP;
2118 }
2119 }
2120
2121 // An existing activity is starting this new activity, so we want to keep the new one in
2122 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002123 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002124 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002125 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002126 return START_SUCCESS;
2127 }
2128
2129 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002130 // The caller is asking that the new activity be started in an explicit
2131 // task it has provided to us.
Bryce Lee2b8e0372018-04-05 17:01:37 -07002132 if (mService.getLockTaskController().isLockTaskModeViolation(mInTask)) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002133 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2134 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2135 }
2136
Andrii Kulian02b7a832016-10-06 23:11:56 -07002137 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08002138
2139 // Check whether we should actually launch the new activity in to the task,
2140 // or just reuse the current activity on top.
2141 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002142 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
2143 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08002144 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07002145 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
chaviw0d562bf2018-03-15 14:24:14 -07002146 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
Yorke Lee64512522017-03-24 13:09:35 -07002147 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002148 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
2149 // We don't need to start a new activity, and the client said not to do
2150 // anything if that is the case, so this is it!
2151 return START_RETURN_INTENT_TO_CALLER;
2152 }
Bryce Lee325e09682017-10-05 17:20:25 -07002153 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002154 return START_DELIVERED_TO_TOP;
2155 }
2156 }
2157
2158 if (!mAddingToTask) {
chaviw0d562bf2018-03-15 14:24:14 -07002159 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
Yorke Lee64512522017-03-24 13:09:35 -07002160 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002161 // We don't actually want to have this activity added to the task, so just
2162 // stop here but still tell the caller that we consumed the intent.
2163 ActivityOptions.abort(mOptions);
2164 return START_TASK_TO_FRONT;
2165 }
2166
Bryce Leeec55eb02017-12-05 20:51:27 -08002167 if (!mLaunchParams.mBounds.isEmpty()) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002168 // TODO: Shouldn't we already know what stack to use by the time we get here?
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002169 ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
2170 if (stack != mInTask.getStack()) {
2171 mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
Yorke Lee64512522017-03-24 13:09:35 -07002172 DEFER_RESUME, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07002173 mTargetStack = mInTask.getStack();
2174 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002175
Bryce Leeec55eb02017-12-05 20:51:27 -08002176 updateBounds(mInTask, mLaunchParams.mBounds);
Yorke Lee64512522017-03-24 13:09:35 -07002177 }
2178
chaviw0d562bf2018-03-15 14:24:14 -07002179 mTargetStack.moveTaskToFrontLocked(
2180 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07002181
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002182 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
2183 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002184 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08002185
2186 return START_SUCCESS;
2187 }
2188
Bryce Leed3624e12017-11-30 08:51:45 -08002189 @VisibleForTesting
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002190 void updateBounds(TaskRecord task, Rect bounds) {
Bryce Leedacefc42017-10-10 12:56:02 -07002191 if (bounds.isEmpty()) {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002192 return;
2193 }
2194
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002195 final ActivityStack stack = task.getStack();
2196 if (stack != null && stack.resizeStackWithLaunchBounds()) {
2197 mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002198 } else {
2199 task.updateOverrideConfiguration(bounds);
2200 }
2201 }
2202
Wale Ogunwale01d66562015-12-29 08:19:19 -08002203 private void setTaskToCurrentTopOrCreateNewTask() {
Bryce Leedacefc42017-10-10 12:56:02 -07002204 mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002205 if (mDoResume) {
2206 mTargetStack.moveToFront("addingToTopTask");
2207 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -08002208 final ActivityRecord prev = mTargetStack.getTopActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07002209 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08002210 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
Bryce Leeb802ea12017-11-15 21:25:03 -08002211 mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002212 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2213 mTargetStack.positionChildWindowContainerAtTop(task);
2214 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002215 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002216 }
2217
2218 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002219 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002220 parent.addActivityToTop(mStartActivity);
2221 } else {
2222 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2223 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002224 }
2225
2226 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2227 boolean launchSingleTask, int launchFlags) {
2228 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2229 (launchSingleInstance || launchSingleTask)) {
2230 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2231 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2232 "\"singleInstance\" or \"singleTask\"");
2233 launchFlags &=
2234 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2235 } else {
2236 switch (r.info.documentLaunchMode) {
2237 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2238 break;
2239 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2240 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2241 break;
2242 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2243 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2244 break;
2245 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2246 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2247 break;
2248 }
2249 }
2250 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002251 }
2252
Bryce Leedacefc42017-10-10 12:56:02 -07002253 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
2254 ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002255 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002256 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002257 if (stack != null) {
2258 return stack;
2259 }
2260
Andrii Kulian02b7a832016-10-06 23:11:56 -07002261 final ActivityStack currentStack = task != null ? task.getStack() : null;
2262 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002263 if (mSupervisor.mFocusedStack != currentStack) {
2264 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2265 "computeStackFocus: Setting " + "focused stack to r=" + r
2266 + " task=" + task);
2267 } else {
2268 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2269 "computeStackFocus: Focused stack already="
2270 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002271 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002272 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002273 }
2274
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002275 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002276 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2277 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2278 return mSupervisor.mFocusedStack;
2279 }
2280
David Stevense5a7b642017-05-22 13:18:23 -07002281 if (mPreferredDisplayId != DEFAULT_DISPLAY) {
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002282 // Try to put the activity in a stack on a secondary display.
David Stevense5a7b642017-05-22 13:18:23 -07002283 stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002284 if (stack == null) {
2285 // If source display is not suitable - look for topmost valid stack in the system.
2286 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
David Stevense5a7b642017-05-22 13:18:23 -07002287 "computeStackFocus: Can't launch on mPreferredDisplayId="
2288 + mPreferredDisplayId + ", looking on all displays.");
2289 stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002290 }
2291 }
2292 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002293 // We first try to put the task in the first dynamic stack on home display.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002294 final ActivityDisplay display = mSupervisor.getDefaultDisplay();
2295 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2296 stack = display.getChildAt(stackNdx);
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002297 if (!stack.isOnHomeDisplay()) {
David Stevensc6b91c62017-02-08 14:23:58 -08002298 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2299 "computeStackFocus: Setting focused stack=" + stack);
2300 return stack;
2301 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002302 }
David Stevensc6b91c62017-02-08 14:23:58 -08002303 // If there is no suitable dynamic stack then we figure out which static stack to use.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002304 stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002305 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002306 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2307 + r + " stackId=" + stack.mStackId);
2308 return stack;
2309 }
2310
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002311 /** Check if provided activity record can launch in currently focused stack. */
Wale Ogunwale68278562017-09-23 17:13:55 -07002312 // TODO: This method can probably be consolidated into getLaunchStack() below.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002313 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002314 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002315 final boolean canUseFocusedStack;
Wale Ogunwale68278562017-09-23 17:13:55 -07002316 if (focusedStack.isActivityTypeAssistant()) {
2317 canUseFocusedStack = r.isActivityTypeAssistant();
2318 } else {
2319 switch (focusedStack.getWindowingMode()) {
2320 case WINDOWING_MODE_FULLSCREEN:
2321 // The fullscreen stack can contain any task regardless of if the task is
2322 // resizeable or not. So, we let the task go in the fullscreen task if it is the
2323 // focus stack.
2324 canUseFocusedStack = true;
2325 break;
2326 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2327 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2328 // Any activity which supports split screen can go in the docked stack.
2329 canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2330 break;
2331 case WINDOWING_MODE_FREEFORM:
2332 // Any activity which supports freeform can go in the freeform stack.
2333 canUseFocusedStack = r.supportsFreeform();
2334 break;
2335 default:
2336 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2337 // resizeable task.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002338 canUseFocusedStack = !focusedStack.isOnHomeDisplay()
Wale Ogunwale68278562017-09-23 17:13:55 -07002339 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2340 }
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002341 }
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002342 return canUseFocusedStack && !newTask
Wale Ogunwale68278562017-09-23 17:13:55 -07002343 // Using the focus stack isn't important enough to override the preferred display.
David Stevense5a7b642017-05-22 13:18:23 -07002344 && (mPreferredDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002345 }
2346
Wale Ogunwale854809c2015-12-27 16:18:19 -08002347 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002348 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002349 // We are reusing a task, keep the stack!
2350 if (mReuseTask != null) {
2351 return mReuseTask.getStack();
2352 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002353
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002354 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
David Stevense5a7b642017-05-22 13:18:23 -07002355 || mPreferredDisplayId != DEFAULT_DISPLAY) {
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08002356 // We don't pass in the default display id into the get launch stack call so it can do a
2357 // full resolution.
2358 final int candidateDisplay =
2359 mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
2360 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002361 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002362 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002363
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002364 // The parent activity doesn't want to launch the activity on top of itself, but
2365 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002366 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002367
2368 if (parentStack != mSupervisor.mFocusedStack) {
2369 // If task's parent stack is not focused - use it during adjacent launch.
2370 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002371 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002372 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2373 // If task is already on top of focused stack - use it. We don't want to move the
2374 // existing focused task to adjacent stack, just deliver new intent in this case.
2375 return mSupervisor.mFocusedStack;
2376 }
2377
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002378 if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002379 // If parent was in docked stack, the natural place to launch another activity
2380 // will be fullscreen, so it can appear alongside the docked window.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002381 final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2382 return parentStack.getDisplay().getOrCreateStack(
2383 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002384 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002385 // If the parent is not in the docked stack, we check if there is docked window
2386 // and if yes, we will launch into that stack. If not, we just put the new
2387 // activity into parent's stack, because we can't find a better place.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002388 final ActivityStack dockedStack =
2389 mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07002390 if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002391 // There is a docked stack, but it isn't visible, so we can't launch into that.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08002392 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002393 } else {
2394 return dockedStack;
2395 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002396 }
2397 }
2398 }
2399
Bryce Lee7daee392017-10-12 13:46:18 -07002400 private boolean isLaunchModeOneOf(int mode1, int mode2) {
2401 return mode1 == mLaunchMode || mode2 == mLaunchMode;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002402 }
2403
Daichi Hirono15a02992016-04-27 18:47:01 +09002404 static boolean isDocumentLaunchesIntoExisting(int flags) {
2405 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2406 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2407 }
liulvpingcfa825f2016-09-26 20:00:15 +08002408
Bryce Lee4c9a5972017-12-01 22:14:24 -08002409 ActivityStarter setIntent(Intent intent) {
2410 mRequest.intent = intent;
2411 return this;
2412 }
2413
Bryce Lee32e09ef2018-03-19 15:29:49 -07002414 @VisibleForTesting
2415 Intent getIntent() {
2416 return mRequest.intent;
2417 }
2418
Bryce Lee4c9a5972017-12-01 22:14:24 -08002419 ActivityStarter setReason(String reason) {
2420 mRequest.reason = reason;
2421 return this;
2422 }
2423
2424 ActivityStarter setCaller(IApplicationThread caller) {
2425 mRequest.caller = caller;
2426 return this;
2427 }
2428
2429 ActivityStarter setEphemeralIntent(Intent intent) {
2430 mRequest.ephemeralIntent = intent;
2431 return this;
2432 }
2433
2434
2435 ActivityStarter setResolvedType(String type) {
2436 mRequest.resolvedType = type;
2437 return this;
2438 }
2439
2440 ActivityStarter setActivityInfo(ActivityInfo info) {
2441 mRequest.activityInfo = info;
2442 return this;
2443 }
2444
2445 ActivityStarter setResolveInfo(ResolveInfo info) {
2446 mRequest.resolveInfo = info;
2447 return this;
2448 }
2449
2450 ActivityStarter setVoiceSession(IVoiceInteractionSession voiceSession) {
2451 mRequest.voiceSession = voiceSession;
2452 return this;
2453 }
2454
2455 ActivityStarter setVoiceInteractor(IVoiceInteractor voiceInteractor) {
2456 mRequest.voiceInteractor = voiceInteractor;
2457 return this;
2458 }
2459
2460 ActivityStarter setResultTo(IBinder resultTo) {
2461 mRequest.resultTo = resultTo;
2462 return this;
2463 }
2464
2465 ActivityStarter setResultWho(String resultWho) {
2466 mRequest.resultWho = resultWho;
2467 return this;
2468 }
2469
2470 ActivityStarter setRequestCode(int requestCode) {
2471 mRequest.requestCode = requestCode;
2472 return this;
2473 }
2474
2475 ActivityStarter setCallingPid(int pid) {
2476 mRequest.callingPid = pid;
2477 return this;
2478 }
2479
2480 ActivityStarter setCallingUid(int uid) {
2481 mRequest.callingUid = uid;
2482 return this;
2483 }
2484
2485 ActivityStarter setCallingPackage(String callingPackage) {
2486 mRequest.callingPackage = callingPackage;
2487 return this;
2488 }
2489
2490 ActivityStarter setRealCallingPid(int pid) {
2491 mRequest.realCallingPid = pid;
2492 return this;
2493 }
2494
2495 ActivityStarter setRealCallingUid(int uid) {
2496 mRequest.realCallingUid = uid;
2497 return this;
2498 }
2499
2500 ActivityStarter setStartFlags(int startFlags) {
2501 mRequest.startFlags = startFlags;
2502 return this;
2503 }
2504
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002505 ActivityStarter setActivityOptions(SafeActivityOptions options) {
Bryce Lee4c9a5972017-12-01 22:14:24 -08002506 mRequest.activityOptions = options;
2507 return this;
2508 }
2509
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002510 ActivityStarter setActivityOptions(Bundle bOptions) {
2511 return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
2512 }
2513
Bryce Lee4c9a5972017-12-01 22:14:24 -08002514 ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) {
2515 mRequest.ignoreTargetSecurity = ignoreTargetSecurity;
2516 return this;
2517 }
2518
2519 ActivityStarter setComponentSpecified(boolean componentSpecified) {
2520 mRequest.componentSpecified = componentSpecified;
2521 return this;
2522 }
2523
2524 ActivityStarter setOutActivity(ActivityRecord[] outActivity) {
2525 mRequest.outActivity = outActivity;
2526 return this;
2527 }
2528
2529 ActivityStarter setInTask(TaskRecord inTask) {
2530 mRequest.inTask = inTask;
2531 return this;
2532 }
2533
2534 ActivityStarter setWaitResult(WaitResult result) {
2535 mRequest.waitResult = result;
2536 return this;
2537 }
2538
2539 ActivityStarter setProfilerInfo(ProfilerInfo info) {
2540 mRequest.profilerInfo = info;
2541 return this;
2542 }
2543
2544 ActivityStarter setGlobalConfiguration(Configuration config) {
2545 mRequest.globalConfig = config;
2546 return this;
2547 }
2548
Bryce Lee4c9a5972017-12-01 22:14:24 -08002549 ActivityStarter setUserId(int userId) {
2550 mRequest.userId = userId;
2551 return this;
2552 }
2553
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002554 ActivityStarter setMayWait(int userId) {
Bryce Lee4c9a5972017-12-01 22:14:24 -08002555 mRequest.mayWait = true;
Bryce Lee4c9a5972017-12-01 22:14:24 -08002556 mRequest.userId = userId;
2557
2558 return this;
2559 }
2560
Bryce Leed3624e12017-11-30 08:51:45 -08002561 void dump(PrintWriter pw, String prefix) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002562 prefix = prefix + " ";
Dianne Hackborne676ec72017-07-25 10:55:08 -07002563 pw.print(prefix);
2564 pw.print("mCurrentUser=");
2565 pw.println(mSupervisor.mCurrentUser);
2566 pw.print(prefix);
2567 pw.print("mLastStartReason=");
2568 pw.println(mLastStartReason);
2569 pw.print(prefix);
2570 pw.print("mLastStartActivityTimeMs=");
2571 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2572 pw.print(prefix);
2573 pw.print("mLastStartActivityResult=");
2574 pw.println(mLastStartActivityResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002575 ActivityRecord r = mLastStartActivityRecord[0];
2576 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002577 pw.print(prefix);
2578 pw.println("mLastStartActivityRecord:");
2579 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002580 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002581 if (mStartActivity != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002582 pw.print(prefix);
2583 pw.println("mStartActivity:");
2584 mStartActivity.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002585 }
2586 if (mIntent != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002587 pw.print(prefix);
2588 pw.print("mIntent=");
2589 pw.println(mIntent);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002590 }
2591 if (mOptions != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002592 pw.print(prefix);
2593 pw.print("mOptions=");
2594 pw.println(mOptions);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002595 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002596 pw.print(prefix);
2597 pw.print("mLaunchSingleTop=");
Bryce Lee7daee392017-10-12 13:46:18 -07002598 pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002599 pw.print(" mLaunchSingleInstance=");
Bryce Lee7daee392017-10-12 13:46:18 -07002600 pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002601 pw.print(" mLaunchSingleTask=");
Bryce Lee7daee392017-10-12 13:46:18 -07002602 pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002603 pw.print(prefix);
2604 pw.print("mLaunchFlags=0x");
2605 pw.print(Integer.toHexString(mLaunchFlags));
2606 pw.print(" mDoResume=");
2607 pw.print(mDoResume);
2608 pw.print(" mAddingToTask=");
2609 pw.println(mAddingToTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002610 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002611}