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.util.ArrayMap;
50 import android.util.ArraySet;
51 import android.util.Slog;
52 import android.util.SparseArray;
53 import com.android.internal.R;
54 import com.android.server.LocalServices;
55 import com.android.server.SystemConfig;
56 import com.android.server.SystemService;
57 import com.android.server.utils.ManagedApplicationService.PendingEvent;
58 import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
59 import com.android.server.utils.ManagedApplicationService;
60 import com.android.server.utils.ManagedApplicationService.BinderChecker;
62 import java.io.FileDescriptor;
63 import java.io.PrintWriter;
64 import java.lang.StringBuilder;
65 import java.text.SimpleDateFormat;
66 import java.util.ArrayDeque;
67 import java.util.ArrayList;
68 import java.util.Collection;
69 import java.util.Date;
70 import java.util.List;
72 import java.util.Objects;
75 * Service tracking whether VR mode is active, and notifying listening services of state changes.
77 * Services running in system server may modify the state of VrManagerService via the interface in
78 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
79 * interface given in VrStateListener.
81 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
82 * hardware/libhardware/modules/vr
84 * In general applications may enable or disable VR mode by calling
85 * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to
86 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
88 * @see {@link android.service.vr.VrListenerService}
89 * @see {@link com.android.server.vr.VrManagerInternal}
90 * @see {@link com.android.server.vr.VrStateListener}
94 public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
96 public static final String TAG = "VrManagerService";
98 public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
100 private static final int PENDING_STATE_DELAY_MS = 300;
101 private static final int EVENT_LOG_SIZE = 32;
102 private static final int INVALID_APPOPS_MODE = -1;
104 private static native void initializeNative();
105 private static native void setVrModeNative(boolean enabled);
107 private final Object mLock = new Object();
109 private final IBinder mOverlayToken = new Binder();
111 // State protected by mLock
112 private boolean mVrModeEnabled;
113 private EnabledComponentsObserver mComponentObserver;
114 private ManagedApplicationService mCurrentVrService;
115 private Context mContext;
116 private ComponentName mCurrentVrModeComponent;
117 private int mCurrentVrModeUser;
118 private boolean mWasDefaultGranted;
119 private boolean mGuard;
120 private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
121 new RemoteCallbackList<>();
122 private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
123 private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
124 private VrState mPendingState;
125 private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
126 private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
128 private static final int MSG_VR_STATE_CHANGE = 0;
129 private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
131 private final Handler mHandler = new Handler() {
133 public void handleMessage(Message msg) {
135 case MSG_VR_STATE_CHANGE : {
136 boolean state = (msg.arg1 == 1);
137 int i = mRemoteCallbacks.beginBroadcast();
141 mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
142 } catch (RemoteException e) {
146 mRemoteCallbacks.finishBroadcast();
148 case MSG_PENDING_VR_STATE_CHANGE : {
149 synchronized(mLock) {
150 VrManagerService.this.consumeAndApplyPendingStateLocked();
154 throw new IllegalStateException("Unknown message type: " + msg.what);
159 private static class VrState {
160 final boolean enabled;
162 final ComponentName targetPackageName;
163 final ComponentName callingPackage;
164 final long timestamp;
165 final boolean defaultPermissionsGranted;
167 VrState(boolean enabled, ComponentName targetPackageName, int userId,
168 ComponentName callingPackage) {
169 this.enabled = enabled;
170 this.userId = userId;
171 this.targetPackageName = targetPackageName;
172 this.callingPackage = callingPackage;
173 this.defaultPermissionsGranted = false;
174 this.timestamp = System.currentTimeMillis();
177 VrState(boolean enabled, ComponentName targetPackageName, int userId,
178 ComponentName callingPackage, boolean defaultPermissionsGranted) {
179 this.enabled = enabled;
180 this.userId = userId;
181 this.targetPackageName = targetPackageName;
182 this.callingPackage = callingPackage;
183 this.defaultPermissionsGranted = defaultPermissionsGranted;
184 this.timestamp = System.currentTimeMillis();
188 private static final BinderChecker sBinderChecker = new BinderChecker() {
190 public IInterface asInterface(IBinder binder) {
191 return IVrListener.Stub.asInterface(binder);
195 public boolean checkType(IInterface service) {
196 return service instanceof IVrListener;
200 private final class NotificationAccessManager {
201 private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
202 private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
205 public void update(Collection<String> packageNames) {
206 int currentUserId = ActivityManager.getCurrentUser();
208 ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
209 if (allowed == null) {
210 allowed = new ArraySet<>();
213 // Make sure we revoke notification access for listeners in other users
214 final int listenerCount = mNotificationAccessPackageToUserId.size();
215 for (int i = listenerCount - 1; i >= 0; i--) {
216 final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
217 if (grantUserId != currentUserId) {
218 String packageName = mNotificationAccessPackageToUserId.keyAt(i);
219 revokeNotificationListenerAccess(packageName, grantUserId);
220 revokeNotificationPolicyAccess(packageName);
221 mNotificationAccessPackageToUserId.removeAt(i);
225 for (String pkg : allowed) {
226 if (!packageNames.contains(pkg)) {
227 revokeNotificationListenerAccess(pkg, currentUserId);
228 revokeNotificationPolicyAccess(pkg);
229 mNotificationAccessPackageToUserId.remove(pkg);
232 for (String pkg : packageNames) {
233 if (!allowed.contains(pkg)) {
234 grantNotificationPolicyAccess(pkg);
235 grantNotificationListenerAccess(pkg, currentUserId);
236 mNotificationAccessPackageToUserId.put(pkg, currentUserId);
241 allowed.addAll(packageNames);
242 mAllowedPackages.put(currentUserId, allowed);
247 * Called when a user, package, or setting changes that could affect whether or not the
248 * currently bound VrListenerService is changed.
251 public void onEnabledComponentChanged() {
252 synchronized (mLock) {
253 int currentUser = ActivityManager.getCurrentUser();
256 ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
258 ArraySet<String> enabledPackages = new ArraySet<>();
259 for (ComponentName n : enabledListeners) {
260 String pkg = n.getPackageName();
261 if (isDefaultAllowed(pkg)) {
262 enabledPackages.add(n.getPackageName());
265 mNotifAccessManager.update(enabledPackages);
267 if (mCurrentVrService == null) {
268 return; // No active services
271 // If there is a pending state change, we'd better deal with that first
272 consumeAndApplyPendingStateLocked();
274 if (mCurrentVrService == null) {
275 return; // No active services
278 // There is an active service, update it if needed
279 updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
280 mCurrentVrService.getUserId(), null);
284 private final IVrManager mVrManager = new IVrManager.Stub() {
287 public void registerListener(IVrStateCallbacks cb) {
288 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
290 throw new IllegalArgumentException("Callback binder object is null.");
293 VrManagerService.this.addStateCallback(cb);
297 public void unregisterListener(IVrStateCallbacks cb) {
298 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
300 throw new IllegalArgumentException("Callback binder object is null.");
303 VrManagerService.this.removeStateCallback(cb);
307 public boolean getVrModeState() {
308 return VrManagerService.this.getVrMode();
312 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
313 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
314 != PackageManager.PERMISSION_GRANTED) {
315 pw.println("permission denied: can't dump VrManagerService from pid="
316 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
319 pw.println("********* Dump of VrManagerService *********");
320 pw.println("Previous state transitions:\n");
322 dumpStateTransitions(pw);
323 pw.println("\n\nRemote Callbacks:");
324 int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
327 pw.print(mRemoteCallbacks.getBroadcastItem(i));
328 if (i>0) pw.println(",");
330 mRemoteCallbacks.finishBroadcast();
332 pw.println("Installed VrListenerService components:");
333 int userId = mCurrentVrModeUser;
334 ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
335 if (installed == null || installed.size() == 0) {
338 for (ComponentName n : installed) {
340 pw.println(n.flattenToString());
343 pw.println("Enabled VrListenerService components:");
344 ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
345 if (enabled == null || enabled.size() == 0) {
348 for (ComponentName n : enabled) {
350 pw.println(n.flattenToString());
354 pw.println("********* End of VrManagerService Dump *********");
359 private void enforceCallerPermission(String permission) {
360 if (mContext.checkCallingOrSelfPermission(permission)
361 != PackageManager.PERMISSION_GRANTED) {
362 throw new SecurityException("Caller does not hold the permission " + permission);
367 * Implementation of VrManagerInternal. Callable only from system services.
369 private final class LocalService extends VrManagerInternal {
371 public void setVrMode(boolean enabled, ComponentName packageName, int userId,
372 ComponentName callingPackage) {
373 VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, false);
377 public void setVrModeImmediate(boolean enabled, ComponentName packageName, int userId,
378 ComponentName callingPackage) {
379 VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, true);
383 public boolean isCurrentVrListener(String packageName, int userId) {
384 return VrManagerService.this.isCurrentVrListener(packageName, userId);
388 public int hasVrPackage(ComponentName packageName, int userId) {
389 return VrManagerService.this.hasVrPackage(packageName, userId);
393 public VrManagerService(Context context) {
398 public void onStart() {
399 synchronized(mLock) {
401 mContext = getContext();
404 publishLocalService(VrManagerInternal.class, new LocalService());
405 publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
407 // If there are no VR packages installed on the device, then disable VR
408 // components, otherwise, enable them.
409 setEnabledStatusOfVrComponents();
412 private void setEnabledStatusOfVrComponents() {
413 ArraySet<ComponentName> vrComponents = SystemConfig.getInstance().getDefaultVrComponents();
414 if (vrComponents == null) {
418 // We only want to enable VR components if there is a VR package installed on the device.
419 // The VR components themselves do not quality as a VR package, so exclude them.
420 ArraySet<String> vrComponentPackageNames = new ArraySet<>();
421 for (ComponentName componentName : vrComponents) {
422 vrComponentPackageNames.add(componentName.getPackageName());
425 // Check to see if there are any packages on the device, other than the VR component
427 PackageManager pm = mContext.getPackageManager();
428 List<PackageInfo> packageInfos = pm.getInstalledPackages(
429 PackageManager.GET_CONFIGURATIONS);
430 boolean vrModeIsUsed = false;
431 for (PackageInfo packageInfo : packageInfos) {
432 if (packageInfo != null && packageInfo.packageName != null &&
433 pm.getApplicationEnabledSetting(packageInfo.packageName) ==
434 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
435 vrModeIsUsed = enableVrComponentsIfVrModeUsed(pm, packageInfo,
436 vrComponentPackageNames, vrComponents);
444 Slog.i(TAG, "No VR packages found, disabling VR components");
445 setVrComponentsEnabledOrDisabled(vrComponents, false);
447 // Register to receive an intent when a new package is installed, in case that package
448 // requires VR components.
449 IntentFilter intentFilter = new IntentFilter();
450 intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
451 intentFilter.addDataScheme("package");
452 mContext.registerReceiver(new BroadcastReceiver() {
454 public void onReceive(Context context, Intent intent) {
455 PackageManager pm = context.getPackageManager();
456 final String packageName = intent.getData().getSchemeSpecificPart();
457 if (packageName != null) {
459 PackageInfo packageInfo = pm.getPackageInfo(packageName,
460 PackageManager.GET_CONFIGURATIONS);
461 enableVrComponentsIfVrModeUsed(pm, packageInfo,
462 vrComponentPackageNames, vrComponents);
463 } catch (NameNotFoundException e) {
471 private void setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents,
473 int state = enabled ?
474 PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
475 PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
476 PackageManager pm = mContext.getPackageManager();
477 for (ComponentName componentName : vrComponents) {
479 // Note that we must first check for the existance of the package before trying
480 // to set its enabled state. This is to prevent PackageManager from throwing
481 // an excepton if the package is not found (not just a NameNotFoundException
483 PackageInfo packageInfo = pm.getPackageInfo(componentName.getPackageName(),
484 PackageManager.GET_CONFIGURATIONS);
485 pm.setApplicationEnabledSetting(componentName.getPackageName(), state , 0);
486 } catch (NameNotFoundException e) {
491 private boolean enableVrComponentsIfVrModeUsed(PackageManager pm, PackageInfo packageInfo,
492 ArraySet<String> vrComponentPackageNames, ArraySet<ComponentName> vrComponents) {
493 boolean isVrComponent = vrComponents != null &&
494 vrComponentPackageNames.contains(packageInfo.packageName);
495 if (packageInfo != null && packageInfo.reqFeatures != null && !isVrComponent) {
496 for (FeatureInfo featureInfo : packageInfo.reqFeatures) {
497 if (featureInfo.name != null &&
498 (featureInfo.name.equals(PackageManager.FEATURE_VR_MODE) ||
499 featureInfo.name.equals(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE))) {
500 Slog.i(TAG, "VR package found, enabling VR components");
501 setVrComponentsEnabledOrDisabled(vrComponents, true);
510 public void onBootPhase(int phase) {
511 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
512 synchronized (mLock) {
513 Looper looper = Looper.getMainLooper();
514 Handler handler = new Handler(looper);
515 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
517 mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
518 Settings.Secure.ENABLED_VR_LISTENERS, looper,
519 android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
520 VrListenerService.SERVICE_INTERFACE, mLock, listeners);
522 mComponentObserver.rebuildAll();
528 public void onStartUser(int userHandle) {
529 synchronized (mLock) {
530 mComponentObserver.onUsersChanged();
535 public void onSwitchUser(int userHandle) {
536 synchronized (mLock) {
537 mComponentObserver.onUsersChanged();
543 public void onStopUser(int userHandle) {
544 synchronized (mLock) {
545 mComponentObserver.onUsersChanged();
551 public void onCleanupUser(int userHandle) {
552 synchronized (mLock) {
553 mComponentObserver.onUsersChanged();
557 private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
558 AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
560 // If user changed drop restrictions for the old user.
561 if (oldUserId != newUserId) {
562 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
563 false, mOverlayToken, null, oldUserId);
566 // Apply the restrictions for the current user based on vr state
567 String[] exemptions = (exemptedPackage == null) ? new String[0] :
568 new String[] { exemptedPackage };
570 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
571 mVrModeEnabled, mOverlayToken, exemptions, newUserId);
574 private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
575 String oldVrServicePackage, int oldUserId) {
576 // If VR state changed and we also have a VR service change.
577 if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
580 final long identity = Binder.clearCallingIdentity();
582 // Set overlay exception state based on VR enabled and current service
583 updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
585 Binder.restoreCallingIdentity(identity);
590 * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
591 * the currently selected VR listener service. If the component selected for the VR listener
592 * service has changed, unbind the previous listener and bind the new listener (if enabled).
594 * Note: Must be called while holding {@code mLock}.
596 * @param enabled new state for VR mode.
597 * @param component new component to be bound as a VR listener.
598 * @param userId user owning the component to be bound.
599 * @param calling the component currently using VR mode, or null to leave unchanged.
601 * @return {@code true} if the component/user combination specified is valid.
603 private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
604 int userId, ComponentName calling) {
606 boolean sendUpdatedCaller = false;
607 final long identity = Binder.clearCallingIdentity();
610 boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
611 EnabledComponentsObserver.NO_ERROR);
612 if (!mVrModeEnabled && !enabled) {
613 return validUserComponent; // Disabled -> Disabled transition does nothing.
616 String oldVrServicePackage = mCurrentVrService != null
617 ? mCurrentVrService.getComponent().getPackageName() : null;
618 final int oldUserId = mCurrentVrModeUser;
620 // Always send mode change events.
621 changeVrModeLocked(enabled);
623 if (!enabled || !validUserComponent) {
624 // Unbind whatever is running
625 if (mCurrentVrService != null) {
626 Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
627 mCurrentVrService.getUserId());
628 mCurrentVrService.disconnect();
629 mCurrentVrService = null;
632 if (mCurrentVrService != null) {
633 // Unbind any running service that doesn't match the component/user selection
634 if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
635 Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() +
636 " for user " + mCurrentVrService.getUserId());
637 createAndConnectService(component, userId);
638 sendUpdatedCaller = true;
640 // The service with the correct component/user is bound
642 // Nothing was previously running, bind a new service
643 createAndConnectService(component, userId);
644 sendUpdatedCaller = true;
648 if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
649 mCurrentVrModeComponent = calling;
650 sendUpdatedCaller = true;
653 if (mCurrentVrModeUser != userId) {
654 mCurrentVrModeUser = userId;
655 sendUpdatedCaller = true;
658 String newVrServicePackage = mCurrentVrService != null
659 ? mCurrentVrService.getComponent().getPackageName() : null;
660 final int newUserId = mCurrentVrModeUser;
662 // Update AppOps settings that change state when entering/exiting VR mode, or changing
663 // the current VrListenerService.
664 updateDependentAppOpsLocked(newVrServicePackage, newUserId,
665 oldVrServicePackage, oldUserId);
667 if (mCurrentVrService != null && sendUpdatedCaller) {
668 final ComponentName c = mCurrentVrModeComponent;
669 mCurrentVrService.sendEvent(new PendingEvent() {
671 public void runEvent(IInterface service) throws RemoteException {
672 IVrListener l = (IVrListener) service;
673 l.focusedActivityChanged(c);
679 return validUserComponent;
681 Binder.restoreCallingIdentity(identity);
685 private boolean isDefaultAllowed(String packageName) {
686 PackageManager pm = mContext.getPackageManager();
688 ApplicationInfo info = null;
690 info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
691 } catch (NameNotFoundException e) {
694 if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
700 private void grantNotificationPolicyAccess(String pkg) {
701 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
702 nm.setNotificationPolicyAccessGranted(pkg, true);
705 private void revokeNotificationPolicyAccess(String pkg) {
706 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
707 // Remove any DND zen rules possibly created by the package.
708 nm.removeAutomaticZenRules(pkg);
709 // Remove Notification Policy Access.
710 nm.setNotificationPolicyAccessGranted(pkg, false);
713 private void grantNotificationListenerAccess(String pkg, int userId) {
714 PackageManager pm = mContext.getPackageManager();
715 ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
716 userId, NotificationListenerService.SERVICE_INTERFACE,
717 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
718 ContentResolver resolver = mContext.getContentResolver();
720 ArraySet<String> current = getNotificationListeners(resolver, userId);
722 for (ComponentName c : possibleServices) {
723 String flatName = c.flattenToString();
724 if (Objects.equals(c.getPackageName(), pkg)
725 && !current.contains(flatName)) {
726 current.add(flatName);
730 if (current.size() > 0) {
731 String flatSettings = formatSettings(current);
732 Settings.Secure.putStringForUser(resolver,
733 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
734 flatSettings, userId);
738 private void revokeNotificationListenerAccess(String pkg, int userId) {
739 ContentResolver resolver = mContext.getContentResolver();
741 ArraySet<String> current = getNotificationListeners(resolver, userId);
743 ArrayList<String> toRemove = new ArrayList<>();
745 for (String c : current) {
746 ComponentName component = ComponentName.unflattenFromString(c);
747 if (component.getPackageName().equals(pkg)) {
752 current.removeAll(toRemove);
754 String flatSettings = formatSettings(current);
755 Settings.Secure.putStringForUser(resolver,
756 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
757 flatSettings, userId);
760 private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
761 final int flags = mContext.getPackageManager().getPermissionFlags(
762 permission, pkg, new UserHandle(userId));
763 return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
764 | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
767 private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
768 String flat = Settings.Secure.getStringForUser(resolver,
769 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
771 ArraySet<String> current = new ArraySet<>();
773 String[] allowed = flat.split(":");
774 for (String s : allowed) {
781 private static String formatSettings(Collection<String> c) {
782 if (c == null || c.isEmpty()) {
786 StringBuilder b = new StringBuilder();
787 boolean start = true;
803 private void createAndConnectService(@NonNull ComponentName component, int userId) {
804 mCurrentVrService = VrManagerService.create(mContext, component, userId);
805 mCurrentVrService.connect();
806 Slog.i(TAG, "Connecting " + component + " for user " + userId);
810 * Send VR mode change callbacks to HAL and system services if mode has actually changed.
812 * Note: Must be called while holding {@code mLock}.
814 * @param enabled new state of the VR mode.
816 private void changeVrModeLocked(boolean enabled) {
817 if (mVrModeEnabled != enabled) {
818 mVrModeEnabled = enabled;
820 // Log mode change event.
821 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
822 setVrModeNative(mVrModeEnabled);
824 onVrModeChangedLocked();
829 * Notify system services of VR mode change.
831 * Note: Must be called while holding {@code mLock}.
833 private void onVrModeChangedLocked() {
834 mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
835 (mVrModeEnabled) ? 1 : 0, 0));
839 * Helper function for making ManagedApplicationService instances.
841 private static ManagedApplicationService create(@NonNull Context context,
842 @NonNull ComponentName component, int userId) {
843 return ManagedApplicationService.build(context, component, userId,
844 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
848 private void consumeAndApplyPendingStateLocked() {
849 if (mPendingState != null) {
850 updateCurrentVrServiceLocked(mPendingState.enabled,
851 mPendingState.targetPackageName, mPendingState.userId,
852 mPendingState.callingPackage);
853 mPendingState = null;
857 private void logStateLocked() {
858 ComponentName currentBoundService = (mCurrentVrService == null) ? null :
859 mCurrentVrService.getComponent();
860 VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
861 mCurrentVrModeComponent, mWasDefaultGranted);
862 if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
863 mLoggingDeque.removeFirst();
865 mLoggingDeque.add(current);
868 private void dumpStateTransitions(PrintWriter pw) {
869 SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
871 if (mLoggingDeque.size() == 0) {
875 for (VrState state : mLoggingDeque) {
876 pw.print(d.format(new Date(state.timestamp)));
878 pw.print("State changed to:");
880 pw.println((state.enabled) ? "ENABLED" : "DISABLED");
884 pw.println(state.userId);
886 pw.print("Current VR Activity=");
887 pw.println((state.callingPackage == null) ?
888 "None" : state.callingPackage.flattenToString());
890 pw.print("Bound VrListenerService=");
891 pw.println((state.targetPackageName == null) ?
892 "None" : state.targetPackageName.flattenToString());
893 if (state.defaultPermissionsGranted) {
895 pw.println("Default permissions granted to the bound VrListenerService.");
902 * Implementation of VrManagerInternal calls. These are callable from system services.
905 private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
906 int userId, @NonNull ComponentName callingPackage, boolean immediate) {
908 synchronized (mLock) {
910 if (!enabled && mCurrentVrService != null && !immediate) {
911 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
912 // and service bind/unbind in case we are immediately switching to another VR app.
913 if (mPendingState == null) {
914 mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
915 PENDING_STATE_DELAY_MS);
918 mPendingState = new VrState(enabled, targetPackageName, userId, callingPackage);
921 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
922 mPendingState = null;
925 updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
929 private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
930 synchronized (mLock) {
931 return mComponentObserver.isValid(targetPackageName, userId);
935 private boolean isCurrentVrListener(String packageName, int userId) {
936 synchronized (mLock) {
937 if (mCurrentVrService == null) {
940 return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
941 userId == mCurrentVrService.getUserId();
946 * Implementation of IVrManager calls.
949 private void addStateCallback(IVrStateCallbacks cb) {
950 mRemoteCallbacks.register(cb);
953 private void removeStateCallback(IVrStateCallbacks cb) {
954 mRemoteCallbacks.unregister(cb);
957 private boolean getVrMode() {
958 synchronized (mLock) {
959 return mVrModeEnabled;