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