blob: 1b7e1edeffe91b91ff68a9a639c358cfbcabc608 [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 Leea3b0e3f02017-05-17 16:45:36 -07001150 if (!ActivityManager.isStartResultSuccessful(result)
Bryce Lee7f936862017-05-09 15:33:18 -07001151 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001152 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001153 }
1154 mService.mWindowManager.continueSurfaceLayout();
1155 }
1156
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001157 postStartActivityProcessing(r, result, mTargetStack);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001158
1159 return result;
1160 }
1161
1162 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001163 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1164 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001165 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1166 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001167
1168 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1169 voiceInteractor);
1170
1171 computeLaunchingTaskFlags();
1172
1173 computeSourceStack();
1174
1175 mIntent.setFlags(mLaunchFlags);
1176
Bryce Lee4a194382017-04-04 14:32:48 -07001177 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001178
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001179 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1180 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1181 if (mOptions != null) {
1182 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1183 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1184 }
Jorim Jaggi2adba072016-03-03 13:43:39 +01001185
Bryce Leeec55eb02017-12-05 20:51:27 -08001186 // windowing mode and preferred launch display values from {@link LaunchParams} take
1187 // priority over those specified in {@link ActivityOptions}.
1188 if (!mLaunchParams.isEmpty()) {
1189 if (mLaunchParams.hasPreferredDisplay()) {
1190 preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
1191 }
1192
1193 if (mLaunchParams.hasWindowingMode()) {
1194 preferredWindowingMode = mLaunchParams.mWindowingMode;
1195 }
1196 }
1197
Bryce Lee4a194382017-04-04 14:32:48 -07001198 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001199 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1200 // still needs to be a lock task mode violation since the task gets cleared out and
1201 // the device would otherwise leave the locked task.
Benjamin Franza83859f2017-07-03 16:34:14 +01001202 if (mService.mLockTaskController.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001203 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1204 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001205 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1206 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1207 }
1208
Bryce Leef65ee7e2018-03-26 16:03:47 -07001209 // True if we are clearing top and resetting of a standard (default) launch mode
1210 // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
1211 final boolean clearTopAndResetStandardLaunchMode =
1212 (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
1213 == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
1214 && mLaunchMode == LAUNCH_MULTIPLE;
1215
1216 // If mStartActivity does not have a task associated with it, associate it with the
1217 // reused activity's task. Do not do so if we're clearing top and resetting for a
1218 // standard launchMode activity.
1219 if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
Bryce Lee4a194382017-04-04 14:32:48 -07001220 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001221 }
Bryce Leef65ee7e2018-03-26 16:03:47 -07001222
Bryce Lee4a194382017-04-04 14:32:48 -07001223 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001224 // This task was started because of movement of the activity based on affinity...
1225 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001226 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001227 }
1228
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001229 // This code path leads to delivering a new intent, we want to make sure we schedule it
1230 // as the first operation, in case the activity will be resumed as a result of later
1231 // operations.
1232 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001233 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Bryce Lee7daee392017-10-12 13:46:18 -07001234 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Lee4a194382017-04-04 14:32:48 -07001235 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001236
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001237 // In this situation we want to remove all activities from the task up to the one
1238 // being started. In most cases this means we are resetting the task to its initial
1239 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001240 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1241 mLaunchFlags);
1242
Bryce Lee4a194382017-04-04 14:32:48 -07001243 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001244 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1245 // task reference is needed in the call below to
1246 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001247 if (reusedActivity.getTask() == null) {
1248 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001249 }
1250
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001251 if (top != null) {
1252 if (top.frontOfTask) {
1253 // Activity aliases may mean we use different intents for the top activity,
1254 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001255 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001256 }
Bryce Lee325e09682017-10-05 17:20:25 -07001257 deliverNewIntent(top);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001258 }
1259 }
1260
Bryce Leed3624e12017-11-30 08:51:45 -08001261 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001262
Bryce Lee4a194382017-04-04 14:32:48 -07001263 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001264
Bryce Lee89cd19a2017-05-17 15:18:35 -07001265 final ActivityRecord outResult =
1266 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1267
1268 // When there is a reused activity and the current result is a trampoline activity,
1269 // set the reused activity as the result.
1270 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1271 outActivity[0] = reusedActivity;
1272 }
1273
Wale Ogunwale01d66562015-12-29 08:19:19 -08001274 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1275 // We don't need to start a new activity, and the client said not to do anything
1276 // if that is the case, so this is it! And for paranoia, make sure we have
1277 // correctly resumed the top activity.
1278 resumeTargetStackIfNeeded();
1279 return START_RETURN_INTENT_TO_CALLER;
1280 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001281
Bryce Leef65ee7e2018-03-26 16:03:47 -07001282 if (reusedActivity != null) {
1283 setTaskFromIntentActivity(reusedActivity);
1284
1285 if (!mAddingToTask && mReuseTask == null) {
1286 // We didn't do anything... but it was needed (a.k.a., client don't use that
1287 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1288
1289 resumeTargetStackIfNeeded();
1290 if (outActivity != null && outActivity.length > 0) {
1291 outActivity[0] = reusedActivity;
1292 }
1293
1294 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001295 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001296 }
1297 }
1298
1299 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001300 final ActivityStack sourceStack = mStartActivity.resultTo != null
1301 ? mStartActivity.resultTo.getStack() : null;
1302 if (sourceStack != null) {
1303 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1304 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1305 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001306 }
1307 ActivityOptions.abort(mOptions);
1308 return START_CLASS_NOT_FOUND;
1309 }
1310
1311 // If the activity being launched is the same as the one currently at the top, then
1312 // we need to check if it should only be launched once.
1313 final ActivityStack topStack = mSupervisor.mFocusedStack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001314 final ActivityRecord topFocused = topStack.getTopActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001315 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1316 final boolean dontStart = top != null && mStartActivity.resultTo == null
1317 && top.realActivity.equals(mStartActivity.realActivity)
1318 && top.userId == mStartActivity.userId
1319 && top.app != null && top.app.thread != null
1320 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001321 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001322 if (dontStart) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001323 // For paranoia, make sure we have correctly resumed the top activity.
1324 topStack.mLastPausedActivity = null;
1325 if (mDoResume) {
1326 mSupervisor.resumeFocusedStackTopActivityLocked();
1327 }
1328 ActivityOptions.abort(mOptions);
1329 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1330 // We don't need to start a new activity, and the client said not to do
1331 // anything if that is the case, so this is it!
1332 return START_RETURN_INTENT_TO_CALLER;
1333 }
Bryce Lee325e09682017-10-05 17:20:25 -07001334
1335 deliverNewIntent(top);
Chong Zhangd44063c2016-04-08 11:52:30 -07001336
1337 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1338 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001339 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001340 preferredLaunchDisplayId, topStack);
Chong Zhangd44063c2016-04-08 11:52:30 -07001341
Wale Ogunwale01d66562015-12-29 08:19:19 -08001342 return START_DELIVERED_TO_TOP;
1343 }
1344
1345 boolean newTask = false;
1346 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001347 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001348
1349 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001350 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001351 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1352 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1353 newTask = true;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001354 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001355 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001356 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001357 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001358 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001359 } else {
1360 // This not being started from an existing activity, and not part of a new task...
1361 // just put it in the top task, though these days this case should never happen.
1362 setTaskToCurrentTopOrCreateNewTask();
1363 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001364 if (result != START_SUCCESS) {
1365 return result;
1366 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001367
1368 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1369 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001370 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1371 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001372 if (newTask) {
Wale Ogunwale66e16852017-10-19 13:35:52 -07001373 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
Bryce Leeaf691c02017-03-20 14:20:22 -07001374 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001375 }
1376 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001377 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001378 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001379
Bryce Leed3624e12017-11-30 08:51:45 -08001380 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001381
Winson Chungb5c41b72016-12-07 15:00:47 -08001382 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1383 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001384 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001385 final ActivityRecord topTaskActivity =
1386 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001387 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001388 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1389 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001390 // If the activity is not focusable, we can't resume it, but still would like to
1391 // make sure it becomes visible as it starts (this will also trigger entry
1392 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001393 // Also, we don't want to resume activities in a task that currently has an overlay
1394 // as the starting activity just needs to be in the visible paused state until the
1395 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001396 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001397 // Go ahead and tell window manager to execute app transition for this activity
1398 // since the app transition will not be triggered through the resume channel.
Bryce Lee7daee392017-10-12 13:46:18 -07001399 mService.mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001400 } else {
Winson Chung32066032016-11-04 11:55:21 -07001401 // If the target stack was not previously focusable (previous top running activity
1402 // on that stack was not visible) then any prior calls to move the stack to the
1403 // will not update the focused stack. If starting the new activity now allows the
1404 // task stack to be focusable, then ensure that we now update the focused stack
1405 // accordingly.
1406 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1407 mTargetStack.moveToFront("startActivityUnchecked");
1408 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001409 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1410 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001411 }
Winson Chung1dbc8112017-09-28 18:05:31 -07001412 } else if (mStartActivity != null) {
1413 mSupervisor.mRecentTasks.add(mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001414 }
1415 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1416
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001417 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001418 preferredLaunchDisplayId, mTargetStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001419
1420 return START_SUCCESS;
1421 }
1422
Bryce Leedaa91e42017-12-06 14:13:01 -08001423 /**
1424 * Resets the {@link ActivityStarter} state.
1425 * @param clearRequest whether the request should be reset to default values.
1426 */
1427 void reset(boolean clearRequest) {
1428 mStartActivity = null;
1429 mIntent = null;
1430 mCallingUid = -1;
1431 mOptions = null;
1432
1433 mLaunchTaskBehind = false;
1434 mLaunchFlags = 0;
1435 mLaunchMode = INVALID_LAUNCH_MODE;
1436
Bryce Leeec55eb02017-12-05 20:51:27 -08001437 mLaunchParams.reset();
Bryce Leedaa91e42017-12-06 14:13:01 -08001438
1439 mNotTop = null;
1440 mDoResume = false;
1441 mStartFlags = 0;
1442 mSourceRecord = null;
1443 mPreferredDisplayId = INVALID_DISPLAY;
1444
1445 mInTask = null;
1446 mAddingToTask = false;
1447 mReuseTask = null;
1448
1449 mNewTaskInfo = null;
1450 mNewTaskIntent = null;
1451 mSourceStack = null;
1452
1453 mTargetStack = null;
1454 mMovedToFront = false;
1455 mNoAnimation = false;
1456 mKeepCurTransition = false;
1457 mAvoidMoveToFront = false;
1458
1459 mVoiceSession = null;
1460 mVoiceInteractor = null;
1461
1462 mIntentDelivered = false;
1463
1464 if (clearRequest) {
1465 mRequest.reset();
1466 }
1467 }
1468
Wale Ogunwale01d66562015-12-29 08:19:19 -08001469 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1470 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1471 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
Bryce Leedaa91e42017-12-06 14:13:01 -08001472 reset(false /* clearRequest */);
1473
Wale Ogunwale01d66562015-12-29 08:19:19 -08001474 mStartActivity = r;
1475 mIntent = r.intent;
1476 mOptions = options;
1477 mCallingUid = r.launchedFromUid;
1478 mSourceRecord = sourceRecord;
1479 mVoiceSession = voiceSession;
1480 mVoiceInteractor = voiceInteractor;
1481
David Stevense5a7b642017-05-22 13:18:23 -07001482 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
David Stevensc6b91c62017-02-08 14:23:58 -08001483
Bryce Leeec55eb02017-12-05 20:51:27 -08001484 mLaunchParams.reset();
Bryce Leedacefc42017-10-10 12:56:02 -07001485
Bryce Leeec55eb02017-12-05 20:51:27 -08001486 mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
1487 options, mLaunchParams);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001488
Bryce Lee7daee392017-10-12 13:46:18 -07001489 mLaunchMode = r.launchMode;
1490
Wale Ogunwale01d66562015-12-29 08:19:19 -08001491 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
Bryce Lee7daee392017-10-12 13:46:18 -07001492 r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1493 LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001494 mLaunchTaskBehind = r.mLaunchTaskBehind
Bryce Lee7daee392017-10-12 13:46:18 -07001495 && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001496 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1497
1498 sendNewTaskResultRequestIfNeeded();
1499
1500 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1501 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1502 }
1503
1504 // If we are actually going to launch in to a new task, there are some cases where
1505 // we further want to do multiple task.
1506 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1507 if (mLaunchTaskBehind
1508 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1509 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1510 }
1511 }
1512
1513 // We'll invoke onUserLeaving before onPause only if the launching
1514 // activity did not explicitly state that this is an automated launch.
1515 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1516 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1517 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1518
1519 // If the caller has asked not to resume at this point, we make note
1520 // of this in the record so that we can skip it when trying to find
1521 // the top running activity.
1522 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001523 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001524 r.delayedResume = true;
1525 mDoResume = false;
1526 }
1527
Winson Chunge2d72172018-01-25 17:46:20 +00001528 if (mOptions != null) {
1529 if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1530 r.mTaskOverlay = true;
1531 if (!mOptions.canTaskOverlayResume()) {
1532 final TaskRecord task = mSupervisor.anyTaskForIdLocked(
1533 mOptions.getLaunchTaskId());
1534 final ActivityRecord top = task != null ? task.getTopActivity() : null;
Bryce Lee7ace3952018-02-16 14:34:32 -08001535 if (top != null && !top.isState(RESUMED)) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001536
Winson Chunge2d72172018-01-25 17:46:20 +00001537 // The caller specifies that we'd like to be avoided to be moved to the
1538 // front, so be it!
1539 mDoResume = false;
1540 mAvoidMoveToFront = true;
1541 }
Winson Chungcbcadc92017-01-12 15:54:12 -08001542 }
Winson Chunge2d72172018-01-25 17:46:20 +00001543 } else if (mOptions.getAvoidMoveToFront()) {
1544 mAvoidMoveToFront = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001545 }
1546 }
1547
Wale Ogunwale01d66562015-12-29 08:19:19 -08001548 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1549
1550 mInTask = inTask;
1551 // In some flows in to this function, we retrieve the task record and hold on to it
1552 // without a lock before calling back in to here... so the task at this point may
1553 // not actually be in recents. Check for that, and if it isn't in recents just
1554 // consider it invalid.
1555 if (inTask != null && !inTask.inRecents) {
1556 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1557 mInTask = null;
1558 }
1559
1560 mStartFlags = startFlags;
1561 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1562 // is the same as the one making the call... or, as a special case, if we do not know
1563 // the caller then we count the current top activity as the caller.
1564 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1565 ActivityRecord checkedCaller = sourceRecord;
1566 if (checkedCaller == null) {
1567 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1568 mNotTop);
1569 }
1570 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1571 // Caller is not the same as launcher, so always needed.
1572 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1573 }
1574 }
1575
1576 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1577 }
1578
1579 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001580 final ActivityStack sourceStack = mStartActivity.resultTo != null
1581 ? mStartActivity.resultTo.getStack() : null;
1582 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001583 // For whatever reason this activity is being launched into a new task...
1584 // yet the caller has requested a result back. Well, that is pretty messed up,
1585 // so instead immediately send back a cancel and let the new task continue launched
1586 // as normal without a dependency on its originator.
1587 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001588 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1589 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1590 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001591 mStartActivity.resultTo = null;
1592 }
1593 }
1594
1595 private void computeLaunchingTaskFlags() {
1596 // If the caller is not coming from another activity, but has given us an explicit task into
1597 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001598 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001599 final Intent baseIntent = mInTask.getBaseIntent();
1600 final ActivityRecord root = mInTask.getRootActivity();
1601 if (baseIntent == null) {
1602 ActivityOptions.abort(mOptions);
1603 throw new IllegalArgumentException("Launching into task without base intent: "
1604 + mInTask);
1605 }
1606
1607 // If this task is empty, then we are adding the first activity -- it
1608 // determines the root, and must be launching as a NEW_TASK.
Bryce Lee7daee392017-10-12 13:46:18 -07001609 if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001610 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1611 ActivityOptions.abort(mOptions);
1612 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1613 + mStartActivity + " into different task " + mInTask);
1614 }
1615 if (root != null) {
1616 ActivityOptions.abort(mOptions);
1617 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1618 + " has root " + root + " but target is singleInstance/Task");
1619 }
1620 }
1621
1622 // If task is empty, then adopt the interesting intent launch flags in to the
1623 // activity being started.
1624 if (root == null) {
1625 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1626 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1627 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1628 | (baseIntent.getFlags() & flagsOfInterest);
1629 mIntent.setFlags(mLaunchFlags);
1630 mInTask.setIntent(mStartActivity);
1631 mAddingToTask = true;
1632
1633 // If the task is not empty and the caller is asking to start it as the root of
1634 // a new task, then we don't actually want to start this on the task. We will
1635 // bring the task to the front, and possibly give it a new intent.
1636 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1637 mAddingToTask = false;
1638
1639 } else {
1640 mAddingToTask = true;
1641 }
1642
1643 mReuseTask = mInTask;
1644 } else {
1645 mInTask = null;
1646 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1647 // when in freeform workspace.
1648 // Also put noDisplay activities in the source task. These by itself can be placed
1649 // in any task/stack, however it could launch other activities like ResolverActivity,
1650 // and we want those to stay in the original task.
1651 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001652 && mSourceRecord.inFreeformWindowingMode()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001653 mAddingToTask = true;
1654 }
1655 }
1656
1657 if (mInTask == null) {
1658 if (mSourceRecord == null) {
1659 // This activity is not being started from another... in this
1660 // case we -always- start a new task.
1661 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1662 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1663 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1664 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1665 }
1666 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1667 // The original activity who is starting us is running as a single
1668 // instance... this new activity it is starting must go on its
1669 // own task.
1670 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
Bryce Lee7daee392017-10-12 13:46:18 -07001671 } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001672 // The activity being started is a single instance... it always
1673 // gets launched into its own task.
1674 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1675 }
1676 }
1677 }
1678
1679 private void computeSourceStack() {
1680 if (mSourceRecord == null) {
1681 mSourceStack = null;
1682 return;
1683 }
1684 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001685 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001686 return;
1687 }
1688
1689 // If the source is finishing, we can't further count it as our source. This is because the
1690 // task it is associated with may now be empty and on its way out, so we don't want to
1691 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1692 // a task for it. But save the task information so it can be used when creating the new task.
1693 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1694 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1695 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1696 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1697 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001698
1699 // It is not guaranteed that the source record will have a task associated with it. For,
1700 // example, if this method is being called for processing a pending activity launch, it
1701 // is possible that the activity has been removed from the task after the launch was
1702 // enqueued.
1703 final TaskRecord sourceTask = mSourceRecord.getTask();
1704 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001705 }
1706 mSourceRecord = null;
1707 mSourceStack = null;
1708 }
1709
1710 /**
1711 * Decide whether the new activity should be inserted into an existing task. Returns null
1712 * if not or an ActivityRecord with the task into which the new activity should be added.
1713 */
1714 private ActivityRecord getReusableIntentActivity() {
1715 // We may want to try to place the new activity in to an existing task. We always
1716 // do this if the target activity is singleTask or singleInstance; we will also do
1717 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1718 // us to still place it in a new task: multi task, always doc mode, or being asked to
1719 // launch this as a new task behind the current one.
1720 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1721 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
Bryce Lee7daee392017-10-12 13:46:18 -07001722 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001723 // If bring to front is requested, and no result is requested and we have not been given
1724 // an explicit task to launch in to, and we can find a task that was started with this
1725 // same component, then instead of launching bring that one to the front.
1726 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1727 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001728 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1729 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1730 intentActivity = task != null ? task.getTopActivity() : null;
1731 } else if (putIntoExistingTask) {
Bryce Lee7daee392017-10-12 13:46:18 -07001732 if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001733 // There can be one and only one instance of single instance activity in the
1734 // history, and it is always in its own unique task, so we do a special search.
Bryce Lee28d80422017-07-21 13:25:13 -07001735 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001736 mStartActivity.isActivityTypeHome());
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001737 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1738 // For the launch adjacent case we only want to put the activity in an existing
1739 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001740 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Bryce Lee7daee392017-10-12 13:46:18 -07001741 !(LAUNCH_SINGLE_TASK == mLaunchMode));
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001742 } else {
1743 // Otherwise find the best task to put the activity in.
David Stevense5a7b642017-05-22 13:18:23 -07001744 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001745 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001746 }
1747 return intentActivity;
1748 }
1749
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001750 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001751 * 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 -07001752 * then return the Vr mode's virtual display ID. If not, if the activity was started with
1753 * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1754 * set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001755 */
David Stevense5a7b642017-05-22 13:18:23 -07001756 private int getPreferedDisplayId(
1757 ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001758 // Check if the Activity is a VR activity. If so, the activity should be launched in
1759 // main display.
1760 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1761 return DEFAULT_DISPLAY;
1762 }
1763
1764 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001765 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001766 if (displayId != INVALID_DISPLAY) {
1767 if (DEBUG_STACK) {
1768 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1769 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001770 return displayId;
1771 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001772
David Stevense5a7b642017-05-22 13:18:23 -07001773 // If the caller requested a display, prefer that display.
1774 final int launchDisplayId =
1775 (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1776 if (launchDisplayId != INVALID_DISPLAY) {
1777 return launchDisplayId;
1778 }
1779
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001780 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1781 // If the activity has a displayId set explicitly, launch it on the same displayId.
1782 if (displayId != INVALID_DISPLAY) {
1783 return displayId;
1784 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001785 return DEFAULT_DISPLAY;
1786 }
1787
1788 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001789 * Figure out which task and activity to bring to front when we have found an existing matching
1790 * activity record in history. May also clear the task if needed.
1791 * @param intentActivity Existing matching activity.
1792 * @return {@link ActivityRecord} brought to front.
1793 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001794 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001795 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001796 mTargetStack.mLastPausedActivity = null;
1797 // If the target task is not in the front, then we need to bring it to the front...
1798 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1799 // the same behavior as if a new instance was being started, which means not bringing it
1800 // to the front if the caller is not itself in the front.
1801 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1802 ActivityRecord curTop = (focusStack == null)
1803 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1804
Bryce Leeaf691c02017-03-20 14:20:22 -07001805 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1806 if (topTask != null
1807 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001808 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001809 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001810 if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1811 mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001812 // We really do want to push this one into the user's face, right now.
1813 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001814 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001815 }
Chong Zhangdea4bd92016-03-15 12:50:03 -07001816
1817 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1818 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1819 // So no point resuming any of the activities here, it just wastes one extra
1820 // resuming, plus enter AND exit transitions.
1821 // Here we only want to bring the target stack forward. Transition will be applied
1822 // to the new activity that's started after the old ones are gone.
1823 final boolean willClearTask =
1824 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1825 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1826 if (!willClearTask) {
1827 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001828 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1829 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001830 if (launchStack == null || launchStack == mTargetStack) {
1831 // We only want to move to the front, if we aren't going to launch on a
1832 // different stack. If we launch on a different stack, we will put the
1833 // task on top there.
chaviw0d562bf2018-03-15 14:24:14 -07001834 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1835 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
Chong Zhangdea4bd92016-03-15 12:50:03 -07001836 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001837 } else if (launchStack.inSplitScreenWindowingMode()) {
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001838 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1839 // If we want to launch adjacent and mTargetStack is not the computed
1840 // launch stack - move task to top of computed stack.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001841 intentTask.reparent(launchStack, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001842 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1843 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001844 } else {
1845 // TODO: This should be reevaluated in MW v2.
1846 // We choose to move task to front instead of launching it adjacent
1847 // when specific stack was requested explicitly and it appeared to be
1848 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
chaviw0d562bf2018-03-15 14:24:14 -07001849 mTargetStack.moveTaskToFrontLocked(intentTask,
Bryce Leeaf691c02017-03-20 14:20:22 -07001850 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001851 "bringToFrontInsteadOfAdjacentLaunch");
1852 }
Bryce Lee32e09ef2018-03-19 15:29:49 -07001853 mMovedToFront = launchStack != launchStack.getDisplay()
1854 .getTopStackInWindowingMode(launchStack.getWindowingMode());
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001855 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1856 // Target and computed stacks are on different displays and we've
1857 // found a matching task - move the existing instance to that display and
1858 // move it to front.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001859 intentActivity.getTask().reparent(launchStack, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001860 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1861 "reparentToDisplay");
1862 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001863 } else if (launchStack.isActivityTypeHome()
1864 && !mTargetStack.isActivityTypeHome()) {
Bryce Lee4ff7da92017-07-17 10:39:24 -07001865 // It is possible for the home activity to be in another stack initially.
1866 // For example, the activity may have been initially started with an intent
1867 // which placed it in the fullscreen stack. To ensure the proper handling of
1868 // the activity based on home stack assumptions, we must move it over.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001869 intentActivity.getTask().reparent(launchStack, ON_TOP,
Bryce Lee4ff7da92017-07-17 10:39:24 -07001870 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1871 "reparentingHome");
1872 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001873 }
1874 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001875
1876 // We are moving a task to the front, use starting window to hide initial drawn
1877 // delay.
1878 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1879 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001880 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001881 }
1882 }
Andrii Kulianb850ea52017-12-12 23:49:10 -08001883 // Need to update mTargetStack because if task was moved out of it, the original stack may
1884 // be destroyed.
1885 mTargetStack = intentActivity.getStack();
Winson Chunge2d72172018-01-25 17:46:20 +00001886 if (!mAvoidMoveToFront && !mMovedToFront && mDoResume) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001887 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1888 + " from " + intentActivity);
1889 mTargetStack.moveToFront("intentActivityFound");
1890 }
1891
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001892 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001893 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001894
Wale Ogunwale01d66562015-12-29 08:19:19 -08001895 // If the caller has requested that the target task be reset, then do so.
1896 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1897 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1898 }
1899 return intentActivity;
1900 }
1901
1902 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1903 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1904 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1905 // The caller has requested to completely replace any existing task with its new
1906 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001907 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1908 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001909 // of history or if it is finished immediately), thus disassociating the task. Also note
1910 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1911 // launching another activity.
1912 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1913 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001914 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001915 task.performClearTaskLocked();
1916 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001917 mReuseTask.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001918 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001919 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001920 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001921 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001922 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001923 // A special case: we need to start the activity because it is not currently
1924 // running, and the caller has asked to clear the current task to have this
1925 // activity at the top.
1926 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001927
1928 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001929 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001930 // Now pretend like this activity is being started by the top of its task, so it
1931 // is put in the right place.
1932 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001933 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001934 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001935 // Target stack got cleared when we all activities were removed above.
1936 // Go ahead and reset it.
1937 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
Bryce Leedacefc42017-10-10 12:56:02 -07001938 mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001939 mTargetStack.addTask(task,
1940 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1941 }
1942 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001943 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001944 // In this case the top activity on the task is the same as the one being launched,
1945 // so we take that as a request to bring the task to the foreground. If the top
1946 // activity in the task is the root activity, deliver this new intent to it if it
1947 // desires.
Bryce Lee7daee392017-10-12 13:46:18 -07001948 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1949 || LAUNCH_SINGLE_TOP == mLaunchMode)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001950 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001951 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001952 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001953 }
Bryce Lee325e09682017-10-05 17:20:25 -07001954 deliverNewIntent(intentActivity);
Bryce Leeaf691c02017-03-20 14:20:22 -07001955 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001956 // In this case we are launching the root activity of the task, but with a
1957 // different intent. We should start a new instance on top.
1958 mAddingToTask = true;
1959 mSourceRecord = intentActivity;
1960 }
1961 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1962 // In this case an activity is being launched in to an existing task, without
1963 // resetting that task. This is typically the situation of launching an activity
1964 // from a notification or shortcut. We want to place the new activity on top of the
1965 // current task.
1966 mAddingToTask = true;
1967 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001968 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001969 // In this case we are launching into an existing task that has not yet been started
1970 // from its front door. The current task has been brought to the front. Ideally,
1971 // we'd probably like to place this new task at the bottom of its stack, but that's
1972 // a little hard to do with the current organization of the code so for now we'll
1973 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001974 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001975 }
1976 }
1977
1978 private void resumeTargetStackIfNeeded() {
1979 if (mDoResume) {
1980 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001981 } else {
1982 ActivityOptions.abort(mOptions);
1983 }
1984 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1985 }
1986
Chong Zhang6cda19c2016-06-14 19:07:56 -07001987 private int setTaskFromReuseOrCreateNewTask(
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001988 TaskRecord taskToAffiliate, ActivityStack topStack) {
Bryce Leedacefc42017-10-10 12:56:02 -07001989 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
Chong Zhang6cda19c2016-06-14 19:07:56 -07001990
1991 // Do no move the target stack to front yet, as we might bail if
1992 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001993
1994 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001995 final TaskRecord task = mTargetStack.createTaskRecord(
1996 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001997 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001998 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
Bryce Leeb802ea12017-11-15 21:25:03 -08001999 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
2000 mOptions);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002001 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Bryce Leeec55eb02017-12-05 20:51:27 -08002002 updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002003
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002004 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002005 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08002006 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002007 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
2008 }
2009
2010 if (taskToAffiliate != null) {
2011 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002012 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002013
Benjamin Franza83859f2017-07-03 16:34:14 +01002014 if (mService.mLockTaskController.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002015 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2016 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2017 }
2018
Chong Zhang6cda19c2016-06-14 19:07:56 -07002019 if (mDoResume) {
2020 mTargetStack.moveToFront("reuseOrNewTask");
2021 }
2022 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08002023 }
2024
Bryce Lee325e09682017-10-05 17:20:25 -07002025 private void deliverNewIntent(ActivityRecord activity) {
2026 if (mIntentDelivered) {
2027 return;
2028 }
2029
2030 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
2031 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
2032 mStartActivity.launchedFromPackage);
2033 mIntentDelivered = true;
2034 }
2035
Wale Ogunwale01d66562015-12-29 08:19:19 -08002036 private int setTaskFromSourceRecord() {
Benjamin Franza83859f2017-07-03 16:34:14 +01002037 if (mService.mLockTaskController.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002038 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2039 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2040 }
2041
Bryce Leeaf691c02017-03-20 14:20:22 -07002042 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002043 final ActivityStack sourceStack = mSourceRecord.getStack();
Andrii Kulian02689a72017-07-06 14:28:59 -07002044 // We only want to allow changing stack in two cases:
2045 // 1. If the target task is not the top one. Otherwise we would move the launching task to
2046 // the other side, rather than show two side by side.
2047 // 2. If activity is not allowed on target display.
2048 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
2049 : sourceStack.mDisplayId;
2050 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
2051 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002052 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002053 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002054 mOptions);
Andrii Kulian02689a72017-07-06 14:28:59 -07002055 // If target stack is not found now - we can't just rely on the source stack, as it may
2056 // be not suitable. Let's check other displays.
2057 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
2058 // Can't use target display, lets find a stack on the source display.
2059 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
2060 sourceStack.mDisplayId, mStartActivity);
2061 }
2062 if (mTargetStack == null) {
2063 // There are no suitable stacks on the target and source display(s). Look on all
2064 // displays.
2065 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
2066 mStartActivity, -1 /* currentFocus */);
2067 }
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002068 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002069
2070 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002071 mTargetStack = sourceStack;
2072 } else if (mTargetStack != sourceStack) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002073 sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
2074 DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002075 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002076
Wale Ogunwale01d66562015-12-29 08:19:19 -08002077 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07002078 if (topTask != sourceTask && !mAvoidMoveToFront) {
chaviw0d562bf2018-03-15 14:24:14 -07002079 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
Wale Ogunwale01d66562015-12-29 08:19:19 -08002080 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07002081 } else if (mDoResume) {
2082 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002083 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002084
Wale Ogunwale01d66562015-12-29 08:19:19 -08002085 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2086 // In this case, we are adding the activity to an existing task, but the caller has
2087 // asked to clear that task if the activity is already running.
2088 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
2089 mKeepCurTransition = true;
2090 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002091 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Bryce Lee325e09682017-10-05 17:20:25 -07002092 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002093 // For paranoia, make sure we have correctly resumed the top activity.
2094 mTargetStack.mLastPausedActivity = null;
2095 if (mDoResume) {
2096 mSupervisor.resumeFocusedStackTopActivityLocked();
2097 }
2098 ActivityOptions.abort(mOptions);
2099 return START_DELIVERED_TO_TOP;
2100 }
2101 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
2102 // In this case, we are launching an activity in our own task that may already be
2103 // running somewhere in the history, and we want to shuffle it to the front of the
2104 // stack if so.
2105 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
2106 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002107 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08002108 task.moveActivityToFrontLocked(top);
2109 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08002110 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Bryce Lee325e09682017-10-05 17:20:25 -07002111 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002112 mTargetStack.mLastPausedActivity = null;
2113 if (mDoResume) {
2114 mSupervisor.resumeFocusedStackTopActivityLocked();
2115 }
2116 return START_DELIVERED_TO_TOP;
2117 }
2118 }
2119
2120 // An existing activity is starting this new activity, so we want to keep the new one in
2121 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002122 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002123 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002124 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002125 return START_SUCCESS;
2126 }
2127
2128 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002129 // The caller is asking that the new activity be started in an explicit
2130 // task it has provided to us.
Benjamin Franza83859f2017-07-03 16:34:14 +01002131 if (mService.mLockTaskController.isLockTaskModeViolation(mInTask)) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002132 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2133 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2134 }
2135
Andrii Kulian02b7a832016-10-06 23:11:56 -07002136 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08002137
2138 // Check whether we should actually launch the new activity in to the task,
2139 // or just reuse the current activity on top.
2140 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002141 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
2142 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08002143 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07002144 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
chaviw0d562bf2018-03-15 14:24:14 -07002145 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
Yorke Lee64512522017-03-24 13:09:35 -07002146 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002147 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
2148 // We don't need to start a new activity, and the client said not to do
2149 // anything if that is the case, so this is it!
2150 return START_RETURN_INTENT_TO_CALLER;
2151 }
Bryce Lee325e09682017-10-05 17:20:25 -07002152 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002153 return START_DELIVERED_TO_TOP;
2154 }
2155 }
2156
2157 if (!mAddingToTask) {
chaviw0d562bf2018-03-15 14:24:14 -07002158 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
Yorke Lee64512522017-03-24 13:09:35 -07002159 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002160 // We don't actually want to have this activity added to the task, so just
2161 // stop here but still tell the caller that we consumed the intent.
2162 ActivityOptions.abort(mOptions);
2163 return START_TASK_TO_FRONT;
2164 }
2165
Bryce Leeec55eb02017-12-05 20:51:27 -08002166 if (!mLaunchParams.mBounds.isEmpty()) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002167 // TODO: Shouldn't we already know what stack to use by the time we get here?
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002168 ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
2169 if (stack != mInTask.getStack()) {
2170 mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
Yorke Lee64512522017-03-24 13:09:35 -07002171 DEFER_RESUME, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07002172 mTargetStack = mInTask.getStack();
2173 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002174
Bryce Leeec55eb02017-12-05 20:51:27 -08002175 updateBounds(mInTask, mLaunchParams.mBounds);
Yorke Lee64512522017-03-24 13:09:35 -07002176 }
2177
chaviw0d562bf2018-03-15 14:24:14 -07002178 mTargetStack.moveTaskToFrontLocked(
2179 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07002180
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002181 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
2182 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002183 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08002184
2185 return START_SUCCESS;
2186 }
2187
Bryce Leed3624e12017-11-30 08:51:45 -08002188 @VisibleForTesting
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002189 void updateBounds(TaskRecord task, Rect bounds) {
Bryce Leedacefc42017-10-10 12:56:02 -07002190 if (bounds.isEmpty()) {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002191 return;
2192 }
2193
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002194 final ActivityStack stack = task.getStack();
2195 if (stack != null && stack.resizeStackWithLaunchBounds()) {
2196 mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002197 } else {
2198 task.updateOverrideConfiguration(bounds);
2199 }
2200 }
2201
Wale Ogunwale01d66562015-12-29 08:19:19 -08002202 private void setTaskToCurrentTopOrCreateNewTask() {
Bryce Leedacefc42017-10-10 12:56:02 -07002203 mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002204 if (mDoResume) {
2205 mTargetStack.moveToFront("addingToTopTask");
2206 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -08002207 final ActivityRecord prev = mTargetStack.getTopActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07002208 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08002209 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
Bryce Leeb802ea12017-11-15 21:25:03 -08002210 mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002211 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2212 mTargetStack.positionChildWindowContainerAtTop(task);
2213 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002214 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002215 }
2216
2217 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002218 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002219 parent.addActivityToTop(mStartActivity);
2220 } else {
2221 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2222 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002223 }
2224
2225 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2226 boolean launchSingleTask, int launchFlags) {
2227 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2228 (launchSingleInstance || launchSingleTask)) {
2229 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2230 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2231 "\"singleInstance\" or \"singleTask\"");
2232 launchFlags &=
2233 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2234 } else {
2235 switch (r.info.documentLaunchMode) {
2236 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2237 break;
2238 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2239 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2240 break;
2241 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2242 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2243 break;
2244 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2245 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2246 break;
2247 }
2248 }
2249 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002250 }
2251
Bryce Leedacefc42017-10-10 12:56:02 -07002252 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
2253 ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002254 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002255 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002256 if (stack != null) {
2257 return stack;
2258 }
2259
Andrii Kulian02b7a832016-10-06 23:11:56 -07002260 final ActivityStack currentStack = task != null ? task.getStack() : null;
2261 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002262 if (mSupervisor.mFocusedStack != currentStack) {
2263 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2264 "computeStackFocus: Setting " + "focused stack to r=" + r
2265 + " task=" + task);
2266 } else {
2267 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2268 "computeStackFocus: Focused stack already="
2269 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002270 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002271 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002272 }
2273
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002274 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002275 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2276 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2277 return mSupervisor.mFocusedStack;
2278 }
2279
David Stevense5a7b642017-05-22 13:18:23 -07002280 if (mPreferredDisplayId != DEFAULT_DISPLAY) {
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002281 // Try to put the activity in a stack on a secondary display.
David Stevense5a7b642017-05-22 13:18:23 -07002282 stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002283 if (stack == null) {
2284 // If source display is not suitable - look for topmost valid stack in the system.
2285 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
David Stevense5a7b642017-05-22 13:18:23 -07002286 "computeStackFocus: Can't launch on mPreferredDisplayId="
2287 + mPreferredDisplayId + ", looking on all displays.");
2288 stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002289 }
2290 }
2291 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002292 // We first try to put the task in the first dynamic stack on home display.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002293 final ActivityDisplay display = mSupervisor.getDefaultDisplay();
2294 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2295 stack = display.getChildAt(stackNdx);
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002296 if (!stack.isOnHomeDisplay()) {
David Stevensc6b91c62017-02-08 14:23:58 -08002297 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2298 "computeStackFocus: Setting focused stack=" + stack);
2299 return stack;
2300 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002301 }
David Stevensc6b91c62017-02-08 14:23:58 -08002302 // If there is no suitable dynamic stack then we figure out which static stack to use.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002303 stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002304 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002305 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2306 + r + " stackId=" + stack.mStackId);
2307 return stack;
2308 }
2309
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002310 /** Check if provided activity record can launch in currently focused stack. */
Wale Ogunwale68278562017-09-23 17:13:55 -07002311 // TODO: This method can probably be consolidated into getLaunchStack() below.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002312 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002313 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002314 final boolean canUseFocusedStack;
Wale Ogunwale68278562017-09-23 17:13:55 -07002315 if (focusedStack.isActivityTypeAssistant()) {
2316 canUseFocusedStack = r.isActivityTypeAssistant();
2317 } else {
2318 switch (focusedStack.getWindowingMode()) {
2319 case WINDOWING_MODE_FULLSCREEN:
2320 // The fullscreen stack can contain any task regardless of if the task is
2321 // resizeable or not. So, we let the task go in the fullscreen task if it is the
2322 // focus stack.
2323 canUseFocusedStack = true;
2324 break;
2325 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2326 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2327 // Any activity which supports split screen can go in the docked stack.
2328 canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2329 break;
2330 case WINDOWING_MODE_FREEFORM:
2331 // Any activity which supports freeform can go in the freeform stack.
2332 canUseFocusedStack = r.supportsFreeform();
2333 break;
2334 default:
2335 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2336 // resizeable task.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002337 canUseFocusedStack = !focusedStack.isOnHomeDisplay()
Wale Ogunwale68278562017-09-23 17:13:55 -07002338 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2339 }
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002340 }
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002341 return canUseFocusedStack && !newTask
Wale Ogunwale68278562017-09-23 17:13:55 -07002342 // Using the focus stack isn't important enough to override the preferred display.
David Stevense5a7b642017-05-22 13:18:23 -07002343 && (mPreferredDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002344 }
2345
Wale Ogunwale854809c2015-12-27 16:18:19 -08002346 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002347 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002348 // We are reusing a task, keep the stack!
2349 if (mReuseTask != null) {
2350 return mReuseTask.getStack();
2351 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002352
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002353 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
David Stevense5a7b642017-05-22 13:18:23 -07002354 || mPreferredDisplayId != DEFAULT_DISPLAY) {
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08002355 // We don't pass in the default display id into the get launch stack call so it can do a
2356 // full resolution.
2357 final int candidateDisplay =
2358 mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
2359 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002360 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002361 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002362
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002363 // The parent activity doesn't want to launch the activity on top of itself, but
2364 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002365 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002366
2367 if (parentStack != mSupervisor.mFocusedStack) {
2368 // If task's parent stack is not focused - use it during adjacent launch.
2369 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002370 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002371 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2372 // If task is already on top of focused stack - use it. We don't want to move the
2373 // existing focused task to adjacent stack, just deliver new intent in this case.
2374 return mSupervisor.mFocusedStack;
2375 }
2376
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002377 if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002378 // If parent was in docked stack, the natural place to launch another activity
2379 // will be fullscreen, so it can appear alongside the docked window.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002380 final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2381 return parentStack.getDisplay().getOrCreateStack(
2382 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002383 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002384 // If the parent is not in the docked stack, we check if there is docked window
2385 // and if yes, we will launch into that stack. If not, we just put the new
2386 // activity into parent's stack, because we can't find a better place.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002387 final ActivityStack dockedStack =
2388 mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07002389 if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002390 // There is a docked stack, but it isn't visible, so we can't launch into that.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08002391 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002392 } else {
2393 return dockedStack;
2394 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002395 }
2396 }
2397 }
2398
Bryce Lee7daee392017-10-12 13:46:18 -07002399 private boolean isLaunchModeOneOf(int mode1, int mode2) {
2400 return mode1 == mLaunchMode || mode2 == mLaunchMode;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002401 }
2402
Daichi Hirono15a02992016-04-27 18:47:01 +09002403 static boolean isDocumentLaunchesIntoExisting(int flags) {
2404 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2405 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2406 }
liulvpingcfa825f2016-09-26 20:00:15 +08002407
Bryce Lee4c9a5972017-12-01 22:14:24 -08002408 ActivityStarter setIntent(Intent intent) {
2409 mRequest.intent = intent;
2410 return this;
2411 }
2412
Bryce Lee32e09ef2018-03-19 15:29:49 -07002413 @VisibleForTesting
2414 Intent getIntent() {
2415 return mRequest.intent;
2416 }
2417
Bryce Lee4c9a5972017-12-01 22:14:24 -08002418 ActivityStarter setReason(String reason) {
2419 mRequest.reason = reason;
2420 return this;
2421 }
2422
2423 ActivityStarter setCaller(IApplicationThread caller) {
2424 mRequest.caller = caller;
2425 return this;
2426 }
2427
2428 ActivityStarter setEphemeralIntent(Intent intent) {
2429 mRequest.ephemeralIntent = intent;
2430 return this;
2431 }
2432
2433
2434 ActivityStarter setResolvedType(String type) {
2435 mRequest.resolvedType = type;
2436 return this;
2437 }
2438
2439 ActivityStarter setActivityInfo(ActivityInfo info) {
2440 mRequest.activityInfo = info;
2441 return this;
2442 }
2443
2444 ActivityStarter setResolveInfo(ResolveInfo info) {
2445 mRequest.resolveInfo = info;
2446 return this;
2447 }
2448
2449 ActivityStarter setVoiceSession(IVoiceInteractionSession voiceSession) {
2450 mRequest.voiceSession = voiceSession;
2451 return this;
2452 }
2453
2454 ActivityStarter setVoiceInteractor(IVoiceInteractor voiceInteractor) {
2455 mRequest.voiceInteractor = voiceInteractor;
2456 return this;
2457 }
2458
2459 ActivityStarter setResultTo(IBinder resultTo) {
2460 mRequest.resultTo = resultTo;
2461 return this;
2462 }
2463
2464 ActivityStarter setResultWho(String resultWho) {
2465 mRequest.resultWho = resultWho;
2466 return this;
2467 }
2468
2469 ActivityStarter setRequestCode(int requestCode) {
2470 mRequest.requestCode = requestCode;
2471 return this;
2472 }
2473
2474 ActivityStarter setCallingPid(int pid) {
2475 mRequest.callingPid = pid;
2476 return this;
2477 }
2478
2479 ActivityStarter setCallingUid(int uid) {
2480 mRequest.callingUid = uid;
2481 return this;
2482 }
2483
2484 ActivityStarter setCallingPackage(String callingPackage) {
2485 mRequest.callingPackage = callingPackage;
2486 return this;
2487 }
2488
2489 ActivityStarter setRealCallingPid(int pid) {
2490 mRequest.realCallingPid = pid;
2491 return this;
2492 }
2493
2494 ActivityStarter setRealCallingUid(int uid) {
2495 mRequest.realCallingUid = uid;
2496 return this;
2497 }
2498
2499 ActivityStarter setStartFlags(int startFlags) {
2500 mRequest.startFlags = startFlags;
2501 return this;
2502 }
2503
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002504 ActivityStarter setActivityOptions(SafeActivityOptions options) {
Bryce Lee4c9a5972017-12-01 22:14:24 -08002505 mRequest.activityOptions = options;
2506 return this;
2507 }
2508
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002509 ActivityStarter setActivityOptions(Bundle bOptions) {
2510 return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
2511 }
2512
Bryce Lee4c9a5972017-12-01 22:14:24 -08002513 ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) {
2514 mRequest.ignoreTargetSecurity = ignoreTargetSecurity;
2515 return this;
2516 }
2517
2518 ActivityStarter setComponentSpecified(boolean componentSpecified) {
2519 mRequest.componentSpecified = componentSpecified;
2520 return this;
2521 }
2522
2523 ActivityStarter setOutActivity(ActivityRecord[] outActivity) {
2524 mRequest.outActivity = outActivity;
2525 return this;
2526 }
2527
2528 ActivityStarter setInTask(TaskRecord inTask) {
2529 mRequest.inTask = inTask;
2530 return this;
2531 }
2532
2533 ActivityStarter setWaitResult(WaitResult result) {
2534 mRequest.waitResult = result;
2535 return this;
2536 }
2537
2538 ActivityStarter setProfilerInfo(ProfilerInfo info) {
2539 mRequest.profilerInfo = info;
2540 return this;
2541 }
2542
2543 ActivityStarter setGlobalConfiguration(Configuration config) {
2544 mRequest.globalConfig = config;
2545 return this;
2546 }
2547
Bryce Lee4c9a5972017-12-01 22:14:24 -08002548 ActivityStarter setUserId(int userId) {
2549 mRequest.userId = userId;
2550 return this;
2551 }
2552
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002553 ActivityStarter setMayWait(int userId) {
Bryce Lee4c9a5972017-12-01 22:14:24 -08002554 mRequest.mayWait = true;
Bryce Lee4c9a5972017-12-01 22:14:24 -08002555 mRequest.userId = userId;
2556
2557 return this;
2558 }
2559
Bryce Leed3624e12017-11-30 08:51:45 -08002560 void dump(PrintWriter pw, String prefix) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002561 prefix = prefix + " ";
Dianne Hackborne676ec72017-07-25 10:55:08 -07002562 pw.print(prefix);
2563 pw.print("mCurrentUser=");
2564 pw.println(mSupervisor.mCurrentUser);
2565 pw.print(prefix);
2566 pw.print("mLastStartReason=");
2567 pw.println(mLastStartReason);
2568 pw.print(prefix);
2569 pw.print("mLastStartActivityTimeMs=");
2570 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2571 pw.print(prefix);
2572 pw.print("mLastStartActivityResult=");
2573 pw.println(mLastStartActivityResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002574 ActivityRecord r = mLastStartActivityRecord[0];
2575 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002576 pw.print(prefix);
2577 pw.println("mLastStartActivityRecord:");
2578 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002579 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002580 if (mStartActivity != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002581 pw.print(prefix);
2582 pw.println("mStartActivity:");
2583 mStartActivity.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002584 }
2585 if (mIntent != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002586 pw.print(prefix);
2587 pw.print("mIntent=");
2588 pw.println(mIntent);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002589 }
2590 if (mOptions != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002591 pw.print(prefix);
2592 pw.print("mOptions=");
2593 pw.println(mOptions);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002594 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002595 pw.print(prefix);
2596 pw.print("mLaunchSingleTop=");
Bryce Lee7daee392017-10-12 13:46:18 -07002597 pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002598 pw.print(" mLaunchSingleInstance=");
Bryce Lee7daee392017-10-12 13:46:18 -07002599 pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002600 pw.print(" mLaunchSingleTask=");
Bryce Lee7daee392017-10-12 13:46:18 -07002601 pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002602 pw.print(prefix);
2603 pw.print("mLaunchFlags=0x");
2604 pw.print(Integer.toHexString(mLaunchFlags));
2605 pw.print(" mDoResume=");
2606 pw.print(mDoResume);
2607 pw.print(" mAddingToTask=");
2608 pw.println(mAddingToTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002609 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002610}