• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2015 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 package com.android.server.vr;
17 
18 import static android.view.Display.INVALID_DISPLAY;
19 
20 import android.Manifest;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.app.ActivityManager;
24 import android.app.ActivityManagerInternal;
25 import android.app.AppOpsManager;
26 import android.app.INotificationManager;
27 import android.app.NotificationManager;
28 import android.app.Vr2dDisplayProperties;
29 import android.content.BroadcastReceiver;
30 import android.content.ComponentName;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.content.pm.ApplicationInfo;
36 import android.content.pm.PackageManager;
37 import android.content.pm.PackageManager.NameNotFoundException;
38 import android.hardware.display.DisplayManager;
39 import android.os.Binder;
40 import android.os.Handler;
41 import android.os.IBinder;
42 import android.os.IInterface;
43 import android.os.Looper;
44 import android.os.Message;
45 import android.os.PackageTagsList;
46 import android.os.RemoteCallbackList;
47 import android.os.RemoteException;
48 import android.os.ServiceManager;
49 import android.os.SystemProperties;
50 import android.os.UserHandle;
51 import android.provider.Settings;
52 import android.service.notification.NotificationListenerService;
53 import android.service.vr.IPersistentVrStateCallbacks;
54 import android.service.vr.IVrListener;
55 import android.service.vr.IVrManager;
56 import android.service.vr.IVrStateCallbacks;
57 import android.service.vr.VrListenerService;
58 import android.text.TextUtils;
59 import android.util.ArrayMap;
60 import android.util.ArraySet;
61 import android.util.Slog;
62 import android.util.SparseArray;
63 
64 import com.android.internal.R;
65 import com.android.internal.util.DumpUtils;
66 import com.android.server.FgThread;
67 import com.android.server.LocalServices;
68 import com.android.server.SystemConfig;
69 import com.android.server.SystemService;
70 import com.android.server.utils.ManagedApplicationService;
71 import com.android.server.utils.ManagedApplicationService.BinderChecker;
72 import com.android.server.utils.ManagedApplicationService.LogEvent;
73 import com.android.server.utils.ManagedApplicationService.LogFormattable;
74 import com.android.server.utils.ManagedApplicationService.PendingEvent;
75 import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
76 import com.android.server.wm.ActivityTaskManagerInternal;
77 import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
78 import com.android.server.wm.WindowManagerInternal;
79 
80 import java.io.FileDescriptor;
81 import java.io.PrintWriter;
82 import java.text.SimpleDateFormat;
83 import java.util.ArrayDeque;
84 import java.util.ArrayList;
85 import java.util.Arrays;
86 import java.util.Collection;
87 import java.util.Date;
88 import java.util.List;
89 import java.util.Objects;
90 
91 /**
92  * Service tracking whether VR mode is active, and notifying listening services of state changes.
93  * <p/>
94  * Services running in system server may modify the state of VrManagerService via the interface in
95  * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
96  * interface given in VrStateListener.
97  * <p/>
98  * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
99  *  hardware/libhardware/modules/vr
100  * <p/>
101  * In general applications may enable or disable VR mode by calling
102  * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
103  * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
104  *
105  * @see android.service.vr.VrListenerService
106  * @see com.android.server.vr.VrManagerInternal
107  * @see com.android.server.vr.VrStateListener
108  *
109  * @hide
110  */
111 public class VrManagerService extends SystemService
112         implements EnabledComponentChangeListener, ScreenObserver {
113 
114     public static final String TAG = "VrManagerService";
115     static final boolean DBG = false;
116 
117     private static final int PENDING_STATE_DELAY_MS = 300;
118     private static final int EVENT_LOG_SIZE = 64;
119     private static final int INVALID_APPOPS_MODE = -1;
120     /** Null set of sleep sleep flags. */
121     private static final int FLAG_NONE = 0;
122     /** Flag set when the device is not sleeping. */
123     private static final int FLAG_AWAKE = 1 << 0;
124     /** Flag set when the screen has been turned on. */
125     private static final int FLAG_SCREEN_ON = 1 << 1;
126     /** Flag set when the keyguard is not active. */
127     private static final int FLAG_KEYGUARD_UNLOCKED = 1 << 2;
128     /** Flag indicating that all system sleep flags have been set.*/
129     private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON | FLAG_KEYGUARD_UNLOCKED;
130 
initializeNative()131     private static native void initializeNative();
setVrModeNative(boolean enabled)132     private static native void setVrModeNative(boolean enabled);
133 
134     private final Object mLock = new Object();
135 
136     private final IBinder mOverlayToken = new Binder();
137 
138     // State protected by mLock
139     private boolean mVrModeAllowed;
140     private boolean mVrModeEnabled;
141     private boolean mPersistentVrModeEnabled;
142     private boolean mRunning2dInVr;
143     private int mVrAppProcessId;
144     private EnabledComponentsObserver mComponentObserver;
145     private ManagedApplicationService mCurrentVrService;
146     private ManagedApplicationService mCurrentVrCompositorService;
147     private ComponentName mDefaultVrService;
148     private Context mContext;
149     private ComponentName mCurrentVrModeComponent;
150     private int mCurrentVrModeUser;
151     private boolean mWasDefaultGranted;
152     private boolean mGuard;
153     private final RemoteCallbackList<IVrStateCallbacks> mVrStateRemoteCallbacks =
154             new RemoteCallbackList<>();
155     private final RemoteCallbackList<IPersistentVrStateCallbacks>
156             mPersistentVrStateRemoteCallbacks = new RemoteCallbackList<>();
157     private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
158     private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
159     private VrState mPendingState;
160     private boolean mLogLimitHit;
161     private final ArrayDeque<LogFormattable> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
162     private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
163     private INotificationManager mNotificationManager;
164     /** Tracks the state of the screen and keyguard UI.*/
165     private int mSystemSleepFlags = FLAG_AWAKE | FLAG_KEYGUARD_UNLOCKED;
166     /**
167      * Set when ACTION_USER_UNLOCKED is fired. We shouldn't try to bind to the
168      * vr service before then. This gets set only once the first time the user unlocks the device
169      * and stays true thereafter.
170      */
171     private boolean mUserUnlocked;
172     private Vr2dDisplay mVr2dDisplay;
173     private boolean mBootsToVr;
174     private boolean mStandby;
175     private boolean mUseStandbyToExitVrMode;
176 
177     // Handles events from the managed services (e.g. VrListenerService and any bound VR compositor
178     // service).
179     private final ManagedApplicationService.EventCallback mEventCallback
180                 = new ManagedApplicationService.EventCallback() {
181         @Override
182         public void onServiceEvent(LogEvent event) {
183             logEvent(event);
184 
185             ComponentName component = null;
186             synchronized (mLock) {
187                 component = ((mCurrentVrService == null) ? null : mCurrentVrService.getComponent());
188 
189                 // If the VrCore main service was disconnected or the binding died we'll rebind
190                 // automatically. Call focusedActivityChanged() once we rebind.
191                 if (component != null && component.equals(event.component) &&
192                         (event.event == LogEvent.EVENT_DISCONNECTED ||
193                          event.event == LogEvent.EVENT_BINDING_DIED)) {
194                     callFocusedActivityChangedLocked();
195                 }
196             }
197 
198             // If not on an AIO device and we permanently stopped trying to connect to the
199             // VrListenerService (or don't have one bound), leave persistent VR mode and VR mode.
200             if (!mBootsToVr && event.event == LogEvent.EVENT_STOPPED_PERMANENTLY &&
201                     (component == null || component.equals(event.component))) {
202                 Slog.e(TAG, "VrListenerSevice has died permanently, leaving system VR mode.");
203                 // We're not a native VR device.  Leave VR + persistent mode.
204                 setPersistentVrModeEnabled(false);
205             }
206         }
207     };
208 
209     private static final int MSG_VR_STATE_CHANGE = 0;
210     private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
211     private static final int MSG_PERSISTENT_VR_MODE_STATE_CHANGE = 2;
212 
213     /**
214      * Set whether VR mode may be enabled.
215      * <p/>
216      * If VR mode is not allowed to be enabled, calls to set VR mode will be cached.  When VR mode
217      * is again allowed to be enabled, the most recent cached state will be applied.
218      *
219      */
updateVrModeAllowedLocked()220     private void updateVrModeAllowedLocked() {
221         boolean ignoreSleepFlags = mBootsToVr && mUseStandbyToExitVrMode;
222         boolean disallowedByStandby = mStandby && mUseStandbyToExitVrMode;
223         boolean allowed = (mSystemSleepFlags == FLAG_ALL || ignoreSleepFlags) && mUserUnlocked
224                 && !disallowedByStandby;
225         if (mVrModeAllowed != allowed) {
226             mVrModeAllowed = allowed;
227             if (DBG) Slog.d(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
228             if (mVrModeAllowed) {
229                 if (mBootsToVr) {
230                     setPersistentVrModeEnabled(true);
231                 }
232                 if (mBootsToVr && !mVrModeEnabled) {
233                   setVrMode(true, mDefaultVrService, 0, -1, null);
234                 }
235             } else {
236                 // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
237                 // exit persistent VR mode when screen is turned off.
238                 setPersistentModeAndNotifyListenersLocked(false);
239 
240                 // Set pending state to current state.
241                 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
242                     ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
243                         mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
244                     : null;
245 
246                 // Unbind current VR service and do necessary callbacks.
247                 updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
248             }
249         }
250     }
251 
setScreenOn(boolean isScreenOn)252     private void setScreenOn(boolean isScreenOn) {
253         setSystemState(FLAG_SCREEN_ON, isScreenOn);
254     }
255 
256     @Override
onAwakeStateChanged(boolean isAwake)257     public void onAwakeStateChanged(boolean isAwake) {
258         setSystemState(FLAG_AWAKE, isAwake);
259     }
260 
261     @Override
onKeyguardStateChanged(boolean isShowing)262     public void onKeyguardStateChanged(boolean isShowing) {
263         setSystemState(FLAG_KEYGUARD_UNLOCKED, !isShowing);
264     }
265 
setSystemState(int flags, boolean isOn)266     private void setSystemState(int flags, boolean isOn) {
267         synchronized(mLock) {
268             int oldState = mSystemSleepFlags;
269             if (isOn) {
270                 mSystemSleepFlags |= flags;
271             } else {
272                 mSystemSleepFlags &= ~flags;
273             }
274             if (oldState != mSystemSleepFlags) {
275                 if (DBG) Slog.d(TAG, "System state: " + getStateAsString());
276                 updateVrModeAllowedLocked();
277             }
278         }
279     }
280 
getStateAsString()281     private String getStateAsString() {
282         return new StringBuilder()
283                 .append((mSystemSleepFlags & FLAG_AWAKE) != 0 ? "awake, " : "")
284                 .append((mSystemSleepFlags & FLAG_SCREEN_ON) != 0 ? "screen_on, " : "")
285                 .append((mSystemSleepFlags & FLAG_KEYGUARD_UNLOCKED) != 0 ? "keyguard_off" : "")
286                 .toString();
287     }
288 
setUserUnlocked()289     private void setUserUnlocked() {
290         synchronized(mLock) {
291             mUserUnlocked = true;
292             updateVrModeAllowedLocked();
293         }
294     }
295 
setStandbyEnabled(boolean standby)296     private void setStandbyEnabled(boolean standby) {
297         synchronized(mLock) {
298             if (!mBootsToVr) {
299                 Slog.e(TAG, "Attempting to set standby mode on a non-standalone device");
300                 return;
301             }
302             mStandby = standby;
303             updateVrModeAllowedLocked();
304         }
305     }
306 
307     private final Handler mHandler = new Handler() {
308         @Override
309         public void handleMessage(Message msg) {
310             switch(msg.what) {
311                 case MSG_VR_STATE_CHANGE : {
312                     boolean state = (msg.arg1 == 1);
313                     int i = mVrStateRemoteCallbacks.beginBroadcast();
314                     while (i > 0) {
315                         i--;
316                         try {
317                             mVrStateRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
318                         } catch (RemoteException e) {
319                             // Noop
320                         }
321                     }
322                     mVrStateRemoteCallbacks.finishBroadcast();
323                 } break;
324                 case MSG_PENDING_VR_STATE_CHANGE : {
325                     synchronized(mLock) {
326                         if (mVrModeAllowed) {
327                            VrManagerService.this.consumeAndApplyPendingStateLocked();
328                         }
329                     }
330                 } break;
331                 case MSG_PERSISTENT_VR_MODE_STATE_CHANGE : {
332                     boolean state = (msg.arg1 == 1);
333                     int i = mPersistentVrStateRemoteCallbacks.beginBroadcast();
334                     while (i > 0) {
335                         i--;
336                         try {
337                             mPersistentVrStateRemoteCallbacks.getBroadcastItem(i)
338                                     .onPersistentVrStateChanged(state);
339                         } catch (RemoteException e) {
340                             // Noop
341                         }
342                     }
343                     mPersistentVrStateRemoteCallbacks.finishBroadcast();
344                 } break;
345                 default :
346                     throw new IllegalStateException("Unknown message type: " + msg.what);
347             }
348         }
349     };
350 
351     // Event used to log when settings are changed for dumpsys logs.
352     private static class SettingEvent implements LogFormattable {
353         public final long timestamp;
354         public final String what;
355 
SettingEvent(String what)356         SettingEvent(String what) {
357             this.timestamp = System.currentTimeMillis();
358             this.what = what;
359         }
360 
361         @Override
toLogString(SimpleDateFormat dateFormat)362         public String toLogString(SimpleDateFormat dateFormat) {
363             return dateFormat.format(new Date(timestamp)) + "   " + what;
364         }
365     }
366 
367     // Event used to track changes of the primary on-screen VR activity.
368     private static class VrState implements LogFormattable {
369         final boolean enabled;
370         final boolean running2dInVr;
371         final int userId;
372         final int processId;
373         final ComponentName targetPackageName;
374         final ComponentName callingPackage;
375         final long timestamp;
376         final boolean defaultPermissionsGranted;
377 
VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId, int processId, ComponentName callingPackage)378         VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
379                 int processId, ComponentName callingPackage) {
380             this.enabled = enabled;
381             this.running2dInVr = running2dInVr;
382             this.userId = userId;
383             this.processId = processId;
384             this.targetPackageName = targetPackageName;
385             this.callingPackage = callingPackage;
386             this.defaultPermissionsGranted = false;
387             this.timestamp = System.currentTimeMillis();
388         }
389 
VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId, int processId, ComponentName callingPackage, boolean defaultPermissionsGranted)390         VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
391             int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
392             this.enabled = enabled;
393             this.running2dInVr = running2dInVr;
394             this.userId = userId;
395             this.processId = processId;
396             this.targetPackageName = targetPackageName;
397             this.callingPackage = callingPackage;
398             this.defaultPermissionsGranted = defaultPermissionsGranted;
399             this.timestamp = System.currentTimeMillis();
400         }
401 
402         @Override
toLogString(SimpleDateFormat dateFormat)403         public String toLogString(SimpleDateFormat dateFormat) {
404             String tab = "  ";
405             String newLine = "\n";
406             StringBuilder sb = new StringBuilder(dateFormat.format(new Date(timestamp)));
407             sb.append(tab);
408             sb.append("State changed to:");
409             sb.append(tab);
410             sb.append((enabled) ? "ENABLED" : "DISABLED");
411             sb.append(newLine);
412             if (enabled) {
413                 sb.append(tab);
414                 sb.append("User=");
415                 sb.append(userId);
416                 sb.append(newLine);
417                 sb.append(tab);
418                 sb.append("Current VR Activity=");
419                 sb.append((callingPackage == null) ? "None" : callingPackage.flattenToString());
420                 sb.append(newLine);
421                 sb.append(tab);
422                 sb.append("Bound VrListenerService=");
423                 sb.append((targetPackageName == null) ? "None"
424                         : targetPackageName.flattenToString());
425                 sb.append(newLine);
426                 if (defaultPermissionsGranted) {
427                     sb.append(tab);
428                     sb.append("Default permissions granted to the bound VrListenerService.");
429                     sb.append(newLine);
430                 }
431             }
432             return sb.toString();
433         }
434     }
435 
436     private static final BinderChecker sBinderChecker = new BinderChecker() {
437         @Override
438         public IInterface asInterface(IBinder binder) {
439             return IVrListener.Stub.asInterface(binder);
440         }
441 
442         @Override
443         public boolean checkType(IInterface service) {
444             return service instanceof IVrListener;
445         }
446     };
447 
448     private final class NotificationAccessManager {
449         private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
450         private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
451                 new ArrayMap<>();
452 
update(Collection<String> packageNames)453         public void update(Collection<String> packageNames) {
454             int currentUserId = ActivityManager.getCurrentUser();
455 
456             ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
457             if (allowed == null) {
458                 allowed = new ArraySet<>();
459             }
460 
461             // Make sure we revoke notification access for listeners in other users
462             final int listenerCount = mNotificationAccessPackageToUserId.size();
463             for (int i = listenerCount - 1; i >= 0; i--) {
464                 final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
465                 if (grantUserId != currentUserId) {
466                     String packageName = mNotificationAccessPackageToUserId.keyAt(i);
467                     revokeNotificationListenerAccess(packageName, grantUserId);
468                     revokeNotificationPolicyAccess(packageName);
469                     revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
470                     mNotificationAccessPackageToUserId.removeAt(i);
471                 }
472             }
473 
474             for (String pkg : allowed) {
475                 if (!packageNames.contains(pkg)) {
476                     revokeNotificationListenerAccess(pkg, currentUserId);
477                     revokeNotificationPolicyAccess(pkg);
478                     revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
479                     mNotificationAccessPackageToUserId.remove(pkg);
480                 }
481             }
482             for (String pkg : packageNames) {
483                 if (!allowed.contains(pkg)) {
484                     grantNotificationPolicyAccess(pkg);
485                     grantNotificationListenerAccess(pkg, currentUserId);
486                     grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
487                     mNotificationAccessPackageToUserId.put(pkg, currentUserId);
488                 }
489             }
490 
491             allowed.clear();
492             allowed.addAll(packageNames);
493             mAllowedPackages.put(currentUserId, allowed);
494         }
495     }
496 
497     /**
498      * Called when a user, package, or setting changes that could affect whether or not the
499      * currently bound VrListenerService is changed.
500      */
501     @Override
onEnabledComponentChanged()502     public void onEnabledComponentChanged() {
503         synchronized (mLock) {
504             int currentUser = ActivityManager.getCurrentUser();
505             // Update listeners
506             ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
507 
508             ArraySet<String> enabledPackages = new ArraySet<>();
509             for (ComponentName n : enabledListeners) {
510                 String pkg = n.getPackageName();
511                 if (isDefaultAllowed(pkg)) {
512                     enabledPackages.add(n.getPackageName());
513                 }
514             }
515             mNotifAccessManager.update(enabledPackages);
516 
517             if (!mVrModeAllowed) {
518                 return; // Don't do anything, we shouldn't be in VR mode.
519             }
520 
521             // If there is a pending state change, we'd better deal with that first
522             consumeAndApplyPendingStateLocked(false);
523 
524             if (mCurrentVrService == null) {
525                 return; // No active services
526             }
527 
528             // There is an active service, update it if needed
529             updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
530                     mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
531                     mVrAppProcessId, mCurrentVrModeComponent);
532         }
533     }
534 
535     private final IVrManager mVrManager = new IVrManager.Stub() {
536 
537         @Override
538         public void registerListener(IVrStateCallbacks cb) {
539             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
540                     Manifest.permission.ACCESS_VR_STATE);
541             if (cb == null) {
542                 throw new IllegalArgumentException("Callback binder object is null.");
543             }
544 
545             VrManagerService.this.addStateCallback(cb);
546         }
547 
548         @Override
549         public void unregisterListener(IVrStateCallbacks cb) {
550             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
551                     Manifest.permission.ACCESS_VR_STATE);
552             if (cb == null) {
553                 throw new IllegalArgumentException("Callback binder object is null.");
554             }
555 
556             VrManagerService.this.removeStateCallback(cb);
557         }
558 
559         @Override
560         public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
561             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
562                     Manifest.permission.ACCESS_VR_STATE);
563             if (cb == null) {
564                 throw new IllegalArgumentException("Callback binder object is null.");
565             }
566 
567             VrManagerService.this.addPersistentStateCallback(cb);
568         }
569 
570         @Override
571         public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
572             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
573                     Manifest.permission.ACCESS_VR_STATE);
574             if (cb == null) {
575                 throw new IllegalArgumentException("Callback binder object is null.");
576             }
577 
578             VrManagerService.this.removePersistentStateCallback(cb);
579         }
580 
581         @Override
582         public boolean getVrModeState() {
583             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
584                     Manifest.permission.ACCESS_VR_STATE);
585             return VrManagerService.this.getVrMode();
586         }
587 
588         @Override
589         public boolean getPersistentVrModeEnabled() {
590             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
591                     Manifest.permission.ACCESS_VR_STATE);
592             return VrManagerService.this.getPersistentVrMode();
593         }
594 
595         @Override
596         public void setPersistentVrModeEnabled(boolean enabled) {
597             enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
598             VrManagerService.this.setPersistentVrModeEnabled(enabled);
599         }
600 
601         @Override
602         public void setVr2dDisplayProperties(
603                 Vr2dDisplayProperties vr2dDisplayProp) {
604             enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
605             VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
606         }
607 
608         @Override
609         public int getVr2dDisplayId() {
610             return VrManagerService.this.getVr2dDisplayId();
611         }
612 
613         @Override
614         public void setAndBindCompositor(String componentName) {
615             enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
616             VrManagerService.this.setAndBindCompositor(
617                 (componentName == null) ? null : ComponentName.unflattenFromString(componentName));
618         }
619 
620         @Override
621         public void setStandbyEnabled(boolean standby) {
622             enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER);
623             VrManagerService.this.setStandbyEnabled(standby);
624         }
625 
626         @Override
627         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
628             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
629 
630             pw.println("********* Dump of VrManagerService *********");
631             pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
632             pw.println("Persistent VR mode is currently: " +
633                     ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
634             pw.println("Currently bound VR listener service: "
635                     + ((mCurrentVrService == null)
636                     ? "None" : mCurrentVrService.getComponent().flattenToString()));
637             pw.println("Currently bound VR compositor service: "
638                     + ((mCurrentVrCompositorService == null)
639                     ? "None" : mCurrentVrCompositorService.getComponent().flattenToString()));
640             pw.println("Previous state transitions:\n");
641             String tab = "  ";
642             dumpStateTransitions(pw);
643             pw.println("\n\nRemote Callbacks:");
644             int i=mVrStateRemoteCallbacks.beginBroadcast(); // create the broadcast item array
645             while(i-->0) {
646                 pw.print(tab);
647                 pw.print(mVrStateRemoteCallbacks.getBroadcastItem(i));
648                 if (i>0) pw.println(",");
649             }
650             mVrStateRemoteCallbacks.finishBroadcast();
651             pw.println("\n\nPersistent Vr State Remote Callbacks:");
652             i=mPersistentVrStateRemoteCallbacks.beginBroadcast();
653             while(i-->0) {
654                 pw.print(tab);
655                 pw.print(mPersistentVrStateRemoteCallbacks.getBroadcastItem(i));
656                 if (i>0) pw.println(",");
657             }
658             mPersistentVrStateRemoteCallbacks.finishBroadcast();
659             pw.println("\n");
660             pw.println("Installed VrListenerService components:");
661             int userId = mCurrentVrModeUser;
662             ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
663             if (installed == null || installed.size() == 0) {
664                 pw.println("None");
665             } else {
666                 for (ComponentName n : installed) {
667                     pw.print(tab);
668                     pw.println(n.flattenToString());
669                 }
670             }
671             pw.println("Enabled VrListenerService components:");
672             ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
673             if (enabled == null || enabled.size() == 0) {
674                 pw.println("None");
675             } else {
676                 for (ComponentName n : enabled) {
677                     pw.print(tab);
678                     pw.println(n.flattenToString());
679                 }
680             }
681             pw.println("\n");
682             pw.println("********* End of VrManagerService Dump *********");
683         }
684 
685     };
686 
687     /**
688      * Enforces that at lease one of the specified permissions is held by the caller.
689      * Throws SecurityException if none of the specified permissions are held.
690      *
691      * @param permissions One or more permissions to check against.
692      */
enforceCallerPermissionAnyOf(String... permissions)693     private void enforceCallerPermissionAnyOf(String... permissions) {
694         for (String permission : permissions) {
695             if (mContext.checkCallingOrSelfPermission(permission)
696                     == PackageManager.PERMISSION_GRANTED) {
697                 return;
698             }
699         }
700         throw new SecurityException("Caller does not hold at least one of the permissions: "
701                 + Arrays.toString(permissions));
702     }
703 
704     /**
705      * Implementation of VrManagerInternal.  Callable only from system services.
706      */
707     private final class LocalService extends VrManagerInternal {
708         @Override
setVrMode(boolean enabled, ComponentName packageName, int userId, int processId, ComponentName callingPackage)709         public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
710                 ComponentName callingPackage) {
711             VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
712         }
713 
714         @Override
onScreenStateChanged(boolean isScreenOn)715         public void onScreenStateChanged(boolean isScreenOn) {
716             VrManagerService.this.setScreenOn(isScreenOn);
717         }
718 
719         @Override
isCurrentVrListener(String packageName, int userId)720         public boolean isCurrentVrListener(String packageName, int userId) {
721             return VrManagerService.this.isCurrentVrListener(packageName, userId);
722         }
723 
724         @Override
hasVrPackage(ComponentName packageName, int userId)725         public int hasVrPackage(ComponentName packageName, int userId) {
726             return VrManagerService.this.hasVrPackage(packageName, userId);
727         }
728 
729         @Override
setPersistentVrModeEnabled(boolean enabled)730         public void setPersistentVrModeEnabled(boolean enabled) {
731             VrManagerService.this.setPersistentVrModeEnabled(enabled);
732         }
733 
734         @Override
setVr2dDisplayProperties( Vr2dDisplayProperties compatDisplayProp)735         public void setVr2dDisplayProperties(
736             Vr2dDisplayProperties compatDisplayProp) {
737             VrManagerService.this.setVr2dDisplayProperties(compatDisplayProp);
738         }
739 
740         @Override
getVr2dDisplayId()741         public int getVr2dDisplayId() {
742             return VrManagerService.this.getVr2dDisplayId();
743         }
744 
745         @Override
addPersistentVrModeStateListener(IPersistentVrStateCallbacks listener)746         public void addPersistentVrModeStateListener(IPersistentVrStateCallbacks listener) {
747             VrManagerService.this.addPersistentStateCallback(listener);
748         }
749     }
750 
VrManagerService(Context context)751     public VrManagerService(Context context) {
752         super(context);
753     }
754 
755     @Override
onStart()756     public void onStart() {
757         synchronized(mLock) {
758             initializeNative();
759             mContext = getContext();
760         }
761 
762         mBootsToVr = SystemProperties.getBoolean("ro.boot.vr", false);
763         mUseStandbyToExitVrMode = mBootsToVr
764                 && SystemProperties.getBoolean("persist.vr.use_standby_to_exit_vr_mode", true);
765         publishLocalService(VrManagerInternal.class, new LocalService());
766         publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
767     }
768 
769     @Override
onBootPhase(int phase)770     public void onBootPhase(int phase) {
771         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
772             LocalServices.getService(ActivityTaskManagerInternal.class)
773                     .registerScreenObserver(this);
774 
775             mNotificationManager = INotificationManager.Stub.asInterface(
776                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
777             synchronized (mLock) {
778                 Looper looper = Looper.getMainLooper();
779                 Handler handler = new Handler(looper);
780                 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
781                 listeners.add(this);
782                 mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
783                         Settings.Secure.ENABLED_VR_LISTENERS, looper,
784                         android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
785                         VrListenerService.SERVICE_INTERFACE, mLock, listeners);
786 
787                 mComponentObserver.rebuildAll();
788             }
789 
790             //TODO: something more robust than picking the first one
791             ArraySet<ComponentName> defaultVrComponents =
792                     SystemConfig.getInstance().getDefaultVrComponents();
793             if (defaultVrComponents.size() > 0) {
794                 mDefaultVrService = defaultVrComponents.valueAt(0);
795             } else {
796                 Slog.i(TAG, "No default vr listener service found.");
797             }
798 
799             DisplayManager dm =
800                     (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
801             mVr2dDisplay = new Vr2dDisplay(
802                     dm,
803                     LocalServices.getService(ActivityManagerInternal.class),
804                     LocalServices.getService(WindowManagerInternal.class),
805                     mVrManager);
806             mVr2dDisplay.init(getContext(), mBootsToVr);
807 
808             IntentFilter intentFilter = new IntentFilter();
809             intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
810             getContext().registerReceiver(new BroadcastReceiver() {
811                     @Override
812                     public void onReceive(Context context, Intent intent) {
813                         if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
814                             VrManagerService.this.setUserUnlocked();
815                         }
816                     }
817                 }, intentFilter);
818         }
819     }
820 
821     @Override
onUserStarting(@onNull TargetUser user)822     public void onUserStarting(@NonNull TargetUser user) {
823         synchronized (mLock) {
824             mComponentObserver.onUsersChanged();
825         }
826     }
827 
828     @Override
onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)829     public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
830         FgThread.getHandler().post(() -> {
831             synchronized (mLock) {
832                 mComponentObserver.onUsersChanged();
833             }
834         });
835 
836     }
837 
838     @Override
onUserStopping(@onNull TargetUser user)839     public void onUserStopping(@NonNull TargetUser user) {
840         synchronized (mLock) {
841             mComponentObserver.onUsersChanged();
842         }
843 
844     }
845 
846     @Override
onUserStopped(@onNull TargetUser user)847     public void onUserStopped(@NonNull TargetUser user) {
848         synchronized (mLock) {
849             mComponentObserver.onUsersChanged();
850         }
851     }
852 
updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId)853     private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
854         AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
855 
856         // If user changed drop restrictions for the old user.
857         if (oldUserId != newUserId) {
858             appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
859                     false, mOverlayToken, null, oldUserId);
860         }
861 
862         // Apply the restrictions for the current user based on vr state
863         PackageTagsList exemptions = null;
864         if (exemptedPackage != null) {
865             exemptions = new PackageTagsList.Builder(1).add(exemptedPackage).build();
866         }
867 
868         appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
869                 mVrModeEnabled, mOverlayToken, exemptions, newUserId);
870     }
871 
updateDependentAppOpsLocked(String newVrServicePackage, int newUserId, String oldVrServicePackage, int oldUserId)872     private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
873             String oldVrServicePackage, int oldUserId) {
874         // If VR state changed and we also have a VR service change.
875         if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
876             return;
877         }
878         final long identity = Binder.clearCallingIdentity();
879         try {
880             // Set overlay exception state based on VR enabled and current service
881             updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
882         } finally {
883             Binder.restoreCallingIdentity(identity);
884         }
885     }
886 
887     /**
888      * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
889      * the currently selected VR listener service.  If the component selected for the VR listener
890      * service has changed, unbind the previous listener and bind the new listener (if enabled).
891      * <p/>
892      * Note: Must be called while holding {@code mLock}.
893      *
894      * @param enabled new state for VR mode.
895      * @param running2dInVr true if we have a top-level 2D intent.
896      * @param component new component to be bound as a VR listener.
897      * @param userId user owning the component to be bound.
898      * @param processId the process hosting the activity specified by calling.
899      * @param calling the component currently using VR mode or a 2D intent.
900      *
901      * @return {@code true} if the component/user combination specified is valid.
902      */
updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr, @NonNull ComponentName component, int userId, int processId, ComponentName calling)903     private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
904             @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
905 
906         boolean sendUpdatedCaller = false;
907         final long identity = Binder.clearCallingIdentity();
908         try {
909 
910             boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
911                     EnabledComponentsObserver.NO_ERROR);
912             boolean goingIntoVrMode = validUserComponent && enabled;
913             if (!mVrModeEnabled && !goingIntoVrMode) {
914                 return validUserComponent; // Disabled -> Disabled transition does nothing.
915             }
916 
917             String oldVrServicePackage = mCurrentVrService != null
918                     ? mCurrentVrService.getComponent().getPackageName() : null;
919             final int oldUserId = mCurrentVrModeUser;
920 
921             // Notify system services and VR HAL of mode change.
922             changeVrModeLocked(goingIntoVrMode);
923 
924             boolean nothingChanged = false;
925             if (!goingIntoVrMode) {
926                 // Not going into VR mode, unbind whatever is running
927                 if (mCurrentVrService != null) {
928                     Slog.i(TAG, "Leaving VR mode, disconnecting "
929                         + mCurrentVrService.getComponent() + " for user "
930                         + mCurrentVrService.getUserId());
931                     mCurrentVrService.disconnect();
932                     updateCompositorServiceLocked(UserHandle.USER_NULL, null);
933                     mCurrentVrService = null;
934                 } else {
935                     nothingChanged = true;
936                 }
937             } else {
938                 // Going into VR mode
939                 if (mCurrentVrService != null) {
940                     // Unbind any running service that doesn't match the latest component/user
941                     // selection.
942                     if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
943                         Slog.i(TAG, "VR mode component changed to " + component
944                             + ", disconnecting " + mCurrentVrService.getComponent()
945                             + " for user " + mCurrentVrService.getUserId());
946                         updateCompositorServiceLocked(UserHandle.USER_NULL, null);
947                         createAndConnectService(component, userId);
948                         sendUpdatedCaller = true;
949                     } else {
950                         nothingChanged = true;
951                     }
952                     // The service with the correct component/user is already bound, do nothing.
953                 } else {
954                     // Nothing was previously running, bind a new service for the latest
955                     // component/user selection.
956                     createAndConnectService(component, userId);
957                     sendUpdatedCaller = true;
958                 }
959             }
960 
961             if ((calling != null || mPersistentVrModeEnabled)
962                     && !Objects.equals(calling, mCurrentVrModeComponent)
963                     || mRunning2dInVr != running2dInVr) {
964                 sendUpdatedCaller = true;
965             }
966             mCurrentVrModeComponent = calling;
967             mRunning2dInVr = running2dInVr;
968             mVrAppProcessId = processId;
969 
970             if (mCurrentVrModeUser != userId) {
971                 mCurrentVrModeUser = userId;
972                 sendUpdatedCaller = true;
973             }
974 
975             String newVrServicePackage = mCurrentVrService != null
976                     ? mCurrentVrService.getComponent().getPackageName() : null;
977             final int newUserId = mCurrentVrModeUser;
978 
979             // Update AppOps settings that change state when entering/exiting VR mode, or changing
980             // the current VrListenerService.
981             updateDependentAppOpsLocked(newVrServicePackage, newUserId,
982                     oldVrServicePackage, oldUserId);
983 
984             if (mCurrentVrService != null && sendUpdatedCaller) {
985                 callFocusedActivityChangedLocked();
986             }
987 
988             if (!nothingChanged) {
989                 logStateLocked();
990             }
991 
992             return validUserComponent;
993         } finally {
994             Binder.restoreCallingIdentity(identity);
995         }
996     }
997 
callFocusedActivityChangedLocked()998     private void callFocusedActivityChangedLocked() {
999         final ComponentName c = mCurrentVrModeComponent;
1000         final boolean b = mRunning2dInVr;
1001         final int pid = mVrAppProcessId;
1002         mCurrentVrService.sendEvent(new PendingEvent() {
1003             @Override
1004             public void runEvent(IInterface service) throws RemoteException {
1005                 // Under specific (and unlikely) timing scenarios, when VrCore
1006                 // crashes and is rebound, focusedActivityChanged() may be
1007                 // called a 2nd time with the same arguments. IVrListeners
1008                 // should make sure to handle that scenario gracefully.
1009                 IVrListener l = (IVrListener) service;
1010                 l.focusedActivityChanged(c, b, pid);
1011             }
1012         });
1013     }
1014 
isDefaultAllowed(String packageName)1015     private boolean isDefaultAllowed(String packageName) {
1016         PackageManager pm = mContext.getPackageManager();
1017 
1018         ApplicationInfo info = null;
1019         try {
1020             info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
1021         } catch (NameNotFoundException e) {
1022         }
1023 
1024         if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
1025             return false;
1026         }
1027         return true;
1028     }
1029 
grantNotificationPolicyAccess(String pkg)1030     private void grantNotificationPolicyAccess(String pkg) {
1031         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
1032         nm.setNotificationPolicyAccessGranted(pkg, true);
1033     }
1034 
revokeNotificationPolicyAccess(String pkg)1035     private void revokeNotificationPolicyAccess(String pkg) {
1036         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
1037         // Remove any DND zen rules possibly created by the package.
1038         nm.removeAutomaticZenRules(pkg);
1039         // Remove Notification Policy Access.
1040         nm.setNotificationPolicyAccessGranted(pkg, false);
1041     }
1042 
grantNotificationListenerAccess(String pkg, int userId)1043     private void grantNotificationListenerAccess(String pkg, int userId) {
1044         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
1045         PackageManager pm = mContext.getPackageManager();
1046         ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
1047                 userId, NotificationListenerService.SERVICE_INTERFACE,
1048                 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
1049 
1050         for (ComponentName c : possibleServices) {
1051             if (Objects.equals(c.getPackageName(), pkg)) {
1052                 nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
1053             }
1054         }
1055     }
1056 
revokeNotificationListenerAccess(String pkg, int userId)1057     private void revokeNotificationListenerAccess(String pkg, int userId) {
1058         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
1059         List<ComponentName> current = nm.getEnabledNotificationListeners(userId);
1060 
1061         for (ComponentName component : current) {
1062             if (component != null && component.getPackageName().equals(pkg)) {
1063                 nm.setNotificationListenerAccessGrantedForUser(component, userId, false);
1064             }
1065         }
1066     }
1067 
grantCoarseLocationPermissionIfNeeded(String pkg, int userId)1068     private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
1069         // Don't clobber the user if permission set in current state explicitly
1070         if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
1071             try {
1072                 mContext.getPackageManager().grantRuntimePermission(pkg,
1073                         Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
1074             } catch (IllegalArgumentException e) {
1075                 // Package was removed during update.
1076                 Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
1077                     + " was removed.");
1078             }
1079         }
1080     }
1081 
revokeCoarseLocationPermissionIfNeeded(String pkg, int userId)1082     private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
1083         // Don't clobber the user if permission set in current state explicitly
1084         if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
1085             try {
1086                 mContext.getPackageManager().revokeRuntimePermission(pkg,
1087                         Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
1088             } catch (IllegalArgumentException e) {
1089                 // Package was removed during update.
1090                 Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
1091                     + " was removed.");
1092             }
1093         }
1094     }
1095 
isPermissionUserUpdated(String permission, String pkg, int userId)1096     private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
1097         final int flags = mContext.getPackageManager().getPermissionFlags(
1098                 permission, pkg, new UserHandle(userId));
1099         return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
1100                 | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
1101     }
1102 
getNotificationListeners(ContentResolver resolver, int userId)1103     private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
1104         String flat = Settings.Secure.getStringForUser(resolver,
1105                 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
1106 
1107         ArraySet<String> current = new ArraySet<>();
1108         if (flat != null) {
1109             String[] allowed = flat.split(":");
1110             for (String s : allowed) {
1111                 if (!TextUtils.isEmpty(s)) {
1112                     current.add(s);
1113                 }
1114             }
1115         }
1116         return current;
1117     }
1118 
formatSettings(Collection<String> c)1119     private static String formatSettings(Collection<String> c) {
1120         if (c == null || c.isEmpty()) {
1121             return "";
1122         }
1123 
1124         StringBuilder b = new StringBuilder();
1125         boolean start = true;
1126         for (String s : c) {
1127             if ("".equals(s)) {
1128                 continue;
1129             }
1130             if (!start) {
1131                 b.append(':');
1132             }
1133             b.append(s);
1134             start = false;
1135         }
1136         return b.toString();
1137     }
1138 
1139 
1140 
createAndConnectService(@onNull ComponentName component, int userId)1141     private void createAndConnectService(@NonNull ComponentName component, int userId) {
1142         mCurrentVrService = createVrListenerService(component, userId);
1143         mCurrentVrService.connect();
1144         Slog.i(TAG, "Connecting " + component + " for user " + userId);
1145     }
1146 
1147     /**
1148      * Send VR mode change callbacks to HAL and system services if mode has actually changed.
1149      * <p/>
1150      * Note: Must be called while holding {@code mLock}.
1151      *
1152      * @param enabled new state of the VR mode.
1153      */
changeVrModeLocked(boolean enabled)1154     private void changeVrModeLocked(boolean enabled) {
1155         if (mVrModeEnabled != enabled) {
1156             mVrModeEnabled = enabled;
1157 
1158             // Log mode change event.
1159             Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
1160             setVrModeNative(mVrModeEnabled);
1161 
1162             onVrModeChangedLocked();
1163         }
1164     }
1165 
1166     /**
1167      * Notify system services of VR mode change.
1168      * <p/>
1169      * Note: Must be called while holding {@code mLock}.
1170      */
onVrModeChangedLocked()1171     private void onVrModeChangedLocked() {
1172         mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
1173                 (mVrModeEnabled) ? 1 : 0, 0));
1174     }
1175 
1176     /**
1177      * Helper function for making ManagedApplicationService for VrListenerService instances.
1178      */
createVrListenerService(@onNull ComponentName component, int userId)1179     private ManagedApplicationService createVrListenerService(@NonNull ComponentName component,
1180             int userId) {
1181         int retryType = (mBootsToVr) ? ManagedApplicationService.RETRY_FOREVER
1182                 : ManagedApplicationService.RETRY_NEVER;
1183         return ManagedApplicationService.build(mContext, component, userId,
1184                 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
1185                 sBinderChecker, /*isImportant*/true, retryType, mHandler, mEventCallback);
1186     }
1187 
1188     /**
1189      * Helper function for making ManagedApplicationService for VR Compositor instances.
1190      */
createVrCompositorService(@onNull ComponentName component, int userId)1191     private ManagedApplicationService createVrCompositorService(@NonNull ComponentName component,
1192             int userId) {
1193         int retryType = (mBootsToVr) ? ManagedApplicationService.RETRY_FOREVER
1194                 : ManagedApplicationService.RETRY_BEST_EFFORT;
1195         return ManagedApplicationService.build(mContext, component, userId, /*clientLabel*/0,
1196                 /*settingsAction*/null, /*binderChecker*/null, /*isImportant*/true, retryType,
1197                 mHandler, /*disconnectCallback*/mEventCallback);
1198     }
1199 
1200     /**
1201      * Apply the pending VR state. If no state is pending, disconnect any currently bound
1202      * VR listener service.
1203      */
consumeAndApplyPendingStateLocked()1204     private void consumeAndApplyPendingStateLocked() {
1205         consumeAndApplyPendingStateLocked(true);
1206     }
1207 
1208     /**
1209      * Apply the pending VR state.
1210      *
1211      * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
1212      *     service will be disconnected if no state is pending. If this is {@code false} then the
1213      *     nothing will be changed when there is no pending state.
1214      */
consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState)1215     private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
1216         if (mPendingState != null) {
1217             updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
1218                     mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
1219                     mPendingState.callingPackage);
1220             mPendingState = null;
1221         } else if (disconnectIfNoPendingState) {
1222             updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
1223         }
1224     }
1225 
logStateLocked()1226     private void logStateLocked() {
1227         ComponentName currentBoundService = (mCurrentVrService == null) ? null :
1228                 mCurrentVrService.getComponent();
1229         logEvent(new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
1230                 mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted));
1231     }
1232 
logEvent(LogFormattable event)1233     private void logEvent(LogFormattable event) {
1234         synchronized (mLoggingDeque) {
1235             if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
1236                 mLoggingDeque.removeFirst();
1237                 mLogLimitHit = true;
1238             }
1239             mLoggingDeque.add(event);
1240         }
1241     }
1242 
dumpStateTransitions(PrintWriter pw)1243     private void dumpStateTransitions(PrintWriter pw) {
1244         SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
1245         synchronized (mLoggingDeque) {
1246             if (mLoggingDeque.size() == 0) {
1247                 pw.print("  ");
1248                 pw.println("None");
1249             }
1250 
1251             if (mLogLimitHit) {
1252                 pw.println("..."); // Indicates log overflow
1253             }
1254 
1255             for (LogFormattable event : mLoggingDeque) {
1256                 pw.println(event.toLogString(d));
1257             }
1258         }
1259     }
1260 
1261     /*
1262      * Implementation of VrManagerInternal calls.  These are callable from system services.
1263      */
setVrMode(boolean enabled, @NonNull ComponentName targetPackageName, int userId, int processId, @NonNull ComponentName callingPackage)1264     private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
1265             int userId, int processId, @NonNull ComponentName callingPackage) {
1266 
1267         synchronized (mLock) {
1268             VrState pending;
1269             ComponentName targetListener;
1270 
1271             // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
1272             // and the system default VR listener is used.
1273             boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
1274             boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
1275             if (running2dInVr) {
1276                 targetListener = mDefaultVrService;
1277             } else {
1278                 targetListener = targetPackageName;
1279             }
1280 
1281             pending = new VrState(targetEnabledState, running2dInVr, targetListener,
1282                     userId, processId, callingPackage);
1283 
1284             if (!mVrModeAllowed) {
1285                 // We're not allowed to be in VR mode.  Make this state pending.  This will be
1286                 // applied the next time we are allowed to enter VR mode unless it is superseded by
1287                 // another call.
1288                 mPendingState = pending;
1289                 return;
1290             }
1291 
1292             if (!targetEnabledState && mCurrentVrService != null) {
1293                 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
1294                 // and service bind/unbind in case we are immediately switching to another VR app.
1295                 if (mPendingState == null) {
1296                     mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
1297                             PENDING_STATE_DELAY_MS);
1298                 }
1299 
1300                 mPendingState = pending;
1301                 return;
1302             } else {
1303                 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
1304                 mPendingState = null;
1305             }
1306 
1307             updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
1308                     userId, processId, callingPackage);
1309         }
1310     }
1311 
setPersistentVrModeEnabled(boolean enabled)1312     private void setPersistentVrModeEnabled(boolean enabled) {
1313         synchronized(mLock) {
1314             setPersistentModeAndNotifyListenersLocked(enabled);
1315             // Disabling persistent mode should disable the overall vr mode.
1316             if (!enabled) {
1317                 setVrMode(false, null, 0, -1, null);
1318             }
1319         }
1320     }
1321 
setVr2dDisplayProperties( Vr2dDisplayProperties compatDisplayProp)1322     public void setVr2dDisplayProperties(
1323         Vr2dDisplayProperties compatDisplayProp) {
1324         final long token = Binder.clearCallingIdentity();
1325         try {
1326             if (mVr2dDisplay != null) {
1327                 mVr2dDisplay.setVirtualDisplayProperties(compatDisplayProp);
1328                 return;
1329             }
1330         } finally {
1331             Binder.restoreCallingIdentity(token);
1332         }
1333         Slog.w(TAG, "Vr2dDisplay is null!");
1334     }
1335 
getVr2dDisplayId()1336     private int getVr2dDisplayId() {
1337         if (mVr2dDisplay != null) {
1338             return mVr2dDisplay.getVirtualDisplayId();
1339         }
1340         Slog.w(TAG, "Vr2dDisplay is null!");
1341         return INVALID_DISPLAY;
1342     }
1343 
setAndBindCompositor(ComponentName componentName)1344     private void setAndBindCompositor(ComponentName componentName) {
1345         final int userId = UserHandle.getCallingUserId();
1346         final long token = Binder.clearCallingIdentity();
1347         try {
1348             synchronized (mLock) {
1349                 updateCompositorServiceLocked(userId, componentName);
1350             }
1351         } finally {
1352             Binder.restoreCallingIdentity(token);
1353         }
1354     }
1355 
updateCompositorServiceLocked(int userId, ComponentName componentName)1356     private void updateCompositorServiceLocked(int userId, ComponentName componentName) {
1357         if (mCurrentVrCompositorService != null
1358                 && mCurrentVrCompositorService.disconnectIfNotMatching(componentName, userId)) {
1359             Slog.i(TAG, "Disconnecting compositor service: "
1360                     + mCurrentVrCompositorService.getComponent());
1361             // Check if existing service matches the requested one, if not (or if the requested
1362             // component is null) disconnect it.
1363             mCurrentVrCompositorService = null;
1364         }
1365 
1366         if (componentName != null && mCurrentVrCompositorService == null) {
1367             // We don't have an existing service matching the requested component, so attempt to
1368             // connect one.
1369             Slog.i(TAG, "Connecting compositor service: " + componentName);
1370             mCurrentVrCompositorService = createVrCompositorService(componentName, userId);
1371             mCurrentVrCompositorService.connect();
1372         }
1373     }
1374 
setPersistentModeAndNotifyListenersLocked(boolean enabled)1375     private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
1376         if (mPersistentVrModeEnabled == enabled) {
1377             return;
1378         }
1379         String eventName = "Persistent VR mode " + ((enabled) ? "enabled" : "disabled");
1380         Slog.i(TAG, eventName);
1381         logEvent(new SettingEvent(eventName));
1382         mPersistentVrModeEnabled = enabled;
1383 
1384         mHandler.sendMessage(mHandler.obtainMessage(MSG_PERSISTENT_VR_MODE_STATE_CHANGE,
1385                 (mPersistentVrModeEnabled) ? 1 : 0, 0));
1386     }
1387 
hasVrPackage(@onNull ComponentName targetPackageName, int userId)1388     private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
1389         synchronized (mLock) {
1390             return mComponentObserver.isValid(targetPackageName, userId);
1391         }
1392     }
1393 
isCurrentVrListener(String packageName, int userId)1394     private boolean isCurrentVrListener(String packageName, int userId) {
1395         synchronized (mLock) {
1396             if (mCurrentVrService == null) {
1397                 return false;
1398             }
1399             return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
1400                     userId == mCurrentVrService.getUserId();
1401         }
1402     }
1403 
1404     /*
1405      * Implementation of IVrManager calls.
1406      */
1407 
addStateCallback(IVrStateCallbacks cb)1408     private void addStateCallback(IVrStateCallbacks cb) {
1409         mVrStateRemoteCallbacks.register(cb);
1410     }
1411 
removeStateCallback(IVrStateCallbacks cb)1412     private void removeStateCallback(IVrStateCallbacks cb) {
1413         mVrStateRemoteCallbacks.unregister(cb);
1414     }
1415 
addPersistentStateCallback(IPersistentVrStateCallbacks cb)1416     private void addPersistentStateCallback(IPersistentVrStateCallbacks cb) {
1417         mPersistentVrStateRemoteCallbacks.register(cb);
1418     }
1419 
removePersistentStateCallback(IPersistentVrStateCallbacks cb)1420     private void removePersistentStateCallback(IPersistentVrStateCallbacks cb) {
1421         mPersistentVrStateRemoteCallbacks.unregister(cb);
1422     }
1423 
getVrMode()1424     private boolean getVrMode() {
1425         synchronized (mLock) {
1426             return mVrModeEnabled;
1427         }
1428     }
1429 
getPersistentVrMode()1430     private boolean getPersistentVrMode() {
1431         synchronized (mLock) {
1432             return mPersistentVrModeEnabled;
1433         }
1434     }
1435 }
1436