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.Activity.FULLSCREEN_MODE_REQUEST_ENTER;
21 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
22 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
23 import static android.app.ActivityTaskManager.INVALID_WINDOWING_MODE;
24 import static android.app.FullscreenRequestHandler.REMOTE_CALLBACK_RESULT_KEY;
25 import static android.app.FullscreenRequestHandler.RESULT_APPROVED;
26 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_DEFAULT_FREEFORM;
27 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_IN_FREEFORM;
28 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY;
29 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_TOP_FOCUSED;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
31 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
32 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
33 import static android.os.Process.INVALID_UID;
34 import static android.os.Process.SYSTEM_UID;
35 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
36 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
37 import static android.view.Display.DEFAULT_DISPLAY;
38 import static android.view.Display.INVALID_DISPLAY;
39 import static android.view.WindowManager.TRANSIT_CHANGE;
40 import static android.view.WindowManager.TRANSIT_TO_BACK;
41 import static android.view.WindowManager.TRANSIT_TO_FRONT;
42 
43 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
44 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IMMERSIVE;
45 import static com.android.server.wm.ActivityRecord.State.DESTROYED;
46 import static com.android.server.wm.ActivityRecord.State.DESTROYING;
47 import static com.android.server.wm.ActivityRecord.State.PAUSING;
48 import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
49 import static com.android.server.wm.ActivityRecord.State.RESUMED;
50 import static com.android.server.wm.ActivityRecord.State.STOPPING;
51 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
52 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
53 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
54 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
55 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
56 import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
57 import static com.android.server.wm.ActivityTaskManagerService.enforceNotIsolatedCaller;
58 
59 import android.Manifest;
60 import android.annotation.ColorInt;
61 import android.annotation.NonNull;
62 import android.annotation.Nullable;
63 import android.app.Activity;
64 import android.app.ActivityManager;
65 import android.app.ActivityTaskManager;
66 import android.app.FullscreenRequestHandler;
67 import android.app.IActivityClientController;
68 import android.app.ICompatCameraControlCallback;
69 import android.app.IRequestFinishCallback;
70 import android.app.PictureInPictureParams;
71 import android.app.PictureInPictureUiState;
72 import android.app.compat.CompatChanges;
73 import android.app.servertransaction.ClientTransaction;
74 import android.app.servertransaction.EnterPipRequestedItem;
75 import android.app.servertransaction.PipStateTransactionItem;
76 import android.compat.annotation.ChangeId;
77 import android.content.ComponentName;
78 import android.content.Context;
79 import android.content.Intent;
80 import android.content.pm.ActivityInfo;
81 import android.content.pm.PackageManagerInternal;
82 import android.content.res.Configuration;
83 import android.os.Binder;
84 import android.os.Bundle;
85 import android.os.IBinder;
86 import android.os.IRemoteCallback;
87 import android.os.Parcel;
88 import android.os.PersistableBundle;
89 import android.os.RemoteException;
90 import android.os.SystemClock;
91 import android.os.Trace;
92 import android.os.UserHandle;
93 import android.service.voice.VoiceInteractionManagerInternal;
94 import android.util.Slog;
95 import android.view.RemoteAnimationDefinition;
96 import android.window.SizeConfigurationBuckets;
97 import android.window.TransitionInfo;
98 
99 import com.android.internal.app.AssistUtils;
100 import com.android.internal.policy.IKeyguardDismissCallback;
101 import com.android.internal.protolog.common.ProtoLog;
102 import com.android.server.LocalServices;
103 import com.android.server.Watchdog;
104 import com.android.server.pm.KnownPackages;
105 import com.android.server.pm.pkg.AndroidPackage;
106 import com.android.server.uri.NeededUriGrants;
107 import com.android.server.vr.VrManagerInternal;
108 
109 /**
110  * Server side implementation for the client activity to interact with system.
111  *
112  * @see android.app.ActivityClient
113  */
114 class ActivityClientController extends IActivityClientController.Stub {
115     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityClientController" : TAG_ATM;
116 
117     private final ActivityTaskManagerService mService;
118     private final WindowManagerGlobalLock mGlobalLock;
119     private final ActivityTaskSupervisor mTaskSupervisor;
120     private final Context mContext;
121 
122     /** Wrapper around VoiceInteractionServiceManager. */
123     private AssistUtils mAssistUtils;
124 
125     /**
126      * Grants access to the launching app's identity if the app opted-in to sharing its identity
127      * by launching this activity with an instance of {@link android.app.ActivityOptions} on which
128      * {@link android.app.ActivityOptions#setShareIdentityEnabled(boolean)} was invoked with a
129      * value of {@code true}, or if the launched activity's uid is the same as the launching
130      * app's. When this change is enabled and one of these requirements is met, the activity
131      * can access the launching app's uid and package name with {@link
132      * android.app.Activity#getLaunchedFromUid()} and {@link
133      * android.app.Activity#getLaunchedFromPackage()}, respectively.
134      */
135     @ChangeId
136     public static final long ACCESS_SHARED_IDENTITY = 259743961L;
137 
ActivityClientController(ActivityTaskManagerService service)138     ActivityClientController(ActivityTaskManagerService service) {
139         mService = service;
140         mGlobalLock = service.mGlobalLock;
141         mTaskSupervisor = service.mTaskSupervisor;
142         mContext = service.mContext;
143     }
144 
onSystemReady()145     void onSystemReady() {
146         mAssistUtils = new AssistUtils(mContext);
147     }
148 
149     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)150     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
151             throws RemoteException {
152         try {
153             return super.onTransact(code, data, reply, flags);
154         } catch (RuntimeException e) {
155             throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(
156                     "ActivityClientController", e);
157         }
158     }
159 
160     @Override
activityIdle(IBinder token, Configuration config, boolean stopProfiling)161     public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
162         final long origId = Binder.clearCallingIdentity();
163         try {
164             synchronized (mGlobalLock) {
165                 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
166                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
167                 if (r == null) {
168                     return;
169                 }
170                 mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */,
171                         false /* processPausingActivities */, config);
172                 if (stopProfiling && r.hasProcess()) {
173                     r.app.clearProfilerIfNeeded();
174                 }
175             }
176         } finally {
177             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
178             Binder.restoreCallingIdentity(origId);
179         }
180     }
181 
182     @Override
activityResumed(IBinder token, boolean handleSplashScreenExit)183     public void activityResumed(IBinder token, boolean handleSplashScreenExit) {
184         final long origId = Binder.clearCallingIdentity();
185         synchronized (mGlobalLock) {
186             ActivityRecord.activityResumedLocked(token, handleSplashScreenExit);
187         }
188         Binder.restoreCallingIdentity(origId);
189     }
190 
191     @Override
activityRefreshed(IBinder token)192     public void activityRefreshed(IBinder token) {
193         final long origId = Binder.clearCallingIdentity();
194         synchronized (mGlobalLock) {
195             ActivityRecord.activityRefreshedLocked(token);
196         }
197         Binder.restoreCallingIdentity(origId);
198     }
199 
200     @Override
activityTopResumedStateLost()201     public void activityTopResumedStateLost() {
202         final long origId = Binder.clearCallingIdentity();
203         synchronized (mGlobalLock) {
204             mTaskSupervisor.handleTopResumedStateReleased(false /* timeout */);
205         }
206         Binder.restoreCallingIdentity(origId);
207     }
208 
209     @Override
activityPaused(IBinder token)210     public void activityPaused(IBinder token) {
211         final long origId = Binder.clearCallingIdentity();
212         synchronized (mGlobalLock) {
213             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused");
214             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
215             if (r != null) {
216                 r.activityPaused(false);
217             }
218             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
219         }
220         Binder.restoreCallingIdentity(origId);
221     }
222 
223     @Override
activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState, CharSequence description)224     public void activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState,
225             CharSequence description) {
226         if (DEBUG_ALL) Slog.v(TAG, "Activity stopped: token=" + token);
227 
228         // Refuse possible leaked file descriptors.
229         if (icicle != null && icicle.hasFileDescriptors()) {
230             throw new IllegalArgumentException("File descriptors passed in Bundle");
231         }
232 
233         final long origId = Binder.clearCallingIdentity();
234 
235         String restartingName = null;
236         int restartingUid = 0;
237         final ActivityRecord r;
238         synchronized (mGlobalLock) {
239             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped");
240             r = ActivityRecord.isInRootTaskLocked(token);
241             if (r != null) {
242                 if (!r.isState(STOPPING, RESTARTING_PROCESS)
243                         && mTaskSupervisor.hasScheduledRestartTimeouts(r)) {
244                     // Recover the restarting state which was replaced by other lifecycle changes.
245                     r.setState(RESTARTING_PROCESS, "continue-restart");
246                 }
247                 if (r.attachedToProcess() && r.isState(RESTARTING_PROCESS)) {
248                     // The activity was requested to restart from
249                     // {@link #restartActivityProcessIfVisible}.
250                     restartingName = r.app.mName;
251                     restartingUid = r.app.mUid;
252                 }
253                 r.activityStopped(icicle, persistentState, description);
254             }
255             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
256         }
257 
258         if (restartingName != null) {
259             // In order to let the foreground activity can be restarted with its saved state from
260             // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed
261             // until the activity reports stopped with the state. And the activity record will be
262             // kept because the record state is restarting, then the activity will be restarted
263             // immediately if it is still the top one.
264             mTaskSupervisor.removeRestartTimeouts(r);
265             mService.mAmInternal.killProcess(restartingName, restartingUid,
266                     "restartActivityProcess");
267         }
268         mService.mAmInternal.trimApplications();
269 
270         Binder.restoreCallingIdentity(origId);
271     }
272 
273     @Override
activityDestroyed(IBinder token)274     public void activityDestroyed(IBinder token) {
275         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
276         final long origId = Binder.clearCallingIdentity();
277         synchronized (mGlobalLock) {
278             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed");
279             try {
280                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
281                 if (r != null) {
282                     r.destroyed("activityDestroyed");
283                 }
284             } finally {
285                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
286                 Binder.restoreCallingIdentity(origId);
287             }
288         }
289     }
290 
291     @Override
activityLocalRelaunch(IBinder token)292     public void activityLocalRelaunch(IBinder token) {
293         final long origId = Binder.clearCallingIdentity();
294         synchronized (mGlobalLock) {
295             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
296             if (r != null) {
297                 r.startRelaunching();
298             }
299         }
300         Binder.restoreCallingIdentity(origId);
301     }
302 
303     @Override
activityRelaunched(IBinder token)304     public void activityRelaunched(IBinder token) {
305         final long origId = Binder.clearCallingIdentity();
306         synchronized (mGlobalLock) {
307             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
308             if (r != null) {
309                 r.finishRelaunching();
310             }
311         }
312         Binder.restoreCallingIdentity(origId);
313     }
314 
315     @Override
reportSizeConfigurations(IBinder token, SizeConfigurationBuckets sizeConfigurations)316     public void reportSizeConfigurations(IBinder token,
317             SizeConfigurationBuckets sizeConfigurations) {
318         ProtoLog.v(WM_DEBUG_CONFIGURATION, "Report configuration: %s %s",
319                 token, sizeConfigurations);
320         synchronized (mGlobalLock) {
321             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
322             if (r != null) {
323                 r.setSizeConfigurations(sizeConfigurations);
324             }
325         }
326     }
327 
328     /**
329      * Attempts to move a task backwards in z-order (the order of activities within the task is
330      * unchanged).
331      *
332      * There are several possible results of this call:
333      * - if the task is locked, then we will show the lock toast.
334      * - if there is a task behind the provided task, then that task is made visible and resumed as
335      * this task is moved to the back.
336      * - otherwise, if there are no other tasks in the root task:
337      * - if this task is in the pinned mode, then we remove the task completely, which will
338      * have the effect of moving the task to the top or bottom of the fullscreen root task
339      * (depending on whether it is visible).
340      * - otherwise, we simply return home and hide this task.
341      *
342      * @param token   A reference to the activity we wish to move.
343      * @param nonRoot If false then this only works if the activity is the root
344      *                of a task; if true it will work for any activity in a task.
345      * @return Returns true if the move completed, false if not.
346      */
347     @Override
moveActivityTaskToBack(IBinder token, boolean nonRoot)348     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
349         enforceNotIsolatedCaller("moveActivityTaskToBack");
350         final long origId = Binder.clearCallingIdentity();
351         try {
352             synchronized (mGlobalLock) {
353                 final int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
354                 final Task task = mService.mRootWindowContainer.anyTaskForId(taskId);
355                 if (task != null) {
356                     return ActivityRecord.getRootTask(token).moveTaskToBack(task);
357                 }
358             }
359         } finally {
360             Binder.restoreCallingIdentity(origId);
361         }
362         return false;
363     }
364 
365     @Override
shouldUpRecreateTask(IBinder token, String destAffinity)366     public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
367         synchronized (mGlobalLock) {
368             final ActivityRecord srec = ActivityRecord.forTokenLocked(token);
369             if (srec != null) {
370                 return srec.getRootTask().shouldUpRecreateTaskLocked(srec, destAffinity);
371             }
372         }
373         return false;
374     }
375 
376     @Override
navigateUpTo(IBinder token, Intent destIntent, String resolvedType, int resultCode, Intent resultData)377     public boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType,
378             int resultCode, Intent resultData) {
379         final ActivityRecord r;
380         synchronized (mGlobalLock) {
381             r = ActivityRecord.isInRootTaskLocked(token);
382             if (r == null) {
383                 return false;
384             }
385         }
386 
387         // Carefully collect grants without holding lock.
388         final NeededUriGrants destGrants = mService.collectGrants(destIntent, r);
389         final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo);
390 
391         synchronized (mGlobalLock) {
392             return r.getRootTask().navigateUpTo(
393                     r, destIntent, resolvedType, destGrants, resultCode, resultData, resultGrants);
394         }
395     }
396 
397     @Override
releaseActivityInstance(IBinder token)398     public boolean releaseActivityInstance(IBinder token) {
399         final long origId = Binder.clearCallingIdentity();
400         try {
401             synchronized (mGlobalLock) {
402                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
403                 if (r == null || !r.isDestroyable()) {
404                     return false;
405                 }
406                 r.destroyImmediately("app-req");
407                 return r.isState(DESTROYING, DESTROYED);
408             }
409         } finally {
410             Binder.restoreCallingIdentity(origId);
411         }
412     }
413 
414     /**
415      * This is the internal entry point for handling Activity.finish().
416      *
417      * @param token      The Binder token referencing the Activity we want to finish.
418      * @param resultCode Result code, if any, from this Activity.
419      * @param resultData Result data (Intent), if any, from this Activity.
420      * @param finishTask Whether to finish the task associated with this Activity.
421      * @return Returns true if the activity successfully finished, or false if it is still running.
422      */
423     @Override
finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask)424     public boolean finishActivity(IBinder token, int resultCode, Intent resultData,
425             int finishTask) {
426         // Refuse possible leaked file descriptors.
427         if (resultData != null && resultData.hasFileDescriptors()) {
428             throw new IllegalArgumentException("File descriptors passed in Intent");
429         }
430 
431         final ActivityRecord r;
432         synchronized (mGlobalLock) {
433             r = ActivityRecord.isInRootTaskLocked(token);
434             if (r == null) {
435                 return true;
436             }
437         }
438 
439         // Carefully collect grants without holding lock.
440         final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo);
441 
442         synchronized (mGlobalLock) {
443             // Check again in case activity was removed when collecting grants.
444             if (!r.isInHistory()) {
445                 return true;
446             }
447 
448             // Keep track of the root activity of the task before we finish it.
449             final Task tr = r.getTask();
450             final ActivityRecord rootR = tr.getRootActivity();
451             if (rootR == null) {
452                 Slog.w(TAG, "Finishing task with all activities already finished");
453             }
454             // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
455             // finish.
456             if (mService.getLockTaskController().activityBlockedFromFinish(r)) {
457                 return false;
458             }
459 
460             // TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked
461             // We should consolidate.
462             if (mService.mController != null) {
463                 // Find the first activity that is not finishing.
464                 final ActivityRecord next =
465                         r.getRootTask().topRunningActivity(token, INVALID_TASK_ID);
466                 if (next != null) {
467                     // ask watcher if this is allowed
468                     boolean resumeOK = true;
469                     try {
470                         resumeOK = mService.mController.activityResuming(next.packageName);
471                     } catch (RemoteException e) {
472                         mService.mController = null;
473                         Watchdog.getInstance().setActivityController(null);
474                     }
475 
476                     if (!resumeOK) {
477                         Slog.i(TAG, "Not finishing activity because controller resumed");
478                         return false;
479                     }
480                 }
481             }
482 
483             // Note down that the process has finished an activity and is in background activity
484             // starts grace period.
485             if (r.app != null) {
486                 r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());
487             }
488 
489             final long origId = Binder.clearCallingIdentity();
490             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity");
491             try {
492                 final boolean res;
493                 final boolean finishWithRootActivity =
494                         finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
495                 if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
496                         || (finishWithRootActivity && r == rootR)) {
497                     // If requested, remove the task that is associated to this activity only if it
498                     // was the root activity in the task. The result code and data is ignored
499                     // because we don't support returning them across task boundaries. Also, to
500                     // keep backwards compatibility we remove the task from recents when finishing
501                     // task with root activity.
502                     mTaskSupervisor.removeTask(tr, false /*killProcess*/,
503                             finishWithRootActivity, "finish-activity", r.getUid(), r.info.name);
504                     res = true;
505                     // Explicitly dismissing the activity so reset its relaunch flag.
506                     r.mRelaunchReason = RELAUNCH_REASON_NONE;
507                 } else {
508                     r.finishIfPossible(resultCode, resultData, resultGrants, "app-request",
509                             true /* oomAdj */);
510                     res = r.finishing;
511                     if (!res) {
512                         Slog.i(TAG, "Failed to finish by app-request");
513                     }
514                 }
515                 return res;
516             } finally {
517                 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
518                 Binder.restoreCallingIdentity(origId);
519             }
520         }
521     }
522 
523     @Override
finishActivityAffinity(IBinder token)524     public boolean finishActivityAffinity(IBinder token) {
525         final long origId = Binder.clearCallingIdentity();
526         try {
527             synchronized (mGlobalLock) {
528                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
529                 if (r == null) {
530                     return false;
531                 }
532 
533                 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
534                 // can finish.
535                 if (mService.getLockTaskController().activityBlockedFromFinish(r)) {
536                     return false;
537                 }
538 
539                 r.getTask().forAllActivities(activity -> r.finishIfSameAffinity(activity),
540                         r /* boundary */, true /* includeBoundary */,
541                         true /* traverseTopToBottom */);
542                 return true;
543             }
544         } finally {
545             Binder.restoreCallingIdentity(origId);
546         }
547     }
548 
549     @Override
finishSubActivity(IBinder token, String resultWho, int requestCode)550     public void finishSubActivity(IBinder token, String resultWho, int requestCode) {
551         final long origId = Binder.clearCallingIdentity();
552         try {
553             synchronized (mGlobalLock) {
554                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
555                 if (r == null) return;
556 
557                 // TODO: This should probably only loop over the task since you need to be in the
558                 // same task to return results.
559                 r.getRootTask().forAllActivities(activity -> {
560                     activity.finishIfSubActivity(r /* parent */, resultWho, requestCode);
561                 }, true /* traverseTopToBottom */);
562 
563                 mService.updateOomAdj();
564             }
565         } finally {
566             Binder.restoreCallingIdentity(origId);
567         }
568     }
569 
570     @Override
setForceSendResultForMediaProjection(IBinder token)571     public void setForceSendResultForMediaProjection(IBinder token) {
572         // Require that this is invoked only during MediaProjection setup.
573         mService.mAmInternal.enforceCallingPermission(
574                 Manifest.permission.MANAGE_MEDIA_PROJECTION,
575                 "setForceSendResultForMediaProjection");
576 
577         final ActivityRecord r;
578         synchronized (mGlobalLock) {
579             r = ActivityRecord.isInRootTaskLocked(token);
580             if (r == null || !r.isInHistory()) {
581                 return;
582             }
583             r.setForceSendResultForMediaProjection();
584         }
585     }
586 
587     @Override
isTopOfTask(IBinder token)588     public boolean isTopOfTask(IBinder token) {
589         synchronized (mGlobalLock) {
590             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
591             return r != null && r.getTask().getTopNonFinishingActivity() == r;
592         }
593     }
594 
595     @Override
willActivityBeVisible(IBinder token)596     public boolean willActivityBeVisible(IBinder token) {
597         synchronized (mGlobalLock) {
598             final Task rootTask = ActivityRecord.getRootTask(token);
599             return rootTask != null && rootTask.willActivityBeVisible(token);
600         }
601     }
602 
603     @Override
getDisplayId(IBinder activityToken)604     public int getDisplayId(IBinder activityToken) {
605         synchronized (mGlobalLock) {
606             final Task rootTask = ActivityRecord.getRootTask(activityToken);
607             if (rootTask != null) {
608                 final int displayId = rootTask.getDisplayId();
609                 return displayId != INVALID_DISPLAY ? displayId : DEFAULT_DISPLAY;
610             }
611             return DEFAULT_DISPLAY;
612         }
613     }
614 
615     @Override
getTaskForActivity(IBinder token, boolean onlyRoot)616     public int getTaskForActivity(IBinder token, boolean onlyRoot) {
617         synchronized (mGlobalLock) {
618             return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
619         }
620     }
621 
622     /**
623      * Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
624      * the task {@link Configuration} cannot be obtained.
625      */
626     @Override
627     @Nullable
getTaskConfiguration(IBinder activityToken)628     public Configuration getTaskConfiguration(IBinder activityToken) {
629         synchronized (mGlobalLock) {
630             final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken);
631             if (ar == null) {
632                 return null;
633             }
634             return ar.getTask().getConfiguration();
635         }
636     }
637 
638     @Override
639     @Nullable
getActivityTokenBelow(IBinder activityToken)640     public IBinder getActivityTokenBelow(IBinder activityToken) {
641         final long ident = Binder.clearCallingIdentity();
642         try {
643             synchronized (mGlobalLock) {
644                 final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken);
645                 if (ar == null) {
646                     return null;
647                 }
648                 // Exclude finishing activity.
649                 final ActivityRecord below = ar.getTask().getActivity((r) -> !r.finishing,
650                         ar, false /*includeBoundary*/, true /*traverseTopToBottom*/);
651                 if (below != null && below.getUid() == ar.getUid()) {
652                     return below.token;
653                 }
654             }
655         } finally {
656             Binder.restoreCallingIdentity(ident);
657         }
658         return null;
659     }
660 
661     @Override
getCallingActivity(IBinder token)662     public ComponentName getCallingActivity(IBinder token) {
663         synchronized (mGlobalLock) {
664             final ActivityRecord r = getCallingRecord(token);
665             return r != null ? r.intent.getComponent() : null;
666         }
667     }
668 
669     @Override
getCallingPackage(IBinder token)670     public String getCallingPackage(IBinder token) {
671         synchronized (mGlobalLock) {
672             final ActivityRecord r = getCallingRecord(token);
673             return r != null ? r.info.packageName : null;
674         }
675     }
676 
getCallingRecord(IBinder token)677     private static ActivityRecord getCallingRecord(IBinder token) {
678         final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
679         return r != null ? r.resultTo : null;
680     }
681 
682     @Override
getLaunchedFromUid(IBinder token)683     public int getLaunchedFromUid(IBinder token) {
684         final int uid = Binder.getCallingUid();
685         final boolean isInternalCaller = isInternalCallerGetLaunchedFrom(uid);
686         synchronized (mGlobalLock) {
687             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
688             if (r != null && (isInternalCaller || canGetLaunchedFromLocked(uid, r))) {
689                 return r.launchedFromUid;
690             }
691         }
692         return INVALID_UID;
693     }
694 
695     @Override
getLaunchedFromPackage(IBinder token)696     public String getLaunchedFromPackage(IBinder token) {
697         final int uid = Binder.getCallingUid();
698         final boolean isInternalCaller = isInternalCallerGetLaunchedFrom(uid);
699         synchronized (mGlobalLock) {
700             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
701             if (r != null && (isInternalCaller || canGetLaunchedFromLocked(uid, r))) {
702                 return r.launchedFromPackage;
703             }
704         }
705         return null;
706     }
707 
708     /** Whether the call to one of the getLaunchedFrom APIs is performed by an internal caller. */
isInternalCallerGetLaunchedFrom(int uid)709     private boolean isInternalCallerGetLaunchedFrom(int uid) {
710         if (UserHandle.getAppId(uid) == SYSTEM_UID) {
711             return true;
712         }
713         final PackageManagerInternal pm = mService.mWindowManager.mPmInternal;
714         final AndroidPackage callingPkg = pm.getPackage(uid);
715         if (callingPkg == null) {
716             return false;
717         }
718         if (callingPkg.isSignedWithPlatformKey()) {
719             return true;
720         }
721         final String[] installerNames = pm.getKnownPackageNames(
722                 KnownPackages.PACKAGE_INSTALLER, UserHandle.getUserId(uid));
723         return installerNames.length > 0 && callingPkg.getPackageName().equals(installerNames[0]);
724     }
725 
726     /**
727      * Returns whether the specified {@code uid} can access the launching app's identity by
728      * verifying whether the provided {@code ActivityRecord r} has opted in to sharing its
729      * identity or if the uid of the activity matches that of the launching app.
730      */
canGetLaunchedFromLocked(int uid, ActivityRecord r)731     private static boolean canGetLaunchedFromLocked(int uid, ActivityRecord r) {
732         if (CompatChanges.isChangeEnabled(ACCESS_SHARED_IDENTITY, uid)) {
733             return r.mShareIdentity || r.launchedFromUid == uid;
734         }
735         return false;
736     }
737 
738     @Override
setRequestedOrientation(IBinder token, int requestedOrientation)739     public void setRequestedOrientation(IBinder token, int requestedOrientation) {
740         final long origId = Binder.clearCallingIdentity();
741         try {
742             synchronized (mGlobalLock) {
743                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
744                 if (r != null) {
745                     EventLogTags.writeWmSetRequestedOrientation(requestedOrientation,
746                             r.shortComponentName);
747                     r.setRequestedOrientation(requestedOrientation);
748                 }
749             }
750         } finally {
751             Binder.restoreCallingIdentity(origId);
752         }
753     }
754 
755     @Override
getRequestedOrientation(IBinder token)756     public int getRequestedOrientation(IBinder token) {
757         synchronized (mGlobalLock) {
758             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
759             return r != null
760                     ? r.getOverrideOrientation()
761                     : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
762         }
763     }
764 
765     @Override
convertFromTranslucent(IBinder token)766     public boolean convertFromTranslucent(IBinder token) {
767         final long origId = Binder.clearCallingIdentity();
768         try {
769             synchronized (mGlobalLock) {
770                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
771                 // Create a transition if the activity is playing in case the below activity didn't
772                 // commit invisible. That's because if any activity below this one has changed its
773                 // visibility while playing transition, there won't able to commit visibility until
774                 // the running transition finish.
775                 final Transition transition = r != null
776                         && r.mTransitionController.inPlayingTransition(r)
777                         && !r.mTransitionController.isCollecting()
778                         ? r.mTransitionController.createTransition(TRANSIT_TO_BACK) : null;
779                 final boolean changed = r != null && r.setOccludesParent(true);
780                 if (transition != null) {
781                     if (changed) {
782                         r.mTransitionController.requestStartTransition(transition,
783                                 null /*startTask */, null /* remoteTransition */,
784                                 null /* displayChange */);
785                         r.mTransitionController.setReady(r.getDisplayContent());
786                     } else {
787                         transition.abort();
788                     }
789                 }
790                 return changed;
791             }
792         } finally {
793             Binder.restoreCallingIdentity(origId);
794         }
795     }
796 
797     @Override
convertToTranslucent(IBinder token, Bundle options)798     public boolean convertToTranslucent(IBinder token, Bundle options) {
799         final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
800         final long origId = Binder.clearCallingIdentity();
801         try {
802             synchronized (mGlobalLock) {
803                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
804                 if (r == null) {
805                     return false;
806                 }
807                 final ActivityRecord under = r.getTask().getActivityBelow(r);
808                 if (under != null) {
809                     under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
810                 }
811                 // Create a transition to make sure the activity change is collected.
812                 final Transition transition = r.mTransitionController.isShellTransitionsEnabled()
813                         && !r.mTransitionController.isCollecting()
814                         ? r.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null;
815                 final boolean changed = r.setOccludesParent(false);
816                 if (transition != null) {
817                     if (changed) {
818                         r.mTransitionController.requestStartTransition(transition,
819                                 null /*startTask */, null /* remoteTransition */,
820                                 null /* displayChange */);
821                         r.mTransitionController.setReady(r.getDisplayContent());
822                         if (under != null && under.returningOptions != null
823                                 && under.returningOptions.getAnimationType()
824                                         == ANIM_SCENE_TRANSITION) {
825                             // Pass along the scene-transition animation-type
826                             transition.setOverrideAnimation(TransitionInfo.AnimationOptions
827                                     .makeSceneTransitionAnimOptions(), null, null);
828                         }
829                     } else {
830                         transition.abort();
831                     }
832                 }
833                 return changed;
834             }
835         } finally {
836             Binder.restoreCallingIdentity(origId);
837         }
838     }
839 
840     @Override
isImmersive(IBinder token)841     public boolean isImmersive(IBinder token) {
842         synchronized (mGlobalLock) {
843             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
844             if (r == null) {
845                 throw new IllegalArgumentException();
846             }
847             return r.immersive;
848         }
849     }
850 
851     @Override
setImmersive(IBinder token, boolean immersive)852     public void setImmersive(IBinder token, boolean immersive) {
853         synchronized (mGlobalLock) {
854             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
855             if (r == null) {
856                 throw new IllegalArgumentException();
857             }
858             r.immersive = immersive;
859 
860             // Update associated state if we're frontmost.
861             if (r.isFocusedActivityOnDisplay()) {
862                 ProtoLog.d(WM_DEBUG_IMMERSIVE, "Frontmost changed immersion: %s", r);
863                 mService.applyUpdateLockStateLocked(r);
864             }
865         }
866     }
867 
868     @Override
enterPictureInPictureMode(IBinder token, final PictureInPictureParams params)869     public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) {
870         final long origId = Binder.clearCallingIdentity();
871         try {
872             synchronized (mGlobalLock) {
873                 final ActivityRecord r = ensureValidPictureInPictureActivityParams(
874                         "enterPictureInPictureMode", token, params);
875                 return mService.enterPictureInPictureMode(r, params, true /* fromClient */);
876             }
877         } finally {
878             Binder.restoreCallingIdentity(origId);
879         }
880     }
881 
882     @Override
setPictureInPictureParams(IBinder token, final PictureInPictureParams params)883     public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) {
884         final long origId = Binder.clearCallingIdentity();
885         try {
886             synchronized (mGlobalLock) {
887                 final ActivityRecord r = ensureValidPictureInPictureActivityParams(
888                         "setPictureInPictureParams", token, params);
889                 r.setPictureInPictureParams(params);
890             }
891         } finally {
892             Binder.restoreCallingIdentity(origId);
893         }
894     }
895 
896     @Override
setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays)897     public void setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays) {
898         final long origId = Binder.clearCallingIdentity();
899         try {
900             synchronized (mGlobalLock) {
901                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
902                 r.setShouldDockBigOverlays(shouldDockBigOverlays);
903             }
904         } finally {
905             Binder.restoreCallingIdentity(origId);
906         }
907     }
908 
909     /**
910      * Splash screen view is attached to activity.
911      */
912     @Override
splashScreenAttached(IBinder token)913     public void splashScreenAttached(IBinder token) {
914         final long origId = Binder.clearCallingIdentity();
915         synchronized (mGlobalLock) {
916             ActivityRecord.splashScreenAttachedLocked(token);
917         }
918         Binder.restoreCallingIdentity(origId);
919     }
920 
921     @Override
requestCompatCameraControl(IBinder token, boolean showControl, boolean transformationApplied, ICompatCameraControlCallback callback)922     public void requestCompatCameraControl(IBinder token, boolean showControl,
923             boolean transformationApplied, ICompatCameraControlCallback callback) {
924         final long origId = Binder.clearCallingIdentity();
925         try {
926             synchronized (mGlobalLock) {
927                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
928                 if (r != null) {
929                     r.updateCameraCompatState(showControl, transformationApplied, callback);
930                 }
931             }
932         } finally {
933             Binder.restoreCallingIdentity(origId);
934         }
935     }
936 
937     /**
938      * Checks the state of the system and the activity associated with the given {@param token} to
939      * verify that picture-in-picture is supported for that activity.
940      *
941      * @return the activity record for the given {@param token} if all the checks pass.
942      */
ensureValidPictureInPictureActivityParams(String caller, IBinder token, PictureInPictureParams params)943     private ActivityRecord ensureValidPictureInPictureActivityParams(String caller,
944             IBinder token, PictureInPictureParams params) {
945         if (!mService.mSupportsPictureInPicture) {
946             throw new IllegalStateException(caller
947                     + ": Device doesn't support picture-in-picture mode.");
948         }
949 
950         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
951         if (r == null) {
952             throw new IllegalStateException(caller
953                     + ": Can't find activity for token=" + token);
954         }
955 
956         if (!r.supportsPictureInPicture()) {
957             throw new IllegalStateException(caller
958                     + ": Current activity does not support picture-in-picture.");
959         }
960 
961         final float minAspectRatio = mContext.getResources().getFloat(
962                 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
963         final float maxAspectRatio = mContext.getResources().getFloat(
964                 com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
965 
966         if (params.hasSetAspectRatio()
967                 && !mService.mWindowManager.isValidPictureInPictureAspectRatio(
968                 r.mDisplayContent, params.getAspectRatioFloat())) {
969             throw new IllegalArgumentException(String.format(caller
970                             + ": Aspect ratio is too extreme (must be between %f and %f).",
971                     minAspectRatio, maxAspectRatio));
972         }
973 
974         if (mService.mSupportsExpandedPictureInPicture && params.hasSetExpandedAspectRatio()
975                 && !mService.mWindowManager.isValidExpandedPictureInPictureAspectRatio(
976                 r.mDisplayContent, params.getExpandedAspectRatioFloat())) {
977             throw new IllegalArgumentException(String.format(caller
978                             + ": Expanded aspect ratio is not extreme enough (must not be between"
979                             + " %f and %f).",
980                     minAspectRatio, maxAspectRatio));
981         }
982 
983         // Truncate the number of actions if necessary.
984         params.truncateActions(ActivityTaskManager.getMaxNumPictureInPictureActions(mContext));
985         return r;
986     }
987 
988     /**
989      * Requests that an activity should enter picture-in-picture mode if possible. This method may
990      * be used by the implementation of non-phone form factors.
991      *
992      * @return false if the activity cannot enter PIP mode.
993      */
requestPictureInPictureMode(@onNull ActivityRecord r)994     boolean requestPictureInPictureMode(@NonNull ActivityRecord r) {
995         if (r.inPinnedWindowingMode()) {
996             return false;
997         }
998 
999         final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
1000                 "requestPictureInPictureMode", /* beforeStopping */ false);
1001         if (!canEnterPictureInPicture) {
1002             return false;
1003         }
1004 
1005         if (r.pictureInPictureArgs.isAutoEnterEnabled()) {
1006             return mService.enterPictureInPictureMode(r, r.pictureInPictureArgs,
1007                     false /* fromClient */);
1008         }
1009 
1010         try {
1011             final ClientTransaction transaction = ClientTransaction.obtain(
1012                     r.app.getThread(), r.token);
1013             transaction.addCallback(EnterPipRequestedItem.obtain());
1014             mService.getLifecycleManager().scheduleTransaction(transaction);
1015             return true;
1016         } catch (Exception e) {
1017             Slog.w(TAG, "Failed to send enter pip requested item: "
1018                     + r.intent.getComponent(), e);
1019             return false;
1020         }
1021     }
1022 
1023     /**
1024      * Alert the client that the Picture-in-Picture state has changed.
1025      */
onPictureInPictureStateChanged(@onNull ActivityRecord r, PictureInPictureUiState pipState)1026     void onPictureInPictureStateChanged(@NonNull ActivityRecord r,
1027             PictureInPictureUiState pipState) {
1028         if (!r.inPinnedWindowingMode()) {
1029             throw new IllegalStateException("Activity is not in PIP mode");
1030         }
1031 
1032         try {
1033             final ClientTransaction transaction = ClientTransaction.obtain(
1034                     r.app.getThread(), r.token);
1035             transaction.addCallback(PipStateTransactionItem.obtain(pipState));
1036             mService.getLifecycleManager().scheduleTransaction(transaction);
1037         } catch (Exception e) {
1038             Slog.w(TAG, "Failed to send pip state transaction item: "
1039                     + r.intent.getComponent(), e);
1040         }
1041     }
1042 
1043     @Override
toggleFreeformWindowingMode(IBinder token)1044     public void toggleFreeformWindowingMode(IBinder token) {
1045         final long ident = Binder.clearCallingIdentity();
1046         try {
1047             synchronized (mGlobalLock) {
1048                 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1049                 if (r == null) {
1050                     throw new IllegalArgumentException(
1051                             "toggleFreeformWindowingMode: No activity record matching token="
1052                                     + token);
1053                 }
1054 
1055                 final Task rootTask = r.getRootTask();
1056                 if (rootTask == null) {
1057                     throw new IllegalStateException("toggleFreeformWindowingMode: the activity "
1058                             + "doesn't have a root task");
1059                 }
1060 
1061                 if (!rootTask.inFreeformWindowingMode()
1062                         && rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
1063                     throw new IllegalStateException("toggleFreeformWindowingMode: You can only "
1064                             + "toggle between fullscreen and freeform.");
1065                 }
1066 
1067                 if (rootTask.inFreeformWindowingMode()) {
1068                     rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
1069                     rootTask.setBounds(null);
1070                 } else if (!r.supportsFreeform()) {
1071                     throw new IllegalStateException(
1072                             "This activity is currently not freeform-enabled");
1073                 } else if (rootTask.getParent().inFreeformWindowingMode()) {
1074                     // If the window is on a freeform display, set it to undefined. It will be
1075                     // resolved to freeform and it can adjust windowing mode when the display mode
1076                     // changes in runtime.
1077                     rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED);
1078                 } else {
1079                     rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
1080                 }
1081             }
1082         } finally {
1083             Binder.restoreCallingIdentity(ident);
1084         }
1085     }
1086 
validateMultiwindowFullscreenRequestLocked( Task topFocusedRootTask, int fullscreenRequest, ActivityRecord requesterActivity)1087     private @FullscreenRequestHandler.RequestResult int validateMultiwindowFullscreenRequestLocked(
1088             Task topFocusedRootTask, int fullscreenRequest, ActivityRecord requesterActivity) {
1089         // If the mode is not by default freeform, the freeform will be a user-driven event.
1090         if (topFocusedRootTask.getParent().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
1091             return RESULT_FAILED_NOT_DEFAULT_FREEFORM;
1092         }
1093         // If this is not coming from the currently top-most activity, reject the request.
1094         if (requesterActivity != topFocusedRootTask.getTopMostActivity()) {
1095             return RESULT_FAILED_NOT_TOP_FOCUSED;
1096         }
1097         if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_ENTER) {
1098             if (topFocusedRootTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
1099                 return RESULT_FAILED_NOT_IN_FREEFORM;
1100             }
1101         } else {
1102             if (topFocusedRootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
1103                 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY;
1104             }
1105             if (topFocusedRootTask.mMultiWindowRestoreWindowingMode == INVALID_WINDOWING_MODE) {
1106                 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY;
1107             }
1108         }
1109         return RESULT_APPROVED;
1110     }
1111 
1112     @Override
requestMultiwindowFullscreen(IBinder callingActivity, int fullscreenRequest, IRemoteCallback callback)1113     public void requestMultiwindowFullscreen(IBinder callingActivity, int fullscreenRequest,
1114             IRemoteCallback callback) {
1115         final long ident = Binder.clearCallingIdentity();
1116         try {
1117             synchronized (mGlobalLock) {
1118                 requestMultiwindowFullscreenLocked(callingActivity, fullscreenRequest, callback);
1119             }
1120         } finally {
1121             Binder.restoreCallingIdentity(ident);
1122         }
1123     }
1124 
requestMultiwindowFullscreenLocked(IBinder callingActivity, int fullscreenRequest, IRemoteCallback callback)1125     private void requestMultiwindowFullscreenLocked(IBinder callingActivity, int fullscreenRequest,
1126             IRemoteCallback callback) {
1127         final ActivityRecord r = ActivityRecord.forTokenLocked(callingActivity);
1128         if (r == null) {
1129             return;
1130         }
1131 
1132         // If the shell transition is not enabled, just execute and done.
1133         final TransitionController controller = r.mTransitionController;
1134         if (!controller.isShellTransitionsEnabled()) {
1135             final @FullscreenRequestHandler.RequestResult int validateResult;
1136             final Task topFocusedRootTask;
1137             topFocusedRootTask = mService.getTopDisplayFocusedRootTask();
1138             validateResult = validateMultiwindowFullscreenRequestLocked(topFocusedRootTask,
1139                     fullscreenRequest, r);
1140             reportMultiwindowFullscreenRequestValidatingResult(callback, validateResult);
1141             if (validateResult == RESULT_APPROVED) {
1142                 executeMultiWindowFullscreenRequest(fullscreenRequest, topFocusedRootTask);
1143             }
1144             return;
1145         }
1146         // Initiate the transition.
1147         final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */, controller,
1148                 mService.mWindowManager.mSyncEngine);
1149         r.mTransitionController.startCollectOrQueue(transition,
1150                 (deferred) -> {
1151                     executeFullscreenRequestTransition(fullscreenRequest, callback, r,
1152                             transition, deferred);
1153                 });
1154     }
1155 
executeFullscreenRequestTransition(int fullscreenRequest, IRemoteCallback callback, ActivityRecord r, Transition transition, boolean queued)1156     private void executeFullscreenRequestTransition(int fullscreenRequest, IRemoteCallback callback,
1157             ActivityRecord r, Transition transition, boolean queued) {
1158         final @FullscreenRequestHandler.RequestResult int validateResult;
1159         final Task topFocusedRootTask;
1160         topFocusedRootTask = mService.getTopDisplayFocusedRootTask();
1161         validateResult = validateMultiwindowFullscreenRequestLocked(topFocusedRootTask,
1162                 fullscreenRequest, r);
1163         reportMultiwindowFullscreenRequestValidatingResult(callback, validateResult);
1164         if (validateResult != RESULT_APPROVED) {
1165             transition.abort();
1166             return;
1167         }
1168         transition.collect(topFocusedRootTask);
1169         executeMultiWindowFullscreenRequest(fullscreenRequest, topFocusedRootTask);
1170         r.mTransitionController.requestStartTransition(transition, topFocusedRootTask,
1171                 null /* remoteTransition */, null /* displayChange */);
1172         transition.setReady(topFocusedRootTask, true);
1173     }
1174 
reportMultiwindowFullscreenRequestValidatingResult(IRemoteCallback callback, @FullscreenRequestHandler.RequestResult int result)1175     private static void reportMultiwindowFullscreenRequestValidatingResult(IRemoteCallback callback,
1176             @FullscreenRequestHandler.RequestResult int result) {
1177         if (callback == null) {
1178             return;
1179         }
1180         Bundle res = new Bundle();
1181         res.putInt(REMOTE_CALLBACK_RESULT_KEY, result);
1182         try {
1183             callback.sendResult(res);
1184         } catch (RemoteException e) {
1185             Slog.w(TAG, "client throws an exception back to the server, ignore it");
1186         }
1187     }
1188 
executeMultiWindowFullscreenRequest(int fullscreenRequest, Task requester)1189     private static void executeMultiWindowFullscreenRequest(int fullscreenRequest, Task requester) {
1190         final int targetWindowingMode;
1191         if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_ENTER) {
1192             requester.mMultiWindowRestoreWindowingMode =
1193                     requester.getRequestedOverrideWindowingMode();
1194             targetWindowingMode = WINDOWING_MODE_FULLSCREEN;
1195         } else {
1196             targetWindowingMode = requester.mMultiWindowRestoreWindowingMode;
1197             requester.mMultiWindowRestoreWindowingMode = INVALID_WINDOWING_MODE;
1198         }
1199         requester.setWindowingMode(targetWindowingMode);
1200         if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) {
1201             requester.setBounds(null);
1202         }
1203     }
1204 
1205     @Override
startLockTaskModeByToken(IBinder token)1206     public void startLockTaskModeByToken(IBinder token) {
1207         synchronized (mGlobalLock) {
1208             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1209             if (r != null) {
1210                 mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */);
1211             }
1212         }
1213     }
1214 
1215     @Override
stopLockTaskModeByToken(IBinder token)1216     public void stopLockTaskModeByToken(IBinder token) {
1217         mService.stopLockTaskModeInternal(token, false /* isSystemCaller */);
1218     }
1219 
1220     @Override
showLockTaskEscapeMessage(IBinder token)1221     public void showLockTaskEscapeMessage(IBinder token) {
1222         synchronized (mGlobalLock) {
1223             if (ActivityRecord.forTokenLocked(token) != null) {
1224                 mService.getLockTaskController().showLockTaskToast();
1225             }
1226         }
1227     }
1228 
1229     @Override
setTaskDescription(IBinder token, ActivityManager.TaskDescription td)1230     public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) {
1231         synchronized (mGlobalLock) {
1232             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1233             if (r != null) {
1234                 r.setTaskDescription(td);
1235             }
1236         }
1237     }
1238 
1239     @Override
showAssistFromActivity(IBinder token, Bundle args)1240     public boolean showAssistFromActivity(IBinder token, Bundle args) {
1241         final long ident = Binder.clearCallingIdentity();
1242         try {
1243             final String callingAttributionTag;
1244             synchronized (mGlobalLock) {
1245                 final ActivityRecord caller = ActivityRecord.forTokenLocked(token);
1246                 final Task topRootTask = mService.getTopDisplayFocusedRootTask();
1247                 final ActivityRecord top = topRootTask != null
1248                         ? topRootTask.getTopNonFinishingActivity() : null;
1249                 if (top != caller) {
1250                     Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
1251                             + " is not current top " + top);
1252                     return false;
1253                 }
1254                 if (!top.nowVisible) {
1255                     Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
1256                             + " is not visible");
1257                     return false;
1258                 }
1259                 callingAttributionTag = top.launchedFromFeatureId;
1260             }
1261             return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION,
1262                     callingAttributionTag, null /* showCallback */, token);
1263         } finally {
1264             Binder.restoreCallingIdentity(ident);
1265         }
1266     }
1267 
1268     @Override
isRootVoiceInteraction(IBinder token)1269     public boolean isRootVoiceInteraction(IBinder token) {
1270         synchronized (mGlobalLock) {
1271             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1272             return r != null && r.rootVoiceInteraction;
1273         }
1274     }
1275 
1276     @Override
startLocalVoiceInteraction(IBinder callingActivity, Bundle options)1277     public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
1278         Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
1279         final String callingAttributionTag;
1280         synchronized (mGlobalLock) {
1281             final Task topRootTask = mService.getTopDisplayFocusedRootTask();
1282             final ActivityRecord activity = topRootTask != null
1283                     ? topRootTask.getTopNonFinishingActivity() : null;
1284             if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
1285                 throw new SecurityException("Only focused activity can call startVoiceInteraction");
1286             }
1287             if (mService.mRunningVoice != null || activity.getTask().voiceSession != null
1288                     || activity.voiceSession != null) {
1289                 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
1290                 return;
1291             }
1292             if (activity.pendingVoiceInteractionStart) {
1293                 Slog.w(TAG, "Pending start of voice interaction already.");
1294                 return;
1295             }
1296             activity.pendingVoiceInteractionStart = true;
1297             callingAttributionTag = activity.launchedFromFeatureId;
1298         }
1299         LocalServices.getService(VoiceInteractionManagerInternal.class)
1300                 .startLocalVoiceInteraction(callingActivity, callingAttributionTag, options);
1301     }
1302 
1303     @Override
stopLocalVoiceInteraction(IBinder callingActivity)1304     public void stopLocalVoiceInteraction(IBinder callingActivity) {
1305         LocalServices.getService(VoiceInteractionManagerInternal.class)
1306                 .stopLocalVoiceInteraction(callingActivity);
1307     }
1308 
1309     @Override
setShowWhenLocked(IBinder token, boolean showWhenLocked)1310     public void setShowWhenLocked(IBinder token, boolean showWhenLocked) {
1311         final long origId = Binder.clearCallingIdentity();
1312         try {
1313             synchronized (mGlobalLock) {
1314                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1315                 if (r != null) {
1316                     r.setShowWhenLocked(showWhenLocked);
1317                 }
1318             }
1319         } finally {
1320             Binder.restoreCallingIdentity(origId);
1321         }
1322     }
1323 
1324     @Override
setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked)1325     public void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) {
1326         final long origId = Binder.clearCallingIdentity();
1327         try {
1328             synchronized (mGlobalLock) {
1329                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1330                 if (r != null) {
1331                     r.setInheritShowWhenLocked(inheritShowWhenLocked);
1332                 }
1333             }
1334         } finally {
1335             Binder.restoreCallingIdentity(origId);
1336         }
1337     }
1338 
1339     @Override
setTurnScreenOn(IBinder token, boolean turnScreenOn)1340     public void setTurnScreenOn(IBinder token, boolean turnScreenOn) {
1341         final long origId = Binder.clearCallingIdentity();
1342         try {
1343             synchronized (mGlobalLock) {
1344                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1345                 if (r != null) {
1346                     r.setTurnScreenOn(turnScreenOn);
1347                 }
1348             }
1349         } finally {
1350             Binder.restoreCallingIdentity(origId);
1351         }
1352     }
1353 
setAllowCrossUidActivitySwitchFromBelow(IBinder token, boolean allowed)1354     public void setAllowCrossUidActivitySwitchFromBelow(IBinder token, boolean allowed) {
1355         final long origId = Binder.clearCallingIdentity();
1356         try {
1357             synchronized (mGlobalLock) {
1358                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1359                 if (r != null) {
1360                     r.setAllowCrossUidActivitySwitchFromBelow(allowed);
1361                 }
1362             }
1363         } finally {
1364             Binder.restoreCallingIdentity(origId);
1365         }
1366     }
1367 
1368     @Override
reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle)1369     public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) {
1370         final long origId = Binder.clearCallingIdentity();
1371         try {
1372             synchronized (mGlobalLock) {
1373                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1374                 if (r != null) {
1375                     mTaskSupervisor.getActivityMetricsLogger().notifyFullyDrawn(r,
1376                             restoredFromBundle);
1377                 }
1378             }
1379         } finally {
1380             Binder.restoreCallingIdentity(origId);
1381         }
1382     }
1383 
1384     @Override
overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim, int backgroundColor)1385     public void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim,
1386             int backgroundColor) {
1387         final long origId = Binder.clearCallingIdentity();
1388         synchronized (mGlobalLock) {
1389             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1390             if (r != null) {
1391                 r.overrideCustomTransition(open, enterAnim, exitAnim, backgroundColor);
1392             }
1393         }
1394         Binder.restoreCallingIdentity(origId);
1395     }
1396 
1397     @Override
clearOverrideActivityTransition(IBinder token, boolean open)1398     public void clearOverrideActivityTransition(IBinder token, boolean open) {
1399         final long origId = Binder.clearCallingIdentity();
1400         synchronized (mGlobalLock) {
1401             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1402             if (r != null) {
1403                 r.clearCustomTransition(open);
1404             }
1405         }
1406         Binder.restoreCallingIdentity(origId);
1407     }
1408 
1409     @Override
overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim, @ColorInt int backgroundColor)1410     public void overridePendingTransition(IBinder token, String packageName,
1411             int enterAnim, int exitAnim, @ColorInt int backgroundColor) {
1412         final long origId = Binder.clearCallingIdentity();
1413         synchronized (mGlobalLock) {
1414             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1415             if (r != null && r.isState(RESUMED, PAUSING)) {
1416                 r.mDisplayContent.mAppTransition.overridePendingAppTransition(
1417                         packageName, enterAnim, exitAnim, backgroundColor, null, null,
1418                         r.mOverrideTaskTransition);
1419                 r.mTransitionController.setOverrideAnimation(
1420                         TransitionInfo.AnimationOptions.makeCustomAnimOptions(packageName,
1421                                 enterAnim, exitAnim, backgroundColor, r.mOverrideTaskTransition),
1422                         null /* startCallback */, null /* finishCallback */);
1423             }
1424         }
1425         Binder.restoreCallingIdentity(origId);
1426     }
1427 
1428     @Override
setVrMode(IBinder token, boolean enabled, ComponentName packageName)1429     public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
1430         mService.enforceSystemHasVrFeature();
1431 
1432         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
1433         final ActivityRecord r;
1434         synchronized (mGlobalLock) {
1435             r = ActivityRecord.isInRootTaskLocked(token);
1436         }
1437         if (r == null) {
1438             throw new IllegalArgumentException();
1439         }
1440 
1441         final int err;
1442         if ((err = vrService.hasVrPackage(packageName, r.mUserId)) != VrManagerInternal.NO_ERROR) {
1443             return err;
1444         }
1445 
1446         // Clear the binder calling uid since this path may call moveToTask().
1447         final long callingId = Binder.clearCallingIdentity();
1448         try {
1449             synchronized (mGlobalLock) {
1450                 r.requestedVrComponent = (enabled) ? packageName : null;
1451 
1452                 // Update associated state if this activity is currently focused.
1453                 if (r.isFocusedActivityOnDisplay()) {
1454                     mService.applyUpdateVrModeLocked(r);
1455                 }
1456                 return 0;
1457             }
1458         } finally {
1459             Binder.restoreCallingIdentity(callingId);
1460         }
1461     }
1462 
1463     @Override
setRecentsScreenshotEnabled(IBinder token, boolean enabled)1464     public void setRecentsScreenshotEnabled(IBinder token, boolean enabled) {
1465         final long origId = Binder.clearCallingIdentity();
1466         try {
1467             synchronized (mGlobalLock) {
1468                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1469                 if (r != null) {
1470                     r.setRecentsScreenshotEnabled(enabled);
1471                 }
1472             }
1473         } finally {
1474             Binder.restoreCallingIdentity(origId);
1475         }
1476     }
1477 
restartActivityProcessIfVisible(IBinder token)1478     void restartActivityProcessIfVisible(IBinder token) {
1479         ActivityTaskManagerService.enforceTaskPermission("restartActivityProcess");
1480         final long callingId = Binder.clearCallingIdentity();
1481         try {
1482             synchronized (mGlobalLock) {
1483                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1484                 if (r != null) {
1485                     r.restartProcessIfVisible();
1486                 }
1487             }
1488         } finally {
1489             Binder.restoreCallingIdentity(callingId);
1490         }
1491     }
1492 
1493     /**
1494      * Removes the outdated home task snapshot.
1495      *
1496      * @param token The token of the home task, or null if you have the
1497      *              {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}
1498      *              permission and want us to find the home task token for you.
1499      */
1500     @Override
invalidateHomeTaskSnapshot(IBinder token)1501     public void invalidateHomeTaskSnapshot(IBinder token) {
1502         if (token == null) {
1503             ActivityTaskManagerService.enforceTaskPermission("invalidateHomeTaskSnapshot");
1504         }
1505 
1506         synchronized (mGlobalLock) {
1507             final ActivityRecord r;
1508             if (token == null) {
1509                 final Task rootTask =
1510                         mService.mRootWindowContainer.getDefaultTaskDisplayArea().getRootHomeTask();
1511                 r = rootTask != null ? rootTask.topRunningActivity() : null;
1512             } else {
1513                 r = ActivityRecord.isInRootTaskLocked(token);
1514             }
1515 
1516             if (r != null && r.isActivityTypeHome()) {
1517                 mService.mWindowManager.mTaskSnapshotController.removeSnapshotCache(
1518                         r.getTask().mTaskId);
1519             }
1520         }
1521     }
1522 
1523     @Override
dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)1524     public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
1525             CharSequence message) {
1526         if (message != null) {
1527             mService.mAmInternal.enforceCallingPermission(
1528                     android.Manifest.permission.SHOW_KEYGUARD_MESSAGE, "dismissKeyguard");
1529         }
1530         final long callingId = Binder.clearCallingIdentity();
1531         try {
1532             synchronized (mGlobalLock) {
1533                 mService.mKeyguardController.dismissKeyguard(token, callback, message);
1534             }
1535         } finally {
1536             Binder.restoreCallingIdentity(callingId);
1537         }
1538     }
1539 
1540     @Override
registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition)1541     public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
1542         mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
1543                 "registerRemoteAnimations");
1544         definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid());
1545         final long origId = Binder.clearCallingIdentity();
1546         try {
1547             synchronized (mGlobalLock) {
1548                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1549                 if (r != null) {
1550                     r.registerRemoteAnimations(definition);
1551                 }
1552             }
1553         } finally {
1554             Binder.restoreCallingIdentity(origId);
1555         }
1556     }
1557 
1558     @Override
unregisterRemoteAnimations(IBinder token)1559     public void unregisterRemoteAnimations(IBinder token) {
1560         mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
1561                 "unregisterRemoteAnimations");
1562         final long origId = Binder.clearCallingIdentity();
1563         try {
1564             synchronized (mGlobalLock) {
1565                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1566                 if (r != null) {
1567                     r.unregisterRemoteAnimations();
1568                 }
1569             }
1570         } finally {
1571             Binder.restoreCallingIdentity(origId);
1572         }
1573     }
1574 
1575     /**
1576      * Return {@code true} when the given Activity is a relative Task root. That is, the rest of
1577      * the Activities in the Task should be finished when it finishes. Otherwise, return {@code
1578      * false}.
1579      */
isRelativeTaskRootActivity(ActivityRecord r, ActivityRecord taskRoot)1580     private boolean isRelativeTaskRootActivity(ActivityRecord r, ActivityRecord taskRoot) {
1581         // Not a relative root if the given Activity is not the root Activity of its TaskFragment.
1582         final TaskFragment taskFragment = r.getTaskFragment();
1583         if (r != taskFragment.getActivity(ar -> !ar.finishing || ar == r,
1584                 false /* traverseTopToBottom */)) {
1585             return false;
1586         }
1587 
1588         // The given Activity is the relative Task root if its TaskFragment is a companion
1589         // TaskFragment to the taskRoot (i.e. the taskRoot TF will be finished together).
1590         return taskRoot.getTaskFragment().getCompanionTaskFragment() == taskFragment;
1591     }
1592 
isTopActivityInTaskFragment(ActivityRecord activity)1593     private boolean isTopActivityInTaskFragment(ActivityRecord activity) {
1594         return activity.getTaskFragment().topRunningActivity() == activity;
1595     }
1596 
requestCallbackFinish(IRequestFinishCallback callback)1597     private void requestCallbackFinish(IRequestFinishCallback callback) {
1598         try {
1599             callback.requestFinish();
1600         } catch (RemoteException e) {
1601             Slog.e(TAG, "Failed to invoke request finish callback", e);
1602         }
1603     }
1604 
1605     @Override
onBackPressed(IBinder token, IRequestFinishCallback callback)1606     public void onBackPressed(IBinder token, IRequestFinishCallback callback) {
1607         final long origId = Binder.clearCallingIdentity();
1608         try {
1609             final Intent baseActivityIntent;
1610             final boolean launchedFromHome;
1611             final boolean isLastRunningActivity;
1612             synchronized (mGlobalLock) {
1613                 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
1614                 if (r == null) return;
1615 
1616                 final Task task = r.getTask();
1617                 final ActivityRecord root = task.getRootActivity(false /*ignoreRelinquishIdentity*/,
1618                         true /*setToBottomIfNone*/);
1619                 final boolean isTaskRoot = r == root;
1620                 if (isTaskRoot) {
1621                     if (mService.mWindowOrganizerController.mTaskOrganizerController
1622                         .handleInterceptBackPressedOnTaskRoot(r.getRootTask())) {
1623                         // This task is handled by a task organizer that has requested the back
1624                         // pressed callback.
1625                         return;
1626                     }
1627                 } else if (!isRelativeTaskRootActivity(r, root)) {
1628                     // Finish the Activity if the activity is not the task root or relative root.
1629                     requestCallbackFinish(callback);
1630                     return;
1631                 }
1632 
1633                 isLastRunningActivity = isTopActivityInTaskFragment(isTaskRoot ? root : r);
1634 
1635                 final boolean isBaseActivity = root.mActivityComponent.equals(task.realActivity);
1636                 baseActivityIntent = isBaseActivity ? root.intent : null;
1637 
1638                 launchedFromHome = root.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
1639             }
1640 
1641             // If the activity was launched directly from the home screen, then we should
1642             // refrain from finishing the activity and instead move it to the back to keep it in
1643             // memory. The requirements for this are:
1644             //   1. The activity is the last running activity in the task.
1645             //   2. The current activity is the base activity for the task.
1646             //   3. The activity was launched by the home process, and is one of the main entry
1647             //      points for the application.
1648             if (baseActivityIntent != null && isLastRunningActivity
1649                     && launchedFromHome && ActivityRecord.isMainIntent(baseActivityIntent)) {
1650                 moveActivityTaskToBack(token, true /* nonRoot */);
1651                 return;
1652             }
1653 
1654             // The default option for handling the back button is to finish the Activity.
1655             requestCallbackFinish(callback);
1656         } finally {
1657             Binder.restoreCallingIdentity(origId);
1658         }
1659     }
1660 
1661     @Override
enableTaskLocaleOverride(IBinder token)1662     public void enableTaskLocaleOverride(IBinder token) {
1663         if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
1664             // Only allow system to align locale.
1665             return;
1666         }
1667 
1668         synchronized (mGlobalLock) {
1669             final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1670             if (r != null) {
1671                 r.getTask().mAlignActivityLocaleWithTask = true;
1672             }
1673         }
1674     }
1675 
1676     /**
1677      * Returns {@code true} if the activity was explicitly requested to be launched in its
1678      * current TaskFragment.
1679      *
1680      * @see ActivityRecord#mRequestedLaunchingTaskFragmentToken
1681      */
isRequestedToLaunchInTaskFragment(IBinder activityToken, IBinder taskFragmentToken)1682     public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
1683             IBinder taskFragmentToken) {
1684         synchronized (mGlobalLock) {
1685             final ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken);
1686             if (r == null) return false;
1687 
1688             return r.mRequestedLaunchingTaskFragmentToken == taskFragmentToken;
1689         }
1690     }
1691 }
1692