blob: 8faf9315f0eaa4aaefeb6f46bfe8010d2ec758b6 [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;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080034import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
35import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080036import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080037import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080038import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080039import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080040import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
41import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080042import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
43import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
44import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
45import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
46import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
47import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
Bryce Leef65ee7e2018-03-26 16:03:47 -070048import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
Wale Ogunwale01d66562015-12-29 08:19:19 -080049import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
50import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
51import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
David Stevensc6b91c62017-02-08 14:23:58 -080052import static android.view.Display.DEFAULT_DISPLAY;
Andrii Kulian16802aa2016-11-02 12:21:33 -070053import static android.view.Display.INVALID_DISPLAY;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080054import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
55import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
56import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
60import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
61import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
65import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
66import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
67import static com.android.server.am.ActivityManagerService.ANIMATE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080068import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
Winson Chung74666102017-02-22 17:49:24 -080069import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080070import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Wale Ogunwalecacfaa22016-01-15 11:26:08 -080071import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080072import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS;
Filip Gruszczynskie826f322016-01-11 17:15:22 -080073import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
Winson Chung74666102017-02-22 17:49:24 -080074import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
75import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
76
Todd Kennedye9910222017-02-21 16:00:11 -080077import android.annotation.NonNull;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +010078import android.annotation.Nullable;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080079import android.app.ActivityManager;
80import android.app.ActivityOptions;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080081import android.app.IApplicationThread;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080082import android.app.PendingIntent;
83import android.app.ProfilerInfo;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -070084import android.app.WaitResult;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080085import android.content.IIntentSender;
86import android.content.Intent;
87import android.content.IntentSender;
88import android.content.pm.ActivityInfo;
89import android.content.pm.ApplicationInfo;
Todd Kennedye9910222017-02-21 16:00:11 -080090import android.content.pm.AuxiliaryResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000091import android.content.pm.PackageManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080092import android.content.pm.ResolveInfo;
Kenny Guyb1b30262016-02-09 16:02:35 +000093import android.content.pm.UserInfo;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080094import android.content.res.Configuration;
95import android.graphics.Rect;
96import android.os.Binder;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080097import android.os.Bundle;
98import android.os.IBinder;
99import android.os.RemoteException;
100import android.os.SystemClock;
101import android.os.UserHandle;
Kenny Guyb1b30262016-02-09 16:02:35 +0000102import android.os.UserManager;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800103import android.service.voice.IVoiceInteractionSession;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700104import android.text.TextUtils;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800105import android.util.EventLog;
Bryce Leedaa91e42017-12-06 14:13:01 -0800106import android.util.Pools.SynchronizedPool;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800107import android.util.Slog;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800108
Bryce Leed3624e12017-11-30 08:51:45 -0800109import com.android.internal.annotations.VisibleForTesting;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800110import com.android.internal.app.HeavyWeightSwitcherActivity;
111import com.android.internal.app.IVoiceInteractor;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800112import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
Bryce Leeec55eb02017-12-05 20:51:27 -0800113import com.android.server.am.LaunchParamsController.LaunchParams;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800114import com.android.server.pm.InstantAppResolver;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800115
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700116import java.io.PrintWriter;
117import java.text.DateFormat;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700118import java.util.Date;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800119
120/**
Bryce Leed3624e12017-11-30 08:51:45 -0800121 * Controller for interpreting how and then launching an activity.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800122 *
123 * This class collects all the logic for determining how an intent and flags should be turned into
124 * an activity and associated task and stack.
125 */
Wale Ogunwale01d66562015-12-29 08:19:19 -0800126class ActivityStarter {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800127 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStarter" : TAG_AM;
128 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
129 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
130 private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
131 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
Bryce Lee7daee392017-10-12 13:46:18 -0700132 private static final int INVALID_LAUNCH_MODE = -1;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800133
134 private final ActivityManagerService mService;
135 private final ActivityStackSupervisor mSupervisor;
Benjamin Franz563707b2017-06-29 15:06:13 +0100136 private final ActivityStartInterceptor mInterceptor;
Bryce Leed3624e12017-11-30 08:51:45 -0800137 private final ActivityStartController mController;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800138
Wale Ogunwale01d66562015-12-29 08:19:19 -0800139 // Share state variable among methods when starting an activity.
140 private ActivityRecord mStartActivity;
141 private Intent mIntent;
142 private int mCallingUid;
143 private ActivityOptions mOptions;
144
Bryce Lee7daee392017-10-12 13:46:18 -0700145 private int mLaunchMode;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800146 private boolean mLaunchTaskBehind;
147 private int mLaunchFlags;
148
Bryce Leeec55eb02017-12-05 20:51:27 -0800149 private LaunchParams mLaunchParams = new LaunchParams();
Wale Ogunwale01d66562015-12-29 08:19:19 -0800150
151 private ActivityRecord mNotTop;
152 private boolean mDoResume;
153 private int mStartFlags;
154 private ActivityRecord mSourceRecord;
Bryce Lee7daee392017-10-12 13:46:18 -0700155
David Stevense5a7b642017-05-22 13:18:23 -0700156 // The display to launch the activity onto, barring any strong reason to do otherwise.
157 private int mPreferredDisplayId;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800158
159 private TaskRecord mInTask;
160 private boolean mAddingToTask;
161 private TaskRecord mReuseTask;
162
163 private ActivityInfo mNewTaskInfo;
164 private Intent mNewTaskIntent;
165 private ActivityStack mSourceStack;
166 private ActivityStack mTargetStack;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800167 private boolean mMovedToFront;
168 private boolean mNoAnimation;
169 private boolean mKeepCurTransition;
Jorim Jaggic875ae72016-04-26 22:41:06 -0700170 private boolean mAvoidMoveToFront;
Wale Ogunwale01d66562015-12-29 08:19:19 -0800171
Bryce Lee325e09682017-10-05 17:20:25 -0700172 // We must track when we deliver the new intent since multiple code paths invoke
173 // {@link #deliverNewIntent}. This is due to early returns in the code path. This flag is used
174 // inside {@link #deliverNewIntent} to suppress duplicate requests and ensure the intent is
175 // delivered at most once.
176 private boolean mIntentDelivered;
177
Wale Ogunwale01d66562015-12-29 08:19:19 -0800178 private IVoiceInteractionSession mVoiceSession;
179 private IVoiceInteractor mVoiceInteractor;
180
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700181 // Last activity record we attempted to start
182 private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
183 // The result of the last activity we attempted to start.
184 private int mLastStartActivityResult;
185 // Time in milli seconds we attempted to start the last activity.
186 private long mLastStartActivityTimeMs;
187 // The reason we were trying to start the last activity
188 private String mLastStartReason;
Wale Ogunwale59bcba62017-06-16 12:42:51 -0700189
Bryce Lee4c9a5972017-12-01 22:14:24 -0800190 /*
191 * Request details provided through setter methods. Should be reset after {@link #execute()}
192 * to avoid unnecessarily retaining parameters. Note that the request is ignored when
193 * {@link #startResolvedActivity} is invoked directly.
194 */
195 private Request mRequest = new Request();
196
Bryce Leed3624e12017-11-30 08:51:45 -0800197 /**
198 * An interface that to provide {@link ActivityStarter} instances to the controller. This is
199 * used by tests to inject their own starter implementations for verification purposes.
200 */
201 @VisibleForTesting
202 interface Factory {
203 /**
Bryce Lee4c9a5972017-12-01 22:14:24 -0800204 * Sets the {@link ActivityStartController} to be passed to {@link ActivityStarter}.
205 */
206 void setController(ActivityStartController controller);
207
208 /**
Bryce Leed3624e12017-11-30 08:51:45 -0800209 * Generates an {@link ActivityStarter} that is ready to handle a new start request.
210 * @param controller The {@link ActivityStartController} which the starter who will own
211 * this instance.
212 * @return an {@link ActivityStarter}
213 */
Bryce Leedaa91e42017-12-06 14:13:01 -0800214 ActivityStarter obtain();
215
216 /**
217 * Recycles a starter for reuse.
218 */
219 void recycle(ActivityStarter starter);
Wale Ogunwale01d66562015-12-29 08:19:19 -0800220 }
221
Bryce Leed3624e12017-11-30 08:51:45 -0800222 /**
223 * Default implementation of {@link StarterFactory}.
224 */
225 static class DefaultFactory implements Factory {
Bryce Leedaa91e42017-12-06 14:13:01 -0800226 /**
227 * The maximum count of starters that should be active at one time:
228 * 1. last ran starter (for logging and post activity processing)
229 * 2. current running starter
230 * 3. starter from re-entry in (2)
231 */
232 private final int MAX_STARTER_COUNT = 3;
233
Bryce Lee4c9a5972017-12-01 22:14:24 -0800234 private ActivityStartController mController;
235 private ActivityManagerService mService;
236 private ActivityStackSupervisor mSupervisor;
237 private ActivityStartInterceptor mInterceptor;
238
Bryce Leedaa91e42017-12-06 14:13:01 -0800239 private SynchronizedPool<ActivityStarter> mStarterPool =
240 new SynchronizedPool<>(MAX_STARTER_COUNT);
241
Bryce Lee4c9a5972017-12-01 22:14:24 -0800242 DefaultFactory(ActivityManagerService service,
243 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
244 mService = service;
245 mSupervisor = supervisor;
246 mInterceptor = interceptor;
Bryce Leed3624e12017-11-30 08:51:45 -0800247 }
Bryce Lee4c9a5972017-12-01 22:14:24 -0800248
249 @Override
250 public void setController(ActivityStartController controller) {
251 mController = controller;
252 }
253
254 @Override
Bryce Leedaa91e42017-12-06 14:13:01 -0800255 public ActivityStarter obtain() {
256 ActivityStarter starter = mStarterPool.acquire();
257
258 if (starter == null) {
259 starter = new ActivityStarter(mController, mService, mSupervisor, mInterceptor);
260 }
261
262 return starter;
263 }
264
265 @Override
266 public void recycle(ActivityStarter starter) {
267 starter.reset(true /* clearRequest*/);
268 mStarterPool.release(starter);
Bryce Lee4c9a5972017-12-01 22:14:24 -0800269 }
270 }
271
272 /**
273 * Container for capturing initial start request details. This information is NOT reset until
274 * the {@link ActivityStarter} is recycled, allowing for multiple invocations with the same
275 * parameters.
276 *
277 * TODO(b/64750076): Investigate consolidating member variables of {@link ActivityStarter} with
278 * the request object. Note that some member variables are referenced in
279 * {@link #dump(PrintWriter, String)} and therefore cannot be cleared immediately after
280 * execution.
281 */
282 private static class Request {
283 private static final int DEFAULT_CALLING_UID = -1;
284 private static final int DEFAULT_CALLING_PID = 0;
285
286 IApplicationThread caller;
287 Intent intent;
288 Intent ephemeralIntent;
289 String resolvedType;
290 ActivityInfo activityInfo;
291 ResolveInfo resolveInfo;
292 IVoiceInteractionSession voiceSession;
293 IVoiceInteractor voiceInteractor;
294 IBinder resultTo;
295 String resultWho;
296 int requestCode;
297 int callingPid = DEFAULT_CALLING_UID;
298 int callingUid = DEFAULT_CALLING_PID;
299 String callingPackage;
300 int realCallingPid;
301 int realCallingUid;
302 int startFlags;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100303 SafeActivityOptions activityOptions;
Bryce Lee4c9a5972017-12-01 22:14:24 -0800304 boolean ignoreTargetSecurity;
305 boolean componentSpecified;
Winson Chunge2d72172018-01-25 17:46:20 +0000306 boolean avoidMoveToFront;
Bryce Lee4c9a5972017-12-01 22:14:24 -0800307 ActivityRecord[] outActivity;
308 TaskRecord inTask;
309 String reason;
310 ProfilerInfo profilerInfo;
311 Configuration globalConfig;
Bryce Lee4c9a5972017-12-01 22:14:24 -0800312 int userId;
313 WaitResult waitResult;
314
315 /**
316 * Indicates that we should wait for the result of the start request. This flag is set when
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100317 * {@link ActivityStarter#setMayWait(int)} is called.
Bryce Lee4c9a5972017-12-01 22:14:24 -0800318 * {@see ActivityStarter#startActivityMayWait}.
319 */
320 boolean mayWait;
Bryce Leedaa91e42017-12-06 14:13:01 -0800321
322 /**
Bryce Leea3cd8e02018-01-09 15:44:24 -0800323 * Ensure constructed request matches reset instance.
324 */
325 Request() {
326 reset();
327 }
328
329 /**
Bryce Leedaa91e42017-12-06 14:13:01 -0800330 * Sets values back to the initial state, clearing any held references.
331 */
332 void reset() {
333 caller = null;
334 intent = null;
335 ephemeralIntent = null;
336 resolvedType = null;
337 activityInfo = null;
338 resolveInfo = null;
339 voiceSession = null;
340 voiceInteractor = null;
341 resultTo = null;
342 resultWho = null;
343 requestCode = 0;
Bryce Leea3cd8e02018-01-09 15:44:24 -0800344 callingPid = DEFAULT_CALLING_PID;
345 callingUid = DEFAULT_CALLING_UID;
Bryce Leedaa91e42017-12-06 14:13:01 -0800346 callingPackage = null;
347 realCallingPid = 0;
348 realCallingUid = 0;
349 startFlags = 0;
350 activityOptions = null;
351 ignoreTargetSecurity = false;
352 componentSpecified = false;
353 outActivity = null;
354 inTask = null;
355 reason = null;
356 profilerInfo = null;
357 globalConfig = null;
Bryce Leedaa91e42017-12-06 14:13:01 -0800358 userId = 0;
359 waitResult = null;
360 mayWait = false;
Winson Chunge2d72172018-01-25 17:46:20 +0000361 avoidMoveToFront = false;
Bryce Leedaa91e42017-12-06 14:13:01 -0800362 }
363
364 /**
365 * Adopts all values from passed in request.
366 */
367 void set(Request request) {
368 caller = request.caller;
369 intent = request.intent;
370 ephemeralIntent = request.ephemeralIntent;
371 resolvedType = request.resolvedType;
372 activityInfo = request.activityInfo;
373 resolveInfo = request.resolveInfo;
374 voiceSession = request.voiceSession;
375 voiceInteractor = request.voiceInteractor;
376 resultTo = request.resultTo;
377 resultWho = request.resultWho;
378 requestCode = request.requestCode;
379 callingPid = request.callingPid;
380 callingUid = request.callingUid;
381 callingPackage = request.callingPackage;
382 realCallingPid = request.realCallingPid;
383 realCallingUid = request.realCallingUid;
384 startFlags = request.startFlags;
385 activityOptions = request.activityOptions;
386 ignoreTargetSecurity = request.ignoreTargetSecurity;
387 componentSpecified = request.componentSpecified;
388 outActivity = request.outActivity;
389 inTask = request.inTask;
390 reason = request.reason;
391 profilerInfo = request.profilerInfo;
392 globalConfig = request.globalConfig;
Bryce Leedaa91e42017-12-06 14:13:01 -0800393 userId = request.userId;
394 waitResult = request.waitResult;
395 mayWait = request.mayWait;
Winson Chunge2d72172018-01-25 17:46:20 +0000396 avoidMoveToFront = request.avoidMoveToFront;
Bryce Leedaa91e42017-12-06 14:13:01 -0800397 }
Bryce Leed3624e12017-11-30 08:51:45 -0800398 }
399
400 ActivityStarter(ActivityStartController controller, ActivityManagerService service,
401 ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
402 mController = controller;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800403 mService = service;
Bryce Leed3624e12017-11-30 08:51:45 -0800404 mSupervisor = supervisor;
405 mInterceptor = interceptor;
Bryce Leedaa91e42017-12-06 14:13:01 -0800406 reset(true);
407 }
408
409 /**
410 * Effectively duplicates the starter passed in. All state and request values will be
411 * mirrored.
412 * @param starter
413 */
414 void set(ActivityStarter starter) {
415 mStartActivity = starter.mStartActivity;
416 mIntent = starter.mIntent;
417 mCallingUid = starter.mCallingUid;
418 mOptions = starter.mOptions;
419
420 mLaunchTaskBehind = starter.mLaunchTaskBehind;
421 mLaunchFlags = starter.mLaunchFlags;
422 mLaunchMode = starter.mLaunchMode;
423
Bryce Leeec55eb02017-12-05 20:51:27 -0800424 mLaunchParams.set(starter.mLaunchParams);
Bryce Leedaa91e42017-12-06 14:13:01 -0800425
426 mNotTop = starter.mNotTop;
427 mDoResume = starter.mDoResume;
428 mStartFlags = starter.mStartFlags;
429 mSourceRecord = starter.mSourceRecord;
430 mPreferredDisplayId = starter.mPreferredDisplayId;
431
432 mInTask = starter.mInTask;
433 mAddingToTask = starter.mAddingToTask;
434 mReuseTask = starter.mReuseTask;
435
436 mNewTaskInfo = starter.mNewTaskInfo;
437 mNewTaskIntent = starter.mNewTaskIntent;
438 mSourceStack = starter.mSourceStack;
439
440 mTargetStack = starter.mTargetStack;
441 mMovedToFront = starter.mMovedToFront;
442 mNoAnimation = starter.mNoAnimation;
443 mKeepCurTransition = starter.mKeepCurTransition;
444 mAvoidMoveToFront = starter.mAvoidMoveToFront;
445
446 mVoiceSession = starter.mVoiceSession;
447 mVoiceInteractor = starter.mVoiceInteractor;
448
449 mIntentDelivered = starter.mIntentDelivered;
450
451 mRequest.set(starter.mRequest);
Bryce Leed3624e12017-11-30 08:51:45 -0800452 }
453
Bryce Lee4c9a5972017-12-01 22:14:24 -0800454 ActivityRecord getStartActivity() {
455 return mStartActivity;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800456 }
457
Bryce Lee4c9a5972017-12-01 22:14:24 -0800458 boolean relatedToPackage(String packageName) {
459 return (mLastStartActivityRecord[0] != null
460 && packageName.equals(mLastStartActivityRecord[0].packageName))
461 || (mStartActivity != null && packageName.equals(mStartActivity.packageName));
462 }
463
464 /**
465 * Starts an activity based on the request parameters provided earlier.
466 * @return The starter result.
467 */
468 int execute() {
Bryce Leedaa91e42017-12-06 14:13:01 -0800469 try {
470 // TODO(b/64750076): Look into passing request directly to these methods to allow
471 // for transactional diffs and preprocessing.
472 if (mRequest.mayWait) {
473 return startActivityMayWait(mRequest.caller, mRequest.callingUid,
474 mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
475 mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
476 mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
477 mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100478 mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
Bryce Leedaa91e42017-12-06 14:13:01 -0800479 mRequest.inTask, mRequest.reason);
480 } else {
481 return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
482 mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
483 mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
484 mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
485 mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
486 mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
487 mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
488 mRequest.outActivity, mRequest.inTask, mRequest.reason);
489 }
490 } finally {
491 onExecutionComplete();
492 }
493 }
494
495 /**
496 * Starts an activity based on the provided {@link ActivityRecord} and environment parameters.
497 * Note that this method is called internally as well as part of {@link #startActivity}.
498 *
499 * @return The start result.
500 */
501 int startResolvedActivity(final ActivityRecord r, ActivityRecord sourceRecord,
502 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
503 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
504 ActivityRecord[] outActivity) {
505 try {
506 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
507 doResume, options, inTask, outActivity);
508 } finally {
509 onExecutionComplete();
Bryce Lee4c9a5972017-12-01 22:14:24 -0800510 }
511 }
512
513 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700514 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
515 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
516 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
517 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100518 SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700519 ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700520
521 if (TextUtils.isEmpty(reason)) {
522 throw new IllegalArgumentException("Need to specify a reason.");
523 }
524 mLastStartReason = reason;
525 mLastStartActivityTimeMs = System.currentTimeMillis();
526 mLastStartActivityRecord[0] = null;
527
528 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
529 aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
530 callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
531 options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700532 inTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700533
534 if (outActivity != null) {
535 // mLastStartActivityRecord[0] is set in the call to startActivity above.
536 outActivity[0] = mLastStartActivityRecord[0];
537 }
Bryce Leef9d49542017-06-26 16:27:32 -0700538
Bryce Lee93e7f792017-10-25 15:54:55 -0700539 return getExternalResult(mLastStartActivityResult);
540 }
541
Bryce Leed3624e12017-11-30 08:51:45 -0800542 static int getExternalResult(int result) {
Bryce Leef9d49542017-06-26 16:27:32 -0700543 // Aborted results are treated as successes externally, but we must track them internally.
Bryce Lee93e7f792017-10-25 15:54:55 -0700544 return result != START_ABORTED ? result : START_SUCCESS;
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700545 }
546
Bryce Leedaa91e42017-12-06 14:13:01 -0800547 /**
548 * Called when execution is complete. Sets state indicating completion and proceeds with
549 * recycling if appropriate.
550 */
551 private void onExecutionComplete() {
552 mController.onExecutionComplete(this);
553 }
554
Wale Ogunwale692dcd62017-06-20 13:38:14 -0700555 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800556 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
557 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
558 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
559 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100560 SafeActivityOptions options,
561 boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
562 TaskRecord inTask) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800563 int err = ActivityManager.START_SUCCESS;
Chad Brubaker06068612017-04-06 09:43:47 -0700564 // Pull the optional Ephemeral Installer-only bundle out of the options early.
565 final Bundle verificationBundle
566 = options != null ? options.popAppVerificationBundle() : null;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800567
568 ProcessRecord callerApp = null;
569 if (caller != null) {
570 callerApp = mService.getRecordForAppLocked(caller);
571 if (callerApp != null) {
572 callingPid = callerApp.pid;
573 callingUid = callerApp.info.uid;
574 } else {
575 Slog.w(TAG, "Unable to find app for caller " + caller
576 + " (pid=" + callingPid + ") when starting: "
577 + intent.toString());
578 err = ActivityManager.START_PERMISSION_DENIED;
579 }
580 }
581
Bryce Lee93e7f792017-10-25 15:54:55 -0700582 final int userId = aInfo != null && aInfo.applicationInfo != null
583 ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800584
585 if (err == ActivityManager.START_SUCCESS) {
586 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
Andrii Kulian03c403d2016-11-11 11:14:12 -0800587 + "} from uid " + callingUid);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800588 }
589
590 ActivityRecord sourceRecord = null;
591 ActivityRecord resultRecord = null;
592 if (resultTo != null) {
593 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
594 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
595 "Will send result to " + resultTo + " " + sourceRecord);
596 if (sourceRecord != null) {
597 if (requestCode >= 0 && !sourceRecord.finishing) {
598 resultRecord = sourceRecord;
599 }
600 }
601 }
602
603 final int launchFlags = intent.getFlags();
604
605 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
606 // Transfer the result target from the source activity to the new
607 // one being started, including any failures.
608 if (requestCode >= 0) {
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100609 SafeActivityOptions.abort(options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800610 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
611 }
612 resultRecord = sourceRecord.resultTo;
613 if (resultRecord != null && !resultRecord.isInStackLocked()) {
614 resultRecord = null;
615 }
616 resultWho = sourceRecord.resultWho;
617 requestCode = sourceRecord.requestCode;
618 sourceRecord.resultTo = null;
619 if (resultRecord != null) {
620 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
621 }
622 if (sourceRecord.launchedFromUid == callingUid) {
623 // The new activity is being launched from the same uid as the previous
624 // activity in the flow, and asking to forward its result back to the
625 // previous. In this case the activity is serving as a trampoline between
626 // the two, so we also want to update its launchedFromPackage to be the
627 // same as the previous activity. Note that this is safe, since we know
628 // these two packages come from the same uid; the caller could just as
629 // well have supplied that same package name itself. This specifially
630 // deals with the case of an intent picker/chooser being launched in the app
631 // flow to redirect to an activity picked by the user, where we want the final
632 // activity to consider it to have been launched by the previous app activity.
633 callingPackage = sourceRecord.launchedFromPackage;
634 }
635 }
636
637 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
638 // We couldn't find a class that can handle the given Intent.
639 // That's the end of that!
640 err = ActivityManager.START_INTENT_NOT_RESOLVED;
641 }
642
643 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
644 // We couldn't find the specific class specified in the Intent.
645 // Also the end of the line.
646 err = ActivityManager.START_CLASS_NOT_FOUND;
647 }
648
649 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
Bryce Leeaf691c02017-03-20 14:20:22 -0700650 && sourceRecord.getTask().voiceSession != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800651 // If this activity is being launched as part of a voice session, we need
652 // to ensure that it is safe to do so. If the upcoming activity will also
653 // be part of the voice session, we can only launch it if it has explicitly
654 // said it supports the VOICE category, or it is a part of the calling app.
655 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
656 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
657 try {
658 intent.addCategory(Intent.CATEGORY_VOICE);
Bryce Leeba8f4422017-11-20 12:35:57 -0800659 if (!mService.getPackageManager().activitySupportsIntent(
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800660 intent.getComponent(), intent, resolvedType)) {
661 Slog.w(TAG,
662 "Activity being started in current voice task does not support voice: "
663 + intent);
664 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
665 }
666 } catch (RemoteException e) {
667 Slog.w(TAG, "Failure checking voice capabilities", e);
668 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
669 }
670 }
671 }
672
673 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
674 // If the caller is starting a new voice session, just make sure the target
675 // is actually allowing it to run this way.
676 try {
Bryce Leeba8f4422017-11-20 12:35:57 -0800677 if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800678 intent, resolvedType)) {
679 Slog.w(TAG,
680 "Activity being started in new voice task does not support: "
681 + intent);
682 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
683 }
684 } catch (RemoteException e) {
685 Slog.w(TAG, "Failure checking voice capabilities", e);
686 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
687 }
688 }
689
Andrii Kulian02b7a832016-10-06 23:11:56 -0700690 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800691
Wale Ogunwale01d66562015-12-29 08:19:19 -0800692 if (err != START_SUCCESS) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800693 if (resultRecord != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -0800694 resultStack.sendActivityResultLocked(
695 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800696 }
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100697 SafeActivityOptions.abort(options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800698 return err;
699 }
700
701 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100702 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
703 callerApp, resultRecord, resultStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800704 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
705 callingPid, resolvedType, aInfo.applicationInfo);
706
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100707 // Merge the two options bundles, while realCallerOptions takes precedence.
708 ActivityOptions checkedOptions = options != null
709 ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
710 : null;
Jorim Jaggi04dc5962018-01-29 18:54:13 +0100711 checkedOptions = mService.getActivityStartController().getPendingRemoteAnimationRegistry()
712 .overrideOptionsIfNeeded(callingPackage, checkedOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800713 if (mService.mController != null) {
714 try {
715 // The Intent we give to the watcher has the extra data
716 // stripped off, since it can contain private information.
717 Intent watchIntent = intent.cloneFilter();
718 abort |= !mService.mController.activityStarting(watchIntent,
719 aInfo.applicationInfo.packageName);
720 } catch (RemoteException e) {
721 mService.mController = null;
722 }
723 }
724
Rubin Xu58d25992016-01-21 17:47:13 +0000725 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Benjamin Franz563707b2017-06-29 15:06:13 +0100726 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100727 callingUid, checkedOptions)) {
Benjamin Franz563707b2017-06-29 15:06:13 +0100728 // activity start was intercepted, e.g. because the target user is currently in quiet
729 // mode (turn off work) or the target application is suspended
730 intent = mInterceptor.mIntent;
731 rInfo = mInterceptor.mRInfo;
732 aInfo = mInterceptor.mAInfo;
733 resolvedType = mInterceptor.mResolvedType;
734 inTask = mInterceptor.mInTask;
735 callingPid = mInterceptor.mCallingPid;
736 callingUid = mInterceptor.mCallingUid;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100737 checkedOptions = mInterceptor.mActivityOptions;
Benjamin Franz563707b2017-06-29 15:06:13 +0100738 }
739
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800740 if (abort) {
741 if (resultRecord != null) {
742 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800743 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800744 }
745 // We pretend to the caller that it was really started, but
746 // they will just get a cancel result.
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100747 ActivityOptions.abort(checkedOptions);
Bryce Leef9d49542017-06-26 16:27:32 -0700748 return START_ABORTED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800749 }
750
751 // If permissions need a review before any of the app components can run, we
752 // launch the review activity and pass a pending intent to start the activity
753 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700754 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800755 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
756 aInfo.packageName, userId)) {
757 IIntentSender target = mService.getIntentSenderLocked(
758 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
759 callingUid, userId, null, null, 0, new Intent[]{intent},
760 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
761 | PendingIntent.FLAG_ONE_SHOT, null);
762
763 final int flags = intent.getFlags();
764 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
765 newIntent.setFlags(flags
766 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
767 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
768 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
769 if (resultRecord != null) {
770 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
771 }
772 intent = newIntent;
773
774 resolvedType = null;
775 callingUid = realCallingUid;
776 callingPid = realCallingPid;
777
778 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
779 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
780 null /*profilerInfo*/);
781
782 if (DEBUG_PERMISSIONS_REVIEW) {
783 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
784 true, false) + "} from uid " + callingUid + " on display "
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700785 + (mSupervisor.mFocusedStack == null
786 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800787 }
788 }
789 }
790
791 // If we have an ephemeral app, abort the process of launching the resolved intent.
792 // Instead, launch the ephemeral installer. Once the installer is finished, it
793 // starts either the intent we resolved here [on install error] or the ephemeral
794 // app [on install success].
Patrick Baumanna89a1722018-02-07 15:26:52 -0800795 if (rInfo != null && rInfo.auxiliaryInfo != null) {
Todd Kennedye9910222017-02-21 16:00:11 -0800796 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700797 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800798 resolvedType = null;
799 callingUid = realCallingUid;
800 callingPid = realCallingPid;
801
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800802 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
803 }
804
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800805 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
806 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
807 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100808 mSupervisor, checkedOptions, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800809 if (outActivity != null) {
810 outActivity[0] = r;
811 }
812
813 if (r.appTimeTracker == null && sourceRecord != null) {
814 // If the caller didn't specify an explicit time tracker, we want to continue
815 // tracking under any it has.
816 r.appTimeTracker = sourceRecord.appTimeTracker;
817 }
818
819 final ActivityStack stack = mSupervisor.mFocusedStack;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100820
821 // If we are starting an activity that is not from the same uid as the currently resumed
822 // one, check whether app switches are allowed.
Bryce Leec4ab62a2018-03-05 14:19:26 -0800823 if (voiceSession == null && (stack.getResumedActivity() == null
824 || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800825 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
826 realCallingPid, realCallingUid, "Activity start")) {
Bryce Leed3624e12017-11-30 08:51:45 -0800827 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
828 sourceRecord, startFlags, stack, callerApp));
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100829 ActivityOptions.abort(checkedOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800830 return ActivityManager.START_SWITCHES_CANCELED;
831 }
832 }
833
834 if (mService.mDidAppSwitch) {
835 // This is the second allowed switch since we stopped switches,
836 // so now just generally allow switches. Use case: user presses
837 // home (switches disabled, switch to home, mDidAppSwitch now true);
838 // user taps a home icon (coming from home so allowed, we hit here
839 // and now allow anyone to switch again).
840 mService.mAppSwitchesAllowedTime = 0;
841 } else {
842 mService.mDidAppSwitch = true;
843 }
844
Bryce Leed3624e12017-11-30 08:51:45 -0800845 mController.doPendingActivityLaunches(false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800846
Bryce Leedaa91e42017-12-06 14:13:01 -0800847 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100848 true /* doResume */, checkedOptions, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800849 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800850
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100851
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800852 /**
853 * Creates a launch intent for the given auxiliary resolution data.
854 */
Patrick Baumann577d4022018-01-31 16:55:10 +0000855 private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700856 Intent originalIntent, String callingPackage, Bundle verificationBundle,
857 String resolvedType, int userId) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000858 if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
Todd Kennedye9910222017-02-21 16:00:11 -0800859 // request phase two resolution
860 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700861 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
862 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800863 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700864 return InstantAppResolver.buildEphemeralInstallerIntent(
Patrick Baumann577d4022018-01-31 16:55:10 +0000865 originalIntent,
866 InstantAppResolver.sanitizeIntent(originalIntent),
867 auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent,
868 callingPackage,
869 verificationBundle,
870 resolvedType,
871 userId,
872 auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity,
873 auxiliaryResponse == null ? null : auxiliaryResponse.token,
874 auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo,
875 auxiliaryResponse == null ? null : auxiliaryResponse.filters);
Todd Kennedye9910222017-02-21 16:00:11 -0800876 }
877
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700878 void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
Bryce Lee7f936862017-05-09 15:33:18 -0700879 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800880 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800881 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800882
Chong Zhang5022da32016-06-21 16:31:37 -0700883 // We're waiting for an activity launch to finish, but that activity simply
Bryce Lee5f0e28f2018-01-30 16:00:03 -0800884 // brought another activity to front. We must also handle the case where the task is already
885 // in the front as a result of the trampoline activity being in the same task (it will be
886 // considered focused as the trampoline will be finished). Let startActivityMayWait() know
887 // about this, so it waits for the new activity to become visible instead.
888 mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);
Chong Zhang5022da32016-06-21 16:31:37 -0700889
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700890 ActivityStack startedActivityStack = null;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700891 final ActivityStack currentStack = r.getStack();
892 if (currentStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700893 startedActivityStack = currentStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800894 } else if (mTargetStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700895 startedActivityStack = targetStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800896 }
897
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700898 if (startedActivityStack == null) {
899 return;
900 }
901
Wale Ogunwaleac36e4d2017-11-29 13:30:26 -0800902 final int clearTaskFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK;
903 boolean clearedTask = (mLaunchFlags & clearTaskFlags) == clearTaskFlags
904 && mReuseTask != null;
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700905 if (startedActivityStack.inPinnedWindowingMode()
906 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
907 || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800908 // The activity was already running in the pinned stack so it wasn't started, but either
909 // brought to the front or the new intent was delivered to it since it was already in
910 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700911 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
912 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800913 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800914 }
915
Bryce Lee4c9a5972017-12-01 22:14:24 -0800916 private int startActivityMayWait(IApplicationThread caller, int callingUid,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800917 String callingPackage, Intent intent, String resolvedType,
918 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
919 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700920 ProfilerInfo profilerInfo, WaitResult outResult,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100921 Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
922 int userId, TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800923 // Refuse possible leaked file descriptors
924 if (intent != null && intent.hasFileDescriptors()) {
925 throw new IllegalArgumentException("File descriptors passed in Intent");
926 }
Bryce Lee2a3cc462017-10-27 10:57:35 -0700927 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800928 boolean componentSpecified = intent.getComponent() != null;
929
930 // Save a copy in case ephemeral needs it
931 final Intent ephemeralIntent = new Intent(intent);
932 // Don't modify the client's object!
933 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700934 if (componentSpecified
Patrick Baumann531db462018-02-13 13:01:47 -0800935 && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
Patrick Baumann577d4022018-01-31 16:55:10 +0000936 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
937 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700938 && mService.getPackageManagerInternalLocked()
939 .isInstantAppInstallerComponent(intent.getComponent())) {
940 // intercept intents targeted directly to the ephemeral installer the
Patrick Baumann577d4022018-01-31 16:55:10 +0000941 // ephemeral installer should never be started with a raw Intent; instead
Todd Kennedyb21be122017-03-24 14:10:01 -0700942 // adjust the intent so it looks like a "normal" instant app launch
943 intent.setComponent(null /*component*/);
944 componentSpecified = false;
945 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800946
947 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000948 if (rInfo == null) {
949 UserInfo userInfo = mSupervisor.getUserInfo(userId);
950 if (userInfo != null && userInfo.isManagedProfile()) {
951 // Special case for managed profiles, if attempting to launch non-cryto aware
952 // app in a locked managed profile from an unlocked parent allow it to resolve
953 // as user will be sent via confirm credentials to unlock the profile.
954 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700955 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000956 long token = Binder.clearCallingIdentity();
957 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700958 UserInfo parent = userManager.getProfileParent(userId);
959 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
960 && userManager.isUserUnlockingOrUnlocked(parent.id)
961 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000962 } finally {
963 Binder.restoreCallingIdentity(token);
964 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700965 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000966 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600967 PackageManager.MATCH_DIRECT_BOOT_AWARE
Patrick Baumann78380272018-04-04 10:41:01 -0700968 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
969 Binder.getCallingUid());
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}