2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.android.server.vr;
18 import android.Manifest;
19 import android.app.ActivityManager;
20 import android.app.AppOpsManager;
21 import android.app.NotificationManager;
22 import android.annotation.NonNull;
23 import android.content.BroadcastReceiver;
24 import android.content.ComponentName;
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.pm.ApplicationInfo;
30 import android.content.pm.FeatureInfo;
31 import android.content.pm.PackageInfo;
32 import android.content.pm.PackageManager;
33 import android.content.pm.PackageManager.NameNotFoundException;
34 import android.os.Binder;
35 import android.os.Handler;
36 import android.os.IBinder;
37 import android.os.IInterface;
38 import android.os.Looper;
39 import android.os.Message;
40 import android.os.RemoteCallbackList;
41 import android.os.RemoteException;
42 import android.os.UserHandle;
43 import android.provider.Settings;
44 import android.service.notification.NotificationListenerService;
45 import android.service.vr.IVrListener;
46 import android.service.vr.IVrManager;
47 import android.service.vr.IVrStateCallbacks;
48 import android.service.vr.VrListenerService;
49 import android.text.TextUtils;
50 import android.util.ArrayMap;
51 import android.util.ArraySet;
52 import android.util.Slog;
53 import android.util.SparseArray;
54 import com.android.internal.R;
55 import com.android.server.LocalServices;
56 import com.android.server.SystemConfig;
57 import com.android.server.SystemService;
58 import com.android.server.utils.ManagedApplicationService.PendingEvent;
59 import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
60 import com.android.server.utils.ManagedApplicationService;
61 import com.android.server.utils.ManagedApplicationService.BinderChecker;
63 import java.io.FileDescriptor;
64 import java.io.PrintWriter;
65 import java.lang.StringBuilder;
66 import java.text.SimpleDateFormat;
67 import java.util.ArrayDeque;
68 import java.util.ArrayList;
69 import java.util.Collection;
70 import java.util.Date;
71 import java.util.List;
73 import java.util.Objects;
76 * Service tracking whether VR mode is active, and notifying listening services of state changes.
78 * Services running in system server may modify the state of VrManagerService via the interface in
79 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
80 * interface given in VrStateListener.
82 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
83 * hardware/libhardware/modules/vr
85 * In general applications may enable or disable VR mode by calling
86 * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to
87 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
89 * @see android.service.vr.VrListenerService
90 * @see com.android.server.vr.VrManagerInternal
91 * @see com.android.server.vr.VrStateListener
95 public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
97 public static final String TAG = "VrManagerService";
99 public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
101 private static final int PENDING_STATE_DELAY_MS = 300;
102 private static final int EVENT_LOG_SIZE = 32;
103 private static final int INVALID_APPOPS_MODE = -1;
104 /** Null set of sleep sleep flags. */
105 private static final int FLAG_NONE = 0;
106 /** Flag set when the device is not sleeping. */
107 private static final int FLAG_AWAKE = 1;
108 /** Flag set when the screen has been turned on. */
109 private static final int FLAG_SCREEN_ON = 2;
110 /** Flag indicating that all system sleep flags have been set.*/
111 private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON;
113 private static native void initializeNative();
114 private static native void setVrModeNative(boolean enabled);
116 private final Object mLock = new Object();
118 private final IBinder mOverlayToken = new Binder();
120 // State protected by mLock
121 private boolean mVrModeAllowed;
122 private boolean mVrModeEnabled;
123 private EnabledComponentsObserver mComponentObserver;
124 private ManagedApplicationService mCurrentVrService;
125 private Context mContext;
126 private ComponentName mCurrentVrModeComponent;
127 private int mCurrentVrModeUser;
128 private boolean mWasDefaultGranted;
129 private boolean mGuard;
130 private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
131 new RemoteCallbackList<>();
132 private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
133 private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
134 private VrState mPendingState;
135 private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
136 private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
137 /** Tracks the state of the screen and keyguard UI.*/
138 private int mSystemSleepFlags = FLAG_NONE;
140 private static final int MSG_VR_STATE_CHANGE = 0;
141 private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
144 * Set whether VR mode may be enabled.
146 * If VR mode is not allowed to be enabled, calls to set VR mode will be cached. When VR mode
147 * is again allowed to be enabled, the most recent cached state will be applied.
149 * @param allowed {@code true} if calling any of the setVrMode methods may cause the device to
152 private void setVrModeAllowedLocked(boolean allowed) {
153 if (mVrModeAllowed != allowed) {
154 mVrModeAllowed = allowed;
155 Slog.i(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
156 if (mVrModeAllowed) {
157 consumeAndApplyPendingStateLocked();
159 // Set pending state to current state.
160 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
161 ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
162 mCurrentVrService.getUserId(), mCurrentVrModeComponent)
165 // Unbind current VR service and do necessary callbacks.
166 updateCurrentVrServiceLocked(false, null, 0, null);
171 private void setSleepState(boolean isAsleep) {
172 synchronized(mLock) {
175 mSystemSleepFlags |= FLAG_AWAKE;
177 mSystemSleepFlags &= ~FLAG_AWAKE;
180 setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
184 private void setScreenOn(boolean isScreenOn) {
185 synchronized(mLock) {
187 mSystemSleepFlags |= FLAG_SCREEN_ON;
189 mSystemSleepFlags &= ~FLAG_SCREEN_ON;
191 setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
195 private final Handler mHandler = new Handler() {
197 public void handleMessage(Message msg) {
199 case MSG_VR_STATE_CHANGE : {
200 boolean state = (msg.arg1 == 1);
201 int i = mRemoteCallbacks.beginBroadcast();
205 mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
206 } catch (RemoteException e) {
210 mRemoteCallbacks.finishBroadcast();
212 case MSG_PENDING_VR_STATE_CHANGE : {
213 synchronized(mLock) {
214 if (mVrModeAllowed) {
215 VrManagerService.this.consumeAndApplyPendingStateLocked();
220 throw new IllegalStateException("Unknown message type: " + msg.what);
225 private static class VrState {
226 final boolean enabled;
228 final ComponentName targetPackageName;
229 final ComponentName callingPackage;
230 final long timestamp;
231 final boolean defaultPermissionsGranted;
233 VrState(boolean enabled, ComponentName targetPackageName, int userId,
234 ComponentName callingPackage) {
235 this.enabled = enabled;
236 this.userId = userId;
237 this.targetPackageName = targetPackageName;
238 this.callingPackage = callingPackage;
239 this.defaultPermissionsGranted = false;
240 this.timestamp = System.currentTimeMillis();
243 VrState(boolean enabled, ComponentName targetPackageName, int userId,
244 ComponentName callingPackage, boolean defaultPermissionsGranted) {
245 this.enabled = enabled;
246 this.userId = userId;
247 this.targetPackageName = targetPackageName;
248 this.callingPackage = callingPackage;
249 this.defaultPermissionsGranted = defaultPermissionsGranted;
250 this.timestamp = System.currentTimeMillis();
254 private static final BinderChecker sBinderChecker = new BinderChecker() {
256 public IInterface asInterface(IBinder binder) {
257 return IVrListener.Stub.asInterface(binder);
261 public boolean checkType(IInterface service) {
262 return service instanceof IVrListener;
266 private final class NotificationAccessManager {
267 private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
268 private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
271 public void update(Collection<String> packageNames) {
272 int currentUserId = ActivityManager.getCurrentUser();
274 ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
275 if (allowed == null) {
276 allowed = new ArraySet<>();
279 // Make sure we revoke notification access for listeners in other users
280 final int listenerCount = mNotificationAccessPackageToUserId.size();
281 for (int i = listenerCount - 1; i >= 0; i--) {
282 final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
283 if (grantUserId != currentUserId) {
284 String packageName = mNotificationAccessPackageToUserId.keyAt(i);
285 revokeNotificationListenerAccess(packageName, grantUserId);
286 revokeNotificationPolicyAccess(packageName);
287 revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
288 mNotificationAccessPackageToUserId.removeAt(i);
292 for (String pkg : allowed) {
293 if (!packageNames.contains(pkg)) {
294 revokeNotificationListenerAccess(pkg, currentUserId);
295 revokeNotificationPolicyAccess(pkg);
296 revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
297 mNotificationAccessPackageToUserId.remove(pkg);
300 for (String pkg : packageNames) {
301 if (!allowed.contains(pkg)) {
302 grantNotificationPolicyAccess(pkg);
303 grantNotificationListenerAccess(pkg, currentUserId);
304 grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
305 mNotificationAccessPackageToUserId.put(pkg, currentUserId);
310 allowed.addAll(packageNames);
311 mAllowedPackages.put(currentUserId, allowed);
316 * Called when a user, package, or setting changes that could affect whether or not the
317 * currently bound VrListenerService is changed.
320 public void onEnabledComponentChanged() {
321 synchronized (mLock) {
322 int currentUser = ActivityManager.getCurrentUser();
324 ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
326 ArraySet<String> enabledPackages = new ArraySet<>();
327 for (ComponentName n : enabledListeners) {
328 String pkg = n.getPackageName();
329 if (isDefaultAllowed(pkg)) {
330 enabledPackages.add(n.getPackageName());
333 mNotifAccessManager.update(enabledPackages);
335 if (!mVrModeAllowed) {
336 return; // Don't do anything, we shouldn't be in VR mode.
339 // If there is a pending state change, we'd better deal with that first
340 consumeAndApplyPendingStateLocked(false);
342 if (mCurrentVrService == null) {
343 return; // No active services
346 // There is an active service, update it if needed
347 updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
348 mCurrentVrService.getUserId(), null);
352 private final IVrManager mVrManager = new IVrManager.Stub() {
355 public void registerListener(IVrStateCallbacks cb) {
356 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
358 throw new IllegalArgumentException("Callback binder object is null.");
361 VrManagerService.this.addStateCallback(cb);
365 public void unregisterListener(IVrStateCallbacks cb) {
366 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
368 throw new IllegalArgumentException("Callback binder object is null.");
371 VrManagerService.this.removeStateCallback(cb);
375 public boolean getVrModeState() {
376 return VrManagerService.this.getVrMode();
380 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
381 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
382 != PackageManager.PERMISSION_GRANTED) {
383 pw.println("permission denied: can't dump VrManagerService from pid="
384 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
387 pw.println("********* Dump of VrManagerService *********");
388 pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
389 pw.println("Previous state transitions:\n");
391 dumpStateTransitions(pw);
392 pw.println("\n\nRemote Callbacks:");
393 int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
396 pw.print(mRemoteCallbacks.getBroadcastItem(i));
397 if (i>0) pw.println(",");
399 mRemoteCallbacks.finishBroadcast();
401 pw.println("Installed VrListenerService components:");
402 int userId = mCurrentVrModeUser;
403 ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
404 if (installed == null || installed.size() == 0) {
407 for (ComponentName n : installed) {
409 pw.println(n.flattenToString());
412 pw.println("Enabled VrListenerService components:");
413 ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
414 if (enabled == null || enabled.size() == 0) {
417 for (ComponentName n : enabled) {
419 pw.println(n.flattenToString());
423 pw.println("********* End of VrManagerService Dump *********");
428 private void enforceCallerPermission(String permission) {
429 if (mContext.checkCallingOrSelfPermission(permission)
430 != PackageManager.PERMISSION_GRANTED) {
431 throw new SecurityException("Caller does not hold the permission " + permission);
436 * Implementation of VrManagerInternal. Callable only from system services.
438 private final class LocalService extends VrManagerInternal {
440 public void setVrMode(boolean enabled, ComponentName packageName, int userId,
441 ComponentName callingPackage) {
442 VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
446 public void onSleepStateChanged(boolean isAsleep) {
447 VrManagerService.this.setSleepState(isAsleep);
451 public void onScreenStateChanged(boolean isScreenOn) {
452 VrManagerService.this.setScreenOn(isScreenOn);
456 public boolean isCurrentVrListener(String packageName, int userId) {
457 return VrManagerService.this.isCurrentVrListener(packageName, userId);
461 public int hasVrPackage(ComponentName packageName, int userId) {
462 return VrManagerService.this.hasVrPackage(packageName, userId);
466 public VrManagerService(Context context) {
471 public void onStart() {
472 synchronized(mLock) {
474 mContext = getContext();
477 publishLocalService(VrManagerInternal.class, new LocalService());
478 publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
482 public void onBootPhase(int phase) {
483 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
484 synchronized (mLock) {
485 Looper looper = Looper.getMainLooper();
486 Handler handler = new Handler(looper);
487 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
489 mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
490 Settings.Secure.ENABLED_VR_LISTENERS, looper,
491 android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
492 VrListenerService.SERVICE_INTERFACE, mLock, listeners);
494 mComponentObserver.rebuildAll();
496 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
497 synchronized (mLock) {
498 mVrModeAllowed = true;
504 public void onStartUser(int userHandle) {
505 synchronized (mLock) {
506 mComponentObserver.onUsersChanged();
511 public void onSwitchUser(int userHandle) {
512 synchronized (mLock) {
513 mComponentObserver.onUsersChanged();
519 public void onStopUser(int userHandle) {
520 synchronized (mLock) {
521 mComponentObserver.onUsersChanged();
527 public void onCleanupUser(int userHandle) {
528 synchronized (mLock) {
529 mComponentObserver.onUsersChanged();
533 private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
534 AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
536 // If user changed drop restrictions for the old user.
537 if (oldUserId != newUserId) {
538 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
539 false, mOverlayToken, null, oldUserId);
542 if (!mVrModeEnabled) {
546 // Apply the restrictions for the current user based on vr state
547 String[] exemptions = (exemptedPackage == null) ? new String[0] :
548 new String[] { exemptedPackage };
550 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
551 true, mOverlayToken, exemptions, newUserId);
554 private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
555 String oldVrServicePackage, int oldUserId) {
556 // If VR state changed and we also have a VR service change.
557 if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
560 final long identity = Binder.clearCallingIdentity();
562 // Set overlay exception state based on VR enabled and current service
563 updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
565 Binder.restoreCallingIdentity(identity);
570 * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
571 * the currently selected VR listener service. If the component selected for the VR listener
572 * service has changed, unbind the previous listener and bind the new listener (if enabled).
574 * Note: Must be called while holding {@code mLock}.
576 * @param enabled new state for VR mode.
577 * @param component new component to be bound as a VR listener.
578 * @param userId user owning the component to be bound.
579 * @param calling the component currently using VR mode, or null to leave unchanged.
581 * @return {@code true} if the component/user combination specified is valid.
583 private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
584 int userId, ComponentName calling) {
586 boolean sendUpdatedCaller = false;
587 final long identity = Binder.clearCallingIdentity();
590 boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
591 EnabledComponentsObserver.NO_ERROR);
592 boolean goingIntoVrMode = validUserComponent && enabled;
593 if (!mVrModeEnabled && !goingIntoVrMode) {
594 return validUserComponent; // Disabled -> Disabled transition does nothing.
597 String oldVrServicePackage = mCurrentVrService != null
598 ? mCurrentVrService.getComponent().getPackageName() : null;
599 final int oldUserId = mCurrentVrModeUser;
601 // Notify system services and VR HAL of mode change.
602 changeVrModeLocked(goingIntoVrMode);
604 boolean nothingChanged = false;
605 if (!goingIntoVrMode) {
606 // Not going into VR mode, unbind whatever is running
607 if (mCurrentVrService != null) {
608 Slog.i(TAG, "Leaving VR mode, disconnecting "
609 + mCurrentVrService.getComponent() + " for user "
610 + mCurrentVrService.getUserId());
611 mCurrentVrService.disconnect();
612 mCurrentVrService = null;
614 nothingChanged = true;
617 // Going into VR mode
618 if (mCurrentVrService != null) {
619 // Unbind any running service that doesn't match the latest component/user
621 if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
622 Slog.i(TAG, "VR mode component changed to " + component
623 + ", disconnecting " + mCurrentVrService.getComponent()
624 + " for user " + mCurrentVrService.getUserId());
625 createAndConnectService(component, userId);
626 sendUpdatedCaller = true;
628 nothingChanged = true;
630 // The service with the correct component/user is already bound, do nothing.
632 // Nothing was previously running, bind a new service for the latest
633 // component/user selection.
634 createAndConnectService(component, userId);
635 sendUpdatedCaller = true;
639 if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
640 mCurrentVrModeComponent = calling;
641 sendUpdatedCaller = true;
644 if (mCurrentVrModeUser != userId) {
645 mCurrentVrModeUser = userId;
646 sendUpdatedCaller = true;
649 String newVrServicePackage = mCurrentVrService != null
650 ? mCurrentVrService.getComponent().getPackageName() : null;
651 final int newUserId = mCurrentVrModeUser;
653 // Update AppOps settings that change state when entering/exiting VR mode, or changing
654 // the current VrListenerService.
655 updateDependentAppOpsLocked(newVrServicePackage, newUserId,
656 oldVrServicePackage, oldUserId);
658 if (mCurrentVrService != null && sendUpdatedCaller) {
659 final ComponentName c = mCurrentVrModeComponent;
660 mCurrentVrService.sendEvent(new PendingEvent() {
662 public void runEvent(IInterface service) throws RemoteException {
663 IVrListener l = (IVrListener) service;
664 l.focusedActivityChanged(c);
669 if (!nothingChanged) {
673 return validUserComponent;
675 Binder.restoreCallingIdentity(identity);
679 private boolean isDefaultAllowed(String packageName) {
680 PackageManager pm = mContext.getPackageManager();
682 ApplicationInfo info = null;
684 info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
685 } catch (NameNotFoundException e) {
688 if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
694 private void grantNotificationPolicyAccess(String pkg) {
695 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
696 nm.setNotificationPolicyAccessGranted(pkg, true);
699 private void revokeNotificationPolicyAccess(String pkg) {
700 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
701 // Remove any DND zen rules possibly created by the package.
702 nm.removeAutomaticZenRules(pkg);
703 // Remove Notification Policy Access.
704 nm.setNotificationPolicyAccessGranted(pkg, false);
707 private void grantNotificationListenerAccess(String pkg, int userId) {
708 PackageManager pm = mContext.getPackageManager();
709 ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
710 userId, NotificationListenerService.SERVICE_INTERFACE,
711 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
712 ContentResolver resolver = mContext.getContentResolver();
714 ArraySet<String> current = getNotificationListeners(resolver, userId);
716 for (ComponentName c : possibleServices) {
717 String flatName = c.flattenToString();
718 if (Objects.equals(c.getPackageName(), pkg)
719 && !current.contains(flatName)) {
720 current.add(flatName);
724 if (current.size() > 0) {
725 String flatSettings = formatSettings(current);
726 Settings.Secure.putStringForUser(resolver,
727 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
728 flatSettings, userId);
732 private void revokeNotificationListenerAccess(String pkg, int userId) {
733 ContentResolver resolver = mContext.getContentResolver();
735 ArraySet<String> current = getNotificationListeners(resolver, userId);
737 ArrayList<String> toRemove = new ArrayList<>();
739 for (String c : current) {
740 ComponentName component = ComponentName.unflattenFromString(c);
741 if (component != null && component.getPackageName().equals(pkg)) {
746 current.removeAll(toRemove);
748 String flatSettings = formatSettings(current);
749 Settings.Secure.putStringForUser(resolver,
750 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
751 flatSettings, userId);
754 private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
755 // Don't clobber the user if permission set in current state explicitly
756 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
758 mContext.getPackageManager().grantRuntimePermission(pkg,
759 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
760 } catch (IllegalArgumentException e) {
761 // Package was removed during update.
762 Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
768 private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
769 // Don't clobber the user if permission set in current state explicitly
770 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
772 mContext.getPackageManager().revokeRuntimePermission(pkg,
773 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
774 } catch (IllegalArgumentException e) {
775 // Package was removed during update.
776 Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
782 private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
783 final int flags = mContext.getPackageManager().getPermissionFlags(
784 permission, pkg, new UserHandle(userId));
785 return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
786 | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
789 private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
790 String flat = Settings.Secure.getStringForUser(resolver,
791 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
793 ArraySet<String> current = new ArraySet<>();
795 String[] allowed = flat.split(":");
796 for (String s : allowed) {
797 if (!TextUtils.isEmpty(s)) {
805 private static String formatSettings(Collection<String> c) {
806 if (c == null || c.isEmpty()) {
810 StringBuilder b = new StringBuilder();
811 boolean start = true;
827 private void createAndConnectService(@NonNull ComponentName component, int userId) {
828 mCurrentVrService = VrManagerService.create(mContext, component, userId);
829 mCurrentVrService.connect();
830 Slog.i(TAG, "Connecting " + component + " for user " + userId);
834 * Send VR mode change callbacks to HAL and system services if mode has actually changed.
836 * Note: Must be called while holding {@code mLock}.
838 * @param enabled new state of the VR mode.
840 private void changeVrModeLocked(boolean enabled) {
841 if (mVrModeEnabled != enabled) {
842 mVrModeEnabled = enabled;
844 // Log mode change event.
845 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
846 setVrModeNative(mVrModeEnabled);
848 onVrModeChangedLocked();
853 * Notify system services of VR mode change.
855 * Note: Must be called while holding {@code mLock}.
857 private void onVrModeChangedLocked() {
858 mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
859 (mVrModeEnabled) ? 1 : 0, 0));
863 * Helper function for making ManagedApplicationService instances.
865 private static ManagedApplicationService create(@NonNull Context context,
866 @NonNull ComponentName component, int userId) {
867 return ManagedApplicationService.build(context, component, userId,
868 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
873 * Apply the pending VR state. If no state is pending, disconnect any currently bound
874 * VR listener service.
876 private void consumeAndApplyPendingStateLocked() {
877 consumeAndApplyPendingStateLocked(true);
881 * Apply the pending VR state.
883 * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
884 * service will be disconnected if no state is pending. If this is {@code false} then the
885 * nothing will be changed when there is no pending state.
887 private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
888 if (mPendingState != null) {
889 updateCurrentVrServiceLocked(mPendingState.enabled,
890 mPendingState.targetPackageName, mPendingState.userId,
891 mPendingState.callingPackage);
892 mPendingState = null;
893 } else if (disconnectIfNoPendingState) {
894 updateCurrentVrServiceLocked(false, null, 0, null);
898 private void logStateLocked() {
899 ComponentName currentBoundService = (mCurrentVrService == null) ? null :
900 mCurrentVrService.getComponent();
901 VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
902 mCurrentVrModeComponent, mWasDefaultGranted);
903 if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
904 mLoggingDeque.removeFirst();
906 mLoggingDeque.add(current);
909 private void dumpStateTransitions(PrintWriter pw) {
910 SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
912 if (mLoggingDeque.size() == 0) {
916 for (VrState state : mLoggingDeque) {
917 pw.print(d.format(new Date(state.timestamp)));
919 pw.print("State changed to:");
921 pw.println((state.enabled) ? "ENABLED" : "DISABLED");
925 pw.println(state.userId);
927 pw.print("Current VR Activity=");
928 pw.println((state.callingPackage == null) ?
929 "None" : state.callingPackage.flattenToString());
931 pw.print("Bound VrListenerService=");
932 pw.println((state.targetPackageName == null) ?
933 "None" : state.targetPackageName.flattenToString());
934 if (state.defaultPermissionsGranted) {
936 pw.println("Default permissions granted to the bound VrListenerService.");
943 * Implementation of VrManagerInternal calls. These are callable from system services.
945 private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
946 int userId, @NonNull ComponentName callingPackage) {
948 synchronized (mLock) {
949 VrState pending = new VrState(enabled, targetPackageName, userId, callingPackage);
950 if (!mVrModeAllowed) {
951 // We're not allowed to be in VR mode. Make this state pending. This will be
952 // applied the next time we are allowed to enter VR mode unless it is superseded by
954 mPendingState = pending;
958 if (!enabled && mCurrentVrService != null) {
959 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
960 // and service bind/unbind in case we are immediately switching to another VR app.
961 if (mPendingState == null) {
962 mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
963 PENDING_STATE_DELAY_MS);
966 mPendingState = pending;
969 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
970 mPendingState = null;
973 updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
977 private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
978 synchronized (mLock) {
979 return mComponentObserver.isValid(targetPackageName, userId);
983 private boolean isCurrentVrListener(String packageName, int userId) {
984 synchronized (mLock) {
985 if (mCurrentVrService == null) {
988 return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
989 userId == mCurrentVrService.getUserId();
994 * Implementation of IVrManager calls.
997 private void addStateCallback(IVrStateCallbacks cb) {
998 mRemoteCallbacks.register(cb);
1001 private void removeStateCallback(IVrStateCallbacks cb) {
1002 mRemoteCallbacks.unregister(cb);
1005 private boolean getVrMode() {
1006 synchronized (mLock) {
1007 return mVrModeEnabled;