1 /**
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.server.vr;
17 
18 import 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;
61 
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;
71 import java.util.Map;
72 import java.util.Objects;
73 
74 /**
75  * Service tracking whether VR mode is active, and notifying listening services of state changes.
76  * <p/>
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.
80  * <p/>
81  * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
82  *  hardware/libhardware/modules/vr
83  * <p/>
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}.
87  *
88  * @see {@link android.service.vr.VrListenerService}
89  * @see {@link com.android.server.vr.VrManagerInternal}
90  * @see {@link com.android.server.vr.VrStateListener}
91  *
92  * @hide
93  */
94 public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
95 
96     public static final String TAG = "VrManagerService";
97 
98     public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
99 
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;
103 
initializeNative()104     private static native void initializeNative();
setVrModeNative(boolean enabled)105     private static native void setVrModeNative(boolean enabled);
106 
107     private final Object mLock = new Object();
108 
109     private final IBinder mOverlayToken = new Binder();
110 
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();
127 
128     private static final int MSG_VR_STATE_CHANGE = 0;
129     private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
130 
131     private final Handler mHandler = new Handler() {
132         @Override
133         public void handleMessage(Message msg) {
134             switch(msg.what) {
135                 case MSG_VR_STATE_CHANGE : {
136                     boolean state = (msg.arg1 == 1);
137                     int i = mRemoteCallbacks.beginBroadcast();
138                     while (i > 0) {
139                         i--;
140                         try {
141                             mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
142                         } catch (RemoteException e) {
143                             // Noop
144                         }
145                     }
146                     mRemoteCallbacks.finishBroadcast();
147                 } break;
148                 case MSG_PENDING_VR_STATE_CHANGE : {
149                     synchronized(mLock) {
150                         VrManagerService.this.consumeAndApplyPendingStateLocked();
151                     }
152                 } break;
153                 default :
154                     throw new IllegalStateException("Unknown message type: " + msg.what);
155             }
156         }
157     };
158 
159     private static class VrState {
160         final boolean enabled;
161         final int userId;
162         final ComponentName targetPackageName;
163         final ComponentName callingPackage;
164         final long timestamp;
165         final boolean defaultPermissionsGranted;
166 
VrState(boolean enabled, ComponentName targetPackageName, int userId, ComponentName callingPackage)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();
175         }
176 
VrState(boolean enabled, ComponentName targetPackageName, int userId, ComponentName callingPackage, boolean defaultPermissionsGranted)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();
185         }
186     }
187 
188     private static final BinderChecker sBinderChecker = new BinderChecker() {
189         @Override
190         public IInterface asInterface(IBinder binder) {
191             return IVrListener.Stub.asInterface(binder);
192         }
193 
194         @Override
195         public boolean checkType(IInterface service) {
196             return service instanceof IVrListener;
197         }
198     };
199 
200     private final class NotificationAccessManager {
201         private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
202         private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
203                 new ArrayMap<>();
204 
update(Collection<String> packageNames)205         public void update(Collection<String> packageNames) {
206             int currentUserId = ActivityManager.getCurrentUser();
207 
208             ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
209             if (allowed == null) {
210                 allowed = new ArraySet<>();
211             }
212 
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);
222                 }
223             }
224 
225             for (String pkg : allowed) {
226                 if (!packageNames.contains(pkg)) {
227                     revokeNotificationListenerAccess(pkg, currentUserId);
228                     revokeNotificationPolicyAccess(pkg);
229                     mNotificationAccessPackageToUserId.remove(pkg);
230                 }
231             }
232             for (String pkg : packageNames) {
233                 if (!allowed.contains(pkg)) {
234                     grantNotificationPolicyAccess(pkg);
235                     grantNotificationListenerAccess(pkg, currentUserId);
236                     mNotificationAccessPackageToUserId.put(pkg, currentUserId);
237                 }
238             }
239 
240             allowed.clear();
241             allowed.addAll(packageNames);
242             mAllowedPackages.put(currentUserId, allowed);
243         }
244     }
245 
246     /**
247      * Called when a user, package, or setting changes that could affect whether or not the
248      * currently bound VrListenerService is changed.
249      */
250     @Override
onEnabledComponentChanged()251     public void onEnabledComponentChanged() {
252         synchronized (mLock) {
253             int currentUser = ActivityManager.getCurrentUser();
254 
255             // Update listeners
256             ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
257 
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());
263                 }
264             }
265             mNotifAccessManager.update(enabledPackages);
266 
267             if (mCurrentVrService == null) {
268                 return; // No active services
269             }
270 
271             // If there is a pending state change, we'd better deal with that first
272             consumeAndApplyPendingStateLocked();
273 
274             if (mCurrentVrService == null) {
275                 return; // No active services
276             }
277 
278             // There is an active service, update it if needed
279             updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
280                     mCurrentVrService.getUserId(), null);
281         }
282     }
283 
284     private final IVrManager mVrManager = new IVrManager.Stub() {
285 
286         @Override
287         public void registerListener(IVrStateCallbacks cb) {
288             enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
289             if (cb == null) {
290                 throw new IllegalArgumentException("Callback binder object is null.");
291             }
292 
293             VrManagerService.this.addStateCallback(cb);
294         }
295 
296         @Override
297         public void unregisterListener(IVrStateCallbacks cb) {
298             enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
299             if (cb == null) {
300                 throw new IllegalArgumentException("Callback binder object is null.");
301             }
302 
303             VrManagerService.this.removeStateCallback(cb);
304         }
305 
306         @Override
307         public boolean getVrModeState() {
308             return VrManagerService.this.getVrMode();
309         }
310 
311         @Override
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());
317                 return;
318             }
319             pw.println("********* Dump of VrManagerService *********");
320             pw.println("Previous state transitions:\n");
321             String tab = "  ";
322             dumpStateTransitions(pw);
323             pw.println("\n\nRemote Callbacks:");
324             int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
325             while(i-->0) {
326                 pw.print(tab);
327                 pw.print(mRemoteCallbacks.getBroadcastItem(i));
328                 if (i>0) pw.println(",");
329             }
330             mRemoteCallbacks.finishBroadcast();
331             pw.println("\n");
332             pw.println("Installed VrListenerService components:");
333             int userId = mCurrentVrModeUser;
334             ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
335             if (installed == null || installed.size() == 0) {
336                 pw.println("None");
337             } else {
338                 for (ComponentName n : installed) {
339                     pw.print(tab);
340                     pw.println(n.flattenToString());
341                 }
342             }
343             pw.println("Enabled VrListenerService components:");
344             ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
345             if (enabled == null || enabled.size() == 0) {
346                 pw.println("None");
347             } else {
348                 for (ComponentName n : enabled) {
349                     pw.print(tab);
350                     pw.println(n.flattenToString());
351                 }
352             }
353             pw.println("\n");
354             pw.println("********* End of VrManagerService Dump *********");
355         }
356 
357     };
358 
enforceCallerPermission(String permission)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);
363         }
364     }
365 
366     /**
367      * Implementation of VrManagerInternal.  Callable only from system services.
368      */
369     private final class LocalService extends VrManagerInternal {
370         @Override
setVrMode(boolean enabled, ComponentName packageName, int userId, ComponentName callingPackage)371         public void setVrMode(boolean enabled, ComponentName packageName, int userId,
372                 ComponentName callingPackage) {
373             VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, false);
374         }
375 
376         @Override
setVrModeImmediate(boolean enabled, ComponentName packageName, int userId, ComponentName callingPackage)377         public void setVrModeImmediate(boolean enabled, ComponentName packageName, int userId,
378                 ComponentName callingPackage) {
379             VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, true);
380         }
381 
382         @Override
isCurrentVrListener(String packageName, int userId)383         public boolean isCurrentVrListener(String packageName, int userId) {
384             return VrManagerService.this.isCurrentVrListener(packageName, userId);
385         }
386 
387         @Override
hasVrPackage(ComponentName packageName, int userId)388         public int hasVrPackage(ComponentName packageName, int userId) {
389             return VrManagerService.this.hasVrPackage(packageName, userId);
390         }
391     }
392 
VrManagerService(Context context)393     public VrManagerService(Context context) {
394         super(context);
395     }
396 
397     @Override
onStart()398     public void onStart() {
399         synchronized(mLock) {
400             initializeNative();
401             mContext = getContext();
402         }
403 
404         publishLocalService(VrManagerInternal.class, new LocalService());
405         publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
406 
407         // If there are no VR packages installed on the device, then disable VR
408         // components, otherwise, enable them.
409         setEnabledStatusOfVrComponents();
410     }
411 
setEnabledStatusOfVrComponents()412     private void setEnabledStatusOfVrComponents() {
413         ArraySet<ComponentName> vrComponents = SystemConfig.getInstance().getDefaultVrComponents();
414         if (vrComponents == null) {
415            return;
416         }
417 
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());
423         }
424 
425         // Check to see if there are any packages on the device, other than the VR component
426         // packages.
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);
437                 if (vrModeIsUsed) {
438                     break;
439                 }
440             }
441         }
442 
443         if (!vrModeIsUsed) {
444             Slog.i(TAG, "No VR packages found, disabling VR components");
445             setVrComponentsEnabledOrDisabled(vrComponents, false);
446 
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() {
453                 @Override
454                 public void onReceive(Context context, Intent intent) {
455                     PackageManager pm = context.getPackageManager();
456                     final String packageName = intent.getData().getSchemeSpecificPart();
457                     if (packageName != null) {
458                         try {
459                             PackageInfo packageInfo = pm.getPackageInfo(packageName,
460                                     PackageManager.GET_CONFIGURATIONS);
461                             enableVrComponentsIfVrModeUsed(pm, packageInfo,
462                                     vrComponentPackageNames, vrComponents);
463                         } catch (NameNotFoundException e) {
464                         }
465                     }
466                 };
467             }, intentFilter);
468         }
469     }
470 
setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents, boolean enabled)471     private void setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents,
472             boolean enabled) {
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) {
478             try {
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
482                 // exception).
483                 PackageInfo packageInfo = pm.getPackageInfo(componentName.getPackageName(),
484                         PackageManager.GET_CONFIGURATIONS);
485                 pm.setApplicationEnabledSetting(componentName.getPackageName(), state , 0);
486             } catch (NameNotFoundException e) {
487             }
488         }
489     }
490 
enableVrComponentsIfVrModeUsed(PackageManager pm, PackageInfo packageInfo, ArraySet<String> vrComponentPackageNames, ArraySet<ComponentName> vrComponents)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);
502                     return true;
503                 }
504             }
505         }
506         return false;
507     }
508 
509     @Override
onBootPhase(int phase)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<>();
516                 listeners.add(this);
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);
521 
522                 mComponentObserver.rebuildAll();
523             }
524         }
525     }
526 
527     @Override
onStartUser(int userHandle)528     public void onStartUser(int userHandle) {
529         synchronized (mLock) {
530             mComponentObserver.onUsersChanged();
531         }
532     }
533 
534     @Override
onSwitchUser(int userHandle)535     public void onSwitchUser(int userHandle) {
536         synchronized (mLock) {
537             mComponentObserver.onUsersChanged();
538         }
539 
540     }
541 
542     @Override
onStopUser(int userHandle)543     public void onStopUser(int userHandle) {
544         synchronized (mLock) {
545             mComponentObserver.onUsersChanged();
546         }
547 
548     }
549 
550     @Override
onCleanupUser(int userHandle)551     public void onCleanupUser(int userHandle) {
552         synchronized (mLock) {
553             mComponentObserver.onUsersChanged();
554         }
555     }
556 
updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId)557     private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
558         AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
559 
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);
564         }
565 
566         // Apply the restrictions for the current user based on vr state
567         String[] exemptions = (exemptedPackage == null) ? new String[0] :
568                 new String[] { exemptedPackage };
569 
570         appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
571                 mVrModeEnabled, mOverlayToken, exemptions, newUserId);
572     }
573 
updateDependentAppOpsLocked(String newVrServicePackage, int newUserId, String oldVrServicePackage, int oldUserId)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)) {
578             return;
579         }
580         final long identity = Binder.clearCallingIdentity();
581         try {
582             // Set overlay exception state based on VR enabled and current service
583             updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
584         } finally {
585             Binder.restoreCallingIdentity(identity);
586         }
587     }
588 
589     /**
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).
593      * <p/>
594      * Note: Must be called while holding {@code mLock}.
595      *
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.
600      *
601      * @return {@code true} if the component/user combination specified is valid.
602      */
updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component, int userId, ComponentName calling)603     private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
604             int userId, ComponentName calling) {
605 
606         boolean sendUpdatedCaller = false;
607         final long identity = Binder.clearCallingIdentity();
608         try {
609 
610             boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
611                     EnabledComponentsObserver.NO_ERROR);
612             if (!mVrModeEnabled && !enabled) {
613                 return validUserComponent; // Disabled -> Disabled transition does nothing.
614             }
615 
616             String oldVrServicePackage = mCurrentVrService != null
617                     ? mCurrentVrService.getComponent().getPackageName() : null;
618             final int oldUserId = mCurrentVrModeUser;
619 
620             // Always send mode change events.
621             changeVrModeLocked(enabled);
622 
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;
630                 }
631             } else {
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;
639                     }
640                     // The service with the correct component/user is bound
641                 } else {
642                     // Nothing was previously running, bind a new service
643                     createAndConnectService(component, userId);
644                     sendUpdatedCaller = true;
645                 }
646             }
647 
648             if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
649                 mCurrentVrModeComponent = calling;
650                 sendUpdatedCaller = true;
651             }
652 
653             if (mCurrentVrModeUser != userId) {
654                 mCurrentVrModeUser = userId;
655                 sendUpdatedCaller = true;
656             }
657 
658             String newVrServicePackage = mCurrentVrService != null
659                     ? mCurrentVrService.getComponent().getPackageName() : null;
660             final int newUserId = mCurrentVrModeUser;
661 
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);
666 
667             if (mCurrentVrService != null && sendUpdatedCaller) {
668                 final ComponentName c = mCurrentVrModeComponent;
669                 mCurrentVrService.sendEvent(new PendingEvent() {
670                     @Override
671                     public void runEvent(IInterface service) throws RemoteException {
672                         IVrListener l = (IVrListener) service;
673                         l.focusedActivityChanged(c);
674                     }
675                 });
676             }
677             logStateLocked();
678 
679             return validUserComponent;
680         } finally {
681             Binder.restoreCallingIdentity(identity);
682         }
683     }
684 
isDefaultAllowed(String packageName)685     private boolean isDefaultAllowed(String packageName) {
686         PackageManager pm = mContext.getPackageManager();
687 
688         ApplicationInfo info = null;
689         try {
690             info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
691         } catch (NameNotFoundException e) {
692         }
693 
694         if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
695             return false;
696         }
697         return true;
698     }
699 
grantNotificationPolicyAccess(String pkg)700     private void grantNotificationPolicyAccess(String pkg) {
701         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
702         nm.setNotificationPolicyAccessGranted(pkg, true);
703     }
704 
revokeNotificationPolicyAccess(String pkg)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);
711     }
712 
grantNotificationListenerAccess(String pkg, int userId)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();
719 
720         ArraySet<String> current = getNotificationListeners(resolver, userId);
721 
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);
727             }
728         }
729 
730         if (current.size() > 0) {
731             String flatSettings = formatSettings(current);
732             Settings.Secure.putStringForUser(resolver,
733                     Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
734                     flatSettings, userId);
735         }
736     }
737 
revokeNotificationListenerAccess(String pkg, int userId)738     private void revokeNotificationListenerAccess(String pkg, int userId) {
739         ContentResolver resolver = mContext.getContentResolver();
740 
741         ArraySet<String> current = getNotificationListeners(resolver, userId);
742 
743         ArrayList<String> toRemove = new ArrayList<>();
744 
745         for (String c : current) {
746             ComponentName component = ComponentName.unflattenFromString(c);
747             if (component.getPackageName().equals(pkg)) {
748                 toRemove.add(c);
749             }
750         }
751 
752         current.removeAll(toRemove);
753 
754         String flatSettings = formatSettings(current);
755         Settings.Secure.putStringForUser(resolver,
756                 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
757                 flatSettings, userId);
758     }
759 
isPermissionUserUpdated(String permission, String pkg, int 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;
765     }
766 
getNotificationListeners(ContentResolver resolver, int userId)767     private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
768         String flat = Settings.Secure.getStringForUser(resolver,
769                 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
770 
771         ArraySet<String> current = new ArraySet<>();
772         if (flat != null) {
773             String[] allowed = flat.split(":");
774             for (String s : allowed) {
775                 current.add(s);
776             }
777         }
778         return current;
779     }
780 
formatSettings(Collection<String> c)781     private static String formatSettings(Collection<String> c) {
782         if (c == null || c.isEmpty()) {
783             return "";
784         }
785 
786         StringBuilder b = new StringBuilder();
787         boolean start = true;
788         for (String s : c) {
789             if ("".equals(s)) {
790                 continue;
791             }
792             if (!start) {
793                 b.append(':');
794             }
795             b.append(s);
796             start = false;
797         }
798         return b.toString();
799     }
800 
801 
802 
createAndConnectService(@onNull ComponentName component, int userId)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);
807     }
808 
809     /**
810      * Send VR mode change callbacks to HAL and system services if mode has actually changed.
811      * <p/>
812      * Note: Must be called while holding {@code mLock}.
813      *
814      * @param enabled new state of the VR mode.
815      */
changeVrModeLocked(boolean enabled)816     private void changeVrModeLocked(boolean enabled) {
817         if (mVrModeEnabled != enabled) {
818             mVrModeEnabled = enabled;
819 
820             // Log mode change event.
821             Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
822             setVrModeNative(mVrModeEnabled);
823 
824             onVrModeChangedLocked();
825         }
826     }
827 
828     /**
829      * Notify system services of VR mode change.
830      * <p/>
831      * Note: Must be called while holding {@code mLock}.
832      */
onVrModeChangedLocked()833     private void onVrModeChangedLocked() {
834         mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
835                 (mVrModeEnabled) ? 1 : 0, 0));
836     }
837 
838     /**
839      * Helper function for making ManagedApplicationService instances.
840      */
create(@onNull Context context, @NonNull ComponentName component, int userId)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,
845                 sBinderChecker);
846     }
847 
consumeAndApplyPendingStateLocked()848     private void consumeAndApplyPendingStateLocked() {
849         if (mPendingState != null) {
850             updateCurrentVrServiceLocked(mPendingState.enabled,
851                     mPendingState.targetPackageName, mPendingState.userId,
852                     mPendingState.callingPackage);
853             mPendingState = null;
854         }
855     }
856 
logStateLocked()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();
864         }
865         mLoggingDeque.add(current);
866     }
867 
dumpStateTransitions(PrintWriter pw)868     private void dumpStateTransitions(PrintWriter pw) {
869         SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
870         String tab = "  ";
871         if (mLoggingDeque.size() == 0) {
872             pw.print(tab);
873             pw.println("None");
874         }
875         for (VrState state : mLoggingDeque) {
876             pw.print(d.format(new Date(state.timestamp)));
877             pw.print(tab);
878             pw.print("State changed to:");
879             pw.print(tab);
880             pw.println((state.enabled) ? "ENABLED" : "DISABLED");
881             if (state.enabled) {
882                 pw.print(tab);
883                 pw.print("User=");
884                 pw.println(state.userId);
885                 pw.print(tab);
886                 pw.print("Current VR Activity=");
887                 pw.println((state.callingPackage == null) ?
888                     "None" : state.callingPackage.flattenToString());
889                 pw.print(tab);
890                 pw.print("Bound VrListenerService=");
891                 pw.println((state.targetPackageName == null) ?
892                     "None" : state.targetPackageName.flattenToString());
893                 if (state.defaultPermissionsGranted) {
894                     pw.print(tab);
895                     pw.println("Default permissions granted to the bound VrListenerService.");
896                 }
897             }
898         }
899     }
900 
901     /*
902      * Implementation of VrManagerInternal calls.  These are callable from system services.
903      */
904 
setVrMode(boolean enabled, @NonNull ComponentName targetPackageName, int userId, @NonNull ComponentName callingPackage, boolean immediate)905     private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
906             int userId, @NonNull ComponentName callingPackage, boolean immediate) {
907 
908         synchronized (mLock) {
909 
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);
916                 }
917 
918                 mPendingState = new VrState(enabled, targetPackageName, userId, callingPackage);
919                 return;
920             } else {
921                 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
922                 mPendingState = null;
923             }
924 
925             updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
926         }
927     }
928 
hasVrPackage(@onNull ComponentName targetPackageName, int userId)929     private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
930         synchronized (mLock) {
931             return mComponentObserver.isValid(targetPackageName, userId);
932         }
933     }
934 
isCurrentVrListener(String packageName, int userId)935     private boolean isCurrentVrListener(String packageName, int userId) {
936         synchronized (mLock) {
937             if (mCurrentVrService == null) {
938                 return false;
939             }
940             return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
941                     userId == mCurrentVrService.getUserId();
942         }
943     }
944 
945     /*
946      * Implementation of IVrManager calls.
947      */
948 
addStateCallback(IVrStateCallbacks cb)949     private void addStateCallback(IVrStateCallbacks cb) {
950         mRemoteCallbacks.register(cb);
951     }
952 
removeStateCallback(IVrStateCallbacks cb)953     private void removeStateCallback(IVrStateCallbacks cb) {
954         mRemoteCallbacks.unregister(cb);
955     }
956 
getVrMode()957     private boolean getVrMode() {
958         synchronized (mLock) {
959             return mVrModeEnabled;
960         }
961     }
962 }
963