1 /*
2  * Copyright (C) 2020 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.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
20 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
21 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
24 import static android.os.Process.INVALID_UID;
25 import static android.os.Process.SYSTEM_UID;
26 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
27 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
28 import static android.view.Display.DEFAULT_DISPLAY;
29 import static android.view.Display.INVALID_DISPLAY;
30 
31 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
32 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IMMERSIVE;
33 import static com.android.server.wm.ActivityRecord.State.DESTROYED;
34 import static com.android.server.wm.ActivityRecord.State.DESTROYING;
35 import static com.android.server.wm.ActivityRecord.State.PAUSING;
36 import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
37 import static com.android.server.wm.ActivityRecord.State.RESUMED;
38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
39 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
40 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
41 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
42 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
43 import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
44 import static com.android.server.wm.ActivityTaskManagerService.enforceNotIsolatedCaller;
45 
46 import android.annotation.NonNull;
47 import android.annotation.Nullable;
48 import android.app.Activity;
49 import android.app.ActivityManager;
50 import android.app.ActivityTaskManager;
51 import android.app.IActivityClientController;
52 import android.app.IRequestFinishCallback;
53 import android.app.PictureInPictureParams;
54 import android.app.PictureInPictureUiState;
55 import android.app.servertransaction.ClientTransaction;
56 import android.app.servertransaction.EnterPipRequestedItem;
57 import android.app.servertransaction.PipStateTransactionItem;
58 import android.content.ComponentName;
59 import android.content.Context;
60 import android.content.Intent;
61 import android.content.pm.ActivityInfo;
62 import android.content.pm.PackageManagerInternal;
63 import android.content.pm.ParceledListSlice;
64 import android.content.pm.ResolveInfo;
65 import android.content.res.Configuration;
66 import android.os.Binder;
67 import android.os.Bundle;
68 import android.os.IBinder;
69 import android.os.Parcel;
70 import android.os.PersistableBundle;
71 import android.os.RemoteException;
72 import android.os.SystemClock;
73 import android.os.Trace;
74 import android.os.UserHandle;
75 import android.service.voice.VoiceInteractionManagerInternal;
76 import android.util.Slog;
77 import android.view.RemoteAnimationDefinition;
78 import android.window.SizeConfigurationBuckets;
79 import android.window.TransitionInfo;
80 
81 import com.android.internal.app.AssistUtils;
82 import com.android.internal.policy.IKeyguardDismissCallback;
83 import com.android.internal.protolog.common.ProtoLog;
84 import com.android.server.LocalServices;
85 import com.android.server.Watchdog;
86 import com.android.server.pm.parsing.pkg.AndroidPackage;
87 import com.android.server.uri.NeededUriGrants;
88 import com.android.server.vr.VrManagerInternal;
89 
90 /**
91  * Server side implementation for the client activity to interact with system.
92  *
93  * @see android.app.ActivityClient
94  */
95 class ActivityClientController extends IActivityClientController.Stub {
96     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityClientController" : TAG_ATM;
97 
98     private final ActivityTaskManagerService mService;
99     private final WindowManagerGlobalLock mGlobalLock;
100     private final ActivityTaskSupervisor mTaskSupervisor;
101     private final Context mContext;
102 
103     /** Wrapper around VoiceInteractionServiceManager. */
104     private AssistUtils mAssistUtils;
105 
ActivityClientController(ActivityTaskManagerService service)106     ActivityClientController(ActivityTaskManagerService service) {
107         mService = service;
108         mGlobalLock = service.mGlobalLock;
109         mTaskSupervisor = service.mTaskSupervisor;
110         mContext = service.mContext;
111     }
112 
onSystemReady()113     void onSystemReady() {
114         mAssistUtils = new AssistUtils(mContext);
115     }
116 
117     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)118     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
119             throws RemoteException {
120         try {
121             return super.onTransact(code, data, reply, flags);
122         } catch (RuntimeException e) {
123             throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(
124                     "ActivityClientController", e);
125         }
126     }
127 
128     @Override
activityIdle(IBinder token, Configuration config, boolean stopProfiling)129     public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
130         final long origId = Binder.clearCallingIdentity();
131         try {
132             synchronized (mGlobalLock) {
133                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
134                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
135                 if (r == null) {
136                     return;
137                 }
138                 mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */,
139                         false /* processPausingActivities */, config);
140                 if (stopProfiling && r.hasProcess()) {
141                     r.app.clearProfilerIfNeeded();
142                 }
143             }
144         } finally {
145             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
146             Binder.restoreCallingIdentity(origId);
147         }
148     }
149 
150     @Override
activityResumed(IBinder token, boolean handleSplashScreenExit)151     public void activityResumed(IBinder token, boolean handleSplashScreenExit) {
152         final long origId = Binder.clearCallingIdentity();
153         synchronized (mGlobalLock) {
154             ActivityRecord.activityResumedLocked(token, handleSplashScreenExit);
155         }
156         Binder.restoreCallingIdentity(origId);
157     }
158 
159     @Override
activityTopResumedStateLost()160     public void activityTopResumedStateLost() {
161         final long origId = Binder.clearCallingIdentity();
162         synchronized (mGlobalLock) {
163             mTaskSupervisor.handleTopResumedStateReleased(false /* timeout */);
164         }
165         Binder.restoreCallingIdentity(origId);
166     }
167 
168     @Override
activityPaused(IBinder token)169     public void activityPaused(IBinder token) {
170         final long origId = Binder.clearCallingIdentity();
171         synchronized (mGlobalLock) {
172             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
173             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
174             if (r != null) {
175                 r.activityPaused(false);
176             }
177             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
178         }
179         Binder.restoreCallingIdentity(origId);
180     }
181 
182     @Override
activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState, CharSequence description)183     public void activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState,
184             CharSequence description) {
185         if (DEBUG_ALL) Slog.v(TAG, "Activity stopped: token=" + token);
186 
187         // Refuse possible leaked file descriptors.
188         if (icicle != null && icicle.hasFileDescriptors()) {
189             throw new IllegalArgumentException("File descriptors passed in Bundle");
190         }
191 
192         final long origId = Binder.clearCallingIdentity();
193 
194         String restartingName = null;
195         int restartingUid = 0;
196         final ActivityRecord r;
197         synchronized (mGlobalLock) {
198             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped");
199             r = ActivityRecord.isInRootTaskLocked(token);
200             if (r != null) {
201                 if (r.attachedToProcess() && r.isState(RESTARTING_PROCESS)) {
202                     // The activity was requested to restart from
203                     // {@link #restartActivityProcessIfVisible}.
204                     restartingName = r.app.mName;
205                     restartingUid = r.app.mUid;
206                 }
207                 r.activityStopped(icicle, persistentState, description);
208             }
209             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
210         }
211 
212         if (restartingName != null) {
213             // In order to let the foreground activity can be restarted with its saved state from
214             // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed
215             // until the activity reports stopped with the state. And the activity record will be
216             // kept because the record state is restarting, then the activity will be restarted
217             // immediately if it is still the top one.
218             mTaskSupervisor.removeRestartTimeouts(r);
219             mService.mAmInternal.killProcess(restartingName, restartingUid,
220                     "restartActivityProcess");
221         }
222         mService.mAmInternal.trimApplications();
223 
224         Binder.restoreCallingIdentity(origId);
225     }
226 
227     @Override
activityDestroyed(IBinder token)228     public void activityDestroyed(IBinder token) {
229         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
230         final long origId = Binder.clearCallingIdentity();
231         synchronized (mGlobalLock) {
232             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed");
233             try {
234                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
235                 if (r != null) {
236                     r.destroyed("activityDestroyed");
237                 }
238             } finally {
239                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
240                 Binder.restoreCallingIdentity(origId);
241             }
242         }
243     }
244 
245     @Override
activityRelaunched(IBinder token)246     public void activityRelaunched(IBinder token) {
247         final long origId = Binder.clearCallingIdentity();
248         synchronized (mGlobalLock) {
249             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
250             if (r != null) {
251                 r.finishRelaunching();
252             }
253         }
254         Binder.restoreCallingIdentity(origId);
255     }
256 
257     @Override
reportSizeConfigurations(IBinder token, SizeConfigurationBuckets sizeConfigurations)258     public void reportSizeConfigurations(IBinder token,
259             SizeConfigurationBuckets sizeConfigurations) {
260         ProtoLog.v(WM_DEBUG_CONFIGURATION, "Report configuration: %s %s",
261                 token, sizeConfigurations);
262         synchronized (mGlobalLock) {
263             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
264             if (r != null) {
265                 r.setSizeConfigurations(sizeConfigurations);
266             }
267         }
268     }
269 
270     /**
271      * Attempts to move a task backwards in z-order (the order of activities within the task is
272      * unchanged).
273      *
274      * There are several possible results of this call:
275      * - if the task is locked, then we will show the lock toast.
276      * - if there is a task behind the provided task, then that task is made visible and resumed as
277      * this task is moved to the back.
278      * - otherwise, if there are no other tasks in the root task:
279      * - if this task is in the pinned mode, then we remove the task completely, which will
280      * have the effect of moving the task to the top or bottom of the fullscreen root task
281      * (depending on whether it is visible).
282      * - otherwise, we simply return home and hide this task.
283      *
284      * @param token   A reference to the activity we wish to move.
285      * @param nonRoot If false then this only works if the activity is the root
286      *                of a task; if true it will work for any activity in a task.
287      * @return Returns true if the move completed, false if not.
288      */
289     @Override
moveActivityTaskToBack(IBinder token, boolean nonRoot)290     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
291         enforceNotIsolatedCaller("moveActivityTaskToBack");
292         final long origId = Binder.clearCallingIdentity();
293         try {
294             synchronized (mGlobalLock) {
295                 final int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
296                 final Task task = mService.mRootWindowContainer.anyTaskForId(taskId);
297                 if (task != null) {
298                     return ActivityRecord.getRootTask(token).moveTaskToBack(task);
299                 }
300             }
301         } finally {
302             Binder.restoreCallingIdentity(origId);
303         }
304         return false;
305     }
306 
307     @Override
shouldUpRecreateTask(IBinder token, String destAffinity)308     public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
309         synchronized (mGlobalLock) {
310             final ActivityRecord srec = ActivityRecord.forTokenLocked(token);
311             if (srec != null) {
312                 return srec.getRootTask().shouldUpRecreateTaskLocked(srec, destAffinity);
313             }
314         }
315         return false;
316     }
317 
318     @Override
navigateUpTo(IBinder token, Intent destIntent, int resultCode, Intent resultData)319     public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
320             Intent resultData) {
321         final ActivityRecord r;
322         synchronized (mGlobalLock) {
323             r = ActivityRecord.isInRootTaskLocked(token);
324             if (r == null) {
325                 return false;
326             }
327         }
328 
329         // Carefully collect grants without holding lock.
330         final NeededUriGrants destGrants = mService.collectGrants(destIntent, r);
331         final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo);
332 
333         synchronized (mGlobalLock) {
334             return r.getRootTask().navigateUpTo(
335                     r, destIntent, destGrants, resultCode, resultData, resultGrants);
336         }
337     }
338 
339     @Override
releaseActivityInstance(IBinder token)340     public boolean releaseActivityInstance(IBinder token) {
341         final long origId = Binder.clearCallingIdentity();
342         try {
343             synchronized (mGlobalLock) {
344                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
345                 if (r == null || !r.isDestroyable()) {
346                     return false;
347                 }
348                 r.destroyImmediately("app-req");
349                 return r.isState(DESTROYING, DESTROYED);
350             }
351         } finally {
352             Binder.restoreCallingIdentity(origId);
353         }
354     }
355 
356     /**
357      * This is the internal entry point for handling Activity.finish().
358      *
359      * @param token      The Binder token referencing the Activity we want to finish.
360      * @param resultCode Result code, if any, from this Activity.
361      * @param resultData Result data (Intent), if any, from this Activity.
362      * @param finishTask Whether to finish the task associated with this Activity.
363      * @return Returns true if the activity successfully finished, or false if it is still running.
364      */
365     @Override
finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask)366     public boolean finishActivity(IBinder token, int resultCode, Intent resultData,
367             int finishTask) {
368         // Refuse possible leaked file descriptors.
369         if (resultData != null && resultData.hasFileDescriptors()) {
370             throw new IllegalArgumentException("File descriptors passed in Intent");
371         }
372 
373         final ActivityRecord r;
374         synchronized (mGlobalLock) {
375             r = ActivityRecord.isInRootTaskLocked(token);
376             if (r == null) {
377                 return true;
378             }
379         }
380 
381         // Carefully collect grants without holding lock.
382         final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo);
383 
384         synchronized (mGlobalLock) {
385             // Check again in case activity was removed when collecting grants.
386             if (!r.isInHistory()) {
387                 return true;
388             }
389 
390             // Keep track of the root activity of the task before we finish it.
391             final Task tr = r.getTask();
392             final ActivityRecord rootR = tr.getRootActivity();
393             if (rootR == null) {
394                 Slog.w(TAG, "Finishing task with all activities already finished");
395             }
396             // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
397             // finish.
398             if (mService.getLockTaskController().activityBlockedFromFinish(r)) {
399                 return false;
400             }
401 
402             // TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked
403             // We should consolidate.
404             if (mService.mController != null) {
405                 // Find the first activity that is not finishing.
406                 final ActivityRecord next =
407                         r.getRootTask().topRunningActivity(token, INVALID_TASK_ID);
408                 if (next != null) {
409                     // ask watcher if this is allowed
410                     boolean resumeOK = true;
411                     try {
412                         resumeOK = mService.mController.activityResuming(next.packageName);
413                     } catch (RemoteException e) {
414                         mService.mController = null;
415                         Watchdog.getInstance().setActivityController(null);
416                     }
417 
418                     if (!resumeOK) {
419                         Slog.i(TAG, "Not finishing activity because controller resumed");
420                         return false;
421                     }
422                 }
423             }
424 
425             // Note down that the process has finished an activity and is in background activity
426             // starts grace period.
427             if (r.app != null) {
428                 r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());
429             }
430 
431             final long origId = Binder.clearCallingIdentity();
432             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity");
433             try {
434                 final boolean res;
435                 final boolean finishWithRootActivity =
436                         finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
437                 if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
438                         || (finishWithRootActivity && r == rootR)) {
439                     // If requested, remove the task that is associated to this activity only if it
440                     // was the root activity in the task. The result code and data is ignored
441                     // because we don't support returning them across task boundaries. Also, to
442                     // keep backwards compatibility we remove the task from recents when finishing
443                     // task with root activity.
444                     mTaskSupervisor.removeTask(tr, false /*killProcess*/,
445                             finishWithRootActivity, "finish-activity");
446                     res = true;
447                     // Explicitly dismissing the activity so reset its relaunch flag.
448                     r.mRelaunchReason = RELAUNCH_REASON_NONE;
449                 } else {
450                     r.finishIfPossible(resultCode, resultData, resultGrants,
451                             "app-request", true /* oomAdj */);
452                     res = r.finishing;
453                     if (!res) {
454                         Slog.i(TAG, "Failed to finish by app-request");
455                     }
456                 }
457                 return res;
458             } finally {
459                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
460                 Binder.restoreCallingIdentity(origId);
461             }
462         }
463     }
464 
465     @Override
finishActivityAffinity(IBinder token)466     public boolean finishActivityAffinity(IBinder token) {
467         final long origId = Binder.clearCallingIdentity();
468         try {
469             synchronized (mGlobalLock) {
470                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
471                 if (r == null) {
472                     return false;
473                 }
474 
475                 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
476                 // can finish.
477                 if (mService.getLockTaskController().activityBlockedFromFinish(r)) {
478                     return false;
479                 }
480 
481                 r.getTask().forAllActivities(activity -> r.finishIfSameAffinity(activity),
482                         r /* boundary */, true /* includeBoundary */,
483                         true /* traverseTopToBottom */);
484                 return true;
485             }
486         } finally {
487             Binder.restoreCallingIdentity(origId);
488         }
489     }
490 
491     @Override
finishSubActivity(IBinder token, String resultWho, int requestCode)492     public void finishSubActivity(IBinder token, String resultWho, int requestCode) {
493         final long origId = Binder.clearCallingIdentity();
494         try {
495             synchronized (mGlobalLock) {
496                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
497                 if (r == null) return;
498 
499                 // TODO: This should probably only loop over the task since you need to be in the
500                 // same task to return results.
501                 r.getRootTask().forAllActivities(activity -> {
502                     activity.finishIfSubActivity(r /* parent */, resultWho, requestCode);
503                 }, true /* traverseTopToBottom */);
504 
505                 mService.updateOomAdj();
506             }
507         } finally {
508             Binder.restoreCallingIdentity(origId);
509         }
510     }
511 
512     @Override
isTopOfTask(IBinder token)513     public boolean isTopOfTask(IBinder token) {
514         synchronized (mGlobalLock) {
515             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
516             return r != null && r.getTask().getTopNonFinishingActivity() == r;
517         }
518     }
519 
520     @Override
willActivityBeVisible(IBinder token)521     public boolean willActivityBeVisible(IBinder token) {
522         synchronized (mGlobalLock) {
523             final Task rootTask = ActivityRecord.getRootTask(token);
524             return rootTask != null && rootTask.willActivityBeVisible(token);
525         }
526     }
527 
528     @Override
getDisplayId(IBinder activityToken)529     public int getDisplayId(IBinder activityToken) {
530         synchronized (mGlobalLock) {
531             final Task rootTask = ActivityRecord.getRootTask(activityToken);
532             if (rootTask != null) {
533                 final int displayId = rootTask.getDisplayId();
534                 return displayId != INVALID_DISPLAY ? displayId : DEFAULT_DISPLAY;
535             }
536             return DEFAULT_DISPLAY;
537         }
538     }
539 
540     @Override
getTaskForActivity(IBinder token, boolean onlyRoot)541     public int getTaskForActivity(IBinder token, boolean onlyRoot) {
542         synchronized (mGlobalLock) {
543             return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
544         }
545     }
546 
547     @Override
548     @Nullable
getActivityTokenBelow(IBinder activityToken)549     public IBinder getActivityTokenBelow(IBinder activityToken) {
550         final long ident = Binder.clearCallingIdentity();
551         try {
552             synchronized (mGlobalLock) {
553                 final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken);
554                 if (ar == null) {
555                     return null;
556                 }
557                 // Exclude finishing activity.
558                 final ActivityRecord below = ar.getTask().getActivity((r) -> !r.finishing,
559                         ar, false /*includeBoundary*/, true /*traverseTopToBottom*/);
560                 if (below != null && below.getUid() == ar.getUid()) {
561                     return below.appToken.asBinder();
562                 }
563             }
564         } finally {
565             Binder.restoreCallingIdentity(ident);
566         }
567         return null;
568     }
569 
570     @Override
getCallingActivity(IBinder token)571     public ComponentName getCallingActivity(IBinder token) {
572         synchronized (mGlobalLock) {
573             final ActivityRecord r = getCallingRecord(token);
574             return r != null ? r.intent.getComponent() : null;
575         }
576     }
577 
578     @Override
getCallingPackage(IBinder token)579     public String getCallingPackage(IBinder token) {
580         synchronized (mGlobalLock) {
581             final ActivityRecord r = getCallingRecord(token);
582             return r != null ? r.info.packageName : null;
583         }
584     }
585 
getCallingRecord(IBinder token)586     private static ActivityRecord getCallingRecord(IBinder token) {
587         final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
588         return r != null ? r.resultTo : null;
589     }
590 
591     @Override
getLaunchedFromUid(IBinder token)592     public int getLaunchedFromUid(IBinder token) {
593         if (!canGetLaunchedFrom()) {
594             return INVALID_UID;
595         }
596         synchronized (mGlobalLock) {
597             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
598             return r != null ? r.launchedFromUid : INVALID_UID;
599         }
600     }
601 
602     @Override
getLaunchedFromPackage(IBinder token)603     public String getLaunchedFromPackage(IBinder token) {
604         if (!canGetLaunchedFrom()) {
605             return null;
606         }
607         synchronized (mGlobalLock) {
608             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
609             return r != null ? r.launchedFromPackage : null;
610         }
611     }
612 
613     /** Whether the caller can get the package or uid that launched its activity. */
canGetLaunchedFrom()614     private boolean canGetLaunchedFrom() {
615         final int uid = Binder.getCallingUid();
616         if (UserHandle.getAppId(uid) == SYSTEM_UID) {
617             return true;
618         }
619         final PackageManagerInternal pm = mService.mWindowManager.mPmInternal;
620         final AndroidPackage callingPkg = pm.getPackage(uid);
621         if (callingPkg == null) {
622             return false;
623         }
624         if (callingPkg.isSignedWithPlatformKey()) {
625             return true;
626         }
627         final String[] installerNames = pm.getKnownPackageNames(
628                 PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.getUserId(uid));
629         return installerNames.length > 0 && callingPkg.getPackageName().equals(installerNames[0]);
630     }
631 
632     @Override
setRequestedOrientation(IBinder token, int requestedOrientation)633     public void setRequestedOrientation(IBinder token, int requestedOrientation) {
634         final long origId = Binder.clearCallingIdentity();
635         try {
636             synchronized (mGlobalLock) {
637                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
638                 if (r != null) {
639                     r.setRequestedOrientation(requestedOrientation);
640                 }
641             }
642         } finally {
643             Binder.restoreCallingIdentity(origId);
644         }
645     }
646 
647     @Override
getRequestedOrientation(IBinder token)648     public int getRequestedOrientation(IBinder token) {
649         synchronized (mGlobalLock) {
650             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
651             return r != null
652                     ? r.getRequestedOrientation() : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
653         }
654     }
655 
656     @Override
convertFromTranslucent(IBinder token)657     public boolean convertFromTranslucent(IBinder token) {
658         final long origId = Binder.clearCallingIdentity();
659         try {
660             synchronized (mGlobalLock) {
661                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
662                 return r != null && r.setOccludesParent(true);
663             }
664         } finally {
665             Binder.restoreCallingIdentity(origId);
666         }
667     }
668 
669     @Override
convertToTranslucent(IBinder token, Bundle options)670     public boolean convertToTranslucent(IBinder token, Bundle options) {
671         final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
672         final long origId = Binder.clearCallingIdentity();
673         try {
674             synchronized (mGlobalLock) {
675                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
676                 if (r == null) {
677                     return false;
678                 }
679                 final ActivityRecord under = r.getTask().getActivityBelow(r);
680                 if (under != null) {
681                     under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
682                 }
683                 return r.setOccludesParent(false);
684             }
685         } finally {
686             Binder.restoreCallingIdentity(origId);
687         }
688     }
689 
690     @Override
isImmersive(IBinder token)691     public boolean isImmersive(IBinder token) {
692         synchronized (mGlobalLock) {
693             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
694             if (r == null) {
695                 throw new IllegalArgumentException();
696             }
697             return r.immersive;
698         }
699     }
700 
701     @Override
setImmersive(IBinder token, boolean immersive)702     public void setImmersive(IBinder token, boolean immersive) {
703         synchronized (mGlobalLock) {
704             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
705             if (r == null) {
706                 throw new IllegalArgumentException();
707             }
708             r.immersive = immersive;
709 
710             // Update associated state if we're frontmost.
711             if (r.isFocusedActivityOnDisplay()) {
712                 ProtoLog.d(WM_DEBUG_IMMERSIVE, "Frontmost changed immersion: %s", r);
713                 mService.applyUpdateLockStateLocked(r);
714             }
715         }
716     }
717 
718     @Override
enterPictureInPictureMode(IBinder token, final PictureInPictureParams params)719     public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) {
720         final long origId = Binder.clearCallingIdentity();
721         try {
722             synchronized (mGlobalLock) {
723                 final ActivityRecord r = ensureValidPictureInPictureActivityParams(
724                         "enterPictureInPictureMode", token, params);
725                 return mService.enterPictureInPictureMode(r, params);
726             }
727         } finally {
728             Binder.restoreCallingIdentity(origId);
729         }
730     }
731 
732     @Override
setPictureInPictureParams(IBinder token, final PictureInPictureParams params)733     public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) {
734         final long origId = Binder.clearCallingIdentity();
735         try {
736             synchronized (mGlobalLock) {
737                 final ActivityRecord r = ensureValidPictureInPictureActivityParams(
738                         "setPictureInPictureParams", token, params);
739 
740                 // Only update the saved args from the args that are set.
741                 r.setPictureInPictureParams(params);
742                 if (r.inPinnedWindowingMode()) {
743                     // If the activity is already in picture-in-picture, update the pinned task now
744                     // if it is not already expanding to fullscreen. Otherwise, the arguments will
745                     // be used the next time the activity enters PiP.
746                     final Task rootTask = r.getRootTask();
747                     rootTask.setPictureInPictureAspectRatio(
748                             r.pictureInPictureArgs.getAspectRatio());
749                     rootTask.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
750                 }
751             }
752         } finally {
753             Binder.restoreCallingIdentity(origId);
754         }
755     }
756 
757     /**
758      * Splash screen view is attached to activity.
759      */
760     @Override
splashScreenAttached(IBinder token)761     public void splashScreenAttached(IBinder token) {
762         final long origId = Binder.clearCallingIdentity();
763         synchronized (mGlobalLock) {
764             ActivityRecord.splashScreenAttachedLocked(token);
765         }
766         Binder.restoreCallingIdentity(origId);
767     }
768 
769     /**
770      * Checks the state of the system and the activity associated with the given {@param token} to
771      * verify that picture-in-picture is supported for that activity.
772      *
773      * @return the activity record for the given {@param token} if all the checks pass.
774      */
ensureValidPictureInPictureActivityParams(String caller, IBinder token, PictureInPictureParams params)775     private ActivityRecord ensureValidPictureInPictureActivityParams(String caller,
776             IBinder token, PictureInPictureParams params) {
777         if (!mService.mSupportsPictureInPicture) {
778             throw new IllegalStateException(caller
779                     + ": Device doesn't support picture-in-picture mode.");
780         }
781 
782         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
783         if (r == null) {
784             throw new IllegalStateException(caller
785                     + ": Can't find activity for token=" + token);
786         }
787 
788         if (!r.supportsPictureInPicture()) {
789             throw new IllegalStateException(caller
790                     + ": Current activity does not support picture-in-picture.");
791         }
792 
793         if (params.hasSetAspectRatio()
794                 && !mService.mWindowManager.isValidPictureInPictureAspectRatio(
795                 r.mDisplayContent, params.getAspectRatio())) {
796             final float minAspectRatio = mContext.getResources().getFloat(
797                     com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
798             final float maxAspectRatio = mContext.getResources().getFloat(
799                     com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
800             throw new IllegalArgumentException(String.format(caller
801                             + ": Aspect ratio is too extreme (must be between %f and %f).",
802                     minAspectRatio, maxAspectRatio));
803         }
804 
805         // Truncate the number of actions if necessary.
806         params.truncateActions(ActivityTaskManager.getMaxNumPictureInPictureActions(mContext));
807         return r;
808     }
809 
810     /**
811      * Requests that an activity should enter picture-in-picture mode if possible. This method may
812      * be used by the implementation of non-phone form factors.
813      */
requestPictureInPictureMode(@onNull ActivityRecord r)814     void requestPictureInPictureMode(@NonNull ActivityRecord r) {
815         if (r.inPinnedWindowingMode()) {
816             throw new IllegalStateException("Activity is already in PIP mode");
817         }
818 
819         final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
820                 "requestPictureInPictureMode", /* beforeStopping */ false);
821         if (!canEnterPictureInPicture) {
822             throw new IllegalStateException(
823                     "Requested PIP on an activity that doesn't support it");
824         }
825 
826         if (r.pictureInPictureArgs.isAutoEnterEnabled()) {
827             mService.enterPictureInPictureMode(r, r.pictureInPictureArgs);
828             return;
829         }
830 
831         try {
832             final ClientTransaction transaction = ClientTransaction.obtain(
833                     r.app.getThread(), r.token);
834             transaction.addCallback(EnterPipRequestedItem.obtain());
835             mService.getLifecycleManager().scheduleTransaction(transaction);
836         } catch (Exception e) {
837             Slog.w(TAG, "Failed to send enter pip requested item: "
838                     + r.intent.getComponent(), e);
839         }
840     }
841 
842     /**
843      * Alert the client that the Picture-in-Picture state has changed.
844      */
onPictureInPictureStateChanged(@onNull ActivityRecord r, PictureInPictureUiState pipState)845     void onPictureInPictureStateChanged(@NonNull ActivityRecord r,
846             PictureInPictureUiState pipState) {
847         if (!r.inPinnedWindowingMode()) {
848             throw new IllegalStateException("Activity is not in PIP mode");
849         }
850 
851         try {
852             final ClientTransaction transaction = ClientTransaction.obtain(
853                     r.app.getThread(), r.token);
854             transaction.addCallback(PipStateTransactionItem.obtain(pipState));
855             mService.getLifecycleManager().scheduleTransaction(transaction);
856         } catch (Exception e) {
857             Slog.w(TAG, "Failed to send pip state transaction item: "
858                     + r.intent.getComponent(), e);
859         }
860     }
861 
862     @Override
toggleFreeformWindowingMode(IBinder token)863     public void toggleFreeformWindowingMode(IBinder token) {
864         final long ident = Binder.clearCallingIdentity();
865         try {
866             synchronized (mGlobalLock) {
867                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
868                 if (r == null) {
869                     throw new IllegalArgumentException(
870                             "toggleFreeformWindowingMode: No activity record matching token="
871                                     + token);
872                 }
873 
874                 final Task rootTask = r.getRootTask();
875                 if (rootTask == null) {
876                     throw new IllegalStateException("toggleFreeformWindowingMode: the activity "
877                             + "doesn't have a root task");
878                 }
879 
880                 if (!rootTask.inFreeformWindowingMode()
881                         && rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
882                     throw new IllegalStateException("toggleFreeformWindowingMode: You can only "
883                             + "toggle between fullscreen and freeform.");
884                 }
885 
886                 if (rootTask.inFreeformWindowingMode()) {
887                     rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
888                 } else if (!r.supportsFreeform()) {
889                     throw new IllegalStateException(
890                             "This activity is currently not freeform-enabled");
891                 } else if (rootTask.getParent().inFreeformWindowingMode()) {
892                     // If the window is on a freeform display, set it to undefined. It will be
893                     // resolved to freeform and it can adjust windowing mode when the display mode
894                     // changes in runtime.
895                     rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED);
896                 } else {
897                     rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
898                 }
899             }
900         } finally {
901             Binder.restoreCallingIdentity(ident);
902         }
903     }
904 
905     @Override
startLockTaskModeByToken(IBinder token)906     public void startLockTaskModeByToken(IBinder token) {
907         synchronized (mGlobalLock) {
908             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
909             if (r != null) {
910                 mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */);
911             }
912         }
913     }
914 
915     @Override
stopLockTaskModeByToken(IBinder token)916     public void stopLockTaskModeByToken(IBinder token) {
917         mService.stopLockTaskModeInternal(token, false /* isSystemCaller */);
918     }
919 
920     @Override
showLockTaskEscapeMessage(IBinder token)921     public void showLockTaskEscapeMessage(IBinder token) {
922         synchronized (mGlobalLock) {
923             if (ActivityRecord.forTokenLocked(token) != null) {
924                 mService.getLockTaskController().showLockTaskToast();
925             }
926         }
927     }
928 
929     @Override
setTaskDescription(IBinder token, ActivityManager.TaskDescription td)930     public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) {
931         synchronized (mGlobalLock) {
932             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
933             if (r != null) {
934                 r.setTaskDescription(td);
935             }
936         }
937     }
938 
939     @Override
showAssistFromActivity(IBinder token, Bundle args)940     public boolean showAssistFromActivity(IBinder token, Bundle args) {
941         final long ident = Binder.clearCallingIdentity();
942         try {
943             synchronized (mGlobalLock) {
944                 final ActivityRecord caller = ActivityRecord.forTokenLocked(token);
945                 final Task topRootTask = mService.getTopDisplayFocusedRootTask();
946                 final ActivityRecord top = topRootTask != null
947                         ? topRootTask.getTopNonFinishingActivity() : null;
948                 if (top != caller) {
949                     Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
950                             + " is not current top " + top);
951                     return false;
952                 }
953                 if (!top.nowVisible) {
954                     Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
955                             + " is not visible");
956                     return false;
957                 }
958             }
959             return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION,
960                     null /* showCallback */, token);
961         } finally {
962             Binder.restoreCallingIdentity(ident);
963         }
964     }
965 
966     @Override
isRootVoiceInteraction(IBinder token)967     public boolean isRootVoiceInteraction(IBinder token) {
968         synchronized (mGlobalLock) {
969             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
970             return r != null && r.rootVoiceInteraction;
971         }
972     }
973 
974     @Override
startLocalVoiceInteraction(IBinder callingActivity, Bundle options)975     public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
976         Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
977         synchronized (mGlobalLock) {
978             final Task topRootTask = mService.getTopDisplayFocusedRootTask();
979             final ActivityRecord activity = topRootTask != null
980                     ? topRootTask.getTopNonFinishingActivity() : null;
981             if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
982                 throw new SecurityException("Only focused activity can call startVoiceInteraction");
983             }
984             if (mService.mRunningVoice != null || activity.getTask().voiceSession != null
985                     || activity.voiceSession != null) {
986                 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
987                 return;
988             }
989             if (activity.pendingVoiceInteractionStart) {
990                 Slog.w(TAG, "Pending start of voice interaction already.");
991                 return;
992             }
993             activity.pendingVoiceInteractionStart = true;
994         }
995         LocalServices.getService(VoiceInteractionManagerInternal.class)
996                 .startLocalVoiceInteraction(callingActivity, options);
997     }
998 
999     @Override
stopLocalVoiceInteraction(IBinder callingActivity)1000     public void stopLocalVoiceInteraction(IBinder callingActivity) {
1001         LocalServices.getService(VoiceInteractionManagerInternal.class)
1002                 .stopLocalVoiceInteraction(callingActivity);
1003     }
1004 
1005     @Override
setShowWhenLocked(IBinder token, boolean showWhenLocked)1006     public void setShowWhenLocked(IBinder token, boolean showWhenLocked) {
1007         final long origId = Binder.clearCallingIdentity();
1008         try {
1009             synchronized (mGlobalLock) {
1010                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1011                 if (r != null) {
1012                     r.setShowWhenLocked(showWhenLocked);
1013                 }
1014             }
1015         } finally {
1016             Binder.restoreCallingIdentity(origId);
1017         }
1018     }
1019 
1020     @Override
setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked)1021     public void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) {
1022         final long origId = Binder.clearCallingIdentity();
1023         try {
1024             synchronized (mGlobalLock) {
1025                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1026                 if (r != null) {
1027                     r.setInheritShowWhenLocked(inheritShowWhenLocked);
1028                 }
1029             }
1030         } finally {
1031             Binder.restoreCallingIdentity(origId);
1032         }
1033     }
1034 
1035     @Override
setTurnScreenOn(IBinder token, boolean turnScreenOn)1036     public void setTurnScreenOn(IBinder token, boolean turnScreenOn) {
1037         final long origId = Binder.clearCallingIdentity();
1038         try {
1039             synchronized (mGlobalLock) {
1040                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1041                 if (r != null) {
1042                     r.setTurnScreenOn(turnScreenOn);
1043                 }
1044             }
1045         } finally {
1046             Binder.restoreCallingIdentity(origId);
1047         }
1048     }
1049 
1050     @Override
reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle)1051     public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) {
1052         final long origId = Binder.clearCallingIdentity();
1053         try {
1054             synchronized (mGlobalLock) {
1055                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1056                 if (r != null) {
1057                     r.reportFullyDrawnLocked(restoredFromBundle);
1058                 }
1059             }
1060         } finally {
1061             Binder.restoreCallingIdentity(origId);
1062         }
1063     }
1064 
1065     @Override
overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim)1066     public void overridePendingTransition(IBinder token, String packageName,
1067             int enterAnim, int exitAnim) {
1068         final long origId = Binder.clearCallingIdentity();
1069         synchronized (mGlobalLock) {
1070             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1071             if (r != null && r.isState(RESUMED, PAUSING)) {
1072                 r.mDisplayContent.mAppTransition.overridePendingAppTransition(
1073                         packageName, enterAnim, exitAnim, null, null,
1074                         r.mOverrideTaskTransition);
1075                 r.mTransitionController.setOverrideAnimation(
1076                         TransitionInfo.AnimationOptions.makeCustomAnimOptions(packageName,
1077                                 enterAnim, exitAnim, r.mOverrideTaskTransition),
1078                         null /* startCallback */, null /* finishCallback */);
1079             }
1080         }
1081         Binder.restoreCallingIdentity(origId);
1082     }
1083 
1084     @Override
setVrMode(IBinder token, boolean enabled, ComponentName packageName)1085     public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
1086         mService.enforceSystemHasVrFeature();
1087 
1088         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
1089         final ActivityRecord r;
1090         synchronized (mGlobalLock) {
1091             r = ActivityRecord.isInRootTaskLocked(token);
1092         }
1093         if (r == null) {
1094             throw new IllegalArgumentException();
1095         }
1096 
1097         final int err;
1098         if ((err = vrService.hasVrPackage(packageName, r.mUserId)) != VrManagerInternal.NO_ERROR) {
1099             return err;
1100         }
1101 
1102         // Clear the binder calling uid since this path may call moveToTask().
1103         final long callingId = Binder.clearCallingIdentity();
1104         try {
1105             synchronized (mGlobalLock) {
1106                 r.requestedVrComponent = (enabled) ? packageName : null;
1107 
1108                 // Update associated state if this activity is currently focused.
1109                 if (r.isFocusedActivityOnDisplay()) {
1110                     mService.applyUpdateVrModeLocked(r);
1111                 }
1112                 return 0;
1113             }
1114         } finally {
1115             Binder.restoreCallingIdentity(callingId);
1116         }
1117     }
1118 
1119     @Override
setDisablePreviewScreenshots(IBinder token, boolean disable)1120     public void setDisablePreviewScreenshots(IBinder token, boolean disable) {
1121         final long origId = Binder.clearCallingIdentity();
1122         try {
1123             synchronized (mGlobalLock) {
1124                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1125                 if (r != null) {
1126                     r.setDisablePreviewScreenshots(disable);
1127                 }
1128             }
1129         } finally {
1130             Binder.restoreCallingIdentity(origId);
1131         }
1132     }
1133 
restartActivityProcessIfVisible(IBinder token)1134     void restartActivityProcessIfVisible(IBinder token) {
1135         ActivityTaskManagerService.enforceTaskPermission("restartActivityProcess");
1136         final long callingId = Binder.clearCallingIdentity();
1137         try {
1138             synchronized (mGlobalLock) {
1139                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1140                 if (r != null) {
1141                     r.restartProcessIfVisible();
1142                 }
1143             }
1144         } finally {
1145             Binder.restoreCallingIdentity(callingId);
1146         }
1147     }
1148 
1149     @Override
invalidateHomeTaskSnapshot(IBinder token)1150     public void invalidateHomeTaskSnapshot(IBinder token) {
1151         synchronized (mGlobalLock) {
1152             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1153             if (r != null && r.isActivityTypeHome()) {
1154                 mService.mWindowManager.mTaskSnapshotController.removeSnapshotCache(
1155                         r.getTask().mTaskId);
1156             }
1157         }
1158     }
1159 
1160     @Override
dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)1161     public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
1162             CharSequence message) {
1163         if (message != null) {
1164             mService.mAmInternal.enforceCallingPermission(
1165                     android.Manifest.permission.SHOW_KEYGUARD_MESSAGE, "dismissKeyguard");
1166         }
1167         final long callingId = Binder.clearCallingIdentity();
1168         try {
1169             synchronized (mGlobalLock) {
1170                 mService.mKeyguardController.dismissKeyguard(token, callback, message);
1171             }
1172         } finally {
1173             Binder.restoreCallingIdentity(callingId);
1174         }
1175     }
1176 
1177     @Override
registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition)1178     public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
1179         mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
1180                 "registerRemoteAnimations");
1181         definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
1182         final long origId = Binder.clearCallingIdentity();
1183         try {
1184             synchronized (mGlobalLock) {
1185                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1186                 if (r != null) {
1187                     r.registerRemoteAnimations(definition);
1188                 }
1189             }
1190         } finally {
1191             Binder.restoreCallingIdentity(origId);
1192         }
1193     }
1194 
1195     @Override
unregisterRemoteAnimations(IBinder token)1196     public void unregisterRemoteAnimations(IBinder token) {
1197         mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
1198                 "unregisterRemoteAnimations");
1199         final long origId = Binder.clearCallingIdentity();
1200         try {
1201             synchronized (mGlobalLock) {
1202                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1203                 if (r != null) {
1204                     r.unregisterRemoteAnimations();
1205                 }
1206             }
1207         } finally {
1208             Binder.restoreCallingIdentity(origId);
1209         }
1210     }
1211 
1212     @Override
onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback)1213     public void onBackPressedOnTaskRoot(IBinder token, IRequestFinishCallback callback) {
1214         final long origId = Binder.clearCallingIdentity();
1215         try {
1216             final Intent baseActivityIntent;
1217             final boolean launchedFromHome;
1218             final boolean isLastRunningActivity;
1219             synchronized (mGlobalLock) {
1220                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1221                 if (r == null) return;
1222 
1223                 if (mService.mWindowOrganizerController.mTaskOrganizerController
1224                         .handleInterceptBackPressedOnTaskRoot(r.getRootTask())) {
1225                     // This task is handled by a task organizer that has requested the back pressed
1226                     // callback.
1227                     return;
1228                 }
1229 
1230                 final Task task = r.getTask();
1231                 isLastRunningActivity = task.topRunningActivity() == r;
1232 
1233                 final boolean isBaseActivity = r.mActivityComponent.equals(task.realActivity);
1234                 baseActivityIntent = isBaseActivity ? r.intent : null;
1235 
1236                 launchedFromHome = r.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
1237             }
1238 
1239             // If the activity is one of the main entry points for the application, then we should
1240             // refrain from finishing the activity and instead move it to the back to keep it in
1241             // memory. The requirements for this are:
1242             //   1. The activity is the last running activity in the task.
1243             //   2. The current activity is the base activity for the task.
1244             //   3. a. If the activity was launched by the home process, we trust that its intent
1245             //         was resolved, so we check if the it is a main intent for the application.
1246             //      b. Otherwise, we query Package Manager to verify whether the activity is a
1247             //         launcher activity for the application.
1248             if (baseActivityIntent != null && isLastRunningActivity
1249                     && ((launchedFromHome && ActivityRecord.isMainIntent(baseActivityIntent))
1250                         || isLauncherActivity(baseActivityIntent.getComponent()))) {
1251                 moveActivityTaskToBack(token, false /* nonRoot */);
1252                 return;
1253             }
1254 
1255             // The default option for handling the back button is to finish the Activity.
1256             try {
1257                 callback.requestFinish();
1258             } catch (RemoteException e) {
1259                 Slog.e(TAG, "Failed to invoke request finish callback", e);
1260             }
1261         } finally {
1262             Binder.restoreCallingIdentity(origId);
1263         }
1264     }
1265 
1266     /**
1267      * Queries PackageManager to see if the given activity is one of the main entry point for the
1268      * application. This should not be called with the WM lock held.
1269      */
1270     @SuppressWarnings("unchecked")
isLauncherActivity(@onNull ComponentName activity)1271     private boolean isLauncherActivity(@NonNull ComponentName activity) {
1272         final Intent queryIntent = new Intent(Intent.ACTION_MAIN);
1273         queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
1274         queryIntent.setPackage(activity.getPackageName());
1275         try {
1276             final ParceledListSlice<ResolveInfo> resolved =
1277                     mService.getPackageManager().queryIntentActivities(
1278                             queryIntent, null, 0, mContext.getUserId());
1279             if (resolved == null) return false;
1280             for (final ResolveInfo ri : resolved.getList()) {
1281                 if (ri.getComponentInfo().getComponentName().equals(activity)) {
1282                     return true;
1283                 }
1284             }
1285         } catch (RemoteException e) {
1286             Slog.e(TAG, "Failed to query intent activities", e);
1287         }
1288         return false;
1289     }
1290 }
1291