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