• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityManager.START_CANCELED;
20 import static android.app.ActivityManager.START_SUCCESS;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
25 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
26 import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL;
27 
28 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
29 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
30 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
31 
32 import android.annotation.NonNull;
33 import android.annotation.Nullable;
34 import android.app.ActivityManager;
35 import android.app.ActivityOptions;
36 import android.app.IApplicationThread;
37 import android.content.ComponentName;
38 import android.content.ContentResolver;
39 import android.content.Intent;
40 import android.content.pm.ActivityInfo;
41 import android.content.pm.ApplicationInfo;
42 import android.content.pm.PackageManager;
43 import android.content.pm.ResolveInfo;
44 import android.os.Binder;
45 import android.os.Bundle;
46 import android.os.IBinder;
47 import android.os.UserHandle;
48 import android.provider.Settings;
49 import android.util.Slog;
50 import android.util.SparseArray;
51 import android.view.RemoteAnimationAdapter;
52 import android.view.WindowManager;
53 import android.window.RemoteTransition;
54 
55 import com.android.internal.annotations.VisibleForTesting;
56 import com.android.internal.util.ArrayUtils;
57 import com.android.server.am.ActivityManagerService;
58 import com.android.server.am.PendingIntentRecord;
59 import com.android.server.uri.NeededUriGrants;
60 import com.android.server.wm.ActivityStarter.DefaultFactory;
61 import com.android.server.wm.ActivityStarter.Factory;
62 
63 import java.io.PrintWriter;
64 import java.util.List;
65 
66 /**
67  * Controller for delegating activity launches.
68  *
69  * This class' main objective is to take external activity start requests and prepare them into
70  * a series of discrete activity launches that can be handled by an {@link ActivityStarter}. It is
71  * also responsible for handling logic that happens around an activity launch, but doesn't
72  * necessarily influence the activity start. Examples include power hint management, processing
73  * through the pending activity list, and recording home activity launches.
74  */
75 public class ActivityStartController {
76     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStartController" : TAG_ATM;
77 
78     private static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 1;
79 
80     private final ActivityTaskManagerService mService;
81     private final ActivityTaskSupervisor mSupervisor;
82 
83     /** Last home activity record we attempted to start. */
84     private ActivityRecord mLastHomeActivityStartRecord;
85 
86     /** Temporary array to capture start activity results */
87     private ActivityRecord[] tmpOutRecord = new ActivityRecord[1];
88 
89     /** The result of the last home activity we attempted to start. */
90     private int mLastHomeActivityStartResult;
91 
92     private final Factory mFactory;
93 
94     private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry;
95 
96     boolean mCheckedForSetup = false;
97 
98     /** Whether an {@link ActivityStarter} is currently executing (starting an Activity). */
99     private boolean mInExecution = false;
100 
101     private final BackgroundActivityStartController mBalController;
102 
103     /**
104      * TODO(b/64750076): Capture information necessary for dump and
105      * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
106      * around
107      */
108     private ActivityStarter mLastStarter;
109 
ActivityStartController(ActivityTaskManagerService service)110     ActivityStartController(ActivityTaskManagerService service) {
111         this(service, service.mTaskSupervisor,
112                 new DefaultFactory(service, service.mTaskSupervisor,
113                     new ActivityStartInterceptor(service, service.mTaskSupervisor)));
114     }
115 
116     @VisibleForTesting
ActivityStartController(ActivityTaskManagerService service, ActivityTaskSupervisor supervisor, Factory factory)117     ActivityStartController(ActivityTaskManagerService service, ActivityTaskSupervisor supervisor,
118             Factory factory) {
119         mService = service;
120         mSupervisor = supervisor;
121         mFactory = factory;
122         mFactory.setController(this);
123         mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock,
124                 service.mH);
125         mBalController = new BackgroundActivityStartController(mService, mSupervisor);
126     }
127 
128     /**
129      * @return A starter to configure and execute starting an activity. It is valid until after
130      *         {@link ActivityStarter#execute} is invoked. At that point, the starter should be
131      *         considered invalid and no longer modified or used.
132      */
obtainStarter(Intent intent, String reason)133     ActivityStarter obtainStarter(Intent intent, String reason) {
134         return mFactory.obtain().setIntent(intent).setReason(reason);
135     }
136 
onExecutionStarted()137     void onExecutionStarted() {
138         mInExecution = true;
139     }
140 
isInExecution()141     boolean isInExecution() {
142         return mInExecution;
143     }
onExecutionComplete(ActivityStarter starter)144     void onExecutionComplete(ActivityStarter starter) {
145         mInExecution = false;
146         if (mLastStarter == null) {
147             mLastStarter = mFactory.obtain();
148         }
149 
150         mLastStarter.set(starter);
151         mFactory.recycle(starter);
152     }
153 
154     /**
155      * TODO(b/64750076): usage of this doesn't seem right. We're making decisions based off the
156      * last starter for an arbitrary task record. Re-evaluate whether we can remove.
157      */
postStartActivityProcessingForLastStarter(ActivityRecord r, int result, Task targetRootTask)158     void postStartActivityProcessingForLastStarter(ActivityRecord r, int result,
159             Task targetRootTask) {
160         if (mLastStarter == null) {
161             return;
162         }
163 
164         mLastStarter.postStartActivityProcessing(r, result, targetRootTask);
165     }
166 
startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, TaskDisplayArea taskDisplayArea)167     void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
168             TaskDisplayArea taskDisplayArea) {
169         final ActivityOptions options = ActivityOptions.makeBasic();
170         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
171         if (!ActivityRecord.isResolverActivity(aInfo.name)) {
172             // The resolver activity shouldn't be put in root home task because when the
173             // foreground is standard type activity, the resolver activity should be put on the
174             // top of current foreground instead of bring root home task to front.
175             options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
176         }
177         final int displayId = taskDisplayArea.getDisplayId();
178         options.setLaunchDisplayId(displayId);
179         options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken
180                 .toWindowContainerToken());
181 
182         // The home activity will be started later, defer resuming to avoid unnecessary operations
183         // (e.g. start home recursively) when creating root home task.
184         mSupervisor.beginDeferResume();
185         final Task rootHomeTask;
186         try {
187             // Make sure root home task exists on display area.
188             rootHomeTask = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
189         } finally {
190             mSupervisor.endDeferResume();
191         }
192 
193         mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
194                 .setOutActivity(tmpOutRecord)
195                 .setCallingUid(0)
196                 .setActivityInfo(aInfo)
197                 .setActivityOptions(options.toBundle())
198                 .execute();
199         mLastHomeActivityStartRecord = tmpOutRecord[0];
200         if (rootHomeTask.mInResumeTopActivity) {
201             // If we are in resume section already, home activity will be initialized, but not
202             // resumed (to avoid recursive resume) and will stay that way until something pokes it
203             // again. We need to schedule another resume.
204             mSupervisor.scheduleResumeTopActivities();
205         }
206     }
207 
208     /**
209      * Starts the "new version setup screen" if appropriate.
210      */
startSetupActivity()211     void startSetupActivity() {
212         // Only do this once per boot.
213         if (mCheckedForSetup) {
214             return;
215         }
216 
217         // We will show this screen if the current one is a different
218         // version than the last one shown, and we are not running in
219         // low-level factory test mode.
220         final ContentResolver resolver = mService.mContext.getContentResolver();
221         if (mService.mFactoryTest != FACTORY_TEST_LOW_LEVEL
222                 && Settings.Global.getInt(resolver, Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
223             mCheckedForSetup = true;
224 
225             // See if we should be showing the platform update setup UI.
226             final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
227             final List<ResolveInfo> ris =
228                     mService.mContext.getPackageManager().queryIntentActivities(intent,
229                             PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA
230                                     | ActivityManagerService.STOCK_PM_FLAGS);
231             if (!ris.isEmpty()) {
232                 final ResolveInfo ri = ris.get(0);
233                 String vers = ri.activityInfo.metaData != null
234                         ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
235                         : null;
236                 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
237                     vers = ri.activityInfo.applicationInfo.metaData.getString(
238                             Intent.METADATA_SETUP_VERSION);
239                 }
240                 String lastVers = Settings.Secure.getString(
241                         resolver, Settings.Secure.LAST_SETUP_SHOWN);
242                 if (vers != null && !vers.equals(lastVers)) {
243                     intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
244                     intent.setComponent(new ComponentName(
245                             ri.activityInfo.packageName, ri.activityInfo.name));
246                     obtainStarter(intent, "startSetupActivity")
247                             .setCallingUid(0)
248                             .setActivityInfo(ri.activityInfo)
249                             .execute();
250                 }
251             }
252         }
253     }
254 
255     /**
256      * If {@code validateIncomingUser} is true, check {@code targetUserId} against the real calling
257      * user ID inferred from {@code realCallingUid}, then return the resolved user-id, taking into
258      * account "current user", etc.
259      *
260      * If {@code validateIncomingUser} is false, it skips the above check, but instead
261      * ensures {@code targetUserId} is a real user ID and not a special user ID such as
262      * {@link android.os.UserHandle#USER_ALL}, etc.
263      */
checkTargetUser(int targetUserId, boolean validateIncomingUser, int realCallingPid, int realCallingUid, String reason)264     int checkTargetUser(int targetUserId, boolean validateIncomingUser,
265             int realCallingPid, int realCallingUid, String reason) {
266         if (validateIncomingUser) {
267             return mService.handleIncomingUser(
268                     realCallingPid, realCallingUid, targetUserId, reason);
269         } else {
270             mService.mAmInternal.ensureNotSpecialUser(targetUserId);
271             return targetUserId;
272         }
273     }
274 
startActivityInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, SafeActivityOptions options, int userId, Task inTask, String reason, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)275     final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,
276             String callingPackage, @Nullable String callingFeatureId, Intent intent,
277             String resolvedType, IBinder resultTo, String resultWho, int requestCode,
278             int startFlags, SafeActivityOptions options, int userId, Task inTask, String reason,
279             boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent,
280             boolean allowBackgroundActivityStart) {
281 
282         userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid,
283                 reason);
284 
285         // TODO: Switch to user app stacks here.
286         return obtainStarter(intent, reason)
287                 .setCallingUid(uid)
288                 .setRealCallingPid(realCallingPid)
289                 .setRealCallingUid(realCallingUid)
290                 .setCallingPackage(callingPackage)
291                 .setCallingFeatureId(callingFeatureId)
292                 .setResolvedType(resolvedType)
293                 .setResultTo(resultTo)
294                 .setResultWho(resultWho)
295                 .setRequestCode(requestCode)
296                 .setStartFlags(startFlags)
297                 .setActivityOptions(options)
298                 .setUserId(userId)
299                 .setInTask(inTask)
300                 .setOriginatingPendingIntent(originatingPendingIntent)
301                 .setAllowBackgroundActivityStart(allowBackgroundActivityStart)
302                 .execute();
303     }
304 
305     /**
306      * Start intents as a package.
307      *
308      * @param uid Make a call as if this UID did.
309      * @param callingPackage Make a call as if this package did.
310      * @param callingFeatureId Make a call as if this feature in the package did.
311      * @param intents Intents to start.
312      * @param userId Start the intents on this user.
313      * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID.
314      * @param originatingPendingIntent PendingIntentRecord that originated this activity start or
315      *        null if not originated by PendingIntent
316      */
startActivitiesInPackage(int uid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)317     final int startActivitiesInPackage(int uid, String callingPackage,
318             @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes,
319             IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser,
320             PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
321         return startActivitiesInPackage(uid, 0 /* realCallingPid */, -1 /* realCallingUid */,
322                 callingPackage, callingFeatureId, intents, resolvedTypes, resultTo, options, userId,
323                 validateIncomingUser, originatingPendingIntent, allowBackgroundActivityStart);
324     }
325 
326     /**
327      * Start intents as a package.
328      *
329      * @param uid Make a call as if this UID did.
330      * @param realCallingPid PID of the real caller.
331      * @param realCallingUid UID of the real caller.
332      * @param callingPackage Make a call as if this package did.
333      * @param intents Intents to start.
334      * @param userId Start the intents on this user.
335      * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID.
336      * @param originatingPendingIntent PendingIntentRecord that originated this activity start or
337      *        null if not originated by PendingIntent
338      */
startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)339     final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid,
340             String callingPackage, @Nullable String callingFeatureId, Intent[] intents,
341             String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
342             boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent,
343             boolean allowBackgroundActivityStart) {
344 
345         final String reason = "startActivityInPackage";
346 
347         userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(),
348                 Binder.getCallingUid(), reason);
349 
350         // TODO: Switch to user app stacks here.
351         return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage,
352                 callingFeatureId, intents, resolvedTypes, resultTo, options, userId, reason,
353                 originatingPendingIntent, allowBackgroundActivityStart);
354     }
355 
startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart)356     int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid,
357             int incomingRealCallingUid, String callingPackage, @Nullable String callingFeatureId,
358             Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options,
359             int userId, String reason, PendingIntentRecord originatingPendingIntent,
360             boolean allowBackgroundActivityStart) {
361         if (intents == null) {
362             throw new NullPointerException("intents is null");
363         }
364         if (resolvedTypes == null) {
365             throw new NullPointerException("resolvedTypes is null");
366         }
367         if (intents.length != resolvedTypes.length) {
368             throw new IllegalArgumentException("intents are length different than resolvedTypes");
369         }
370 
371         final int realCallingPid = incomingRealCallingPid != 0
372                 ? incomingRealCallingPid
373                 : Binder.getCallingPid();
374         final int realCallingUid = incomingRealCallingUid != -1
375                 ? incomingRealCallingUid
376                 : Binder.getCallingUid();
377 
378         int callingPid;
379         if (callingUid >= 0) {
380             callingPid = -1;
381         } else if (caller == null) {
382             callingPid = realCallingPid;
383             callingUid = realCallingUid;
384         } else {
385             callingPid = callingUid = -1;
386         }
387         final int filterCallingUid = ActivityStarter.computeResolveFilterUid(
388                 callingUid, realCallingUid, UserHandle.USER_NULL);
389         final SparseArray<String> startingUidPkgs = new SparseArray<>();
390         final long origId = Binder.clearCallingIdentity();
391 
392         SafeActivityOptions bottomOptions = null;
393         if (options != null) {
394             // To ensure the first N-1 activities (N == total # of activities) are also launched
395             // into the correct display and root task, use a copy of the passed-in options (keeping
396             // only display-related and launch-root-task information) for these activities.
397             bottomOptions = options.selectiveCloneLaunchOptions();
398         }
399         try {
400             intents = ArrayUtils.filterNotNull(intents, Intent[]::new);
401             final ActivityStarter[] starters = new ActivityStarter[intents.length];
402             // Do not hold WM global lock on this loop because when resolving intent, it may
403             // potentially acquire activity manager lock that leads to deadlock.
404             for (int i = 0; i < intents.length; i++) {
405                 Intent intent = intents[i];
406                 NeededUriGrants intentGrants = null;
407 
408                 // Refuse possible leaked file descriptors.
409                 if (intent.hasFileDescriptors()) {
410                     throw new IllegalArgumentException("File descriptors passed in Intent");
411                 }
412 
413                 // Get the flag earlier because the intent may be modified in resolveActivity below.
414                 final boolean componentSpecified = intent.getComponent() != null;
415                 // Don't modify the client's object!
416                 intent = new Intent(intent);
417 
418                 // Collect information about the target of the Intent.
419                 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i],
420                         0 /* startFlags */, null /* profilerInfo */, userId, filterCallingUid);
421                 aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
422 
423                 if (aInfo != null) {
424                     try {
425                         // Carefully collect grants without holding lock
426                         intentGrants = mSupervisor.mService.mUgmInternal
427                                 .checkGrantUriPermissionFromIntent(intent, filterCallingUid,
428                                         aInfo.applicationInfo.packageName,
429                                         UserHandle.getUserId(aInfo.applicationInfo.uid));
430                     } catch (SecurityException e) {
431                         Slog.d(TAG, "Not allowed to start activity since no uri permission.");
432                         return START_CANCELED;
433                     }
434 
435                     if ((aInfo.applicationInfo.privateFlags
436                             & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
437                         throw new IllegalArgumentException(
438                                 "FLAG_CANT_SAVE_STATE not supported here");
439                     }
440                     startingUidPkgs.put(aInfo.applicationInfo.uid,
441                             aInfo.applicationInfo.packageName);
442                 }
443 
444                 final boolean top = i == intents.length - 1;
445                 final SafeActivityOptions checkedOptions = top
446                         ? options
447                         : bottomOptions;
448                 starters[i] = obtainStarter(intent, reason)
449                         .setIntentGrants(intentGrants)
450                         .setCaller(caller)
451                         .setResolvedType(resolvedTypes[i])
452                         .setActivityInfo(aInfo)
453                         .setRequestCode(-1)
454                         .setCallingPid(callingPid)
455                         .setCallingUid(callingUid)
456                         .setCallingPackage(callingPackage)
457                         .setCallingFeatureId(callingFeatureId)
458                         .setRealCallingPid(realCallingPid)
459                         .setRealCallingUid(realCallingUid)
460                         .setActivityOptions(checkedOptions)
461                         .setComponentSpecified(componentSpecified)
462 
463                         // Top activity decides on animation being run, so we allow only for the
464                         // top one as otherwise an activity below might consume it.
465                         .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
466                         .setOriginatingPendingIntent(originatingPendingIntent)
467                         .setAllowBackgroundActivityStart(allowBackgroundActivityStart);
468             }
469             // Log if the activities to be started have different uids.
470             if (startingUidPkgs.size() > 1) {
471                 final StringBuilder sb = new StringBuilder("startActivities: different apps [");
472                 final int size = startingUidPkgs.size();
473                 for (int i = 0; i < size; i++) {
474                     sb.append(startingUidPkgs.valueAt(i)).append(i == size - 1 ? "]" : ", ");
475                 }
476                 sb.append(" from ").append(callingPackage);
477                 Slog.wtf(TAG, sb.toString());
478             }
479 
480             final IBinder sourceResultTo = resultTo;
481             final ActivityRecord[] outActivity = new ActivityRecord[1];
482             // Lock the loop to ensure the activities launched in a sequence.
483             synchronized (mService.mGlobalLock) {
484                 mService.deferWindowLayout();
485                 // To avoid creating multiple starting window when creating starting multiples
486                 // activities, we defer the creation of the starting window once all start request
487                 // are processed
488                 mService.mWindowManager.mStartingSurfaceController.beginDeferAddStartingWindow();
489                 try {
490                     for (int i = 0; i < starters.length; i++) {
491                         final int startResult = starters[i].setResultTo(resultTo)
492                                 .setOutActivity(outActivity).execute();
493                         if (startResult < START_SUCCESS) {
494                             // Abort by error result and recycle unused starters.
495                             for (int j = i + 1; j < starters.length; j++) {
496                                 mFactory.recycle(starters[j]);
497                             }
498                             return startResult;
499                         }
500                         final ActivityRecord started = outActivity[0];
501                         if (started != null && started.getUid() == filterCallingUid) {
502                             // Only the started activity which has the same uid as the source caller
503                             // can be the caller of next activity.
504                             resultTo = started.token;
505                         } else {
506                             resultTo = sourceResultTo;
507                             // Different apps not adjacent to the caller are forced to be new task.
508                             if (i < starters.length - 1) {
509                                 starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
510                             }
511                         }
512                     }
513                 } finally {
514                     mService.mWindowManager.mStartingSurfaceController.endDeferAddStartingWindow(
515                             options != null ? options.getOriginalOptions() : null);
516                     mService.continueWindowLayout();
517                 }
518             }
519         } finally {
520             Binder.restoreCallingIdentity(origId);
521         }
522 
523         return START_SUCCESS;
524     }
525 
526     /**
527      * Starts an activity in the TaskFragment.
528      * @param taskFragment TaskFragment {@link TaskFragment} to start the activity in.
529      * @param activityIntent intent to start the activity.
530      * @param activityOptions ActivityOptions to start the activity with.
531      * @param resultTo the caller activity
532      * @param callingUid the caller uid
533      * @param callingPid the caller pid
534      * @return the start result.
535      */
startActivityInTaskFragment(@onNull TaskFragment taskFragment, @NonNull Intent activityIntent, @Nullable Bundle activityOptions, @Nullable IBinder resultTo, int callingUid, int callingPid, @Nullable IBinder errorCallbackToken)536     int startActivityInTaskFragment(@NonNull TaskFragment taskFragment,
537             @NonNull Intent activityIntent, @Nullable Bundle activityOptions,
538             @Nullable IBinder resultTo, int callingUid, int callingPid,
539             @Nullable IBinder errorCallbackToken) {
540         final ActivityRecord caller =
541                 resultTo != null ? ActivityRecord.forTokenLocked(resultTo) : null;
542         return obtainStarter(activityIntent, "startActivityInTaskFragment")
543                 .setActivityOptions(activityOptions)
544                 .setInTaskFragment(taskFragment)
545                 .setResultTo(resultTo)
546                 .setRequestCode(-1)
547                 .setCallingUid(callingUid)
548                 .setCallingPid(callingPid)
549                 .setRealCallingUid(callingUid)
550                 .setRealCallingPid(callingPid)
551                 .setUserId(caller != null ? caller.mUserId : mService.getCurrentUserId())
552                 .setErrorCallbackToken(errorCallbackToken)
553                 .execute();
554     }
555 
startExistingRecentsIfPossible(Intent intent, ActivityOptions options)556     boolean startExistingRecentsIfPossible(Intent intent, ActivityOptions options) {
557         final int activityType = mService.getRecentTasks().getRecentsComponent()
558                 .equals(intent.getComponent()) ? ACTIVITY_TYPE_RECENTS : ACTIVITY_TYPE_HOME;
559         final Task rootTask = mService.mRootWindowContainer.getDefaultTaskDisplayArea()
560                 .getRootTask(WINDOWING_MODE_UNDEFINED, activityType);
561         if (rootTask == null) return false;
562         final RemoteTransition remote = options.getRemoteTransition();
563         final ActivityRecord r = rootTask.topRunningActivity();
564         if (r == null || r.isVisibleRequested() || !r.attachedToProcess() || remote == null
565                 || !r.mActivityComponent.equals(intent.getComponent())
566                 // Recents keeps invisible while device is locked.
567                 || r.mDisplayContent.isKeyguardLocked()) {
568             return false;
569         }
570         mService.mRootWindowContainer.startPowerModeLaunchIfNeeded(true /* forceSend */, r);
571         final ActivityMetricsLogger.LaunchingState launchingState =
572                 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
573         final Transition transition = new Transition(WindowManager.TRANSIT_TO_FRONT,
574                 0 /* flags */, r.mTransitionController, mService.mWindowManager.mSyncEngine);
575         if (r.mTransitionController.isCollecting()) {
576             // Special case: we are entering recents while an existing transition is running. In
577             // this case, we know it's safe to "defer" the activity launch, so lets do so now so
578             // that it can get its own transition and thus update launcher correctly.
579             mService.mWindowManager.mSyncEngine.queueSyncSet(
580                     () -> {
581                         if (r.isAttached()) {
582                             r.mTransitionController.moveToCollecting(transition);
583                         }
584                     },
585                     () -> {
586                         if (r.isAttached() && transition.isCollecting()) {
587                             startExistingRecentsIfPossibleInner(options, r, rootTask,
588                                     launchingState, remote, transition);
589                         }
590                     });
591         } else {
592             r.mTransitionController.moveToCollecting(transition);
593             startExistingRecentsIfPossibleInner(options, r, rootTask, launchingState, remote,
594                     transition);
595         }
596         return true;
597     }
598 
startExistingRecentsIfPossibleInner(ActivityOptions options, ActivityRecord r, Task rootTask, ActivityMetricsLogger.LaunchingState launchingState, RemoteTransition remoteTransition, Transition transition)599     private void startExistingRecentsIfPossibleInner(ActivityOptions options, ActivityRecord r,
600             Task rootTask, ActivityMetricsLogger.LaunchingState launchingState,
601             RemoteTransition remoteTransition, Transition transition) {
602         final Task task = r.getTask();
603         mService.deferWindowLayout();
604         try {
605             r.mTransitionController.requestStartTransition(transition,
606                     task, remoteTransition, null /* displayChange */);
607             r.mTransitionController.collect(task);
608             r.mTransitionController.setTransientLaunch(r,
609                     TaskDisplayArea.getRootTaskAbove(rootTask));
610             task.moveToFront("startExistingRecents");
611             task.mInResumeTopActivity = true;
612             task.resumeTopActivity(null /* prev */, options, true /* deferPause */);
613             mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState,
614                     ActivityManager.START_TASK_TO_FRONT, false, r, options);
615         } finally {
616             task.mInResumeTopActivity = false;
617             mService.continueWindowLayout();
618         }
619     }
620 
registerRemoteAnimationForNextActivityStart(String packageName, RemoteAnimationAdapter adapter, @Nullable IBinder launchCookie)621     void registerRemoteAnimationForNextActivityStart(String packageName,
622             RemoteAnimationAdapter adapter, @Nullable IBinder launchCookie) {
623         mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter, launchCookie);
624     }
625 
getPendingRemoteAnimationRegistry()626     PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() {
627         return mPendingRemoteAnimationRegistry;
628     }
629 
dumpLastHomeActivityStartResult(PrintWriter pw, String prefix)630     void dumpLastHomeActivityStartResult(PrintWriter pw, String prefix) {
631         pw.print(prefix);
632         pw.print("mLastHomeActivityStartResult=");
633         pw.println(mLastHomeActivityStartResult);
634     }
635 
dump(PrintWriter pw, String prefix, String dumpPackage)636     void dump(PrintWriter pw, String prefix, String dumpPackage) {
637         boolean dumped = false;
638 
639         final boolean dumpPackagePresent = dumpPackage != null;
640 
641         if (mLastHomeActivityStartRecord != null && (!dumpPackagePresent
642                 || dumpPackage.equals(mLastHomeActivityStartRecord.packageName))) {
643             dumped = true;
644             dumpLastHomeActivityStartResult(pw, prefix);
645             pw.print(prefix);
646             pw.println("mLastHomeActivityStartRecord:");
647             mLastHomeActivityStartRecord.dump(pw, prefix + "  ", true /* dumpAll */);
648         }
649 
650         if (mLastStarter != null) {
651             final boolean dump = !dumpPackagePresent
652                     || mLastStarter.relatedToPackage(dumpPackage)
653                     || (mLastHomeActivityStartRecord != null
654                             && dumpPackage.equals(mLastHomeActivityStartRecord.packageName));
655 
656             if (dump) {
657                 if (!dumped) {
658                     dumped = true;
659                     dumpLastHomeActivityStartResult(pw, prefix);
660                 }
661                 pw.print(prefix);
662                 pw.println("mLastStarter:");
663                 mLastStarter.dump(pw, prefix + "  ");
664 
665                 if (dumpPackagePresent) {
666                     return;
667                 }
668             }
669         }
670 
671         if (!dumped) {
672             pw.print(prefix);
673             pw.println("(nothing)");
674         }
675     }
676 
getBackgroundActivityLaunchController()677     BackgroundActivityStartController getBackgroundActivityLaunchController() {
678         return mBalController;
679     }
680 }
681