blob: b061ba4106d44160866fb0ccbf731a2deadec2f0 [file] [log] [blame]
Kenny Guyb1b30262016-02-09 16:02:35 +00001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080017package com.android.server.am;
18
Wale Ogunwale01d66562015-12-29 08:19:19 -080019import static android.app.Activity.RESULT_CANCELED;
Bryce Leef9d49542017-06-26 16:27:32 -070020import static android.app.ActivityManager.START_ABORTED;
Bryce Leeaa5e8c32017-03-01 16:01:06 -080021import static android.app.ActivityManager.START_CANCELED;
Wale Ogunwale01d66562015-12-29 08:19:19 -080022import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
23import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
24import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
25import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
26import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
27import static android.app.ActivityManager.START_SUCCESS;
28import static android.app.ActivityManager.START_TASK_TO_FRONT;
Wale Ogunwale68278562017-09-23 17:13:55 -070029import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070031import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
32import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale0568aed2017-09-08 13:29:37 -070033import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Patrick Baumann577d4022018-01-31 16:55:10 +000034import static android.content.Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080035import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
36import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
Wale Ogunwale2a25a622016-01-30 11:27:21 -080037import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080038import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080039import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -080040import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwale01d66562015-12-29 08:19:19 -080041import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
42import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
Wale Ogunwale01d66562015-12-29 08:19:19 -080043import static android.content.Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP;
44import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
45import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
46import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
47import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
48import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
49import 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;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800711 if (mService.mController != null) {
712 try {
713 // The Intent we give to the watcher has the extra data
714 // stripped off, since it can contain private information.
715 Intent watchIntent = intent.cloneFilter();
716 abort |= !mService.mController.activityStarting(watchIntent,
717 aInfo.applicationInfo.packageName);
718 } catch (RemoteException e) {
719 mService.mController = null;
720 }
721 }
722
Rubin Xu58d25992016-01-21 17:47:13 +0000723 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
Benjamin Franz563707b2017-06-29 15:06:13 +0100724 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100725 callingUid, checkedOptions)) {
Benjamin Franz563707b2017-06-29 15:06:13 +0100726 // activity start was intercepted, e.g. because the target user is currently in quiet
727 // mode (turn off work) or the target application is suspended
728 intent = mInterceptor.mIntent;
729 rInfo = mInterceptor.mRInfo;
730 aInfo = mInterceptor.mAInfo;
731 resolvedType = mInterceptor.mResolvedType;
732 inTask = mInterceptor.mInTask;
733 callingPid = mInterceptor.mCallingPid;
734 callingUid = mInterceptor.mCallingUid;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100735 checkedOptions = mInterceptor.mActivityOptions;
Benjamin Franz563707b2017-06-29 15:06:13 +0100736 }
737
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800738 if (abort) {
739 if (resultRecord != null) {
740 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
Wale Ogunwale01d66562015-12-29 08:19:19 -0800741 RESULT_CANCELED, null);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800742 }
743 // We pretend to the caller that it was really started, but
744 // they will just get a cancel result.
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100745 ActivityOptions.abort(checkedOptions);
Bryce Leef9d49542017-06-26 16:27:32 -0700746 return START_ABORTED;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800747 }
748
749 // If permissions need a review before any of the app components can run, we
750 // launch the review activity and pass a pending intent to start the activity
751 // we are to launching now after the review is completed.
Svet Ganov77df6f32016-08-17 11:46:34 -0700752 if (mService.mPermissionReviewRequired && aInfo != null) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800753 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
754 aInfo.packageName, userId)) {
755 IIntentSender target = mService.getIntentSenderLocked(
756 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
757 callingUid, userId, null, null, 0, new Intent[]{intent},
758 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
759 | PendingIntent.FLAG_ONE_SHOT, null);
760
761 final int flags = intent.getFlags();
762 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
763 newIntent.setFlags(flags
764 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
765 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
766 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
767 if (resultRecord != null) {
768 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
769 }
770 intent = newIntent;
771
772 resolvedType = null;
773 callingUid = realCallingUid;
774 callingPid = realCallingPid;
775
776 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
777 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
778 null /*profilerInfo*/);
779
780 if (DEBUG_PERMISSIONS_REVIEW) {
781 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
782 true, false) + "} from uid " + callingUid + " on display "
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700783 + (mSupervisor.mFocusedStack == null
784 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800785 }
786 }
787 }
788
789 // If we have an ephemeral app, abort the process of launching the resolved intent.
790 // Instead, launch the ephemeral installer. Once the installer is finished, it
791 // starts either the intent we resolved here [on install error] or the ephemeral
792 // app [on install success].
Patrick Baumann577d4022018-01-31 16:55:10 +0000793 if (rInfo != null && rInfo.isInstantAppAvailable) {
Todd Kennedye9910222017-02-21 16:00:11 -0800794 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
Chad Brubaker06068612017-04-06 09:43:47 -0700795 callingPackage, verificationBundle, resolvedType, userId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800796 resolvedType = null;
797 callingUid = realCallingUid;
798 callingPid = realCallingPid;
799
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800800 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
801 }
802
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800803 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
804 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
805 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100806 mSupervisor, checkedOptions, sourceRecord);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800807 if (outActivity != null) {
808 outActivity[0] = r;
809 }
810
811 if (r.appTimeTracker == null && sourceRecord != null) {
812 // If the caller didn't specify an explicit time tracker, we want to continue
813 // tracking under any it has.
814 r.appTimeTracker = sourceRecord.appTimeTracker;
815 }
816
817 final ActivityStack stack = mSupervisor.mFocusedStack;
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100818
819 // If we are starting an activity that is not from the same uid as the currently resumed
820 // one, check whether app switches are allowed.
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800821 if (voiceSession == null && (stack.mResumedActivity == null
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100822 || stack.mResumedActivity.info.applicationInfo.uid != realCallingUid)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800823 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
824 realCallingPid, realCallingUid, "Activity start")) {
Bryce Leed3624e12017-11-30 08:51:45 -0800825 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
826 sourceRecord, startFlags, stack, callerApp));
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100827 ActivityOptions.abort(checkedOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800828 return ActivityManager.START_SWITCHES_CANCELED;
829 }
830 }
831
832 if (mService.mDidAppSwitch) {
833 // This is the second allowed switch since we stopped switches,
834 // so now just generally allow switches. Use case: user presses
835 // home (switches disabled, switch to home, mDidAppSwitch now true);
836 // user taps a home icon (coming from home so allowed, we hit here
837 // and now allow anyone to switch again).
838 mService.mAppSwitchesAllowedTime = 0;
839 } else {
840 mService.mDidAppSwitch = true;
841 }
842
Bryce Leed3624e12017-11-30 08:51:45 -0800843 mController.doPendingActivityLaunches(false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800844
Bryce Leedaa91e42017-12-06 14:13:01 -0800845 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100846 true /* doResume */, checkedOptions, inTask, outActivity);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800847 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800848
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100849
Bryce Leeaa5e8c32017-03-01 16:01:06 -0800850 /**
851 * Creates a launch intent for the given auxiliary resolution data.
852 */
Patrick Baumann577d4022018-01-31 16:55:10 +0000853 private @NonNull Intent createLaunchIntent(@Nullable AuxiliaryResolveInfo auxiliaryResponse,
Chad Brubaker06068612017-04-06 09:43:47 -0700854 Intent originalIntent, String callingPackage, Bundle verificationBundle,
855 String resolvedType, int userId) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000856 if (auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo) {
Todd Kennedye9910222017-02-21 16:00:11 -0800857 // request phase two resolution
858 mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
Chad Brubaker06068612017-04-06 09:43:47 -0700859 auxiliaryResponse, originalIntent, resolvedType, callingPackage,
860 verificationBundle, userId);
Todd Kennedye9910222017-02-21 16:00:11 -0800861 }
Todd Kennedydfc27c62017-05-17 15:32:10 -0700862 return InstantAppResolver.buildEphemeralInstallerIntent(
Patrick Baumann577d4022018-01-31 16:55:10 +0000863 originalIntent,
864 InstantAppResolver.sanitizeIntent(originalIntent),
865 auxiliaryResponse == null ? null : auxiliaryResponse.failureIntent,
866 callingPackage,
867 verificationBundle,
868 resolvedType,
869 userId,
870 auxiliaryResponse == null ? null : auxiliaryResponse.installFailureActivity,
871 auxiliaryResponse == null ? null : auxiliaryResponse.token,
872 auxiliaryResponse != null && auxiliaryResponse.needsPhaseTwo,
873 auxiliaryResponse == null ? null : auxiliaryResponse.filters);
Todd Kennedye9910222017-02-21 16:00:11 -0800874 }
875
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700876 void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
Bryce Lee7f936862017-05-09 15:33:18 -0700877 if (ActivityManager.isStartResultFatalError(result)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800878 return;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800879 }
Filip Gruszczynski303210b2016-01-08 16:28:08 -0800880
Chong Zhang5022da32016-06-21 16:31:37 -0700881 // We're waiting for an activity launch to finish, but that activity simply
Bryce Lee5f0e28f2018-01-30 16:00:03 -0800882 // brought another activity to front. We must also handle the case where the task is already
883 // in the front as a result of the trampoline activity being in the same task (it will be
884 // considered focused as the trampoline will be finished). Let startActivityMayWait() know
885 // about this, so it waits for the new activity to become visible instead.
886 mSupervisor.reportWaitingActivityLaunchedIfNeeded(r, result);
Chong Zhang5022da32016-06-21 16:31:37 -0700887
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700888 ActivityStack startedActivityStack = null;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700889 final ActivityStack currentStack = r.getStack();
890 if (currentStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700891 startedActivityStack = currentStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800892 } else if (mTargetStack != null) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700893 startedActivityStack = targetStack;
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800894 }
895
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700896 if (startedActivityStack == null) {
897 return;
898 }
899
Wale Ogunwaleac36e4d2017-11-29 13:30:26 -0800900 final int clearTaskFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK;
901 boolean clearedTask = (mLaunchFlags & clearTaskFlags) == clearTaskFlags
902 && mReuseTask != null;
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700903 if (startedActivityStack.inPinnedWindowingMode()
904 && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
905 || clearedTask)) {
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800906 // The activity was already running in the pinned stack so it wasn't started, but either
907 // brought to the front or the new intent was delivered to it since it was already in
908 // front. Notify anyone interested in this piece of information.
Winson Chunge6385a22017-05-02 18:15:16 -0700909 mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
910 clearedTask);
Wale Ogunwalecc25a8a2016-01-23 14:31:37 -0800911 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800912 }
913
Bryce Lee4c9a5972017-12-01 22:14:24 -0800914 private int startActivityMayWait(IApplicationThread caller, int callingUid,
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800915 String callingPackage, Intent intent, String resolvedType,
916 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
917 IBinder resultTo, String resultWho, int requestCode, int startFlags,
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700918 ProfilerInfo profilerInfo, WaitResult outResult,
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +0100919 Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
920 int userId, TaskRecord inTask, String reason) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800921 // Refuse possible leaked file descriptors
922 if (intent != null && intent.hasFileDescriptors()) {
923 throw new IllegalArgumentException("File descriptors passed in Intent");
924 }
Bryce Lee2a3cc462017-10-27 10:57:35 -0700925 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800926 boolean componentSpecified = intent.getComponent() != null;
927
928 // Save a copy in case ephemeral needs it
929 final Intent ephemeralIntent = new Intent(intent);
930 // Don't modify the client's object!
931 intent = new Intent(intent);
Todd Kennedyb21be122017-03-24 14:10:01 -0700932 if (componentSpecified
Patrick Baumann577d4022018-01-31 16:55:10 +0000933 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
934 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
Todd Kennedyb21be122017-03-24 14:10:01 -0700935 && mService.getPackageManagerInternalLocked()
936 .isInstantAppInstallerComponent(intent.getComponent())) {
937 // intercept intents targeted directly to the ephemeral installer the
Patrick Baumann577d4022018-01-31 16:55:10 +0000938 // ephemeral installer should never be started with a raw Intent; instead
Todd Kennedyb21be122017-03-24 14:10:01 -0700939 // adjust the intent so it looks like a "normal" instant app launch
940 intent.setComponent(null /*component*/);
941 componentSpecified = false;
942 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800943
944 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
Kenny Guyb1b30262016-02-09 16:02:35 +0000945 if (rInfo == null) {
946 UserInfo userInfo = mSupervisor.getUserInfo(userId);
947 if (userInfo != null && userInfo.isManagedProfile()) {
948 // Special case for managed profiles, if attempting to launch non-cryto aware
949 // app in a locked managed profile from an unlocked parent allow it to resolve
950 // as user will be sent via confirm credentials to unlock the profile.
951 UserManager userManager = UserManager.get(mService.mContext);
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700952 boolean profileLockedAndParentUnlockingOrUnlocked = false;
Tony Mak13436452016-02-24 11:08:38 +0000953 long token = Binder.clearCallingIdentity();
954 try {
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700955 UserInfo parent = userManager.getProfileParent(userId);
956 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
957 && userManager.isUserUnlockingOrUnlocked(parent.id)
958 && !userManager.isUserUnlockingOrUnlocked(userId);
Tony Mak13436452016-02-24 11:08:38 +0000959 } finally {
960 Binder.restoreCallingIdentity(token);
961 }
Fyodor Kupolovce4db0a2016-05-11 14:21:18 -0700962 if (profileLockedAndParentUnlockingOrUnlocked) {
Kenny Guyb1b30262016-02-09 16:02:35 +0000963 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600964 PackageManager.MATCH_DIRECT_BOOT_AWARE
965 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
Kenny Guyb1b30262016-02-09 16:02:35 +0000966 }
967 }
968 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800969 // Collect information about the target of the Intent.
970 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
971
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800972 synchronized (mService) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800973 final int realCallingPid = Binder.getCallingPid();
974 final int realCallingUid = Binder.getCallingUid();
975 int callingPid;
976 if (callingUid >= 0) {
977 callingPid = -1;
978 } else if (caller == null) {
979 callingPid = realCallingPid;
980 callingUid = realCallingUid;
981 } else {
982 callingPid = callingUid = -1;
983 }
984
Andrii Kulian94e82d9b02017-07-13 15:33:06 -0700985 final ActivityStack stack = mSupervisor.mFocusedStack;
Andrii Kulian8072d112016-09-16 11:11:01 -0700986 stack.mConfigWillChange = globalConfig != null
Andrii Kulian1779e612016-10-12 21:58:25 -0700987 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -0800988 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
989 "Starting activity when config will change = " + stack.mConfigWillChange);
990
991 final long origId = Binder.clearCallingIdentity();
992
993 if (aInfo != null &&
994 (aInfo.applicationInfo.privateFlags
995 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
996 // This may be a heavy-weight process! Check to see if we already
997 // have another, different heavy-weight process running.
998 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
999 final ProcessRecord heavy = mService.mHeavyWeightProcess;
1000 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
1001 || !heavy.processName.equals(aInfo.processName))) {
1002 int appCallingUid = callingUid;
1003 if (caller != null) {
1004 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
1005 if (callerApp != null) {
1006 appCallingUid = callerApp.info.uid;
1007 } else {
1008 Slog.w(TAG, "Unable to find app for caller " + caller
1009 + " (pid=" + callingPid + ") when starting: "
1010 + intent.toString());
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01001011 SafeActivityOptions.abort(options);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001012 return ActivityManager.START_PERMISSION_DENIED;
1013 }
1014 }
1015
1016 IIntentSender target = mService.getIntentSenderLocked(
1017 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
1018 appCallingUid, userId, null, null, 0, new Intent[] { intent },
1019 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
1020 | PendingIntent.FLAG_ONE_SHOT, null);
1021
1022 Intent newIntent = new Intent();
1023 if (requestCode >= 0) {
1024 // Caller is requesting a result.
1025 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
1026 }
1027 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
1028 new IntentSender(target));
1029 if (heavy.activities.size() > 0) {
1030 ActivityRecord hist = heavy.activities.get(0);
1031 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
1032 hist.packageName);
1033 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
Bryce Leeaf691c02017-03-20 14:20:22 -07001034 hist.getTask().taskId);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001035 }
1036 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
1037 aInfo.packageName);
1038 newIntent.setFlags(intent.getFlags());
1039 newIntent.setClassName("android",
1040 HeavyWeightSwitcherActivity.class.getName());
1041 intent = newIntent;
1042 resolvedType = null;
1043 caller = null;
1044 callingUid = Binder.getCallingUid();
1045 callingPid = Binder.getCallingPid();
1046 componentSpecified = true;
1047 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
1048 aInfo = rInfo != null ? rInfo.activityInfo : null;
1049 if (aInfo != null) {
1050 aInfo = mService.getActivityInfoForUser(aInfo, userId);
1051 }
1052 }
1053 }
1054 }
1055
Jorim Jaggi275561a2016-02-23 10:11:02 -05001056 final ActivityRecord[] outRecord = new ActivityRecord[1];
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01001057 int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
1058 voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
1059 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
1060 ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001061
1062 Binder.restoreCallingIdentity(origId);
1063
1064 if (stack.mConfigWillChange) {
1065 // If the caller also wants to switch to a new configuration,
1066 // do so now. This allows a clean switch, as we are waiting
1067 // for the current activity to pause (so we will not destroy
1068 // it), and have not yet started the next activity.
1069 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
1070 "updateConfiguration()");
1071 stack.mConfigWillChange = false;
1072 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1073 "Updating to new configuration after starting activity.");
Andrii Kulian8072d112016-09-16 11:11:01 -07001074 mService.updateConfigurationLocked(globalConfig, null, false);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001075 }
1076
1077 if (outResult != null) {
1078 outResult.result = res;
Bryce Lee4a194382017-04-04 14:32:48 -07001079
Bryce Lee5f0e28f2018-01-30 16:00:03 -08001080 final ActivityRecord r = outRecord[0];
1081
1082 switch(res) {
1083 case START_SUCCESS: {
1084 mSupervisor.mWaitingActivityLaunched.add(outResult);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001085 do {
1086 try {
1087 mService.wait();
1088 } catch (InterruptedException e) {
1089 }
Bryce Lee5f0e28f2018-01-30 16:00:03 -08001090 } while (outResult.result != START_TASK_TO_FRONT
1091 && !outResult.timeout && outResult.who == null);
1092 if (outResult.result == START_TASK_TO_FRONT) {
1093 res = START_TASK_TO_FRONT;
1094 }
1095 break;
1096 }
1097 case START_DELIVERED_TO_TOP: {
1098 outResult.timeout = false;
1099 outResult.who = r.realActivity;
1100 outResult.totalTime = 0;
1101 outResult.thisTime = 0;
1102 break;
1103 }
1104 case START_TASK_TO_FRONT: {
1105 // ActivityRecord may represent a different activity, but it should not be
1106 // in the resumed state.
1107 if (r.nowVisible && r.state == RESUMED) {
1108 outResult.timeout = false;
1109 outResult.who = r.realActivity;
1110 outResult.totalTime = 0;
1111 outResult.thisTime = 0;
1112 } else {
1113 outResult.thisTime = SystemClock.uptimeMillis();
1114 mSupervisor.waitActivityVisible(r.realActivity, outResult);
1115 // Note: the timeout variable is not currently not ever set.
1116 do {
1117 try {
1118 mService.wait();
1119 } catch (InterruptedException e) {
1120 }
1121 } while (!outResult.timeout && outResult.who == null);
1122 }
1123 break;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001124 }
1125 }
1126 }
1127
Bryce Lee2a3cc462017-10-27 10:57:35 -07001128 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08001129 return res;
1130 }
1131 }
1132
Bryce Leedaa91e42017-12-06 14:13:01 -08001133 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
1134 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1135 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1136 ActivityRecord[] outActivity) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001137 int result = START_CANCELED;
1138 try {
1139 mService.mWindowManager.deferSurfaceLayout();
1140 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001141 startFlags, doResume, options, inTask, outActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001142 } finally {
1143 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1144 // activity in an incomplete state can lead to issues, such as performing operations
1145 // without a window container.
Bryce Leea3b0e3f02017-05-17 16:45:36 -07001146 if (!ActivityManager.isStartResultSuccessful(result)
Bryce Lee7f936862017-05-09 15:33:18 -07001147 && mStartActivity.getTask() != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001148 mStartActivity.getTask().removeActivity(mStartActivity);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001149 }
1150 mService.mWindowManager.continueSurfaceLayout();
1151 }
1152
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001153 postStartActivityProcessing(r, result, mTargetStack);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001154
1155 return result;
1156 }
1157
1158 // Note: This method should only be called from {@link startActivity}.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001159 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1160 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
Bryce Lee4a194382017-04-04 14:32:48 -07001161 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1162 ActivityRecord[] outActivity) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001163
1164 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1165 voiceInteractor);
1166
1167 computeLaunchingTaskFlags();
1168
1169 computeSourceStack();
1170
1171 mIntent.setFlags(mLaunchFlags);
1172
Bryce Lee4a194382017-04-04 14:32:48 -07001173 ActivityRecord reusedActivity = getReusableIntentActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001174
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001175 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1176 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1177 if (mOptions != null) {
1178 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1179 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1180 }
Jorim Jaggi2adba072016-03-03 13:43:39 +01001181
Bryce Leeec55eb02017-12-05 20:51:27 -08001182 // windowing mode and preferred launch display values from {@link LaunchParams} take
1183 // priority over those specified in {@link ActivityOptions}.
1184 if (!mLaunchParams.isEmpty()) {
1185 if (mLaunchParams.hasPreferredDisplay()) {
1186 preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
1187 }
1188
1189 if (mLaunchParams.hasWindowingMode()) {
1190 preferredWindowingMode = mLaunchParams.mWindowingMode;
1191 }
1192 }
1193
Bryce Lee4a194382017-04-04 14:32:48 -07001194 if (reusedActivity != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001195 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1196 // still needs to be a lock task mode violation since the task gets cleared out and
1197 // the device would otherwise leave the locked task.
Benjamin Franza83859f2017-07-03 16:34:14 +01001198 if (mService.mLockTaskController.isLockTaskModeViolation(reusedActivity.getTask(),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001199 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1200 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001201 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1202 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1203 }
1204
Bryce Leeaf691c02017-03-20 14:20:22 -07001205 if (mStartActivity.getTask() == null) {
Bryce Lee4a194382017-04-04 14:32:48 -07001206 mStartActivity.setTask(reusedActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001207 }
Bryce Lee4a194382017-04-04 14:32:48 -07001208 if (reusedActivity.getTask().intent == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001209 // This task was started because of movement of the activity based on affinity...
1210 // Now that we are actually launching it, we can assign the base intent.
Bryce Lee4a194382017-04-04 14:32:48 -07001211 reusedActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001212 }
1213
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001214 // This code path leads to delivering a new intent, we want to make sure we schedule it
1215 // as the first operation, in case the activity will be resumed as a result of later
1216 // operations.
1217 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Daichi Hirono15a02992016-04-27 18:47:01 +09001218 || isDocumentLaunchesIntoExisting(mLaunchFlags)
Bryce Lee7daee392017-10-12 13:46:18 -07001219 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Lee4a194382017-04-04 14:32:48 -07001220 final TaskRecord task = reusedActivity.getTask();
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001221
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001222 // In this situation we want to remove all activities from the task up to the one
1223 // being started. In most cases this means we are resetting the task to its initial
1224 // state.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001225 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1226 mLaunchFlags);
1227
Bryce Lee4a194382017-04-04 14:32:48 -07001228 // The above code can remove {@code reusedActivity} from the task, leading to the
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001229 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1230 // task reference is needed in the call below to
1231 // {@link setTargetStackAndMoveToFrontIfNeeded}.
Bryce Lee4a194382017-04-04 14:32:48 -07001232 if (reusedActivity.getTask() == null) {
1233 reusedActivity.setTask(task);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001234 }
1235
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001236 if (top != null) {
1237 if (top.frontOfTask) {
1238 // Activity aliases may mean we use different intents for the top activity,
1239 // so make sure the task now has the identity of the new intent.
Bryce Leeaf691c02017-03-20 14:20:22 -07001240 top.getTask().setIntent(mStartActivity);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001241 }
Bryce Lee325e09682017-10-05 17:20:25 -07001242 deliverNewIntent(top);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001243 }
1244 }
1245
Bryce Leed3624e12017-11-30 08:51:45 -08001246 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001247
Bryce Lee4a194382017-04-04 14:32:48 -07001248 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001249
Bryce Lee89cd19a2017-05-17 15:18:35 -07001250 final ActivityRecord outResult =
1251 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1252
1253 // When there is a reused activity and the current result is a trampoline activity,
1254 // set the reused activity as the result.
1255 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1256 outActivity[0] = reusedActivity;
1257 }
1258
Wale Ogunwale01d66562015-12-29 08:19:19 -08001259 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1260 // We don't need to start a new activity, and the client said not to do anything
1261 // if that is the case, so this is it! And for paranoia, make sure we have
1262 // correctly resumed the top activity.
1263 resumeTargetStackIfNeeded();
1264 return START_RETURN_INTENT_TO_CALLER;
1265 }
Bryce Lee4a194382017-04-04 14:32:48 -07001266 setTaskFromIntentActivity(reusedActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001267
1268 if (!mAddingToTask && mReuseTask == null) {
1269 // We didn't do anything... but it was needed (a.k.a., client don't use that
1270 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1271 resumeTargetStackIfNeeded();
Fyodor Kupolov625f4932017-05-03 09:30:19 -07001272 if (outActivity != null && outActivity.length > 0) {
Jorim Jaggicdfc04e2017-04-28 19:06:24 +02001273 outActivity[0] = reusedActivity;
1274 }
Bryce Lee28d80422017-07-21 13:25:13 -07001275
Selim Cinek7b1447e2018-01-23 13:52:35 -08001276 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001277 }
1278 }
1279
1280 if (mStartActivity.packageName == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001281 final ActivityStack sourceStack = mStartActivity.resultTo != null
1282 ? mStartActivity.resultTo.getStack() : null;
1283 if (sourceStack != null) {
1284 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1285 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1286 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001287 }
1288 ActivityOptions.abort(mOptions);
1289 return START_CLASS_NOT_FOUND;
1290 }
1291
1292 // If the activity being launched is the same as the one currently at the top, then
1293 // we need to check if it should only be launched once.
1294 final ActivityStack topStack = mSupervisor.mFocusedStack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001295 final ActivityRecord topFocused = topStack.getTopActivity();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001296 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1297 final boolean dontStart = top != null && mStartActivity.resultTo == null
1298 && top.realActivity.equals(mStartActivity.realActivity)
1299 && top.userId == mStartActivity.userId
1300 && top.app != null && top.app.thread != null
1301 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001302 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001303 if (dontStart) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001304 // For paranoia, make sure we have correctly resumed the top activity.
1305 topStack.mLastPausedActivity = null;
1306 if (mDoResume) {
1307 mSupervisor.resumeFocusedStackTopActivityLocked();
1308 }
1309 ActivityOptions.abort(mOptions);
1310 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1311 // We don't need to start a new activity, and the client said not to do
1312 // anything if that is the case, so this is it!
1313 return START_RETURN_INTENT_TO_CALLER;
1314 }
Bryce Lee325e09682017-10-05 17:20:25 -07001315
1316 deliverNewIntent(top);
Chong Zhangd44063c2016-04-08 11:52:30 -07001317
1318 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1319 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001320 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001321 preferredLaunchDisplayId, topStack);
Chong Zhangd44063c2016-04-08 11:52:30 -07001322
Wale Ogunwale01d66562015-12-29 08:19:19 -08001323 return START_DELIVERED_TO_TOP;
1324 }
1325
1326 boolean newTask = false;
1327 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
Bryce Leeaf691c02017-03-20 14:20:22 -07001328 ? mSourceRecord.getTask() : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001329
1330 // Should this be considered a new task?
Chong Zhang6cda19c2016-06-14 19:07:56 -07001331 int result = START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001332 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1333 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1334 newTask = true;
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001335 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001336 } else if (mSourceRecord != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001337 result = setTaskFromSourceRecord();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001338 } else if (mInTask != null) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001339 result = setTaskFromInTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001340 } else {
1341 // This not being started from an existing activity, and not part of a new task...
1342 // just put it in the top task, though these days this case should never happen.
1343 setTaskToCurrentTopOrCreateNewTask();
1344 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001345 if (result != START_SUCCESS) {
1346 return result;
1347 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001348
1349 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1350 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
Todd Kennedy0e989d02017-01-13 14:15:36 -08001351 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1352 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
Wale Ogunwale01d66562015-12-29 08:19:19 -08001353 if (newTask) {
Wale Ogunwale66e16852017-10-19 13:35:52 -07001354 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
Bryce Leeaf691c02017-03-20 14:20:22 -07001355 mStartActivity.getTask().taskId);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001356 }
1357 ActivityStack.logStartActivity(
Bryce Leeaf691c02017-03-20 14:20:22 -07001358 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001359 mTargetStack.mLastPausedActivity = null;
Wei Wang98f03f92016-05-18 11:32:52 -07001360
Bryce Leed3624e12017-11-30 08:51:45 -08001361 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
Wei Wang98f03f92016-05-18 11:32:52 -07001362
Winson Chungb5c41b72016-12-07 15:00:47 -08001363 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1364 mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001365 if (mDoResume) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001366 final ActivityRecord topTaskActivity =
1367 mStartActivity.getTask().topRunningActivityLocked();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001368 if (!mTargetStack.isFocusable()
Wale Ogunwale68741142016-05-17 09:40:02 -07001369 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1370 && mStartActivity != topTaskActivity)) {
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001371 // If the activity is not focusable, we can't resume it, but still would like to
1372 // make sure it becomes visible as it starts (this will also trigger entry
1373 // animation). An example of this are PIP activities.
Wale Ogunwale3b232392016-05-13 15:37:13 -07001374 // Also, we don't want to resume activities in a task that currently has an overlay
1375 // as the starting activity just needs to be in the visible paused state until the
1376 // over is removed.
Wale Ogunwale480dca02016-02-06 13:58:29 -08001377 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
Wale Ogunwaleae846f42016-02-22 14:00:56 -08001378 // Go ahead and tell window manager to execute app transition for this activity
1379 // since the app transition will not be triggered through the resume channel.
Bryce Lee7daee392017-10-12 13:46:18 -07001380 mService.mWindowManager.executeAppTransition();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001381 } else {
Winson Chung32066032016-11-04 11:55:21 -07001382 // If the target stack was not previously focusable (previous top running activity
1383 // on that stack was not visible) then any prior calls to move the stack to the
1384 // will not update the focused stack. If starting the new activity now allows the
1385 // task stack to be focusable, then ensure that we now update the focused stack
1386 // accordingly.
1387 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1388 mTargetStack.moveToFront("startActivityUnchecked");
1389 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001390 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1391 mOptions);
Filip Gruszczynski3d7fdc12016-01-31 17:33:29 -08001392 }
Winson Chung1dbc8112017-09-28 18:05:31 -07001393 } else if (mStartActivity != null) {
1394 mSupervisor.mRecentTasks.add(mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001395 }
1396 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1397
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001398 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001399 preferredLaunchDisplayId, mTargetStack);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001400
1401 return START_SUCCESS;
1402 }
1403
Bryce Leedaa91e42017-12-06 14:13:01 -08001404 /**
1405 * Resets the {@link ActivityStarter} state.
1406 * @param clearRequest whether the request should be reset to default values.
1407 */
1408 void reset(boolean clearRequest) {
1409 mStartActivity = null;
1410 mIntent = null;
1411 mCallingUid = -1;
1412 mOptions = null;
1413
1414 mLaunchTaskBehind = false;
1415 mLaunchFlags = 0;
1416 mLaunchMode = INVALID_LAUNCH_MODE;
1417
Bryce Leeec55eb02017-12-05 20:51:27 -08001418 mLaunchParams.reset();
Bryce Leedaa91e42017-12-06 14:13:01 -08001419
1420 mNotTop = null;
1421 mDoResume = false;
1422 mStartFlags = 0;
1423 mSourceRecord = null;
1424 mPreferredDisplayId = INVALID_DISPLAY;
1425
1426 mInTask = null;
1427 mAddingToTask = false;
1428 mReuseTask = null;
1429
1430 mNewTaskInfo = null;
1431 mNewTaskIntent = null;
1432 mSourceStack = null;
1433
1434 mTargetStack = null;
1435 mMovedToFront = false;
1436 mNoAnimation = false;
1437 mKeepCurTransition = false;
1438 mAvoidMoveToFront = false;
1439
1440 mVoiceSession = null;
1441 mVoiceInteractor = null;
1442
1443 mIntentDelivered = false;
1444
1445 if (clearRequest) {
1446 mRequest.reset();
1447 }
1448 }
1449
Wale Ogunwale01d66562015-12-29 08:19:19 -08001450 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1451 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1452 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
Bryce Leedaa91e42017-12-06 14:13:01 -08001453 reset(false /* clearRequest */);
1454
Wale Ogunwale01d66562015-12-29 08:19:19 -08001455 mStartActivity = r;
1456 mIntent = r.intent;
1457 mOptions = options;
1458 mCallingUid = r.launchedFromUid;
1459 mSourceRecord = sourceRecord;
1460 mVoiceSession = voiceSession;
1461 mVoiceInteractor = voiceInteractor;
1462
David Stevense5a7b642017-05-22 13:18:23 -07001463 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
David Stevensc6b91c62017-02-08 14:23:58 -08001464
Bryce Leeec55eb02017-12-05 20:51:27 -08001465 mLaunchParams.reset();
Bryce Leedacefc42017-10-10 12:56:02 -07001466
Bryce Leeec55eb02017-12-05 20:51:27 -08001467 mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
1468 options, mLaunchParams);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001469
Bryce Lee7daee392017-10-12 13:46:18 -07001470 mLaunchMode = r.launchMode;
1471
Wale Ogunwale01d66562015-12-29 08:19:19 -08001472 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
Bryce Lee7daee392017-10-12 13:46:18 -07001473 r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1474 LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001475 mLaunchTaskBehind = r.mLaunchTaskBehind
Bryce Lee7daee392017-10-12 13:46:18 -07001476 && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001477 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1478
1479 sendNewTaskResultRequestIfNeeded();
1480
1481 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1482 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1483 }
1484
1485 // If we are actually going to launch in to a new task, there are some cases where
1486 // we further want to do multiple task.
1487 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1488 if (mLaunchTaskBehind
1489 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1490 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1491 }
1492 }
1493
1494 // We'll invoke onUserLeaving before onPause only if the launching
1495 // activity did not explicitly state that this is an automated launch.
1496 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1497 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1498 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1499
1500 // If the caller has asked not to resume at this point, we make note
1501 // of this in the record so that we can skip it when trying to find
1502 // the top running activity.
1503 mDoResume = doResume;
Chong Zhang87761972016-08-22 13:53:24 -07001504 if (!doResume || !r.okToShowLocked()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001505 r.delayedResume = true;
1506 mDoResume = false;
1507 }
1508
Winson Chunge2d72172018-01-25 17:46:20 +00001509 if (mOptions != null) {
1510 if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1511 r.mTaskOverlay = true;
1512 if (!mOptions.canTaskOverlayResume()) {
1513 final TaskRecord task = mSupervisor.anyTaskForIdLocked(
1514 mOptions.getLaunchTaskId());
1515 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1516 if (top != null && top.state != RESUMED) {
Jorim Jaggic875ae72016-04-26 22:41:06 -07001517
Winson Chunge2d72172018-01-25 17:46:20 +00001518 // The caller specifies that we'd like to be avoided to be moved to the
1519 // front, so be it!
1520 mDoResume = false;
1521 mAvoidMoveToFront = true;
1522 }
Winson Chungcbcadc92017-01-12 15:54:12 -08001523 }
Winson Chunge2d72172018-01-25 17:46:20 +00001524 } else if (mOptions.getAvoidMoveToFront()) {
1525 mAvoidMoveToFront = true;
Jorim Jaggic875ae72016-04-26 22:41:06 -07001526 }
1527 }
1528
Wale Ogunwale01d66562015-12-29 08:19:19 -08001529 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1530
1531 mInTask = inTask;
1532 // In some flows in to this function, we retrieve the task record and hold on to it
1533 // without a lock before calling back in to here... so the task at this point may
1534 // not actually be in recents. Check for that, and if it isn't in recents just
1535 // consider it invalid.
1536 if (inTask != null && !inTask.inRecents) {
1537 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1538 mInTask = null;
1539 }
1540
1541 mStartFlags = startFlags;
1542 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1543 // is the same as the one making the call... or, as a special case, if we do not know
1544 // the caller then we count the current top activity as the caller.
1545 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1546 ActivityRecord checkedCaller = sourceRecord;
1547 if (checkedCaller == null) {
1548 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1549 mNotTop);
1550 }
1551 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1552 // Caller is not the same as launcher, so always needed.
1553 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1554 }
1555 }
1556
1557 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1558 }
1559
1560 private void sendNewTaskResultRequestIfNeeded() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001561 final ActivityStack sourceStack = mStartActivity.resultTo != null
1562 ? mStartActivity.resultTo.getStack() : null;
1563 if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001564 // For whatever reason this activity is being launched into a new task...
1565 // yet the caller has requested a result back. Well, that is pretty messed up,
1566 // so instead immediately send back a cancel and let the new task continue launched
1567 // as normal without a dependency on its originator.
1568 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001569 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1570 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1571 null /* data */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001572 mStartActivity.resultTo = null;
1573 }
1574 }
1575
1576 private void computeLaunchingTaskFlags() {
1577 // If the caller is not coming from another activity, but has given us an explicit task into
1578 // which they would like us to launch the new activity, then let's see about doing that.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001579 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001580 final Intent baseIntent = mInTask.getBaseIntent();
1581 final ActivityRecord root = mInTask.getRootActivity();
1582 if (baseIntent == null) {
1583 ActivityOptions.abort(mOptions);
1584 throw new IllegalArgumentException("Launching into task without base intent: "
1585 + mInTask);
1586 }
1587
1588 // If this task is empty, then we are adding the first activity -- it
1589 // determines the root, and must be launching as a NEW_TASK.
Bryce Lee7daee392017-10-12 13:46:18 -07001590 if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001591 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1592 ActivityOptions.abort(mOptions);
1593 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1594 + mStartActivity + " into different task " + mInTask);
1595 }
1596 if (root != null) {
1597 ActivityOptions.abort(mOptions);
1598 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1599 + " has root " + root + " but target is singleInstance/Task");
1600 }
1601 }
1602
1603 // If task is empty, then adopt the interesting intent launch flags in to the
1604 // activity being started.
1605 if (root == null) {
1606 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1607 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1608 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1609 | (baseIntent.getFlags() & flagsOfInterest);
1610 mIntent.setFlags(mLaunchFlags);
1611 mInTask.setIntent(mStartActivity);
1612 mAddingToTask = true;
1613
1614 // If the task is not empty and the caller is asking to start it as the root of
1615 // a new task, then we don't actually want to start this on the task. We will
1616 // bring the task to the front, and possibly give it a new intent.
1617 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1618 mAddingToTask = false;
1619
1620 } else {
1621 mAddingToTask = true;
1622 }
1623
1624 mReuseTask = mInTask;
1625 } else {
1626 mInTask = null;
1627 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1628 // when in freeform workspace.
1629 // Also put noDisplay activities in the source task. These by itself can be placed
1630 // in any task/stack, however it could launch other activities like ResolverActivity,
1631 // and we want those to stay in the original task.
1632 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001633 && mSourceRecord.inFreeformWindowingMode()) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001634 mAddingToTask = true;
1635 }
1636 }
1637
1638 if (mInTask == null) {
1639 if (mSourceRecord == null) {
1640 // This activity is not being started from another... in this
1641 // case we -always- start a new task.
1642 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1643 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1644 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1645 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1646 }
1647 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1648 // The original activity who is starting us is running as a single
1649 // instance... this new activity it is starting must go on its
1650 // own task.
1651 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
Bryce Lee7daee392017-10-12 13:46:18 -07001652 } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001653 // The activity being started is a single instance... it always
1654 // gets launched into its own task.
1655 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1656 }
1657 }
1658 }
1659
1660 private void computeSourceStack() {
1661 if (mSourceRecord == null) {
1662 mSourceStack = null;
1663 return;
1664 }
1665 if (!mSourceRecord.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001666 mSourceStack = mSourceRecord.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001667 return;
1668 }
1669
1670 // If the source is finishing, we can't further count it as our source. This is because the
1671 // task it is associated with may now be empty and on its way out, so we don't want to
1672 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1673 // a task for it. But save the task information so it can be used when creating the new task.
1674 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1675 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1676 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1677 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1678 mNewTaskInfo = mSourceRecord.info;
Bryce Leed9ed45d2017-05-22 15:57:24 -07001679
1680 // It is not guaranteed that the source record will have a task associated with it. For,
1681 // example, if this method is being called for processing a pending activity launch, it
1682 // is possible that the activity has been removed from the task after the launch was
1683 // enqueued.
1684 final TaskRecord sourceTask = mSourceRecord.getTask();
1685 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
Wale Ogunwale01d66562015-12-29 08:19:19 -08001686 }
1687 mSourceRecord = null;
1688 mSourceStack = null;
1689 }
1690
1691 /**
1692 * Decide whether the new activity should be inserted into an existing task. Returns null
1693 * if not or an ActivityRecord with the task into which the new activity should be added.
1694 */
1695 private ActivityRecord getReusableIntentActivity() {
1696 // We may want to try to place the new activity in to an existing task. We always
1697 // do this if the target activity is singleTask or singleInstance; we will also do
1698 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1699 // us to still place it in a new task: multi task, always doc mode, or being asked to
1700 // launch this as a new task behind the current one.
1701 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1702 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
Bryce Lee7daee392017-10-12 13:46:18 -07001703 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001704 // If bring to front is requested, and no result is requested and we have not been given
1705 // an explicit task to launch in to, and we can find a task that was started with this
1706 // same component, then instead of launching bring that one to the front.
1707 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1708 ActivityRecord intentActivity = null;
Jorim Jaggi2adba072016-03-03 13:43:39 +01001709 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1710 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1711 intentActivity = task != null ? task.getTopActivity() : null;
1712 } else if (putIntoExistingTask) {
Bryce Lee7daee392017-10-12 13:46:18 -07001713 if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001714 // There can be one and only one instance of single instance activity in the
1715 // history, and it is always in its own unique task, so we do a special search.
Bryce Lee28d80422017-07-21 13:25:13 -07001716 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001717 mStartActivity.isActivityTypeHome());
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001718 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1719 // For the launch adjacent case we only want to put the activity in an existing
1720 // task if the activity already exists in the history.
Andrii Kulian039ba482016-06-22 17:16:45 -07001721 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
Bryce Lee7daee392017-10-12 13:46:18 -07001722 !(LAUNCH_SINGLE_TASK == mLaunchMode));
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001723 } else {
1724 // Otherwise find the best task to put the activity in.
David Stevense5a7b642017-05-22 13:18:23 -07001725 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
Wale Ogunwale13dbfff2016-05-20 08:50:15 -07001726 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001727 }
1728 return intentActivity;
1729 }
1730
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001731 /**
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001732 * 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 -07001733 * then return the Vr mode's virtual display ID. If not, if the activity was started with
1734 * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID
1735 * set, use that to launch the activity.
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001736 */
David Stevense5a7b642017-05-22 13:18:23 -07001737 private int getPreferedDisplayId(
1738 ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) {
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001739 // Check if the Activity is a VR activity. If so, the activity should be launched in
1740 // main display.
1741 if (startingActivity != null && startingActivity.requestedVrComponent != null) {
1742 return DEFAULT_DISPLAY;
1743 }
1744
1745 // Get the virtual display id from ActivityManagerService.
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001746 int displayId = mService.mVr2dDisplayId;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001747 if (displayId != INVALID_DISPLAY) {
1748 if (DEBUG_STACK) {
1749 Slog.d(TAG, "getSourceDisplayId :" + displayId);
1750 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001751 return displayId;
1752 }
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001753
David Stevense5a7b642017-05-22 13:18:23 -07001754 // If the caller requested a display, prefer that display.
1755 final int launchDisplayId =
1756 (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY;
1757 if (launchDisplayId != INVALID_DISPLAY) {
1758 return launchDisplayId;
1759 }
1760
Karthik Ravi Shankarf29b4c22017-04-06 17:02:01 -07001761 displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY;
1762 // If the activity has a displayId set explicitly, launch it on the same displayId.
1763 if (displayId != INVALID_DISPLAY) {
1764 return displayId;
1765 }
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08001766 return DEFAULT_DISPLAY;
1767 }
1768
1769 /**
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001770 * Figure out which task and activity to bring to front when we have found an existing matching
1771 * activity record in history. May also clear the task if needed.
1772 * @param intentActivity Existing matching activity.
1773 * @return {@link ActivityRecord} brought to front.
1774 */
Wale Ogunwale01d66562015-12-29 08:19:19 -08001775 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001776 mTargetStack = intentActivity.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08001777 mTargetStack.mLastPausedActivity = null;
1778 // If the target task is not in the front, then we need to bring it to the front...
1779 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1780 // the same behavior as if a new instance was being started, which means not bringing it
1781 // to the front if the caller is not itself in the front.
1782 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1783 ActivityRecord curTop = (focusStack == null)
1784 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1785
Bryce Leeaf691c02017-03-20 14:20:22 -07001786 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1787 if (topTask != null
1788 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
Jorim Jaggic875ae72016-04-26 22:41:06 -07001789 && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001790 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001791 if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1792 mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001793 // We really do want to push this one into the user's face, right now.
1794 if (mLaunchTaskBehind && mSourceRecord != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001795 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001796 }
Chong Zhangdea4bd92016-03-15 12:50:03 -07001797
1798 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1799 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1800 // So no point resuming any of the activities here, it just wastes one extra
1801 // resuming, plus enter AND exit transitions.
1802 // Here we only want to bring the target stack forward. Transition will be applied
1803 // to the new activity that's started after the old ones are gone.
1804 final boolean willClearTask =
1805 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1806 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1807 if (!willClearTask) {
1808 final ActivityStack launchStack = getLaunchStack(
Bryce Leeaf691c02017-03-20 14:20:22 -07001809 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
1810 final TaskRecord intentTask = intentActivity.getTask();
Chong Zhangdea4bd92016-03-15 12:50:03 -07001811 if (launchStack == null || launchStack == mTargetStack) {
1812 // We only want to move to the front, if we aren't going to launch on a
1813 // different stack. If we launch on a different stack, we will put the
1814 // task on top there.
Bryce Leeaf691c02017-03-20 14:20:22 -07001815 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
Chong Zhangdea4bd92016-03-15 12:50:03 -07001816 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1817 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001818 } else if (launchStack.inSplitScreenWindowingMode()) {
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001819 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1820 // If we want to launch adjacent and mTargetStack is not the computed
1821 // launch stack - move task to top of computed stack.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001822 intentTask.reparent(launchStack, ON_TOP,
Winson Chung74666102017-02-22 17:49:24 -08001823 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1824 "launchToSide");
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001825 } else {
1826 // TODO: This should be reevaluated in MW v2.
1827 // We choose to move task to front instead of launching it adjacent
1828 // when specific stack was requested explicitly and it appeared to be
1829 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
Bryce Leeaf691c02017-03-20 14:20:22 -07001830 mTargetStack.moveTaskToFrontLocked(intentTask,
1831 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
Andrii Kulianad6f2e52016-06-15 15:27:01 -07001832 "bringToFrontInsteadOfAdjacentLaunch");
1833 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07001834 mMovedToFront = true;
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001835 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1836 // Target and computed stacks are on different displays and we've
1837 // found a matching task - move the existing instance to that display and
1838 // move it to front.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001839 intentActivity.getTask().reparent(launchStack, ON_TOP,
Andrii Kulianfab9cd82017-03-21 19:37:09 -07001840 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1841 "reparentToDisplay");
1842 mMovedToFront = true;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001843 } else if (launchStack.isActivityTypeHome()
1844 && !mTargetStack.isActivityTypeHome()) {
Bryce Lee4ff7da92017-07-17 10:39:24 -07001845 // It is possible for the home activity to be in another stack initially.
1846 // For example, the activity may have been initially started with an intent
1847 // which placed it in the fullscreen stack. To ensure the proper handling of
1848 // the activity based on home stack assumptions, we must move it over.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001849 intentActivity.getTask().reparent(launchStack, ON_TOP,
Bryce Lee4ff7da92017-07-17 10:39:24 -07001850 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1851 "reparentingHome");
1852 mMovedToFront = true;
Chong Zhangdea4bd92016-03-15 12:50:03 -07001853 }
1854 mOptions = null;
Jorim Jaggi02886a82016-12-06 09:10:06 -08001855
1856 // We are moving a task to the front, use starting window to hide initial drawn
1857 // delay.
1858 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1859 true /* taskSwitch */);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001860 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08001861 }
1862 }
Andrii Kulianb850ea52017-12-12 23:49:10 -08001863 // Need to update mTargetStack because if task was moved out of it, the original stack may
1864 // be destroyed.
1865 mTargetStack = intentActivity.getStack();
Winson Chunge2d72172018-01-25 17:46:20 +00001866 if (!mAvoidMoveToFront && !mMovedToFront && mDoResume) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001867 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1868 + " from " + intentActivity);
1869 mTargetStack.moveToFront("intentActivityFound");
1870 }
1871
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001872 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001873 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
Jorim Jaggid53f0922016-04-06 22:16:23 -07001874
Wale Ogunwale01d66562015-12-29 08:19:19 -08001875 // If the caller has requested that the target task be reset, then do so.
1876 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1877 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1878 }
1879 return intentActivity;
1880 }
1881
1882 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
1883 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1884 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
1885 // The caller has requested to completely replace any existing task with its new
1886 // activity. Well that should not be too hard...
Bryce Lee41801b42017-03-02 13:23:12 -08001887 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
1888 // removed from calling performClearTaskLocked (For example, if it is being brought out
Bryce Lee59dad4e2017-03-09 11:54:08 -08001889 // of history or if it is finished immediately), thus disassociating the task. Also note
1890 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
1891 // launching another activity.
1892 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
1893 // already launching one.
Bryce Leeaf691c02017-03-20 14:20:22 -07001894 final TaskRecord task = intentActivity.getTask();
Bryce Lee59dad4e2017-03-09 11:54:08 -08001895 task.performClearTaskLocked();
1896 mReuseTask = task;
Bryce Lee41801b42017-03-02 13:23:12 -08001897 mReuseTask.setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001898 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07001899 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001900 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
Wale Ogunwale01d66562015-12-29 08:19:19 -08001901 mLaunchFlags);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08001902 if (top == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001903 // A special case: we need to start the activity because it is not currently
1904 // running, and the caller has asked to clear the current task to have this
1905 // activity at the top.
1906 mAddingToTask = true;
Bryce Lee353112c2017-02-23 09:46:45 -08001907
1908 // We are no longer placing the activity in the task we previously thought we were.
Bryce Leeaf691c02017-03-20 14:20:22 -07001909 mStartActivity.setTask(null);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001910 // Now pretend like this activity is being started by the top of its task, so it
1911 // is put in the right place.
1912 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001913 final TaskRecord task = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001914 if (task != null && task.getStack() == null) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001915 // Target stack got cleared when we all activities were removed above.
1916 // Go ahead and reset it.
1917 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
Bryce Leedacefc42017-10-10 12:56:02 -07001918 mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001919 mTargetStack.addTask(task,
1920 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
1921 }
1922 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001923 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001924 // In this case the top activity on the task is the same as the one being launched,
1925 // so we take that as a request to bring the task to the foreground. If the top
1926 // activity in the task is the root activity, deliver this new intent to it if it
1927 // desires.
Bryce Lee7daee392017-10-12 13:46:18 -07001928 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1929 || LAUNCH_SINGLE_TOP == mLaunchMode)
Wale Ogunwale01d66562015-12-29 08:19:19 -08001930 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001931 if (intentActivity.frontOfTask) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001932 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001933 }
Bryce Lee325e09682017-10-05 17:20:25 -07001934 deliverNewIntent(intentActivity);
Bryce Leeaf691c02017-03-20 14:20:22 -07001935 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001936 // In this case we are launching the root activity of the task, but with a
1937 // different intent. We should start a new instance on top.
1938 mAddingToTask = true;
1939 mSourceRecord = intentActivity;
1940 }
1941 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1942 // In this case an activity is being launched in to an existing task, without
1943 // resetting that task. This is typically the situation of launching an activity
1944 // from a notification or shortcut. We want to place the new activity on top of the
1945 // current task.
1946 mAddingToTask = true;
1947 mSourceRecord = intentActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001948 } else if (!intentActivity.getTask().rootWasReset) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08001949 // In this case we are launching into an existing task that has not yet been started
1950 // from its front door. The current task has been brought to the front. Ideally,
1951 // we'd probably like to place this new task at the bottom of its stack, but that's
1952 // a little hard to do with the current organization of the code so for now we'll
1953 // just drop it.
Bryce Leeaf691c02017-03-20 14:20:22 -07001954 intentActivity.getTask().setIntent(mStartActivity);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001955 }
1956 }
1957
1958 private void resumeTargetStackIfNeeded() {
1959 if (mDoResume) {
1960 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001961 } else {
1962 ActivityOptions.abort(mOptions);
1963 }
1964 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1965 }
1966
Chong Zhang6cda19c2016-06-14 19:07:56 -07001967 private int setTaskFromReuseOrCreateNewTask(
Wale Ogunwale0568aed2017-09-08 13:29:37 -07001968 TaskRecord taskToAffiliate, ActivityStack topStack) {
Bryce Leedacefc42017-10-10 12:56:02 -07001969 mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);
Chong Zhang6cda19c2016-06-14 19:07:56 -07001970
1971 // Do no move the target stack to front yet, as we might bail if
1972 // isLockTaskModeViolation fails below.
Wale Ogunwale01d66562015-12-29 08:19:19 -08001973
1974 if (mReuseTask == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001975 final TaskRecord task = mTargetStack.createTaskRecord(
1976 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
Wale Ogunwale01d66562015-12-29 08:19:19 -08001977 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
Wale Ogunwale72919d22016-12-08 18:58:50 -08001978 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
Bryce Leeb802ea12017-11-15 21:25:03 -08001979 mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
1980 mOptions);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001981 addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
Bryce Leeec55eb02017-12-05 20:51:27 -08001982 updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07001983
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001984 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07001985 + " in new task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08001986 } else {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001987 addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
1988 }
1989
1990 if (taskToAffiliate != null) {
1991 mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
Wale Ogunwale01d66562015-12-29 08:19:19 -08001992 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07001993
Benjamin Franza83859f2017-07-03 16:34:14 +01001994 if (mService.mLockTaskController.isLockTaskModeViolation(mStartActivity.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07001995 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
1996 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1997 }
1998
Chong Zhang6cda19c2016-06-14 19:07:56 -07001999 if (mDoResume) {
2000 mTargetStack.moveToFront("reuseOrNewTask");
2001 }
2002 return START_SUCCESS;
Wale Ogunwale01d66562015-12-29 08:19:19 -08002003 }
2004
Bryce Lee325e09682017-10-05 17:20:25 -07002005 private void deliverNewIntent(ActivityRecord activity) {
2006 if (mIntentDelivered) {
2007 return;
2008 }
2009
2010 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
2011 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
2012 mStartActivity.launchedFromPackage);
2013 mIntentDelivered = true;
2014 }
2015
Wale Ogunwale01d66562015-12-29 08:19:19 -08002016 private int setTaskFromSourceRecord() {
Benjamin Franza83859f2017-07-03 16:34:14 +01002017 if (mService.mLockTaskController.isLockTaskModeViolation(mSourceRecord.getTask())) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002018 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2019 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2020 }
2021
Bryce Leeaf691c02017-03-20 14:20:22 -07002022 final TaskRecord sourceTask = mSourceRecord.getTask();
Andrii Kulian02b7a832016-10-06 23:11:56 -07002023 final ActivityStack sourceStack = mSourceRecord.getStack();
Andrii Kulian02689a72017-07-06 14:28:59 -07002024 // We only want to allow changing stack in two cases:
2025 // 1. If the target task is not the top one. Otherwise we would move the launching task to
2026 // the other side, rather than show two side by side.
2027 // 2. If activity is not allowed on target display.
2028 final int targetDisplayId = mTargetStack != null ? mTargetStack.mDisplayId
2029 : sourceStack.mDisplayId;
2030 final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
2031 || !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002032 if (moveStackAllowed) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002033 mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002034 mOptions);
Andrii Kulian02689a72017-07-06 14:28:59 -07002035 // If target stack is not found now - we can't just rely on the source stack, as it may
2036 // be not suitable. Let's check other displays.
2037 if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
2038 // Can't use target display, lets find a stack on the source display.
2039 mTargetStack = mService.mStackSupervisor.getValidLaunchStackOnDisplay(
2040 sourceStack.mDisplayId, mStartActivity);
2041 }
2042 if (mTargetStack == null) {
2043 // There are no suitable stacks on the target and source display(s). Look on all
2044 // displays.
2045 mTargetStack = mService.mStackSupervisor.getNextValidLaunchStackLocked(
2046 mStartActivity, -1 /* currentFocus */);
2047 }
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002048 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002049
2050 if (mTargetStack == null) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002051 mTargetStack = sourceStack;
2052 } else if (mTargetStack != sourceStack) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002053 sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
2054 DEFER_RESUME, "launchToSide");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002055 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002056
Wale Ogunwale01d66562015-12-29 08:19:19 -08002057 final TaskRecord topTask = mTargetStack.topTask();
Jorim Jaggic875ae72016-04-26 22:41:06 -07002058 if (topTask != sourceTask && !mAvoidMoveToFront) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08002059 mTargetStack.moveTaskToFrontLocked(sourceTask, mNoAnimation, mOptions,
2060 mStartActivity.appTimeTracker, "sourceTaskToFront");
Chong Zhang6cda19c2016-06-14 19:07:56 -07002061 } else if (mDoResume) {
2062 mTargetStack.moveToFront("sourceStackToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002063 }
Chong Zhang6cda19c2016-06-14 19:07:56 -07002064
Wale Ogunwale01d66562015-12-29 08:19:19 -08002065 if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2066 // In this case, we are adding the activity to an existing task, but the caller has
2067 // asked to clear that task if the activity is already running.
2068 ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
2069 mKeepCurTransition = true;
2070 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002071 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
Bryce Lee325e09682017-10-05 17:20:25 -07002072 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002073 // For paranoia, make sure we have correctly resumed the top activity.
2074 mTargetStack.mLastPausedActivity = null;
2075 if (mDoResume) {
2076 mSupervisor.resumeFocusedStackTopActivityLocked();
2077 }
2078 ActivityOptions.abort(mOptions);
2079 return START_DELIVERED_TO_TOP;
2080 }
2081 } else if (!mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
2082 // In this case, we are launching an activity in our own task that may already be
2083 // running somewhere in the history, and we want to shuffle it to the front of the
2084 // stack if so.
2085 final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
2086 if (top != null) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002087 final TaskRecord task = top.getTask();
Wale Ogunwale01d66562015-12-29 08:19:19 -08002088 task.moveActivityToFrontLocked(top);
2089 top.updateOptionsLocked(mOptions);
Filip Gruszczynskie826f322016-01-11 17:15:22 -08002090 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
Bryce Lee325e09682017-10-05 17:20:25 -07002091 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002092 mTargetStack.mLastPausedActivity = null;
2093 if (mDoResume) {
2094 mSupervisor.resumeFocusedStackTopActivityLocked();
2095 }
2096 return START_DELIVERED_TO_TOP;
2097 }
2098 }
2099
2100 // An existing activity is starting this new activity, so we want to keep the new one in
2101 // the same task as the one that is starting it.
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002102 addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002103 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002104 + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002105 return START_SUCCESS;
2106 }
2107
2108 private int setTaskFromInTask() {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002109 // The caller is asking that the new activity be started in an explicit
2110 // task it has provided to us.
Benjamin Franza83859f2017-07-03 16:34:14 +01002111 if (mService.mLockTaskController.isLockTaskModeViolation(mInTask)) {
Chong Zhang6cda19c2016-06-14 19:07:56 -07002112 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
2113 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
2114 }
2115
Andrii Kulian02b7a832016-10-06 23:11:56 -07002116 mTargetStack = mInTask.getStack();
Wale Ogunwale01d66562015-12-29 08:19:19 -08002117
2118 // Check whether we should actually launch the new activity in to the task,
2119 // or just reuse the current activity on top.
2120 ActivityRecord top = mInTask.getTopActivity();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002121 if (top != null && top.realActivity.equals(mStartActivity.realActivity)
2122 && top.userId == mStartActivity.userId) {
Wale Ogunwale01d66562015-12-29 08:19:19 -08002123 if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
Bryce Lee7daee392017-10-12 13:46:18 -07002124 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
Yorke Lee64512522017-03-24 13:09:35 -07002125 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
2126 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002127 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
2128 // We don't need to start a new activity, and the client said not to do
2129 // anything if that is the case, so this is it!
2130 return START_RETURN_INTENT_TO_CALLER;
2131 }
Bryce Lee325e09682017-10-05 17:20:25 -07002132 deliverNewIntent(top);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002133 return START_DELIVERED_TO_TOP;
2134 }
2135 }
2136
2137 if (!mAddingToTask) {
Yorke Lee64512522017-03-24 13:09:35 -07002138 mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
2139 mStartActivity.appTimeTracker, "inTaskToFront");
Wale Ogunwale01d66562015-12-29 08:19:19 -08002140 // We don't actually want to have this activity added to the task, so just
2141 // stop here but still tell the caller that we consumed the intent.
2142 ActivityOptions.abort(mOptions);
2143 return START_TASK_TO_FRONT;
2144 }
2145
Bryce Leeec55eb02017-12-05 20:51:27 -08002146 if (!mLaunchParams.mBounds.isEmpty()) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -07002147 // TODO: Shouldn't we already know what stack to use by the time we get here?
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002148 ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
2149 if (stack != mInTask.getStack()) {
2150 mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
Yorke Lee64512522017-03-24 13:09:35 -07002151 DEFER_RESUME, "inTaskToFront");
Yorke Lee64512522017-03-24 13:09:35 -07002152 mTargetStack = mInTask.getStack();
2153 }
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002154
Bryce Leeec55eb02017-12-05 20:51:27 -08002155 updateBounds(mInTask, mLaunchParams.mBounds);
Yorke Lee64512522017-03-24 13:09:35 -07002156 }
2157
2158 mTargetStack.moveTaskToFrontLocked(
2159 mInTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, "inTaskToFront");
2160
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002161 addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
2162 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002163 + " in explicit task " + mStartActivity.getTask());
Wale Ogunwale01d66562015-12-29 08:19:19 -08002164
2165 return START_SUCCESS;
2166 }
2167
Bryce Leed3624e12017-11-30 08:51:45 -08002168 @VisibleForTesting
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002169 void updateBounds(TaskRecord task, Rect bounds) {
Bryce Leedacefc42017-10-10 12:56:02 -07002170 if (bounds.isEmpty()) {
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002171 return;
2172 }
2173
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002174 final ActivityStack stack = task.getStack();
2175 if (stack != null && stack.resizeStackWithLaunchBounds()) {
2176 mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
Bryce Lee4e4a3ec2017-09-27 08:25:03 -07002177 } else {
2178 task.updateOverrideConfiguration(bounds);
2179 }
2180 }
2181
Wale Ogunwale01d66562015-12-29 08:19:19 -08002182 private void setTaskToCurrentTopOrCreateNewTask() {
Bryce Leedacefc42017-10-10 12:56:02 -07002183 mTargetStack = computeStackFocus(mStartActivity, false, mLaunchFlags, mOptions);
Wale Ogunwale01d66562015-12-29 08:19:19 -08002184 if (mDoResume) {
2185 mTargetStack.moveToFront("addingToTopTask");
2186 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -08002187 final ActivityRecord prev = mTargetStack.getTopActivity();
Bryce Leeaf691c02017-03-20 14:20:22 -07002188 final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
Wale Ogunwale72919d22016-12-08 18:58:50 -08002189 mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
Bryce Leeb802ea12017-11-15 21:25:03 -08002190 mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002191 addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
2192 mTargetStack.positionChildWindowContainerAtTop(task);
2193 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
Bryce Leeaf691c02017-03-20 14:20:22 -07002194 + " in new guessed " + mStartActivity.getTask());
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002195 }
2196
2197 private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002198 if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08002199 parent.addActivityToTop(mStartActivity);
2200 } else {
2201 mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
2202 }
Wale Ogunwale01d66562015-12-29 08:19:19 -08002203 }
2204
2205 private int adjustLaunchFlagsToDocumentMode(ActivityRecord r, boolean launchSingleInstance,
2206 boolean launchSingleTask, int launchFlags) {
2207 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2208 (launchSingleInstance || launchSingleTask)) {
2209 // We have a conflict between the Intent and the Activity manifest, manifest wins.
2210 Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
2211 "\"singleInstance\" or \"singleTask\"");
2212 launchFlags &=
2213 ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_MULTIPLE_TASK);
2214 } else {
2215 switch (r.info.documentLaunchMode) {
2216 case ActivityInfo.DOCUMENT_LAUNCH_NONE:
2217 break;
2218 case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
2219 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2220 break;
2221 case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
2222 launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
2223 break;
2224 case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
2225 launchFlags &= ~FLAG_ACTIVITY_MULTIPLE_TASK;
2226 break;
2227 }
2228 }
2229 return launchFlags;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002230 }
2231
Bryce Leedacefc42017-10-10 12:56:02 -07002232 private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
2233 ActivityOptions aOptions) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002234 final TaskRecord task = r.getTask();
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002235 ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002236 if (stack != null) {
2237 return stack;
2238 }
2239
Andrii Kulian02b7a832016-10-06 23:11:56 -07002240 final ActivityStack currentStack = task != null ? task.getStack() : null;
2241 if (currentStack != null) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002242 if (mSupervisor.mFocusedStack != currentStack) {
2243 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2244 "computeStackFocus: Setting " + "focused stack to r=" + r
2245 + " task=" + task);
2246 } else {
2247 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2248 "computeStackFocus: Focused stack already="
2249 + mSupervisor.mFocusedStack);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002250 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002251 return currentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002252 }
2253
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002254 if (canLaunchIntoFocusedStack(r, newTask)) {
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002255 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2256 "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
2257 return mSupervisor.mFocusedStack;
2258 }
2259
David Stevense5a7b642017-05-22 13:18:23 -07002260 if (mPreferredDisplayId != DEFAULT_DISPLAY) {
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002261 // Try to put the activity in a stack on a secondary display.
David Stevense5a7b642017-05-22 13:18:23 -07002262 stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002263 if (stack == null) {
2264 // If source display is not suitable - look for topmost valid stack in the system.
2265 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
David Stevense5a7b642017-05-22 13:18:23 -07002266 "computeStackFocus: Can't launch on mPreferredDisplayId="
2267 + mPreferredDisplayId + ", looking on all displays.");
2268 stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
Andrii Kuliana8fe3df2017-06-16 15:29:26 -07002269 }
2270 }
2271 if (stack == null) {
David Stevensc6b91c62017-02-08 14:23:58 -08002272 // We first try to put the task in the first dynamic stack on home display.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002273 final ActivityDisplay display = mSupervisor.getDefaultDisplay();
2274 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
2275 stack = display.getChildAt(stackNdx);
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002276 if (!stack.isOnHomeDisplay()) {
David Stevensc6b91c62017-02-08 14:23:58 -08002277 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
2278 "computeStackFocus: Setting focused stack=" + stack);
2279 return stack;
2280 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002281 }
David Stevensc6b91c62017-02-08 14:23:58 -08002282 // If there is no suitable dynamic stack then we figure out which static stack to use.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002283 stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002284 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002285 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
2286 + r + " stackId=" + stack.mStackId);
2287 return stack;
2288 }
2289
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002290 /** Check if provided activity record can launch in currently focused stack. */
Wale Ogunwale68278562017-09-23 17:13:55 -07002291 // TODO: This method can probably be consolidated into getLaunchStack() below.
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002292 private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002293 final ActivityStack focusedStack = mSupervisor.mFocusedStack;
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002294 final boolean canUseFocusedStack;
Wale Ogunwale68278562017-09-23 17:13:55 -07002295 if (focusedStack.isActivityTypeAssistant()) {
2296 canUseFocusedStack = r.isActivityTypeAssistant();
2297 } else {
2298 switch (focusedStack.getWindowingMode()) {
2299 case WINDOWING_MODE_FULLSCREEN:
2300 // The fullscreen stack can contain any task regardless of if the task is
2301 // resizeable or not. So, we let the task go in the fullscreen task if it is the
2302 // focus stack.
2303 canUseFocusedStack = true;
2304 break;
2305 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
2306 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
2307 // Any activity which supports split screen can go in the docked stack.
2308 canUseFocusedStack = r.supportsSplitScreenWindowingMode();
2309 break;
2310 case WINDOWING_MODE_FREEFORM:
2311 // Any activity which supports freeform can go in the freeform stack.
2312 canUseFocusedStack = r.supportsFreeform();
2313 break;
2314 default:
2315 // Dynamic stacks behave similarly to the fullscreen stack and can contain any
2316 // resizeable task.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002317 canUseFocusedStack = !focusedStack.isOnHomeDisplay()
Wale Ogunwale68278562017-09-23 17:13:55 -07002318 && r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
2319 }
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002320 }
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002321 return canUseFocusedStack && !newTask
Wale Ogunwale68278562017-09-23 17:13:55 -07002322 // Using the focus stack isn't important enough to override the preferred display.
David Stevense5a7b642017-05-22 13:18:23 -07002323 && (mPreferredDisplayId == focusedStack.mDisplayId);
Andrii Kulianfb1bf692017-01-17 11:17:34 -08002324 }
2325
Wale Ogunwale854809c2015-12-27 16:18:19 -08002326 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
Jorim Jaggi4ad98562016-04-19 20:30:47 -07002327 ActivityOptions aOptions) {
Bryce Leea19b5ad2017-06-07 16:54:11 -07002328 // We are reusing a task, keep the stack!
2329 if (mReuseTask != null) {
2330 return mReuseTask.getStack();
2331 }
Jorim Jaggib8c58762016-04-20 17:58:29 -07002332
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -08002333 if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
David Stevense5a7b642017-05-22 13:18:23 -07002334 || mPreferredDisplayId != DEFAULT_DISPLAY) {
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08002335 // We don't pass in the default display id into the get launch stack call so it can do a
2336 // full resolution.
2337 final int candidateDisplay =
2338 mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
2339 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002340 }
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002341 // Otherwise handle adjacent launch.
Wale Ogunwale854809c2015-12-27 16:18:19 -08002342
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002343 // The parent activity doesn't want to launch the activity on top of itself, but
2344 // instead tries to put it onto other side in side-by-side mode.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07002345 final ActivityStack parentStack = task != null ? task.getStack(): mSupervisor.mFocusedStack;
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002346
2347 if (parentStack != mSupervisor.mFocusedStack) {
2348 // If task's parent stack is not focused - use it during adjacent launch.
2349 return parentStack;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002350 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002351 if (mSupervisor.mFocusedStack != null && task == mSupervisor.mFocusedStack.topTask()) {
2352 // If task is already on top of focused stack - use it. We don't want to move the
2353 // existing focused task to adjacent stack, just deliver new intent in this case.
2354 return mSupervisor.mFocusedStack;
2355 }
2356
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002357 if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002358 // If parent was in docked stack, the natural place to launch another activity
2359 // will be fullscreen, so it can appear alongside the docked window.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002360 final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
2361 return parentStack.getDisplay().getOrCreateStack(
2362 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002363 } else {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002364 // If the parent is not in the docked stack, we check if there is docked window
2365 // and if yes, we will launch into that stack. If not, we just put the new
2366 // activity into parent's stack, because we can't find a better place.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07002367 final ActivityStack dockedStack =
2368 mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07002369 if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002370 // There is a docked stack, but it isn't visible, so we can't launch into that.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08002371 return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
Andrii Kulian4ac2a582016-03-25 00:07:38 -07002372 } else {
2373 return dockedStack;
2374 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002375 }
2376 }
2377 }
2378
Bryce Lee7daee392017-10-12 13:46:18 -07002379 private boolean isLaunchModeOneOf(int mode1, int mode2) {
2380 return mode1 == mLaunchMode || mode2 == mLaunchMode;
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002381 }
2382
Daichi Hirono15a02992016-04-27 18:47:01 +09002383 static boolean isDocumentLaunchesIntoExisting(int flags) {
2384 return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
2385 (flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;
2386 }
liulvpingcfa825f2016-09-26 20:00:15 +08002387
Bryce Lee4c9a5972017-12-01 22:14:24 -08002388 ActivityStarter setIntent(Intent intent) {
2389 mRequest.intent = intent;
2390 return this;
2391 }
2392
2393 ActivityStarter setReason(String reason) {
2394 mRequest.reason = reason;
2395 return this;
2396 }
2397
2398 ActivityStarter setCaller(IApplicationThread caller) {
2399 mRequest.caller = caller;
2400 return this;
2401 }
2402
2403 ActivityStarter setEphemeralIntent(Intent intent) {
2404 mRequest.ephemeralIntent = intent;
2405 return this;
2406 }
2407
2408
2409 ActivityStarter setResolvedType(String type) {
2410 mRequest.resolvedType = type;
2411 return this;
2412 }
2413
2414 ActivityStarter setActivityInfo(ActivityInfo info) {
2415 mRequest.activityInfo = info;
2416 return this;
2417 }
2418
2419 ActivityStarter setResolveInfo(ResolveInfo info) {
2420 mRequest.resolveInfo = info;
2421 return this;
2422 }
2423
2424 ActivityStarter setVoiceSession(IVoiceInteractionSession voiceSession) {
2425 mRequest.voiceSession = voiceSession;
2426 return this;
2427 }
2428
2429 ActivityStarter setVoiceInteractor(IVoiceInteractor voiceInteractor) {
2430 mRequest.voiceInteractor = voiceInteractor;
2431 return this;
2432 }
2433
2434 ActivityStarter setResultTo(IBinder resultTo) {
2435 mRequest.resultTo = resultTo;
2436 return this;
2437 }
2438
2439 ActivityStarter setResultWho(String resultWho) {
2440 mRequest.resultWho = resultWho;
2441 return this;
2442 }
2443
2444 ActivityStarter setRequestCode(int requestCode) {
2445 mRequest.requestCode = requestCode;
2446 return this;
2447 }
2448
2449 ActivityStarter setCallingPid(int pid) {
2450 mRequest.callingPid = pid;
2451 return this;
2452 }
2453
2454 ActivityStarter setCallingUid(int uid) {
2455 mRequest.callingUid = uid;
2456 return this;
2457 }
2458
2459 ActivityStarter setCallingPackage(String callingPackage) {
2460 mRequest.callingPackage = callingPackage;
2461 return this;
2462 }
2463
2464 ActivityStarter setRealCallingPid(int pid) {
2465 mRequest.realCallingPid = pid;
2466 return this;
2467 }
2468
2469 ActivityStarter setRealCallingUid(int uid) {
2470 mRequest.realCallingUid = uid;
2471 return this;
2472 }
2473
2474 ActivityStarter setStartFlags(int startFlags) {
2475 mRequest.startFlags = startFlags;
2476 return this;
2477 }
2478
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002479 ActivityStarter setActivityOptions(SafeActivityOptions options) {
Bryce Lee4c9a5972017-12-01 22:14:24 -08002480 mRequest.activityOptions = options;
2481 return this;
2482 }
2483
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002484 ActivityStarter setActivityOptions(Bundle bOptions) {
2485 return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
2486 }
2487
Bryce Lee4c9a5972017-12-01 22:14:24 -08002488 ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) {
2489 mRequest.ignoreTargetSecurity = ignoreTargetSecurity;
2490 return this;
2491 }
2492
2493 ActivityStarter setComponentSpecified(boolean componentSpecified) {
2494 mRequest.componentSpecified = componentSpecified;
2495 return this;
2496 }
2497
2498 ActivityStarter setOutActivity(ActivityRecord[] outActivity) {
2499 mRequest.outActivity = outActivity;
2500 return this;
2501 }
2502
2503 ActivityStarter setInTask(TaskRecord inTask) {
2504 mRequest.inTask = inTask;
2505 return this;
2506 }
2507
2508 ActivityStarter setWaitResult(WaitResult result) {
2509 mRequest.waitResult = result;
2510 return this;
2511 }
2512
2513 ActivityStarter setProfilerInfo(ProfilerInfo info) {
2514 mRequest.profilerInfo = info;
2515 return this;
2516 }
2517
2518 ActivityStarter setGlobalConfiguration(Configuration config) {
2519 mRequest.globalConfig = config;
2520 return this;
2521 }
2522
Bryce Lee4c9a5972017-12-01 22:14:24 -08002523 ActivityStarter setUserId(int userId) {
2524 mRequest.userId = userId;
2525 return this;
2526 }
2527
Jorim Jaggi4d8d32c2018-01-19 15:57:41 +01002528 ActivityStarter setMayWait(int userId) {
Bryce Lee4c9a5972017-12-01 22:14:24 -08002529 mRequest.mayWait = true;
Bryce Lee4c9a5972017-12-01 22:14:24 -08002530 mRequest.userId = userId;
2531
2532 return this;
2533 }
2534
Bryce Leed3624e12017-11-30 08:51:45 -08002535 void dump(PrintWriter pw, String prefix) {
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002536 prefix = prefix + " ";
Dianne Hackborne676ec72017-07-25 10:55:08 -07002537 pw.print(prefix);
2538 pw.print("mCurrentUser=");
2539 pw.println(mSupervisor.mCurrentUser);
2540 pw.print(prefix);
2541 pw.print("mLastStartReason=");
2542 pw.println(mLastStartReason);
2543 pw.print(prefix);
2544 pw.print("mLastStartActivityTimeMs=");
2545 pw.println(DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
2546 pw.print(prefix);
2547 pw.print("mLastStartActivityResult=");
2548 pw.println(mLastStartActivityResult);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002549 ActivityRecord r = mLastStartActivityRecord[0];
2550 if (r != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002551 pw.print(prefix);
2552 pw.println("mLastStartActivityRecord:");
2553 r.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002554 }
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002555 if (mStartActivity != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002556 pw.print(prefix);
2557 pw.println("mStartActivity:");
2558 mStartActivity.dump(pw, prefix + " ");
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002559 }
2560 if (mIntent != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002561 pw.print(prefix);
2562 pw.print("mIntent=");
2563 pw.println(mIntent);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002564 }
2565 if (mOptions != null) {
Dianne Hackborne676ec72017-07-25 10:55:08 -07002566 pw.print(prefix);
2567 pw.print("mOptions=");
2568 pw.println(mOptions);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002569 }
Dianne Hackborne676ec72017-07-25 10:55:08 -07002570 pw.print(prefix);
2571 pw.print("mLaunchSingleTop=");
Bryce Lee7daee392017-10-12 13:46:18 -07002572 pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002573 pw.print(" mLaunchSingleInstance=");
Bryce Lee7daee392017-10-12 13:46:18 -07002574 pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002575 pw.print(" mLaunchSingleTask=");
Bryce Lee7daee392017-10-12 13:46:18 -07002576 pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
Dianne Hackborne676ec72017-07-25 10:55:08 -07002577 pw.print(prefix);
2578 pw.print("mLaunchFlags=0x");
2579 pw.print(Integer.toHexString(mLaunchFlags));
2580 pw.print(" mDoResume=");
2581 pw.print(mDoResume);
2582 pw.print(" mAddingToTask=");
2583 pw.println(mAddingToTask);
Wale Ogunwale692dcd62017-06-20 13:38:14 -07002584 }
Filip Gruszczynski07a0e492015-12-17 14:16:38 -08002585}