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