VrManagerService.java revision dc34df5d310245a268ee9ea3872a612c6f7950b5
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 */ 16package com.android.server.vr; 17 18import android.Manifest; 19import android.app.AppOpsManager; 20import android.app.NotificationManager; 21import android.annotation.NonNull; 22import android.content.ComponentName; 23import android.content.ContentResolver; 24import android.content.Context; 25import android.content.pm.ApplicationInfo; 26import android.content.pm.PackageManager; 27import android.content.pm.PackageManager.NameNotFoundException; 28import android.os.Binder; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.IInterface; 32import android.os.Looper; 33import android.os.Message; 34import android.os.RemoteCallbackList; 35import android.os.RemoteException; 36import android.os.UserHandle; 37import android.provider.Settings; 38import android.service.notification.NotificationListenerService; 39import android.service.vr.IVrListener; 40import android.service.vr.IVrManager; 41import android.service.vr.IVrStateCallbacks; 42import android.service.vr.VrListenerService; 43import android.util.ArraySet; 44import android.util.Slog; 45 46import com.android.internal.R; 47import com.android.server.SystemService; 48import com.android.server.utils.ManagedApplicationService.PendingEvent; 49import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener; 50import com.android.server.utils.ManagedApplicationService; 51import com.android.server.utils.ManagedApplicationService.BinderChecker; 52 53import java.io.FileDescriptor; 54import java.io.PrintWriter; 55import java.lang.StringBuilder; 56import java.lang.ref.WeakReference; 57import java.util.ArrayList; 58import java.util.Collection; 59import java.util.Objects; 60import java.util.Set; 61 62/** 63 * Service tracking whether VR mode is active, and notifying listening services of state changes. 64 * <p/> 65 * Services running in system server may modify the state of VrManagerService via the interface in 66 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the 67 * interface given in VrStateListener. 68 * <p/> 69 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.: 70 * hardware/libhardware/modules/vr 71 * <p/> 72 * In general applications may enable or disable VR mode by calling 73 * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to 74 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}. 75 * 76 * @see {@link android.service.vr.VrListenerService} 77 * @see {@link com.android.server.vr.VrManagerInternal} 78 * @see {@link com.android.server.vr.VrStateListener} 79 * 80 * @hide 81 */ 82public class VrManagerService extends SystemService implements EnabledComponentChangeListener{ 83 84 public static final String TAG = "VrManagerService"; 85 86 public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager"; 87 88 private static native void initializeNative(); 89 private static native void setVrModeNative(boolean enabled); 90 91 private final Object mLock = new Object(); 92 93 private final IBinder mOverlayToken = new Binder(); 94 95 // State protected by mLock 96 private boolean mVrModeEnabled; 97 private EnabledComponentsObserver mComponentObserver; 98 private ManagedApplicationService mCurrentVrService; 99 private Context mContext; 100 private ComponentName mCurrentVrModeComponent; 101 private int mCurrentVrModeUser; 102 private boolean mWasDefaultGranted; 103 private boolean mGuard; 104 private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks = 105 new RemoteCallbackList<>(); 106 private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>(); 107 private String mPreviousNotificationPolicyAccessPackage; 108 private String mPreviousManageOverlayPackage; 109 110 private static final int MSG_VR_STATE_CHANGE = 0; 111 112 private final Handler mHandler = new Handler() { 113 @Override 114 public void handleMessage(Message msg) { 115 switch(msg.what) { 116 case MSG_VR_STATE_CHANGE : { 117 boolean state = (msg.arg1 == 1); 118 int i = mRemoteCallbacks.beginBroadcast(); 119 while (i > 0) { 120 i--; 121 try { 122 mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state); 123 } catch (RemoteException e) { 124 // Noop 125 } 126 } 127 mRemoteCallbacks.finishBroadcast(); 128 } break; 129 default : 130 throw new IllegalStateException("Unknown message type: " + msg.what); 131 } 132 } 133 }; 134 135 private static final BinderChecker sBinderChecker = new BinderChecker() { 136 @Override 137 public IInterface asInterface(IBinder binder) { 138 return IVrListener.Stub.asInterface(binder); 139 } 140 141 @Override 142 public boolean checkType(IInterface service) { 143 return service instanceof IVrListener; 144 } 145 }; 146 147 /** 148 * Called when a user, package, or setting changes that could affect whether or not the 149 * currently bound VrListenerService is changed. 150 */ 151 @Override 152 public void onEnabledComponentChanged() { 153 synchronized (mLock) { 154 if (mCurrentVrService == null) { 155 return; // No active services 156 } 157 158 // There is an active service, update it if needed 159 updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(), 160 mCurrentVrService.getUserId(), null); 161 } 162 } 163 164 private final IVrManager mVrManager = new IVrManager.Stub() { 165 166 @Override 167 public void registerListener(IVrStateCallbacks cb) { 168 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); 169 if (cb == null) { 170 throw new IllegalArgumentException("Callback binder object is null."); 171 } 172 173 VrManagerService.this.addStateCallback(cb); 174 } 175 176 @Override 177 public void unregisterListener(IVrStateCallbacks cb) { 178 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); 179 if (cb == null) { 180 throw new IllegalArgumentException("Callback binder object is null."); 181 } 182 183 VrManagerService.this.removeStateCallback(cb); 184 } 185 186 @Override 187 public boolean getVrModeState() { 188 return VrManagerService.this.getVrMode(); 189 } 190 191 @Override 192 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 193 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 194 != PackageManager.PERMISSION_GRANTED) { 195 pw.println("permission denied: can't dump VrManagerService from pid=" 196 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 197 return; 198 } 199 pw.print("mVrModeEnabled="); 200 pw.println(mVrModeEnabled); 201 pw.print("mCurrentVrModeUser="); 202 pw.println(mCurrentVrModeUser); 203 pw.print("mRemoteCallbacks="); 204 int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array 205 while(i-->0) { 206 pw.print(mRemoteCallbacks.getBroadcastItem(i)); 207 if (i>0) pw.print(", "); 208 } 209 mRemoteCallbacks.finishBroadcast(); 210 pw.println(); 211 pw.print("mCurrentVrService="); 212 pw.println(mCurrentVrService != null ? mCurrentVrService.getComponent() : "(none)"); 213 pw.print("mCurrentVrModeComponent="); 214 pw.println(mCurrentVrModeComponent); 215 } 216 217 }; 218 219 private void enforceCallerPermission(String permission) { 220 if (mContext.checkCallingOrSelfPermission(permission) 221 != PackageManager.PERMISSION_GRANTED) { 222 throw new SecurityException("Caller does not hold the permission " + permission); 223 } 224 } 225 226 /** 227 * Implementation of VrManagerInternal. Callable only from system services. 228 */ 229 private final class LocalService extends VrManagerInternal { 230 @Override 231 public void setVrMode(boolean enabled, ComponentName packageName, int userId, 232 ComponentName callingPackage) { 233 VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage); 234 } 235 236 @Override 237 public boolean isCurrentVrListener(String packageName, int userId) { 238 return VrManagerService.this.isCurrentVrListener(packageName, userId); 239 } 240 241 @Override 242 public int hasVrPackage(ComponentName packageName, int userId) { 243 return VrManagerService.this.hasVrPackage(packageName, userId); 244 } 245 } 246 247 public VrManagerService(Context context) { 248 super(context); 249 } 250 251 @Override 252 public void onStart() { 253 synchronized(mLock) { 254 initializeNative(); 255 mContext = getContext(); 256 } 257 258 publishLocalService(VrManagerInternal.class, new LocalService()); 259 publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder()); 260 } 261 262 @Override 263 public void onBootPhase(int phase) { 264 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 265 synchronized (mLock) { 266 Looper looper = Looper.getMainLooper(); 267 Handler handler = new Handler(looper); 268 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>(); 269 listeners.add(this); 270 mComponentObserver = EnabledComponentsObserver.build(mContext, handler, 271 Settings.Secure.ENABLED_VR_LISTENERS, looper, 272 android.Manifest.permission.BIND_VR_LISTENER_SERVICE, 273 VrListenerService.SERVICE_INTERFACE, mLock, listeners); 274 275 mComponentObserver.rebuildAll(); 276 } 277 } 278 } 279 280 @Override 281 public void onStartUser(int userHandle) { 282 synchronized (mLock) { 283 mComponentObserver.onUsersChanged(); 284 } 285 } 286 287 @Override 288 public void onSwitchUser(int userHandle) { 289 synchronized (mLock) { 290 mComponentObserver.onUsersChanged(); 291 } 292 293 } 294 295 @Override 296 public void onStopUser(int userHandle) { 297 synchronized (mLock) { 298 mComponentObserver.onUsersChanged(); 299 } 300 301 } 302 303 @Override 304 public void onCleanupUser(int userHandle) { 305 synchronized (mLock) { 306 mComponentObserver.onUsersChanged(); 307 } 308 } 309 310 private void updateOverlayStateLocked(ComponentName exemptedComponent) { 311 final long identity = Binder.clearCallingIdentity(); 312 try { 313 AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class); 314 if (appOpsManager != null) { 315 String[] exemptions = (exemptedComponent == null) ? new String[0] : 316 new String[] { exemptedComponent.getPackageName() }; 317 318 appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, 319 mVrModeEnabled, mOverlayToken, exemptions); 320 } 321 } finally { 322 Binder.restoreCallingIdentity(identity); 323 } 324 } 325 326 /** 327 * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of 328 * the currently selected VR listener service. If the component selected for the VR listener 329 * service has changed, unbind the previous listener and bind the new listener (if enabled). 330 * <p/> 331 * Note: Must be called while holding {@code mLock}. 332 * 333 * @param enabled new state for VR mode. 334 * @param component new component to be bound as a VR listener. 335 * @param userId user owning the component to be bound. 336 * @param calling the component currently using VR mode, or null to leave unchanged. 337 * 338 * @return {@code true} if the component/user combination specified is valid. 339 */ 340 private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component, 341 int userId, ComponentName calling) { 342 343 boolean sendUpdatedCaller = false; 344 final long identity = Binder.clearCallingIdentity(); 345 try { 346 347 boolean validUserComponent = (mComponentObserver.isValid(component, userId) == 348 EnabledComponentsObserver.NO_ERROR); 349 350 // Always send mode change events. 351 changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null); 352 353 if (!enabled || !validUserComponent) { 354 // Unbind whatever is running 355 if (mCurrentVrService != null) { 356 Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " + 357 mCurrentVrService.getUserId()); 358 mCurrentVrService.disconnect(); 359 disableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 360 new UserHandle(mCurrentVrService.getUserId())); 361 mCurrentVrService = null; 362 } 363 } else { 364 if (mCurrentVrService != null) { 365 // Unbind any running service that doesn't match the component/user selection 366 if (mCurrentVrService.disconnectIfNotMatching(component, userId)) { 367 Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + 368 " for user " + mCurrentVrService.getUserId()); 369 disableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 370 new UserHandle(mCurrentVrService.getUserId())); 371 createAndConnectService(component, userId); 372 enableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 373 new UserHandle(mCurrentVrService.getUserId())); 374 sendUpdatedCaller = true; 375 } 376 // The service with the correct component/user is bound 377 } else { 378 // Nothing was previously running, bind a new service 379 createAndConnectService(component, userId); 380 enableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 381 new UserHandle(mCurrentVrService.getUserId())); 382 sendUpdatedCaller = true; 383 } 384 } 385 386 if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) { 387 mCurrentVrModeComponent = calling; 388 mCurrentVrModeUser = userId; 389 sendUpdatedCaller = true; 390 } 391 392 if (mCurrentVrService != null && sendUpdatedCaller) { 393 final ComponentName c = mCurrentVrModeComponent; 394 mCurrentVrService.sendEvent(new PendingEvent() { 395 @Override 396 public void runEvent(IInterface service) throws RemoteException { 397 IVrListener l = (IVrListener) service; 398 l.focusedActivityChanged(c); 399 } 400 }); 401 } 402 403 return validUserComponent; 404 } finally { 405 Binder.restoreCallingIdentity(identity); 406 } 407 } 408 409 /** 410 * Enable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given 411 * component package and user. 412 * 413 * @param component the component whose package should be enabled. 414 * @param userId the user that owns the given component. 415 */ 416 private void enableImpliedPermissionsLocked(ComponentName component, UserHandle userId) { 417 if (mGuard) { 418 // Impossible 419 throw new IllegalStateException("Enabling permissions without disabling."); 420 } 421 mGuard = true; 422 423 PackageManager pm = mContext.getPackageManager(); 424 425 String pName = component.getPackageName(); 426 if (pm == null) { 427 Slog.e(TAG, "Couldn't set implied permissions for " + pName + 428 ", PackageManager isn't running"); 429 return; 430 } 431 432 ApplicationInfo info = null; 433 try { 434 info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA); 435 } catch (NameNotFoundException e) { 436 } 437 438 if (info == null) { 439 Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package."); 440 return; 441 } 442 443 if (!(info.isSystemApp() || info.isUpdatedSystemApp())) { 444 return; // Application is not pre-installed, avoid setting implied permissions 445 } 446 447 mWasDefaultGranted = true; 448 449 grantOverlayAccess(pName, userId); 450 grantNotificationPolicyAccess(pName); 451 grantNotificationListenerAccess(pName, userId); 452 } 453 454 /** 455 * Disable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given 456 * component package and user. 457 * 458 * @param component the component whose package should be disabled. 459 * @param userId the user that owns the given component. 460 */ 461 private void disableImpliedPermissionsLocked(ComponentName component, UserHandle userId) { 462 if (!mGuard) { 463 // Impossible 464 throw new IllegalStateException("Disabling permissions without enabling."); 465 } 466 mGuard = false; 467 468 PackageManager pm = mContext.getPackageManager(); 469 470 if (pm == null) { 471 Slog.e(TAG, "Couldn't remove implied permissions for " + component + 472 ", PackageManager isn't running"); 473 return; 474 } 475 476 String pName = component.getPackageName(); 477 if (mWasDefaultGranted) { 478 revokeOverlayAccess(userId); 479 revokeNotificationPolicyAccess(pName); 480 revokeNotificiationListenerAccess(); 481 mWasDefaultGranted = false; 482 } 483 484 } 485 486 private void grantOverlayAccess(String pkg, UserHandle userId) { 487 PackageManager pm = mContext.getPackageManager(); 488 boolean prev = (PackageManager.PERMISSION_GRANTED == 489 pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg)); 490 mPreviousManageOverlayPackage = null; 491 if (!prev) { 492 pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW, 493 userId); 494 mPreviousManageOverlayPackage = pkg; 495 } 496 } 497 498 private void revokeOverlayAccess(UserHandle userId) { 499 PackageManager pm = mContext.getPackageManager(); 500 if (mPreviousManageOverlayPackage != null) { 501 pm.revokeRuntimePermission(mPreviousManageOverlayPackage, 502 android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId); 503 mPreviousManageOverlayPackage = null; 504 } 505 } 506 507 508 private void grantNotificationPolicyAccess(String pkg) { 509 NotificationManager nm = mContext.getSystemService(NotificationManager.class); 510 boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg); 511 mPreviousNotificationPolicyAccessPackage = null; 512 if (!prev) { 513 mPreviousNotificationPolicyAccessPackage = pkg; 514 nm.setNotificationPolicyAccessGranted(pkg, true); 515 } 516 } 517 518 private void revokeNotificationPolicyAccess(String pkg) { 519 NotificationManager nm = mContext.getSystemService(NotificationManager.class); 520 if (mPreviousNotificationPolicyAccessPackage != null) { 521 if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) { 522 // Remove any DND zen rules possibly created by the package. 523 nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage); 524 // Remove Notification Policy Access. 525 nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false); 526 mPreviousNotificationPolicyAccessPackage = null; 527 } else { 528 Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg); 529 } 530 } 531 } 532 533 private void grantNotificationListenerAccess(String pkg, UserHandle userId) { 534 PackageManager pm = mContext.getPackageManager(); 535 ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm, 536 userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE, 537 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); 538 ContentResolver resolver = mContext.getContentResolver(); 539 540 ArraySet<String> current = getCurrentNotifListeners(resolver); 541 542 mPreviousToggledListenerSettings.clear(); 543 544 for (ComponentName c : possibleServices) { 545 String flatName = c.flattenToString(); 546 if (Objects.equals(c.getPackageName(), pkg) 547 && !current.contains(flatName)) { 548 mPreviousToggledListenerSettings.add(flatName); 549 current.add(flatName); 550 } 551 } 552 553 if (current.size() > 0) { 554 String flatSettings = formatSettings(current); 555 Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, 556 flatSettings); 557 } 558 } 559 560 private void revokeNotificiationListenerAccess() { 561 if (mPreviousToggledListenerSettings.isEmpty()) { 562 return; 563 } 564 565 ContentResolver resolver = mContext.getContentResolver(); 566 ArraySet<String> current = getCurrentNotifListeners(resolver); 567 568 current.removeAll(mPreviousToggledListenerSettings); 569 mPreviousToggledListenerSettings.clear(); 570 571 String flatSettings = formatSettings(current); 572 Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, 573 flatSettings); 574 } 575 576 private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) { 577 String flat = Settings.Secure.getString(resolver, 578 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); 579 580 ArraySet<String> current = new ArraySet<>(); 581 if (flat != null) { 582 String[] allowed = flat.split(":"); 583 for (String s : allowed) { 584 current.add(s); 585 } 586 } 587 return current; 588 } 589 590 private static String formatSettings(Collection<String> c) { 591 if (c == null || c.isEmpty()) { 592 return ""; 593 } 594 595 StringBuilder b = new StringBuilder(); 596 boolean start = true; 597 for (String s : c) { 598 if ("".equals(s)) { 599 continue; 600 } 601 if (!start) { 602 b.append(':'); 603 } 604 b.append(s); 605 start = false; 606 } 607 return b.toString(); 608 } 609 610 611 612 private void createAndConnectService(@NonNull ComponentName component, int userId) { 613 mCurrentVrService = VrManagerService.create(mContext, component, userId); 614 mCurrentVrService.connect(); 615 Slog.i(TAG, "Connecting " + component + " for user " + userId); 616 } 617 618 /** 619 * Send VR mode change callbacks to HAL and system services if mode has actually changed. 620 * <p/> 621 * Note: Must be called while holding {@code mLock}. 622 * 623 * @param enabled new state of the VR mode. 624 * @param exemptedComponent a component to exempt from AppOps restrictions for overlays. 625 */ 626 private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) { 627 if (mVrModeEnabled != enabled) { 628 mVrModeEnabled = enabled; 629 630 // Log mode change event. 631 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled")); 632 setVrModeNative(mVrModeEnabled); 633 634 updateOverlayStateLocked(exemptedComponent); 635 onVrModeChangedLocked(); 636 } 637 } 638 639 /** 640 * Notify system services of VR mode change. 641 * <p/> 642 * Note: Must be called while holding {@code mLock}. 643 */ 644 private void onVrModeChangedLocked() { 645 mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE, 646 (mVrModeEnabled) ? 1 : 0, 0)); 647 } 648 649 /** 650 * Helper function for making ManagedApplicationService instances. 651 */ 652 private static ManagedApplicationService create(@NonNull Context context, 653 @NonNull ComponentName component, int userId) { 654 return ManagedApplicationService.build(context, component, userId, 655 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS, 656 sBinderChecker); 657 } 658 659 /* 660 * Implementation of VrManagerInternal calls. These are callable from system services. 661 */ 662 663 private boolean setVrMode(boolean enabled, @NonNull ComponentName targetPackageName, 664 int userId, @NonNull ComponentName callingPackage) { 665 synchronized (mLock) { 666 return updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage); 667 } 668 } 669 670 private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) { 671 synchronized (mLock) { 672 return mComponentObserver.isValid(targetPackageName, userId); 673 } 674 } 675 676 private boolean isCurrentVrListener(String packageName, int userId) { 677 synchronized (mLock) { 678 if (mCurrentVrService == null) { 679 return false; 680 } 681 return mCurrentVrService.getComponent().getPackageName().equals(packageName) && 682 userId == mCurrentVrService.getUserId(); 683 } 684 } 685 686 /* 687 * Implementation of IVrManager calls. 688 */ 689 690 private void addStateCallback(IVrStateCallbacks cb) { 691 mRemoteCallbacks.register(cb); 692 } 693 694 private void removeStateCallback(IVrStateCallbacks cb) { 695 mRemoteCallbacks.unregister(cb); 696 } 697 698 private boolean getVrMode() { 699 synchronized (mLock) { 700 return mVrModeEnabled; 701 } 702 } 703} 704