VrManagerService.java revision 98576cf949a1ffbece3722451713aac01ed27968
1e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk/**
2dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Copyright (C) 2015 The Android Open Source Project
3dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *
4dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * you may not use this file except in compliance with the License.
6dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * You may obtain a copy of the License at
7dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *
8dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *
10dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * See the License for the specific language governing permissions and
14dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * limitations under the License.
15dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */
16dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkpackage com.android.server.vr;
17dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
1847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.app.AppOpsManager;
1998576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.app.NotificationManager;
20e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull;
21e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ComponentName;
2298576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.ContentResolver;
2398576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.Context;
2498576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.ApplicationInfo;
2598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager;
2698576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager.NameNotFoundException;
2747d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.Binder;
28e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler;
2947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.IBinder;
30e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface;
31e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Looper;
32c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport android.os.RemoteException;
3398576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.os.UserHandle;
34e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings;
3598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.service.notification.NotificationListenerService;
36e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.IVrListener;
37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.VrListenerService;
38dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.ArraySet;
39dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.Slog;
40dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
41e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.internal.R;
42dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport com.android.server.SystemService;
43c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport com.android.server.utils.ManagedApplicationService.PendingEvent;
44e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
45e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService;
46e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService.BinderChecker;
47dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
4898576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.lang.StringBuilder;
49dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport java.util.ArrayList;
5098576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.util.Collection;
51c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport java.util.Objects;
52e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport java.util.Set;
53dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
54dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk/**
55e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Service tracking whether VR mode is active, and notifying listening services of state changes.
56e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
57e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Services running in system server may modify the state of VrManagerService via the interface in
58e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
59e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * interface given in VrStateListener.
60e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
61e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
62e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk *  hardware/libhardware/modules/vr
63e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
64e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * In general applications may enable or disable VR mode by calling
6598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
6698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
67e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk *
68e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link android.service.vr.VrListenerService}
69e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrManagerInternal}
70e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrStateListener}
71dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *
72e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide
73dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */
74e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class VrManagerService extends SystemService implements EnabledComponentChangeListener{
75dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
76dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public static final String TAG = "VrManagerService";
77dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
78baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk    private static native void initializeNative();
79baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk    private static native void setVrModeNative(boolean enabled);
80baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
81dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private final Object mLock = new Object();
8247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
8347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    private final IBinder mOverlayToken = new Binder();
8447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
85e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    // State protected by mLock
8698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean mVrModeEnabled;
87e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private final Set<VrStateListener> mListeners = new ArraySet<>();
88e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private EnabledComponentsObserver mComponentObserver;
89e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private ManagedApplicationService mCurrentVrService;
90e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private Context mContext;
91c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private ComponentName mCurrentVrModeComponent;
92c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private int mCurrentVrModeUser;
9398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean mWasDefaultGranted;
9498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean mGuard;
9598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
9698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private String mPreviousNotificationPolicyAccessPackage;
9798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private String mPreviousManageOverlayPackage;
98e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
99e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static final BinderChecker sBinderChecker = new BinderChecker() {
100e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
101e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public IInterface asInterface(IBinder binder) {
102e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return IVrListener.Stub.asInterface(binder);
103e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
104e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
105e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
106e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public boolean checkType(IInterface service) {
107e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return service instanceof IVrListener;
108e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    };
110e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
111e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
112e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Called when a user, package, or setting changes that could affect whether or not the
113e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * currently bound VrListenerService is changed.
114e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
115e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
116e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onEnabledComponentChanged() {
117e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
118e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService == null) {
119e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                return; // No active services
120e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
121e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
122e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // There is an active service, update it if needed
123e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
124c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    mCurrentVrService.getUserId(), null);
125e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
126e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
127dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
128e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
129e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal.  Callable only from system services.
130e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
131dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private final class LocalService extends VrManagerInternal {
132dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
133dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public boolean isInVrMode() {
134dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            return VrManagerService.this.getVrMode();
135dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
136dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
137dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
138c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
139c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                ComponentName callingPackage) {
140c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
141dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
142dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
143dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
144dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public void registerListener(VrStateListener listener) {
145dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            VrManagerService.this.addListener(listener);
146dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
147dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
148dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
149dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public void unregisterListener(VrStateListener listener) {
150dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            VrManagerService.this.removeListener(listener);
151dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
152e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
153e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
154e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public int hasVrPackage(ComponentName packageName, int userId) {
155e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return VrManagerService.this.hasVrPackage(packageName, userId);
156e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
157dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
158dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
159dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public VrManagerService(Context context) {
160dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        super(context);
161dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
162dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
163dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    @Override
164dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public void onStart() {
165baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        synchronized(mLock) {
166baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk            initializeNative();
167e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mContext = getContext();
168baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        }
169baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
170dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        publishLocalService(VrManagerInternal.class, new LocalService());
171dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
172dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
173e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
174e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onBootPhase(int phase) {
1758507004a35a94e9bb4653dc049505aa54d1e6175Ruben Brunk        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
176e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            synchronized (mLock) {
177e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Looper looper = Looper.getMainLooper();
178e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Handler handler = new Handler(looper);
179e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
180e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                listeners.add(this);
181e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
182e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
183e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
184e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
185e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
186e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver.rebuildAll();
187e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
188e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
189e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
190e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
191e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
192e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStartUser(int userHandle) {
193dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
194e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
195dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
196dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
197dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
198e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
199e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onSwitchUser(int userHandle) {
200dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
201e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
202e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
203e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
204e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
205e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
206e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
207e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStopUser(int userHandle) {
208e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
209e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
210dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
211e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
212dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
213dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
214e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
215e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onCleanupUser(int userHandle) {
216dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
217e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
218dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
219dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
220dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
22129931bc684bde6b430923122777684178ee2681cRuben Brunk    private void updateOverlayStateLocked(ComponentName exemptedComponent) {
22247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        final long identity = Binder.clearCallingIdentity();
22347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        try {
22447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
22547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            if (appOpsManager != null) {
22629931bc684bde6b430923122777684178ee2681cRuben Brunk                String[] exemptions = (exemptedComponent == null) ? new String[0] :
22729931bc684bde6b430923122777684178ee2681cRuben Brunk                        new String[] { exemptedComponent.getPackageName() };
22829931bc684bde6b430923122777684178ee2681cRuben Brunk
22947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov                appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
23029931bc684bde6b430923122777684178ee2681cRuben Brunk                        mVrModeEnabled, mOverlayToken, exemptions);
23147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            }
23247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        } finally {
23347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            Binder.restoreCallingIdentity(identity);
23447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        }
23547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    }
23647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
237e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
238e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
239e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * the currently selected VR listener service.  If the component selected for the VR listener
240e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * service has changed, unbind the previous listener and bind the new listener (if enabled).
241e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
242e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
243e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
244e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state for VR mode.
245e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param component new component to be bound as a VR listener.
246e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param userId user owning the component to be bound.
247c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk     * @param calling the component currently using VR mode, or null to leave unchanged.
248e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
249e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @return {@code true} if the component/user combination specified is valid.
250e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
25198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
25298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            int userId, ComponentName calling) {
253c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
254c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        boolean sendUpdatedCaller = false;
25598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        final long identity = Binder.clearCallingIdentity();
25698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        try {
257e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
25898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
25998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    EnabledComponentsObserver.NO_ERROR);
260e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
26198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            // Always send mode change events.
26298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
26329931bc684bde6b430923122777684178ee2681cRuben Brunk
26498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (!enabled || !validUserComponent) {
26598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                // Unbind whatever is running
26698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                if (mCurrentVrService != null) {
267c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
26898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                            mCurrentVrService.getUserId());
26998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    mCurrentVrService.disconnect();
27098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    disableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
27198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                            new UserHandle(mCurrentVrService.getUserId()));
27298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    mCurrentVrService = null;
27398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                }
27498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            } else {
27598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                if (mCurrentVrService != null) {
27698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    // Unbind any running service that doesn't match the component/user selection
27798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
27898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() +
27998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                                " for user " + mCurrentVrService.getUserId());
28098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        disableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
28198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                                new UserHandle(mCurrentVrService.getUserId()));
28298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        createAndConnectService(component, userId);
28398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        enableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
28498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                                new UserHandle(mCurrentVrService.getUserId()));
28598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        sendUpdatedCaller = true;
28698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    }
28798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    // The service with the correct component/user is bound
28898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                } else {
28998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    // Nothing was previously running, bind a new service
290c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    createAndConnectService(component, userId);
29198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    enableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
29298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                            new UserHandle(mCurrentVrService.getUserId()));
293c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    sendUpdatedCaller = true;
294c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                }
29598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
29698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
29798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent))  {
29898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mCurrentVrModeComponent = calling;
29998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mCurrentVrModeUser = userId;
300c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                sendUpdatedCaller = true;
301e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
30298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
30398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (mCurrentVrService != null && sendUpdatedCaller) {
30498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                final ComponentName c = mCurrentVrModeComponent;
30598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mCurrentVrService.sendEvent(new PendingEvent() {
30698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    @Override
30798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    public void runEvent(IInterface service) throws RemoteException {
30898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        IVrListener l = (IVrListener) service;
30998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        l.focusedActivityChanged(c);
31098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    }
31198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                });
31298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
31398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
31498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return validUserComponent;
31598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        } finally {
31698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Binder.restoreCallingIdentity(identity);
317c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        }
31898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
319c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
32098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    /**
32198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * Enable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given
32298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * component package and user.
32398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     *
32498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param component the component whose package should be enabled.
32598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param userId the user that owns the given component.
32698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     */
32798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void enableImpliedPermissionsLocked(ComponentName component, UserHandle userId) {
32898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mGuard) {
32998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            // Impossible
33098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            throw new IllegalStateException("Enabling permissions without disabling.");
331c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        }
33298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mGuard = true;
333c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
33498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
33598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
33698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String pName = component.getPackageName();
33798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (pm == null) {
33898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Slog.e(TAG, "Couldn't set implied permissions for " + pName +
33998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                ", PackageManager isn't running");
34098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
341e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
342e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
34398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ApplicationInfo info = null;
34498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        try {
34598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA);
34698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        } catch (NameNotFoundException e) {
34798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
34898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
34998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (info == null) {
35098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package.");
35198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
35298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
35398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
35498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!(info.isSystemApp() || info.isUpdatedSystemApp())) {
35598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return; // Application is not pre-installed, avoid setting implied permissions
35698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
35798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
35898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mWasDefaultGranted = true;
35998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
36098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        grantOverlayAccess(pName, userId);
36198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        grantNotificationPolicyAccess(pName);
36298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        grantNotificationListenerAccess(pName, userId);
363e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
364e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
36598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    /**
36698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * Disable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given
36798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * component package and user.
36898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     *
36998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param component the component whose package should be disabled.
37098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param userId the user that owns the given component.
37198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     */
37298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void disableImpliedPermissionsLocked(ComponentName component, UserHandle userId) {
37398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!mGuard) {
37498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            // Impossible
37598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            throw new IllegalStateException("Disabling permissions without enabling.");
37698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
37798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mGuard = false;
37898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
37998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
38098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
38198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (pm == null) {
38298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Slog.e(TAG, "Couldn't remove implied permissions for " + component +
38398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                ", PackageManager isn't running");
38498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
38598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
38698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
38798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String pName = component.getPackageName();
38898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mWasDefaultGranted) {
38998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            revokeOverlayAccess(userId);
39098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            revokeNotificationPolicyAccess(pName);
39198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            revokeNotificiationListenerAccess();
39298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mWasDefaultGranted = false;
39398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
39498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
39598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
39698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
39798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void grantOverlayAccess(String pkg, UserHandle userId) {
39898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
39998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        boolean prev = (PackageManager.PERMISSION_GRANTED ==
40098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg));
40198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousManageOverlayPackage = null;
40298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!prev) {
40398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW,
40498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    userId);
40598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousManageOverlayPackage = pkg;
40698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
40798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
40898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
40998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void revokeOverlayAccess(UserHandle userId) {
41098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
41198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mPreviousManageOverlayPackage != null) {
41298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            pm.revokeRuntimePermission(mPreviousManageOverlayPackage,
41398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId);
41498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousManageOverlayPackage = null;
41598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
41698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
41798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
41898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
41998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void grantNotificationPolicyAccess(String pkg) {
42098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
42198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg);
42298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousNotificationPolicyAccessPackage = null;
42398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!prev) {
42498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousNotificationPolicyAccessPackage = pkg;
42598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            nm.setNotificationPolicyAccessGranted(pkg, true);
42698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
42798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
42898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
42998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void revokeNotificationPolicyAccess(String pkg) {
43098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
43198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mPreviousNotificationPolicyAccessPackage != null) {
43298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
43398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousNotificationPolicyAccessPackage = null;
43498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
43598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
43698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
43798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
43898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
43998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
44098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE,
44198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
44298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ContentResolver resolver = mContext.getContentResolver();
44398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
44498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<String> current = getCurrentNotifListeners(resolver);
44598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
44698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousToggledListenerSettings.clear();
44798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
44898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        for (ComponentName c : possibleServices) {
44998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            String flatName = c.flattenToString();
45098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (Objects.equals(c.getPackageName(), pkg)
45198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    && !current.contains(flatName)) {
45298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mPreviousToggledListenerSettings.add(flatName);
45398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                current.add(flatName);
45498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
45598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
45698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
45798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (current.size() > 0) {
45898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            String flatSettings = formatSettings(current);
45998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
46098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    flatSettings);
46198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
46298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
46398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
46498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void revokeNotificiationListenerAccess() {
46598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mPreviousToggledListenerSettings.isEmpty()) {
46698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
46798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
46898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
46998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ContentResolver resolver = mContext.getContentResolver();
47098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<String> current = getCurrentNotifListeners(resolver);
47198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
47298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        current.removeAll(mPreviousToggledListenerSettings);
47398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousToggledListenerSettings.clear();
47498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
47598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String flatSettings = formatSettings(current);
47698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
47798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                flatSettings);
47898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
47998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
48098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
48198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String flat = Settings.Secure.getString(resolver,
48298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
48398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
48498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<String> current = new ArraySet<>();
48598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (flat != null) {
48698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            String[] allowed = flat.split(":");
48798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            for (String s : allowed) {
48898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                current.add(s);
48998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
49098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
49198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        return current;
49298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
49398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
49498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private static String formatSettings(Collection<String> c) {
49598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (c == null || c.isEmpty()) {
49698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return "";
49798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
49898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
49998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        StringBuilder b = new StringBuilder();
50098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        boolean start = true;
50198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        for (String s : c) {
50298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if ("".equals(s)) {
50398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                continue;
50498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
50598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (!start) {
50698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                b.append(':');
50798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
50898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            b.append(s);
50998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            start = false;
51098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
51198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        return b.toString();
51298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
51398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
51498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
51598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
516c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private void createAndConnectService(@NonNull ComponentName component, int userId) {
517c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        mCurrentVrService = VrManagerService.create(mContext, component, userId);
518c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        mCurrentVrService.connect();
519c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        Slog.i(TAG, "Connecting " + component + " for user " + userId);
520c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    }
521c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
522e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
523e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
524e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
525e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
526e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
527e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state of the VR mode.
52829931bc684bde6b430923122777684178ee2681cRuben Brunk     * @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
529e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
53029931bc684bde6b430923122777684178ee2681cRuben Brunk    private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
531e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (mVrModeEnabled != enabled) {
532e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mVrModeEnabled = enabled;
533e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
534e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Log mode change event.
535e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
536e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            setVrModeNative(mVrModeEnabled);
537e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
53829931bc684bde6b430923122777684178ee2681cRuben Brunk            updateOverlayStateLocked(exemptedComponent);
539e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            onVrModeChangedLocked();
540dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
541dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
542dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
543dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    /**
544dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     * Notify system services of VR mode change.
545e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
546e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
547dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     */
548dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private void onVrModeChangedLocked() {
549dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        for (VrStateListener l : mListeners) {
550dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            l.onVrStateChanged(mVrModeEnabled);
551dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
552dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
553e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
554e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
555e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Helper function for making ManagedApplicationService instances.
556e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
557e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static ManagedApplicationService create(@NonNull Context context,
558e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            @NonNull ComponentName component, int userId) {
559e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        return ManagedApplicationService.build(context, component, userId,
560e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
561e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                sBinderChecker);
562e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
563e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
564e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /*
565e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal calls.  These are callable from system services.
566e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
567e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
568e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
569c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            int userId, @NonNull ComponentName callingPackage) {
570e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
571c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            return updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
572e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
573e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
574e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
575e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean getVrMode() {
576e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
577e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return mVrModeEnabled;
578e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
579e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
580e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
581e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void addListener(VrStateListener listener) {
582e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
583e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mListeners.add(listener);
584e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
585e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
586e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
587e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void removeListener(VrStateListener listener) {
588e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
589e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mListeners.remove(listener);
590e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
591e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
592e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
593e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
594e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
595e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return mComponentObserver.isValid(targetPackageName, userId);
596e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
597e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
598dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk}
599