VrManagerService.java revision cdf9ce7229e791fe345b0860fe32433f15c95db8
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 static android.view.Display.INVALID_DISPLAY;
19
20import android.Manifest;
21import android.app.ActivityManagerInternal;
22import android.app.ActivityManager;
23import android.app.AppOpsManager;
24import android.app.CompatibilityDisplayProperties;
25import android.app.NotificationManager;
26import android.annotation.NonNull;
27import android.content.ComponentName;
28import android.content.ContentResolver;
29import android.content.Context;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
33import android.hardware.display.DisplayManager;
34import android.os.Binder;
35import android.os.Handler;
36import android.os.IBinder;
37import android.os.IInterface;
38import android.os.Looper;
39import android.os.Message;
40import android.os.RemoteCallbackList;
41import android.os.RemoteException;
42import android.os.ServiceManager;
43import android.os.UserHandle;
44import android.provider.Settings;
45import android.service.notification.NotificationListenerService;
46import android.service.vr.IPersistentVrStateCallbacks;
47import android.service.vr.IVrListener;
48import android.service.vr.IVrManager;
49import android.service.vr.IVrStateCallbacks;
50import android.service.vr.IVrWindowManager;
51import android.service.vr.VrListenerService;
52import android.text.TextUtils;
53import android.util.ArrayMap;
54import android.util.ArraySet;
55import android.util.Slog;
56import android.util.SparseArray;
57
58import com.android.internal.R;
59import com.android.internal.util.DumpUtils;
60import com.android.server.LocalServices;
61import com.android.server.SystemConfig;
62import com.android.server.SystemService;
63import com.android.server.utils.ManagedApplicationService.PendingEvent;
64import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
65import com.android.server.utils.ManagedApplicationService;
66import com.android.server.utils.ManagedApplicationService.BinderChecker;
67
68import java.io.FileDescriptor;
69import java.io.PrintWriter;
70import java.lang.StringBuilder;
71import java.text.SimpleDateFormat;
72import java.util.ArrayDeque;
73import java.util.ArrayList;
74import java.util.Collection;
75import java.util.Date;
76import java.util.Objects;
77
78/**
79 * Service tracking whether VR mode is active, and notifying listening services of state changes.
80 * <p/>
81 * Services running in system server may modify the state of VrManagerService via the interface in
82 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
83 * interface given in VrStateListener.
84 * <p/>
85 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
86 *  hardware/libhardware/modules/vr
87 * <p/>
88 * In general applications may enable or disable VR mode by calling
89 * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
90 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
91 *
92 * @see android.service.vr.VrListenerService
93 * @see com.android.server.vr.VrManagerInternal
94 * @see com.android.server.vr.VrStateListener
95 *
96 * @hide
97 */
98public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
99
100    public static final String TAG = "VrManagerService";
101
102    private static final int PENDING_STATE_DELAY_MS = 300;
103    private static final int EVENT_LOG_SIZE = 32;
104    private static final int INVALID_APPOPS_MODE = -1;
105    /** Null set of sleep sleep flags. */
106    private static final int FLAG_NONE = 0;
107    /** Flag set when the device is not sleeping. */
108    private static final int FLAG_AWAKE = 1;
109    /** Flag set when the screen has been turned on. */
110    private static final int FLAG_SCREEN_ON = 2;
111    /** Flag indicating that all system sleep flags have been set.*/
112    private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON;
113
114    private static native void initializeNative();
115    private static native void setVrModeNative(boolean enabled);
116
117    private final Object mLock = new Object();
118
119    private final IBinder mOverlayToken = new Binder();
120
121    // State protected by mLock
122    private boolean mVrModeAllowed;
123    private boolean mVrModeEnabled;
124    private boolean mPersistentVrModeEnabled;
125    private EnabledComponentsObserver mComponentObserver;
126    private ManagedApplicationService mCurrentVrService;
127    private ComponentName mDefaultVrService;
128    private Context mContext;
129    private ComponentName mCurrentVrModeComponent;
130    private int mCurrentVrModeUser;
131    private boolean mWasDefaultGranted;
132    private boolean mGuard;
133    private final RemoteCallbackList<IVrStateCallbacks> mVrStateRemoteCallbacks =
134            new RemoteCallbackList<>();
135    private final RemoteCallbackList<IPersistentVrStateCallbacks>
136            mPersistentVrStateRemoteCallbacks = new RemoteCallbackList<>();
137    private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
138    private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
139    private VrState mPendingState;
140    private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
141    private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
142    /** Tracks the state of the screen and keyguard UI.*/
143    private int mSystemSleepFlags = FLAG_AWAKE;
144    private CompatibilityDisplay mCompatibilityDisplay;
145
146    private static final int MSG_VR_STATE_CHANGE = 0;
147    private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
148    private static final int MSG_PERSISTENT_VR_MODE_STATE_CHANGE = 2;
149
150    /**
151     * Set whether VR mode may be enabled.
152     * <p/>
153     * If VR mode is not allowed to be enabled, calls to set VR mode will be cached.  When VR mode
154     * is again allowed to be enabled, the most recent cached state will be applied.
155     *
156     * @param allowed {@code true} if calling any of the setVrMode methods may cause the device to
157     *   enter VR mode.
158     */
159    private void setVrModeAllowedLocked(boolean allowed) {
160        if (mVrModeAllowed != allowed) {
161            mVrModeAllowed = allowed;
162            Slog.i(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
163            if (mVrModeAllowed) {
164                consumeAndApplyPendingStateLocked();
165            } else {
166                // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
167                // exit persistent VR mode when screen is turned off.
168                setPersistentModeAndNotifyListenersLocked(false);
169
170                // Set pending state to current state.
171                mPendingState = (mVrModeEnabled && mCurrentVrService != null)
172                    ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
173                        mCurrentVrService.getUserId(), mCurrentVrModeComponent)
174                    : null;
175
176                // Unbind current VR service and do necessary callbacks.
177                updateCurrentVrServiceLocked(false, null, 0, null);
178            }
179        }
180    }
181
182    private void setSleepState(boolean isAsleep) {
183        synchronized(mLock) {
184
185            if (!isAsleep) {
186                mSystemSleepFlags |= FLAG_AWAKE;
187            } else {
188                mSystemSleepFlags &= ~FLAG_AWAKE;
189            }
190
191            setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
192        }
193    }
194
195    private void setScreenOn(boolean isScreenOn) {
196        synchronized(mLock) {
197            if (isScreenOn) {
198                mSystemSleepFlags |= FLAG_SCREEN_ON;
199            } else {
200                mSystemSleepFlags &= ~FLAG_SCREEN_ON;
201            }
202            setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
203        }
204    }
205
206    private final Handler mHandler = new Handler() {
207        @Override
208        public void handleMessage(Message msg) {
209            switch(msg.what) {
210                case MSG_VR_STATE_CHANGE : {
211                    boolean state = (msg.arg1 == 1);
212                    int i = mVrStateRemoteCallbacks.beginBroadcast();
213                    while (i > 0) {
214                        i--;
215                        try {
216                            mVrStateRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
217                        } catch (RemoteException e) {
218                            // Noop
219                        }
220                    }
221                    mVrStateRemoteCallbacks.finishBroadcast();
222                } break;
223                case MSG_PENDING_VR_STATE_CHANGE : {
224                    synchronized(mLock) {
225                        if (mVrModeAllowed) {
226                           VrManagerService.this.consumeAndApplyPendingStateLocked();
227                        }
228                    }
229                } break;
230                case MSG_PERSISTENT_VR_MODE_STATE_CHANGE : {
231                    boolean state = (msg.arg1 == 1);
232                    int i = mPersistentVrStateRemoteCallbacks.beginBroadcast();
233                    while (i > 0) {
234                        i--;
235                        try {
236                            mPersistentVrStateRemoteCallbacks.getBroadcastItem(i)
237                                    .onPersistentVrStateChanged(state);
238                        } catch (RemoteException e) {
239                            // Noop
240                        }
241                    }
242                    mPersistentVrStateRemoteCallbacks.finishBroadcast();
243                } break;
244                default :
245                    throw new IllegalStateException("Unknown message type: " + msg.what);
246            }
247        }
248    };
249
250    private static class VrState {
251        final boolean enabled;
252        final int userId;
253        final ComponentName targetPackageName;
254        final ComponentName callingPackage;
255        final long timestamp;
256        final boolean defaultPermissionsGranted;
257
258        VrState(boolean enabled, ComponentName targetPackageName, int userId,
259                ComponentName callingPackage) {
260            this.enabled = enabled;
261            this.userId = userId;
262            this.targetPackageName = targetPackageName;
263            this.callingPackage = callingPackage;
264            this.defaultPermissionsGranted = false;
265            this.timestamp = System.currentTimeMillis();
266        }
267
268        VrState(boolean enabled, ComponentName targetPackageName, int userId,
269            ComponentName callingPackage, boolean defaultPermissionsGranted) {
270            this.enabled = enabled;
271            this.userId = userId;
272            this.targetPackageName = targetPackageName;
273            this.callingPackage = callingPackage;
274            this.defaultPermissionsGranted = defaultPermissionsGranted;
275            this.timestamp = System.currentTimeMillis();
276        }
277    }
278
279    private static final BinderChecker sBinderChecker = new BinderChecker() {
280        @Override
281        public IInterface asInterface(IBinder binder) {
282            return IVrListener.Stub.asInterface(binder);
283        }
284
285        @Override
286        public boolean checkType(IInterface service) {
287            return service instanceof IVrListener;
288        }
289    };
290
291    private final class NotificationAccessManager {
292        private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
293        private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
294                new ArrayMap<>();
295
296        public void update(Collection<String> packageNames) {
297            int currentUserId = ActivityManager.getCurrentUser();
298
299            ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
300            if (allowed == null) {
301                allowed = new ArraySet<>();
302            }
303
304            // Make sure we revoke notification access for listeners in other users
305            final int listenerCount = mNotificationAccessPackageToUserId.size();
306            for (int i = listenerCount - 1; i >= 0; i--) {
307                final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
308                if (grantUserId != currentUserId) {
309                    String packageName = mNotificationAccessPackageToUserId.keyAt(i);
310                    revokeNotificationListenerAccess(packageName, grantUserId);
311                    revokeNotificationPolicyAccess(packageName);
312                    revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
313                    mNotificationAccessPackageToUserId.removeAt(i);
314                }
315            }
316
317            for (String pkg : allowed) {
318                if (!packageNames.contains(pkg)) {
319                    revokeNotificationListenerAccess(pkg, currentUserId);
320                    revokeNotificationPolicyAccess(pkg);
321                    revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
322                    mNotificationAccessPackageToUserId.remove(pkg);
323                }
324            }
325            for (String pkg : packageNames) {
326                if (!allowed.contains(pkg)) {
327                    grantNotificationPolicyAccess(pkg);
328                    grantNotificationListenerAccess(pkg, currentUserId);
329                    grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
330                    mNotificationAccessPackageToUserId.put(pkg, currentUserId);
331                }
332            }
333
334            allowed.clear();
335            allowed.addAll(packageNames);
336            mAllowedPackages.put(currentUserId, allowed);
337        }
338    }
339
340    /**
341     * Called when a user, package, or setting changes that could affect whether or not the
342     * currently bound VrListenerService is changed.
343     */
344    @Override
345    public void onEnabledComponentChanged() {
346        synchronized (mLock) {
347            int currentUser = ActivityManager.getCurrentUser();
348            // Update listeners
349            ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
350
351            ArraySet<String> enabledPackages = new ArraySet<>();
352            for (ComponentName n : enabledListeners) {
353                String pkg = n.getPackageName();
354                if (isDefaultAllowed(pkg)) {
355                    enabledPackages.add(n.getPackageName());
356                }
357            }
358            mNotifAccessManager.update(enabledPackages);
359
360            if (!mVrModeAllowed) {
361                return; // Don't do anything, we shouldn't be in VR mode.
362            }
363
364            // If there is a pending state change, we'd better deal with that first
365            consumeAndApplyPendingStateLocked(false);
366
367            if (mCurrentVrService == null) {
368                return; // No active services
369            }
370
371            // There is an active service, update it if needed
372            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
373                    mCurrentVrService.getUserId(), null);
374        }
375    }
376
377    private final IVrManager mVrManager = new IVrManager.Stub() {
378
379        @Override
380        public void registerListener(IVrStateCallbacks cb) {
381            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
382            if (cb == null) {
383                throw new IllegalArgumentException("Callback binder object is null.");
384            }
385
386            VrManagerService.this.addStateCallback(cb);
387        }
388
389        @Override
390        public void unregisterListener(IVrStateCallbacks cb) {
391            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
392            if (cb == null) {
393                throw new IllegalArgumentException("Callback binder object is null.");
394            }
395
396            VrManagerService.this.removeStateCallback(cb);
397        }
398
399        @Override
400        public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
401            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
402            if (cb == null) {
403                throw new IllegalArgumentException("Callback binder object is null.");
404            }
405
406            VrManagerService.this.addPersistentStateCallback(cb);
407        }
408
409        @Override
410        public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
411            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
412            if (cb == null) {
413                throw new IllegalArgumentException("Callback binder object is null.");
414            }
415
416            VrManagerService.this.removePersistentStateCallback(cb);
417        }
418
419        @Override
420        public boolean getVrModeState() {
421            return VrManagerService.this.getVrMode();
422        }
423
424        @Override
425        public void setPersistentVrModeEnabled(boolean enabled) {
426            enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
427            VrManagerService.this.setPersistentVrModeEnabled(enabled);
428        }
429
430        @Override
431        public void setCompatibilityDisplayProperties(
432                CompatibilityDisplayProperties compatDisplayProp) {
433            enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
434            VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
435        }
436
437        @Override
438        public int getCompatibilityDisplayId() {
439            return VrManagerService.this.getCompatibilityDisplayId();
440        }
441
442        @Override
443        public void connectController(FileDescriptor fd) throws android.os.RemoteException {
444            enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
445            VrManagerService.this.connectController(fd);
446        }
447
448        @Override
449        public void disconnectController() throws android.os.RemoteException {
450            enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
451            VrManagerService.this.disconnectController();
452        }
453
454        @Override
455        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
456            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
457
458            pw.println("********* Dump of VrManagerService *********");
459            pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
460            pw.println("Persistent VR mode is currently: " +
461                    ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
462            pw.println("Previous state transitions:\n");
463            String tab = "  ";
464            dumpStateTransitions(pw);
465            pw.println("\n\nRemote Callbacks:");
466            int i=mVrStateRemoteCallbacks.beginBroadcast(); // create the broadcast item array
467            while(i-->0) {
468                pw.print(tab);
469                pw.print(mVrStateRemoteCallbacks.getBroadcastItem(i));
470                if (i>0) pw.println(",");
471            }
472            mVrStateRemoteCallbacks.finishBroadcast();
473            pw.println("\n\nPersistent Vr State Remote Callbacks:");
474            i=mPersistentVrStateRemoteCallbacks.beginBroadcast();
475            while(i-->0) {
476                pw.print(tab);
477                pw.print(mPersistentVrStateRemoteCallbacks.getBroadcastItem(i));
478                if (i>0) pw.println(",");
479            }
480            mPersistentVrStateRemoteCallbacks.finishBroadcast();
481            pw.println("\n");
482            pw.println("Installed VrListenerService components:");
483            int userId = mCurrentVrModeUser;
484            ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
485            if (installed == null || installed.size() == 0) {
486                pw.println("None");
487            } else {
488                for (ComponentName n : installed) {
489                    pw.print(tab);
490                    pw.println(n.flattenToString());
491                }
492            }
493            pw.println("Enabled VrListenerService components:");
494            ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
495            if (enabled == null || enabled.size() == 0) {
496                pw.println("None");
497            } else {
498                for (ComponentName n : enabled) {
499                    pw.print(tab);
500                    pw.println(n.flattenToString());
501                }
502            }
503            pw.println("\n");
504            pw.println("********* End of VrManagerService Dump *********");
505        }
506
507    };
508
509    private void enforceCallerPermission(String permission) {
510        if (mContext.checkCallingOrSelfPermission(permission)
511                != PackageManager.PERMISSION_GRANTED) {
512            throw new SecurityException("Caller does not hold the permission " + permission);
513        }
514    }
515
516    /**
517     * Implementation of VrManagerInternal.  Callable only from system services.
518     */
519    private final class LocalService extends VrManagerInternal {
520        @Override
521        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
522                ComponentName callingPackage) {
523            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
524        }
525
526        @Override
527        public void onSleepStateChanged(boolean isAsleep) {
528            VrManagerService.this.setSleepState(isAsleep);
529        }
530
531        @Override
532        public void onScreenStateChanged(boolean isScreenOn) {
533            VrManagerService.this.setScreenOn(isScreenOn);
534        }
535
536        @Override
537        public boolean isCurrentVrListener(String packageName, int userId) {
538            return VrManagerService.this.isCurrentVrListener(packageName, userId);
539        }
540
541        @Override
542        public int hasVrPackage(ComponentName packageName, int userId) {
543            return VrManagerService.this.hasVrPackage(packageName, userId);
544        }
545
546        @Override
547        public void setPersistentVrModeEnabled(boolean enabled) {
548            VrManagerService.this.setPersistentVrModeEnabled(enabled);
549        }
550
551        @Override
552        public void setCompatibilityDisplayProperties(
553            CompatibilityDisplayProperties compatDisplayProp) {
554            VrManagerService.this.setCompatibilityDisplayProperties(compatDisplayProp);
555        }
556
557        @Override
558        public int getCompatibilityDisplayId() {
559            return VrManagerService.this.getCompatibilityDisplayId();
560        }
561
562        @Override
563        public void addPersistentVrModeStateListener(IPersistentVrStateCallbacks listener) {
564            VrManagerService.this.addPersistentStateCallback(listener);
565        }
566    }
567
568    public VrManagerService(Context context) {
569        super(context);
570    }
571
572    @Override
573    public void onStart() {
574        synchronized(mLock) {
575            initializeNative();
576            mContext = getContext();
577        }
578
579        publishLocalService(VrManagerInternal.class, new LocalService());
580        publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
581    }
582
583    @Override
584    public void onBootPhase(int phase) {
585        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
586            synchronized (mLock) {
587                Looper looper = Looper.getMainLooper();
588                Handler handler = new Handler(looper);
589                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
590                listeners.add(this);
591                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
592                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
593                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
594                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
595
596                mComponentObserver.rebuildAll();
597            }
598
599            //TODO: something more robust than picking the first one
600            ArraySet<ComponentName> defaultVrComponents =
601                    SystemConfig.getInstance().getDefaultVrComponents();
602            if (defaultVrComponents.size() > 0) {
603                mDefaultVrService = defaultVrComponents.valueAt(0);
604            } else {
605                Slog.i(TAG, "No default vr listener service found.");
606            }
607
608            DisplayManager dm =
609                    (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
610            ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
611            mCompatibilityDisplay = new CompatibilityDisplay(dm, ami, mVrManager);
612            mCompatibilityDisplay.init(getContext());
613        } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
614            synchronized (mLock) {
615                mVrModeAllowed = true;
616            }
617        }
618    }
619
620    @Override
621    public void onStartUser(int userHandle) {
622        synchronized (mLock) {
623            mComponentObserver.onUsersChanged();
624        }
625    }
626
627    @Override
628    public void onSwitchUser(int userHandle) {
629        synchronized (mLock) {
630            mComponentObserver.onUsersChanged();
631        }
632
633    }
634
635    @Override
636    public void onStopUser(int userHandle) {
637        synchronized (mLock) {
638            mComponentObserver.onUsersChanged();
639        }
640
641    }
642
643    @Override
644    public void onCleanupUser(int userHandle) {
645        synchronized (mLock) {
646            mComponentObserver.onUsersChanged();
647        }
648    }
649
650    private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
651        AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
652
653        // If user changed drop restrictions for the old user.
654        if (oldUserId != newUserId) {
655            appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
656                    false, mOverlayToken, null, oldUserId);
657        }
658
659        if (!mVrModeEnabled) {
660            return;
661        }
662
663        // Apply the restrictions for the current user based on vr state
664        String[] exemptions = (exemptedPackage == null) ? new String[0] :
665                new String[] { exemptedPackage };
666
667        appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
668                true, mOverlayToken, exemptions, newUserId);
669    }
670
671    private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
672            String oldVrServicePackage, int oldUserId) {
673        // If VR state changed and we also have a VR service change.
674        if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
675            return;
676        }
677        final long identity = Binder.clearCallingIdentity();
678        try {
679            // Set overlay exception state based on VR enabled and current service
680            updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
681        } finally {
682            Binder.restoreCallingIdentity(identity);
683        }
684    }
685
686    /**
687     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
688     * the currently selected VR listener service.  If the component selected for the VR listener
689     * service has changed, unbind the previous listener and bind the new listener (if enabled).
690     * <p/>
691     * Note: Must be called while holding {@code mLock}.
692     *
693     * @param enabled new state for VR mode.
694     * @param component new component to be bound as a VR listener.
695     * @param userId user owning the component to be bound.
696     * @param calling the component currently using VR mode, or null to leave unchanged.
697     *
698     * @return {@code true} if the component/user combination specified is valid.
699     */
700    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
701            int userId, ComponentName calling) {
702
703        boolean sendUpdatedCaller = false;
704        final long identity = Binder.clearCallingIdentity();
705        try {
706
707            boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
708                    EnabledComponentsObserver.NO_ERROR);
709            boolean goingIntoVrMode = validUserComponent && enabled;
710            if (!mVrModeEnabled && !goingIntoVrMode) {
711                return validUserComponent; // Disabled -> Disabled transition does nothing.
712            }
713
714            String oldVrServicePackage = mCurrentVrService != null
715                    ? mCurrentVrService.getComponent().getPackageName() : null;
716            final int oldUserId = mCurrentVrModeUser;
717
718            // Notify system services and VR HAL of mode change.
719            changeVrModeLocked(goingIntoVrMode);
720
721            boolean nothingChanged = false;
722            if (!goingIntoVrMode) {
723                // Not going into VR mode, unbind whatever is running
724                if (mCurrentVrService != null) {
725                    Slog.i(TAG, "Leaving VR mode, disconnecting "
726                        + mCurrentVrService.getComponent() + " for user "
727                        + mCurrentVrService.getUserId());
728                    mCurrentVrService.disconnect();
729                    mCurrentVrService = null;
730                } else {
731                    nothingChanged = true;
732                }
733            } else {
734                // Going into VR mode
735                if (mCurrentVrService != null) {
736                    // Unbind any running service that doesn't match the latest component/user
737                    // selection.
738                    if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
739                        Slog.i(TAG, "VR mode component changed to " + component
740                            + ", disconnecting " + mCurrentVrService.getComponent()
741                            + " for user " + mCurrentVrService.getUserId());
742                        createAndConnectService(component, userId);
743                        sendUpdatedCaller = true;
744                    } else {
745                        nothingChanged = true;
746                    }
747                    // The service with the correct component/user is already bound, do nothing.
748                } else {
749                    // Nothing was previously running, bind a new service for the latest
750                    // component/user selection.
751                    createAndConnectService(component, userId);
752                    sendUpdatedCaller = true;
753                }
754            }
755
756            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
757                sendUpdatedCaller = true;
758            }
759            mCurrentVrModeComponent = calling;
760
761            if (mCurrentVrModeUser != userId) {
762                mCurrentVrModeUser = userId;
763                sendUpdatedCaller = true;
764            }
765
766            String newVrServicePackage = mCurrentVrService != null
767                    ? mCurrentVrService.getComponent().getPackageName() : null;
768            final int newUserId = mCurrentVrModeUser;
769
770            // Update AppOps settings that change state when entering/exiting VR mode, or changing
771            // the current VrListenerService.
772            updateDependentAppOpsLocked(newVrServicePackage, newUserId,
773                    oldVrServicePackage, oldUserId);
774
775            if (mCurrentVrService != null && sendUpdatedCaller) {
776                final ComponentName c = mCurrentVrModeComponent;
777                mCurrentVrService.sendEvent(new PendingEvent() {
778                    @Override
779                    public void runEvent(IInterface service) throws RemoteException {
780                        IVrListener l = (IVrListener) service;
781                        l.focusedActivityChanged(c);
782                    }
783                });
784            }
785
786            if (!nothingChanged) {
787                logStateLocked();
788            }
789
790            return validUserComponent;
791        } finally {
792            Binder.restoreCallingIdentity(identity);
793        }
794    }
795
796    private boolean isDefaultAllowed(String packageName) {
797        PackageManager pm = mContext.getPackageManager();
798
799        ApplicationInfo info = null;
800        try {
801            info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
802        } catch (NameNotFoundException e) {
803        }
804
805        if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
806            return false;
807        }
808        return true;
809    }
810
811    private void grantNotificationPolicyAccess(String pkg) {
812        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
813        nm.setNotificationPolicyAccessGranted(pkg, true);
814    }
815
816    private void revokeNotificationPolicyAccess(String pkg) {
817        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
818        // Remove any DND zen rules possibly created by the package.
819        nm.removeAutomaticZenRules(pkg);
820        // Remove Notification Policy Access.
821        nm.setNotificationPolicyAccessGranted(pkg, false);
822    }
823
824    private void grantNotificationListenerAccess(String pkg, int userId) {
825        PackageManager pm = mContext.getPackageManager();
826        ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
827                userId, NotificationListenerService.SERVICE_INTERFACE,
828                android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
829        ContentResolver resolver = mContext.getContentResolver();
830
831        ArraySet<String> current = getNotificationListeners(resolver, userId);
832
833        for (ComponentName c : possibleServices) {
834            String flatName = c.flattenToString();
835            if (Objects.equals(c.getPackageName(), pkg)
836                    && !current.contains(flatName)) {
837                current.add(flatName);
838            }
839        }
840
841        if (current.size() > 0) {
842            String flatSettings = formatSettings(current);
843            Settings.Secure.putStringForUser(resolver,
844                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
845                    flatSettings, userId);
846        }
847    }
848
849    private void revokeNotificationListenerAccess(String pkg, int userId) {
850        ContentResolver resolver = mContext.getContentResolver();
851
852        ArraySet<String> current = getNotificationListeners(resolver, userId);
853
854        ArrayList<String> toRemove = new ArrayList<>();
855
856        for (String c : current) {
857            ComponentName component = ComponentName.unflattenFromString(c);
858            if (component != null && component.getPackageName().equals(pkg)) {
859                toRemove.add(c);
860            }
861        }
862
863        current.removeAll(toRemove);
864
865        String flatSettings = formatSettings(current);
866        Settings.Secure.putStringForUser(resolver,
867                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
868                flatSettings, userId);
869    }
870
871    private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
872        // Don't clobber the user if permission set in current state explicitly
873        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
874            try {
875                mContext.getPackageManager().grantRuntimePermission(pkg,
876                        Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
877            } catch (IllegalArgumentException e) {
878                // Package was removed during update.
879                Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
880                    + " was removed.");
881            }
882        }
883    }
884
885    private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
886        // Don't clobber the user if permission set in current state explicitly
887        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
888            try {
889                mContext.getPackageManager().revokeRuntimePermission(pkg,
890                        Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
891            } catch (IllegalArgumentException e) {
892                // Package was removed during update.
893                Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
894                    + " was removed.");
895            }
896        }
897    }
898
899    private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
900        final int flags = mContext.getPackageManager().getPermissionFlags(
901                permission, pkg, new UserHandle(userId));
902        return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
903                | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
904    }
905
906    private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
907        String flat = Settings.Secure.getStringForUser(resolver,
908                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
909
910        ArraySet<String> current = new ArraySet<>();
911        if (flat != null) {
912            String[] allowed = flat.split(":");
913            for (String s : allowed) {
914                if (!TextUtils.isEmpty(s)) {
915                    current.add(s);
916                }
917            }
918        }
919        return current;
920    }
921
922    private static String formatSettings(Collection<String> c) {
923        if (c == null || c.isEmpty()) {
924            return "";
925        }
926
927        StringBuilder b = new StringBuilder();
928        boolean start = true;
929        for (String s : c) {
930            if ("".equals(s)) {
931                continue;
932            }
933            if (!start) {
934                b.append(':');
935            }
936            b.append(s);
937            start = false;
938        }
939        return b.toString();
940    }
941
942
943
944    private void createAndConnectService(@NonNull ComponentName component, int userId) {
945        mCurrentVrService = VrManagerService.create(mContext, component, userId);
946        mCurrentVrService.connect();
947        Slog.i(TAG, "Connecting " + component + " for user " + userId);
948    }
949
950    /**
951     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
952     * <p/>
953     * Note: Must be called while holding {@code mLock}.
954     *
955     * @param enabled new state of the VR mode.
956     */
957    private void changeVrModeLocked(boolean enabled) {
958        if (mVrModeEnabled != enabled) {
959            mVrModeEnabled = enabled;
960
961            // Log mode change event.
962            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
963            setVrModeNative(mVrModeEnabled);
964
965            onVrModeChangedLocked();
966        }
967    }
968
969    /**
970     * Notify system services of VR mode change.
971     * <p/>
972     * Note: Must be called while holding {@code mLock}.
973     */
974    private void onVrModeChangedLocked() {
975        mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
976                (mVrModeEnabled) ? 1 : 0, 0));
977    }
978
979    /**
980     * Helper function for making ManagedApplicationService instances.
981     */
982    private static ManagedApplicationService create(@NonNull Context context,
983            @NonNull ComponentName component, int userId) {
984        return ManagedApplicationService.build(context, component, userId,
985                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
986                sBinderChecker);
987    }
988
989    /**
990     * Apply the pending VR state. If no state is pending, disconnect any currently bound
991     * VR listener service.
992     */
993    private void consumeAndApplyPendingStateLocked() {
994        consumeAndApplyPendingStateLocked(true);
995    }
996
997    /**
998     * Apply the pending VR state.
999     *
1000     * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
1001     *     service will be disconnected if no state is pending. If this is {@code false} then the
1002     *     nothing will be changed when there is no pending state.
1003     */
1004    private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
1005        if (mPendingState != null) {
1006            updateCurrentVrServiceLocked(mPendingState.enabled,
1007                    mPendingState.targetPackageName, mPendingState.userId,
1008                    mPendingState.callingPackage);
1009            mPendingState = null;
1010        } else if (disconnectIfNoPendingState) {
1011            updateCurrentVrServiceLocked(false, null, 0, null);
1012        }
1013    }
1014
1015    private void logStateLocked() {
1016        ComponentName currentBoundService = (mCurrentVrService == null) ? null :
1017            mCurrentVrService.getComponent();
1018        VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
1019            mCurrentVrModeComponent, mWasDefaultGranted);
1020        if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
1021            mLoggingDeque.removeFirst();
1022        }
1023        mLoggingDeque.add(current);
1024    }
1025
1026    private void dumpStateTransitions(PrintWriter pw) {
1027        SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
1028        String tab = "  ";
1029        if (mLoggingDeque.size() == 0) {
1030            pw.print(tab);
1031            pw.println("None");
1032        }
1033        for (VrState state : mLoggingDeque) {
1034            pw.print(d.format(new Date(state.timestamp)));
1035            pw.print(tab);
1036            pw.print("State changed to:");
1037            pw.print(tab);
1038            pw.println((state.enabled) ? "ENABLED" : "DISABLED");
1039            if (state.enabled) {
1040                pw.print(tab);
1041                pw.print("User=");
1042                pw.println(state.userId);
1043                pw.print(tab);
1044                pw.print("Current VR Activity=");
1045                pw.println((state.callingPackage == null) ?
1046                    "None" : state.callingPackage.flattenToString());
1047                pw.print(tab);
1048                pw.print("Bound VrListenerService=");
1049                pw.println((state.targetPackageName == null) ?
1050                    "None" : state.targetPackageName.flattenToString());
1051                if (state.defaultPermissionsGranted) {
1052                    pw.print(tab);
1053                    pw.println("Default permissions granted to the bound VrListenerService.");
1054                }
1055            }
1056        }
1057    }
1058
1059    /*
1060     * Implementation of VrManagerInternal calls.  These are callable from system services.
1061     */
1062    private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
1063            int userId, @NonNull ComponentName callingPackage) {
1064
1065        synchronized (mLock) {
1066            VrState pending;
1067            ComponentName targetListener;
1068            ComponentName foregroundVrComponent;
1069
1070            // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
1071            // and the system default VR listener is used.
1072            boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
1073            if (!enabled && mPersistentVrModeEnabled) {
1074                targetListener = mDefaultVrService;
1075
1076                // Current foreground component isn't a VR one (in 2D app case)
1077                foregroundVrComponent = null;
1078            } else {
1079                targetListener = targetPackageName;
1080                foregroundVrComponent = callingPackage;
1081            }
1082            pending = new VrState(
1083                    targetEnabledState, targetListener, userId, foregroundVrComponent);
1084
1085            if (!mVrModeAllowed) {
1086                // We're not allowed to be in VR mode.  Make this state pending.  This will be
1087                // applied the next time we are allowed to enter VR mode unless it is superseded by
1088                // another call.
1089                mPendingState = pending;
1090                return;
1091            }
1092
1093            if (!targetEnabledState && mCurrentVrService != null) {
1094                // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
1095                // and service bind/unbind in case we are immediately switching to another VR app.
1096                if (mPendingState == null) {
1097                    mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
1098                            PENDING_STATE_DELAY_MS);
1099                }
1100
1101                mPendingState = pending;
1102                return;
1103            } else {
1104                mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
1105                mPendingState = null;
1106            }
1107
1108            updateCurrentVrServiceLocked(
1109                    targetEnabledState, targetListener, userId, foregroundVrComponent);
1110        }
1111    }
1112
1113    private void setPersistentVrModeEnabled(boolean enabled) {
1114        synchronized(mLock) {
1115            setPersistentModeAndNotifyListenersLocked(enabled);
1116            // Disabling persistent mode when not showing a VR should disable the overall vr mode.
1117            if (!enabled && mCurrentVrModeComponent == null) {
1118                setVrMode(false, null, 0, null);
1119            }
1120        }
1121    }
1122
1123    public void setCompatibilityDisplayProperties(
1124        CompatibilityDisplayProperties compatDisplayProp) {
1125        if (mCompatibilityDisplay != null) {
1126            mCompatibilityDisplay.setVirtualDisplayProperties(compatDisplayProp);
1127            return;
1128        }
1129        Slog.w(TAG, "CompatibilityDisplay is null!");
1130    }
1131
1132    private int getCompatibilityDisplayId() {
1133        if (mCompatibilityDisplay != null) {
1134            return mCompatibilityDisplay.getVirtualDisplayId();
1135        }
1136        Slog.w(TAG, "CompatibilityDisplay is null!");
1137        return INVALID_DISPLAY;
1138    }
1139
1140    private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
1141        if (mPersistentVrModeEnabled == enabled) {
1142            return;
1143        }
1144        mPersistentVrModeEnabled = enabled;
1145
1146        mHandler.sendMessage(mHandler.obtainMessage(MSG_PERSISTENT_VR_MODE_STATE_CHANGE,
1147                (mPersistentVrModeEnabled) ? 1 : 0, 0));
1148    }
1149
1150    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
1151        synchronized (mLock) {
1152            return mComponentObserver.isValid(targetPackageName, userId);
1153        }
1154    }
1155
1156    private boolean isCurrentVrListener(String packageName, int userId) {
1157        synchronized (mLock) {
1158            if (mCurrentVrService == null) {
1159                return false;
1160            }
1161            return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
1162                    userId == mCurrentVrService.getUserId();
1163        }
1164    }
1165
1166    /*
1167     * Implementation of IVrManager calls.
1168     */
1169
1170    private void addStateCallback(IVrStateCallbacks cb) {
1171        mVrStateRemoteCallbacks.register(cb);
1172    }
1173
1174    private void removeStateCallback(IVrStateCallbacks cb) {
1175        mVrStateRemoteCallbacks.unregister(cb);
1176    }
1177
1178    private void addPersistentStateCallback(IPersistentVrStateCallbacks cb) {
1179        mPersistentVrStateRemoteCallbacks.register(cb);
1180    }
1181
1182    private void removePersistentStateCallback(IPersistentVrStateCallbacks cb) {
1183        mPersistentVrStateRemoteCallbacks.unregister(cb);
1184    }
1185
1186    private boolean getVrMode() {
1187        synchronized (mLock) {
1188            return mVrModeEnabled;
1189        }
1190    }
1191
1192    private void connectController(FileDescriptor fd) throws android.os.RemoteException {
1193        // TODO(b/36506799): move vr_wm code to VrCore and remove this.
1194        IVrWindowManager remote =
1195                IVrWindowManager.Stub.asInterface(
1196                        ServiceManager.getService(IVrWindowManager.SERVICE_NAME));
1197        remote.connectController(fd);
1198    }
1199
1200    private void disconnectController() throws android.os.RemoteException {
1201        // TODO(b/36506799): move vr_wm code to VrCore and remove this.
1202        IVrWindowManager remote =
1203                IVrWindowManager.Stub.asInterface(
1204                        ServiceManager.getService(IVrWindowManager.SERVICE_NAME));
1205        remote.disconnectController();
1206    }
1207}
1208