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 android.app;
18 
19 import android.annotation.Nullable;
20 import android.annotation.RequiresPermission;
21 import android.content.ComponentName;
22 import android.content.Intent;
23 import android.content.res.Configuration;
24 import android.content.res.Resources;
25 import android.os.Bundle;
26 import android.os.IBinder;
27 import android.os.IRemoteCallback;
28 import android.os.PersistableBundle;
29 import android.os.RemoteException;
30 import android.util.Singleton;
31 import android.view.RemoteAnimationDefinition;
32 import android.window.SizeConfigurationBuckets;
33 
34 import com.android.internal.policy.IKeyguardDismissCallback;
35 
36 /**
37  * Provides the activity associated operations that communicate with system.
38  *
39  * @hide
40  */
41 public class ActivityClient {
ActivityClient()42     private ActivityClient() {}
43 
44     /** Reports the main thread is idle after the activity is resumed. */
activityIdle(IBinder token, Configuration config, boolean stopProfiling)45     public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
46         try {
47             getActivityClientController().activityIdle(token, config, stopProfiling);
48         } catch (RemoteException e) {
49             e.rethrowFromSystemServer();
50         }
51     }
52 
53     /** Reports {@link Activity#onResume()} is done. */
activityResumed(IBinder token, boolean handleSplashScreenExit)54     public void activityResumed(IBinder token, boolean handleSplashScreenExit) {
55         try {
56             getActivityClientController().activityResumed(token, handleSplashScreenExit);
57         } catch (RemoteException e) {
58             e.rethrowFromSystemServer();
59         }
60     }
61 
62     /** Reports {@link android.app.servertransaction.RefreshCallbackItem} is executed. */
activityRefreshed(IBinder token)63     public void activityRefreshed(IBinder token) {
64         try {
65             getActivityClientController().activityRefreshed(token);
66         } catch (RemoteException e) {
67             e.rethrowFromSystemServer();
68         }
69     }
70 
71     /**
72      * Reports after {@link Activity#onTopResumedActivityChanged(boolean)} is called for losing the
73      * top most position.
74      */
activityTopResumedStateLost()75     public void activityTopResumedStateLost() {
76         try {
77             getActivityClientController().activityTopResumedStateLost();
78         } catch (RemoteException e) {
79             e.rethrowFromSystemServer();
80         }
81     }
82 
83     /** Reports {@link Activity#onPause()} is done. */
activityPaused(IBinder token)84     public void activityPaused(IBinder token) {
85         try {
86             getActivityClientController().activityPaused(token);
87         } catch (RemoteException e) {
88             e.rethrowFromSystemServer();
89         }
90     }
91 
92     /** Reports {@link Activity#onStop()} is done. */
activityStopped(IBinder token, Bundle state, PersistableBundle persistentState, CharSequence description)93     public void activityStopped(IBinder token, Bundle state, PersistableBundle persistentState,
94             CharSequence description) {
95         try {
96             getActivityClientController().activityStopped(token, state, persistentState,
97                     description);
98         } catch (RemoteException e) {
99             e.rethrowFromSystemServer();
100         }
101     }
102 
103     /** Reports {@link Activity#onDestroy()} is done. */
activityDestroyed(IBinder token)104     public void activityDestroyed(IBinder token) {
105         try {
106             getActivityClientController().activityDestroyed(token);
107         } catch (RemoteException e) {
108             e.rethrowFromSystemServer();
109         }
110     }
111 
112     /** Reports the activity starts local relaunch. */
activityLocalRelaunch(IBinder token)113     public void activityLocalRelaunch(IBinder token) {
114         try {
115             getActivityClientController().activityLocalRelaunch(token);
116         } catch (RemoteException e) {
117             e.rethrowFromSystemServer();
118         }
119     }
120 
121     /** Reports the activity has completed relaunched. */
activityRelaunched(IBinder token)122     public void activityRelaunched(IBinder token) {
123         try {
124             getActivityClientController().activityRelaunched(token);
125         } catch (RemoteException e) {
126             e.rethrowFromSystemServer();
127         }
128     }
129 
reportSizeConfigurations(IBinder token, SizeConfigurationBuckets sizeConfigurations)130     void reportSizeConfigurations(IBinder token, SizeConfigurationBuckets sizeConfigurations) {
131         try {
132             getActivityClientController().reportSizeConfigurations(token, sizeConfigurations);
133         } catch (RemoteException e) {
134             e.rethrowFromSystemServer();
135         }
136     }
137 
moveActivityTaskToBack(IBinder token, boolean nonRoot)138     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
139         try {
140             return getActivityClientController().moveActivityTaskToBack(token, nonRoot);
141         } catch (RemoteException e) {
142             throw e.rethrowFromSystemServer();
143         }
144     }
145 
shouldUpRecreateTask(IBinder token, String destAffinity)146     boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
147         try {
148             return getActivityClientController().shouldUpRecreateTask(token, destAffinity);
149         } catch (RemoteException e) {
150             throw e.rethrowFromSystemServer();
151         }
152     }
153 
navigateUpTo(IBinder token, Intent destIntent, String resolvedType, int resultCode, Intent resultData)154     boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType, int resultCode,
155             Intent resultData) {
156         try {
157             return getActivityClientController().navigateUpTo(token, destIntent, resolvedType,
158                     resultCode, resultData);
159         } catch (RemoteException e) {
160             throw e.rethrowFromSystemServer();
161         }
162     }
163 
releaseActivityInstance(IBinder token)164     boolean releaseActivityInstance(IBinder token) {
165         try {
166             return getActivityClientController().releaseActivityInstance(token);
167         } catch (RemoteException e) {
168             throw e.rethrowFromSystemServer();
169         }
170     }
171 
finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask)172     public boolean finishActivity(IBinder token, int resultCode, Intent resultData,
173             int finishTask) {
174         try {
175             return getActivityClientController().finishActivity(token, resultCode, resultData,
176                     finishTask);
177         } catch (RemoteException e) {
178             throw e.rethrowFromSystemServer();
179         }
180     }
181 
finishActivityAffinity(IBinder token)182     boolean finishActivityAffinity(IBinder token) {
183         try {
184             return getActivityClientController().finishActivityAffinity(token);
185         } catch (RemoteException e) {
186             throw e.rethrowFromSystemServer();
187         }
188     }
189 
finishSubActivity(IBinder token, String resultWho, int requestCode)190     void finishSubActivity(IBinder token, String resultWho, int requestCode) {
191         try {
192             getActivityClientController().finishSubActivity(token, resultWho, requestCode);
193         } catch (RemoteException e) {
194             e.rethrowFromSystemServer();
195         }
196     }
197 
198     @RequiresPermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION)
setForceSendResultForMediaProjection(IBinder token)199     void setForceSendResultForMediaProjection(IBinder token) {
200         try {
201             getActivityClientController().setForceSendResultForMediaProjection(token);
202         } catch (RemoteException e) {
203             throw e.rethrowFromSystemServer();
204         }
205     }
206 
isTopOfTask(IBinder token)207     public boolean isTopOfTask(IBinder token) {
208         try {
209             return getActivityClientController().isTopOfTask(token);
210         } catch (RemoteException e) {
211             throw e.rethrowFromSystemServer();
212         }
213     }
214 
willActivityBeVisible(IBinder token)215     boolean willActivityBeVisible(IBinder token) {
216         try {
217             return getActivityClientController().willActivityBeVisible(token);
218         } catch (RemoteException e) {
219             throw e.rethrowFromSystemServer();
220         }
221     }
222 
getDisplayId(IBinder token)223     public int getDisplayId(IBinder token) {
224         try {
225             return getActivityClientController().getDisplayId(token);
226         } catch (RemoteException e) {
227             throw e.rethrowFromSystemServer();
228         }
229     }
230 
getTaskForActivity(IBinder token, boolean onlyRoot)231     public int getTaskForActivity(IBinder token, boolean onlyRoot) {
232         try {
233             return getActivityClientController().getTaskForActivity(token, onlyRoot);
234         } catch (RemoteException e) {
235             throw e.rethrowFromSystemServer();
236         }
237     }
238 
239     /**
240      * Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if
241      * the task {@link Configuration} cannot be obtained.
242      */
243     @Nullable
getTaskConfiguration(IBinder activityToken)244     public Configuration getTaskConfiguration(IBinder activityToken) {
245         try {
246             return getActivityClientController().getTaskConfiguration(activityToken);
247         } catch (RemoteException e) {
248             throw e.rethrowFromSystemServer();
249         }
250     }
251 
252     /**
253      * Returns the non-finishing activity token below in the same task if it belongs to the same
254      * process.
255      */
256     @Nullable
getActivityTokenBelow(IBinder activityToken)257     public IBinder getActivityTokenBelow(IBinder activityToken) {
258         try {
259             return getActivityClientController().getActivityTokenBelow(activityToken);
260         } catch (RemoteException e) {
261             throw e.rethrowFromSystemServer();
262         }
263     }
264 
getCallingActivity(IBinder token)265     ComponentName getCallingActivity(IBinder token) {
266         try {
267             return getActivityClientController().getCallingActivity(token);
268         } catch (RemoteException e) {
269             throw e.rethrowFromSystemServer();
270         }
271     }
272 
getCallingPackage(IBinder token)273     String getCallingPackage(IBinder token) {
274         try {
275             return getActivityClientController().getCallingPackage(token);
276         } catch (RemoteException e) {
277             throw e.rethrowFromSystemServer();
278         }
279     }
280 
getLaunchedFromUid(IBinder token)281     public int getLaunchedFromUid(IBinder token) {
282         try {
283             return getActivityClientController().getLaunchedFromUid(token);
284         } catch (RemoteException e) {
285             throw e.rethrowFromSystemServer();
286         }
287     }
288 
getLaunchedFromPackage(IBinder token)289     public String getLaunchedFromPackage(IBinder token) {
290         try {
291             return getActivityClientController().getLaunchedFromPackage(token);
292         } catch (RemoteException e) {
293             throw e.rethrowFromSystemServer();
294         }
295     }
296 
setRequestedOrientation(IBinder token, int requestedOrientation)297     public void setRequestedOrientation(IBinder token, int requestedOrientation) {
298         try {
299             getActivityClientController().setRequestedOrientation(token, requestedOrientation);
300         } catch (RemoteException e) {
301             e.rethrowFromSystemServer();
302         }
303     }
304 
getRequestedOrientation(IBinder token)305     int getRequestedOrientation(IBinder token) {
306         try {
307             return getActivityClientController().getRequestedOrientation(token);
308         } catch (RemoteException e) {
309             throw e.rethrowFromSystemServer();
310         }
311     }
312 
convertFromTranslucent(IBinder token)313     boolean convertFromTranslucent(IBinder token) {
314         try {
315             return getActivityClientController().convertFromTranslucent(token);
316         } catch (RemoteException e) {
317             throw e.rethrowFromSystemServer();
318         }
319     }
320 
convertToTranslucent(IBinder token, Bundle options)321     boolean convertToTranslucent(IBinder token, Bundle options) {
322         try {
323             return getActivityClientController().convertToTranslucent(token, options);
324         } catch (RemoteException e) {
325             throw e.rethrowFromSystemServer();
326         }
327     }
328 
reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle)329     void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) {
330         try {
331             getActivityClientController().reportActivityFullyDrawn(token, restoredFromBundle);
332         } catch (RemoteException e) {
333             e.rethrowFromSystemServer();
334         }
335     }
336 
isImmersive(IBinder token)337     boolean isImmersive(IBinder token) {
338         try {
339             return getActivityClientController().isImmersive(token);
340         } catch (RemoteException e) {
341             throw e.rethrowFromSystemServer();
342         }
343     }
344 
setImmersive(IBinder token, boolean immersive)345     void setImmersive(IBinder token, boolean immersive) {
346         try {
347             getActivityClientController().setImmersive(token, immersive);
348         } catch (RemoteException e) {
349             e.rethrowFromSystemServer();
350         }
351     }
352 
enterPictureInPictureMode(IBinder token, PictureInPictureParams params)353     boolean enterPictureInPictureMode(IBinder token, PictureInPictureParams params) {
354         try {
355             return getActivityClientController().enterPictureInPictureMode(token, params);
356         } catch (RemoteException e) {
357             throw e.rethrowFromSystemServer();
358         }
359     }
360 
setPictureInPictureParams(IBinder token, PictureInPictureParams params)361     void setPictureInPictureParams(IBinder token, PictureInPictureParams params) {
362         try {
363             getActivityClientController().setPictureInPictureParams(token, params);
364         } catch (RemoteException e) {
365             e.rethrowFromSystemServer();
366         }
367     }
368 
setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays)369     void setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays) {
370         try {
371             getActivityClientController().setShouldDockBigOverlays(token, shouldDockBigOverlays);
372         } catch (RemoteException e) {
373             e.rethrowFromSystemServer();
374         }
375     }
376 
toggleFreeformWindowingMode(IBinder token)377     void toggleFreeformWindowingMode(IBinder token) {
378         try {
379             getActivityClientController().toggleFreeformWindowingMode(token);
380         } catch (RemoteException e) {
381             e.rethrowFromSystemServer();
382         }
383     }
384 
requestMultiwindowFullscreen(IBinder token, int request, IRemoteCallback callback)385     void requestMultiwindowFullscreen(IBinder token, int request, IRemoteCallback callback) {
386         try {
387             getActivityClientController().requestMultiwindowFullscreen(token, request, callback);
388         } catch (RemoteException e) {
389             e.rethrowFromSystemServer();
390         }
391     }
392 
startLockTaskModeByToken(IBinder token)393     void startLockTaskModeByToken(IBinder token) {
394         try {
395             getActivityClientController().startLockTaskModeByToken(token);
396         } catch (RemoteException e) {
397             e.rethrowFromSystemServer();
398         }
399     }
400 
stopLockTaskModeByToken(IBinder token)401     void stopLockTaskModeByToken(IBinder token) {
402         try {
403             getActivityClientController().stopLockTaskModeByToken(token);
404         } catch (RemoteException e) {
405             e.rethrowFromSystemServer();
406         }
407     }
408 
showLockTaskEscapeMessage(IBinder token)409     void showLockTaskEscapeMessage(IBinder token) {
410         try {
411             getActivityClientController().showLockTaskEscapeMessage(token);
412         } catch (RemoteException e) {
413             e.rethrowFromSystemServer();
414         }
415     }
416 
setTaskDescription(IBinder token, ActivityManager.TaskDescription td)417     void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) {
418         try {
419             getActivityClientController().setTaskDescription(token, td);
420         } catch (RemoteException e) {
421             e.rethrowFromSystemServer();
422         }
423     }
424 
showAssistFromActivity(IBinder token, Bundle args)425     boolean showAssistFromActivity(IBinder token, Bundle args) {
426         try {
427             return getActivityClientController().showAssistFromActivity(token, args);
428         } catch (RemoteException e) {
429             throw e.rethrowFromSystemServer();
430         }
431     }
432 
isRootVoiceInteraction(IBinder token)433     boolean isRootVoiceInteraction(IBinder token) {
434         try {
435             return getActivityClientController().isRootVoiceInteraction(token);
436         } catch (RemoteException e) {
437             throw e.rethrowFromSystemServer();
438         }
439     }
440 
startLocalVoiceInteraction(IBinder callingActivity, Bundle options)441     void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
442         try {
443             getActivityClientController().startLocalVoiceInteraction(callingActivity, options);
444         } catch (RemoteException e) {
445             e.rethrowFromSystemServer();
446         }
447     }
448 
stopLocalVoiceInteraction(IBinder callingActivity)449     void stopLocalVoiceInteraction(IBinder callingActivity) {
450         try {
451             getActivityClientController().stopLocalVoiceInteraction(callingActivity);
452         } catch (RemoteException e) {
453             e.rethrowFromSystemServer();
454         }
455     }
456 
setShowWhenLocked(IBinder token, boolean showWhenLocked)457     void setShowWhenLocked(IBinder token, boolean showWhenLocked) {
458         try {
459             getActivityClientController().setShowWhenLocked(token, showWhenLocked);
460         } catch (RemoteException e) {
461             e.rethrowFromSystemServer();
462         }
463     }
464 
setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked)465     void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) {
466         try {
467             getActivityClientController().setInheritShowWhenLocked(token, inheritShowWhenLocked);
468         } catch (RemoteException e) {
469             e.rethrowFromSystemServer();
470         }
471     }
472 
setTurnScreenOn(IBinder token, boolean turnScreenOn)473     void setTurnScreenOn(IBinder token, boolean turnScreenOn) {
474         try {
475             getActivityClientController().setTurnScreenOn(token, turnScreenOn);
476         } catch (RemoteException e) {
477             e.rethrowFromSystemServer();
478         }
479     }
480 
setAllowCrossUidActivitySwitchFromBelow(IBinder token, boolean allowed)481     void setAllowCrossUidActivitySwitchFromBelow(IBinder token, boolean allowed) {
482         try {
483             getActivityClientController().setAllowCrossUidActivitySwitchFromBelow(token, allowed);
484         } catch (RemoteException e) {
485             e.rethrowFromSystemServer();
486         }
487     }
488 
setVrMode(IBinder token, boolean enabled, ComponentName packageName)489     int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
490         try {
491             return getActivityClientController().setVrMode(token, enabled, packageName);
492         } catch (RemoteException e) {
493             throw e.rethrowFromSystemServer();
494         }
495     }
496 
overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim, int backgroundColor)497     void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim,
498             int backgroundColor) {
499         try {
500             getActivityClientController().overrideActivityTransition(
501                     token, open, enterAnim, exitAnim, backgroundColor);
502         } catch (RemoteException e) {
503             e.rethrowFromSystemServer();
504         }
505     }
506 
clearOverrideActivityTransition(IBinder token, boolean open)507     void clearOverrideActivityTransition(IBinder token, boolean open) {
508         try {
509             getActivityClientController().clearOverrideActivityTransition(token, open);
510         } catch (RemoteException e) {
511             e.rethrowFromSystemServer();
512         }
513     }
514 
overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim, int backgroundColor)515     void overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim,
516             int backgroundColor) {
517         try {
518             getActivityClientController().overridePendingTransition(token, packageName,
519                     enterAnim, exitAnim, backgroundColor);
520         } catch (RemoteException e) {
521             e.rethrowFromSystemServer();
522         }
523     }
524 
setRecentsScreenshotEnabled(IBinder token, boolean enabled)525     void setRecentsScreenshotEnabled(IBinder token, boolean enabled) {
526         try {
527             getActivityClientController().setRecentsScreenshotEnabled(token, enabled);
528         } catch (RemoteException e) {
529             e.rethrowFromSystemServer();
530         }
531     }
532 
533     /**
534      * Removes the outdated snapshot of the home task.
535      *
536      * @param homeToken The token of the home task, or null if you have the
537      *                  {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS} permission and
538      *                  want us to find the home task token for you.
539      */
invalidateHomeTaskSnapshot(IBinder homeToken)540     public void invalidateHomeTaskSnapshot(IBinder homeToken) {
541         try {
542             getActivityClientController().invalidateHomeTaskSnapshot(homeToken);
543         } catch (RemoteException e) {
544             e.rethrowFromSystemServer();
545         }
546     }
547 
dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)548     void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
549             CharSequence message) {
550         try {
551             getActivityClientController().dismissKeyguard(token, callback, message);
552         } catch (RemoteException e) {
553             e.rethrowFromSystemServer();
554         }
555     }
556 
registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition)557     void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
558         try {
559             getActivityClientController().registerRemoteAnimations(token, definition);
560         } catch (RemoteException e) {
561             e.rethrowFromSystemServer();
562         }
563     }
564 
unregisterRemoteAnimations(IBinder token)565     void unregisterRemoteAnimations(IBinder token) {
566         try {
567             getActivityClientController().unregisterRemoteAnimations(token);
568         } catch (RemoteException e) {
569             e.rethrowFromSystemServer();
570         }
571     }
572 
onBackPressed(IBinder token, IRequestFinishCallback callback)573     void onBackPressed(IBinder token, IRequestFinishCallback callback) {
574         try {
575             getActivityClientController().onBackPressed(token, callback);
576         } catch (RemoteException e) {
577             e.rethrowFromSystemServer();
578         }
579     }
580 
581     /**
582      * Reports the splash screen view has attached to client.
583      */
reportSplashScreenAttached(IBinder token)584     void reportSplashScreenAttached(IBinder token) {
585         try {
586             getActivityClientController().splashScreenAttached(token);
587         } catch (RemoteException e) {
588             e.rethrowFromSystemServer();
589         }
590     }
591 
enableTaskLocaleOverride(IBinder token)592     void enableTaskLocaleOverride(IBinder token) {
593         try {
594             getActivityClientController().enableTaskLocaleOverride(token);
595         } catch (RemoteException e) {
596             e.rethrowFromSystemServer();
597         }
598     }
599 
600     /**
601      * Returns {@code true} if the activity was explicitly requested to be launched in the
602      * TaskFragment.
603      *
604      * @param activityToken The token of the Activity.
605      * @param taskFragmentToken The token of the TaskFragment.
606      */
isRequestedToLaunchInTaskFragment(IBinder activityToken, IBinder taskFragmentToken)607     public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken,
608             IBinder taskFragmentToken) {
609         try {
610             return getActivityClientController().isRequestedToLaunchInTaskFragment(activityToken,
611                     taskFragmentToken);
612         } catch (RemoteException e) {
613             throw e.rethrowFromSystemServer();
614         }
615     }
616 
617     /**
618      * Shows or hides a Camera app compat toggle for stretched issues with the requested state.
619      *
620      * @param token The token for the window that needs a control.
621      * @param showControl Whether the control should be shown or hidden.
622      * @param transformationApplied Whether the treatment is already applied.
623      * @param callback The callback executed when the user clicks on a control.
624      */
requestCompatCameraControl(Resources res, IBinder token, boolean showControl, boolean transformationApplied, ICompatCameraControlCallback callback)625     void requestCompatCameraControl(Resources res, IBinder token, boolean showControl,
626             boolean transformationApplied, ICompatCameraControlCallback callback) {
627         if (!res.getBoolean(com.android.internal.R.bool
628                 .config_isCameraCompatControlForStretchedIssuesEnabled)) {
629             return;
630         }
631         try {
632             getActivityClientController().requestCompatCameraControl(
633                     token, showControl, transformationApplied, callback);
634         } catch (RemoteException e) {
635             e.rethrowFromSystemServer();
636         }
637     }
638 
getInstance()639     public static ActivityClient getInstance() {
640         return sInstance.get();
641     }
642 
643     /**
644      * If system server has passed the controller interface, store it so the subsequent access can
645      * speed up.
646      */
setActivityClientController( IActivityClientController activityClientController)647     public static IActivityClientController setActivityClientController(
648             IActivityClientController activityClientController) {
649         // No lock because it is no harm to encounter race condition. The thread safe Singleton#get
650         // will take over that case.
651         return INTERFACE_SINGLETON.mKnownInstance = activityClientController;
652     }
653 
getActivityClientController()654     private static IActivityClientController getActivityClientController() {
655         final IActivityClientController controller = INTERFACE_SINGLETON.mKnownInstance;
656         return controller != null ? controller : INTERFACE_SINGLETON.get();
657     }
658 
659     private static final Singleton<ActivityClient> sInstance = new Singleton<ActivityClient>() {
660         @Override
661         protected ActivityClient create() {
662             return new ActivityClient();
663         }
664     };
665 
666     private static final ActivityClientControllerSingleton INTERFACE_SINGLETON =
667             new ActivityClientControllerSingleton();
668 
669     private static class ActivityClientControllerSingleton
670             extends Singleton<IActivityClientController> {
671         /**
672          * A quick look up to reduce potential extra binder transactions. E.g. getting activity
673          * task manager from service manager and controller from activity task manager.
674          */
675         IActivityClientController mKnownInstance;
676 
677         @Override
create()678         protected IActivityClientController create() {
679             try {
680                 return ActivityTaskManager.getService().getActivityClientController();
681             } catch (RemoteException e) {
682                 throw e.rethrowFromSystemServer();
683             }
684         }
685     }
686 }
687