VrManagerService.java revision dc34df5d310245a268ee9ea3872a612c6f7950b5
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
18c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.Manifest;
1947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.app.AppOpsManager;
2098576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.app.NotificationManager;
21e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull;
22e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ComponentName;
2398576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.ContentResolver;
2498576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.Context;
2598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.ApplicationInfo;
2698576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager;
2798576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager.NameNotFoundException;
2847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.Binder;
29e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler;
3047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.IBinder;
31e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface;
32e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Looper;
33c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.os.Message;
34c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.os.RemoteCallbackList;
35c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport android.os.RemoteException;
3698576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.os.UserHandle;
37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings;
3898576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.service.notification.NotificationListenerService;
39e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.IVrListener;
40c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.service.vr.IVrManager;
41c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.service.vr.IVrStateCallbacks;
42e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.VrListenerService;
43dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.ArraySet;
44dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.Slog;
45dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
46e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.internal.R;
47dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport com.android.server.SystemService;
48c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport com.android.server.utils.ManagedApplicationService.PendingEvent;
49e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
50e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService;
51e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService.BinderChecker;
52dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
53dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandlerimport java.io.FileDescriptor;
54dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandlerimport java.io.PrintWriter;
5598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.lang.StringBuilder;
56c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport java.lang.ref.WeakReference;
57dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport java.util.ArrayList;
5898576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.util.Collection;
59c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport java.util.Objects;
60e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport java.util.Set;
61dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
62dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk/**
63e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Service tracking whether VR mode is active, and notifying listening services of state changes.
64e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
65e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Services running in system server may modify the state of VrManagerService via the interface in
66e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
67e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * interface given in VrStateListener.
68e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
69e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
70e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk *  hardware/libhardware/modules/vr
71e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
72e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * In general applications may enable or disable VR mode by calling
7398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
7498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
75e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk *
76e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link android.service.vr.VrListenerService}
77e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrManagerInternal}
78e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrStateListener}
79dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *
80e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide
81dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */
82e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class VrManagerService extends SystemService implements EnabledComponentChangeListener{
83dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
84dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public static final String TAG = "VrManagerService";
85dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
86c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
87c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
88baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk    private static native void initializeNative();
89baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk    private static native void setVrModeNative(boolean enabled);
90baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
91dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private final Object mLock = new Object();
9247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
9347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    private final IBinder mOverlayToken = new Binder();
9447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
95e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    // State protected by mLock
9698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean mVrModeEnabled;
97e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private EnabledComponentsObserver mComponentObserver;
98e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private ManagedApplicationService mCurrentVrService;
99e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private Context mContext;
100c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private ComponentName mCurrentVrModeComponent;
101c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private int mCurrentVrModeUser;
10298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean mWasDefaultGranted;
10398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean mGuard;
104c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
105c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            new RemoteCallbackList<>();
10698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
10798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private String mPreviousNotificationPolicyAccessPackage;
10898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private String mPreviousManageOverlayPackage;
109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
110c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private static final int MSG_VR_STATE_CHANGE = 0;
111c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
112c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private final Handler mHandler = new Handler() {
113c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        @Override
114c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        public void handleMessage(Message msg) {
115c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            switch(msg.what) {
116c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                case MSG_VR_STATE_CHANGE : {
117c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                    boolean state = (msg.arg1 == 1);
118c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                    int i = mRemoteCallbacks.beginBroadcast();
119c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                    while (i > 0) {
120c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                        i--;
121c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                        try {
122c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                            mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
123c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                        } catch (RemoteException e) {
124c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                            // Noop
125c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                        }
126c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                    }
127c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                    mRemoteCallbacks.finishBroadcast();
128c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                } break;
129c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                default :
130c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                    throw new IllegalStateException("Unknown message type: " + msg.what);
131c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            }
132c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        }
133c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    };
134c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
135e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static final BinderChecker sBinderChecker = new BinderChecker() {
136e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
137e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public IInterface asInterface(IBinder binder) {
138e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return IVrListener.Stub.asInterface(binder);
139e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
140e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
141e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
142e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public boolean checkType(IInterface service) {
143e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return service instanceof IVrListener;
144e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
145e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    };
146e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
147e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
148e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Called when a user, package, or setting changes that could affect whether or not the
149e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * currently bound VrListenerService is changed.
150e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
151e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
152e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onEnabledComponentChanged() {
153e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
154e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService == null) {
155e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                return; // No active services
156e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
157e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
158e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // There is an active service, update it if needed
159e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
160c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    mCurrentVrService.getUserId(), null);
161e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
162e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
163dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
164c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private final IVrManager mVrManager = new IVrManager.Stub() {
165c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
166dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
167c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        public void registerListener(IVrStateCallbacks cb) {
168c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
169c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            if (cb == null) {
170c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                throw new IllegalArgumentException("Callback binder object is null.");
171c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            }
172c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
173c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            VrManagerService.this.addStateCallback(cb);
174dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
175dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
176dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
177c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        public void unregisterListener(IVrStateCallbacks cb) {
178c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
179c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            if (cb == null) {
180c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                throw new IllegalArgumentException("Callback binder object is null.");
181c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            }
182c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
183c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            VrManagerService.this.removeStateCallback(cb);
184dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
185dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
186dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
187c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        public boolean getVrModeState() {
188c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            return VrManagerService.this.getVrMode();
189c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        }
190c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
191dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler        @Override
192dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
193dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
194dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler                    != PackageManager.PERMISSION_GRANTED) {
195dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler                pw.println("permission denied: can't dump VrManagerService from pid="
196dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
197dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler                return;
198dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            }
199dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.print("mVrModeEnabled=");
200dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.println(mVrModeEnabled);
201dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.print("mCurrentVrModeUser=");
202dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.println(mCurrentVrModeUser);
203dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.print("mRemoteCallbacks=");
204dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
205dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            while(i-->0) {
206dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler                pw.print(mRemoteCallbacks.getBroadcastItem(i));
207dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler                if (i>0) pw.print(", ");
208dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            }
209dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            mRemoteCallbacks.finishBroadcast();
210dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.println();
211dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.print("mCurrentVrService=");
212dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.println(mCurrentVrService != null ? mCurrentVrService.getComponent() : "(none)");
213dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.print("mCurrentVrModeComponent=");
214dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler            pw.println(mCurrentVrModeComponent);
215dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler        }
216dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler
217c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    };
218c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
219c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private void enforceCallerPermission(String permission) {
220c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        if (mContext.checkCallingOrSelfPermission(permission)
221c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                != PackageManager.PERMISSION_GRANTED) {
222c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            throw new SecurityException("Caller does not hold the permission " + permission);
2238f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        }
224c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    }
2258f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk
226c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    /**
227c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk     * Implementation of VrManagerInternal.  Callable only from system services.
228c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk     */
229c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private final class LocalService extends VrManagerInternal {
2308f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        @Override
231c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
232c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                ComponentName callingPackage) {
233c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
234dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
235dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
236dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
237c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        public boolean isCurrentVrListener(String packageName, int userId) {
238c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            return VrManagerService.this.isCurrentVrListener(packageName, userId);
239dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
240e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
241e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
242e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public int hasVrPackage(ComponentName packageName, int userId) {
243e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return VrManagerService.this.hasVrPackage(packageName, userId);
244e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
245dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
246dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
247dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public VrManagerService(Context context) {
248dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        super(context);
249dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
250dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
251dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    @Override
252dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public void onStart() {
253baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        synchronized(mLock) {
254baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk            initializeNative();
255e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mContext = getContext();
256baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        }
257baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
258dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        publishLocalService(VrManagerInternal.class, new LocalService());
259c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
260dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
261dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
262e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
263e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onBootPhase(int phase) {
2648507004a35a94e9bb4653dc049505aa54d1e6175Ruben Brunk        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
265e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            synchronized (mLock) {
266e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Looper looper = Looper.getMainLooper();
267e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Handler handler = new Handler(looper);
268e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
269e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                listeners.add(this);
270e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
271e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
272e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
273e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
274e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
275e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver.rebuildAll();
276e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
277e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
278e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
279e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
280e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
281e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStartUser(int userHandle) {
282dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
283e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
284dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
285dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
286dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
287e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
288e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onSwitchUser(int userHandle) {
289dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
290e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
291e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
292e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
293e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
294e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
295e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
296e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStopUser(int userHandle) {
297e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
298e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
299dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
300e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
301dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
302dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
303e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
304e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onCleanupUser(int userHandle) {
305dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
306e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
307dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
308dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
309dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
31029931bc684bde6b430923122777684178ee2681cRuben Brunk    private void updateOverlayStateLocked(ComponentName exemptedComponent) {
31147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        final long identity = Binder.clearCallingIdentity();
31247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        try {
31347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
31447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            if (appOpsManager != null) {
31529931bc684bde6b430923122777684178ee2681cRuben Brunk                String[] exemptions = (exemptedComponent == null) ? new String[0] :
31629931bc684bde6b430923122777684178ee2681cRuben Brunk                        new String[] { exemptedComponent.getPackageName() };
31729931bc684bde6b430923122777684178ee2681cRuben Brunk
31847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov                appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
31929931bc684bde6b430923122777684178ee2681cRuben Brunk                        mVrModeEnabled, mOverlayToken, exemptions);
32047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            }
32147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        } finally {
32247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            Binder.restoreCallingIdentity(identity);
32347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        }
32447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    }
32547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
326e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
327e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
328e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * the currently selected VR listener service.  If the component selected for the VR listener
329e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * service has changed, unbind the previous listener and bind the new listener (if enabled).
330e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
331e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
332e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
333e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state for VR mode.
334e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param component new component to be bound as a VR listener.
335e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param userId user owning the component to be bound.
336c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk     * @param calling the component currently using VR mode, or null to leave unchanged.
337e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
338e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @return {@code true} if the component/user combination specified is valid.
339e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
34098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
34198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            int userId, ComponentName calling) {
342c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
343c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        boolean sendUpdatedCaller = false;
34498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        final long identity = Binder.clearCallingIdentity();
34598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        try {
346e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
34798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
34898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    EnabledComponentsObserver.NO_ERROR);
349e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
35098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            // Always send mode change events.
35198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
35229931bc684bde6b430923122777684178ee2681cRuben Brunk
35398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (!enabled || !validUserComponent) {
35498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                // Unbind whatever is running
35598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                if (mCurrentVrService != null) {
356c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
35798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                            mCurrentVrService.getUserId());
35898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    mCurrentVrService.disconnect();
35998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    disableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
36098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                            new UserHandle(mCurrentVrService.getUserId()));
36198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    mCurrentVrService = null;
36298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                }
36398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            } else {
36498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                if (mCurrentVrService != null) {
36598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    // Unbind any running service that doesn't match the component/user selection
36698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
36798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() +
36898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                                " for user " + mCurrentVrService.getUserId());
36998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        disableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
37098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                                new UserHandle(mCurrentVrService.getUserId()));
37198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        createAndConnectService(component, userId);
37298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        enableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
37398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                                new UserHandle(mCurrentVrService.getUserId()));
37498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        sendUpdatedCaller = true;
37598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    }
37698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    // The service with the correct component/user is bound
37798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                } else {
37898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    // Nothing was previously running, bind a new service
379c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    createAndConnectService(component, userId);
38098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    enableImpliedPermissionsLocked(mCurrentVrService.getComponent(),
38198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                            new UserHandle(mCurrentVrService.getUserId()));
382c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    sendUpdatedCaller = true;
383c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                }
38498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
38598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
38698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent))  {
38798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mCurrentVrModeComponent = calling;
38898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mCurrentVrModeUser = userId;
389c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                sendUpdatedCaller = true;
390e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
39198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
39298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (mCurrentVrService != null && sendUpdatedCaller) {
39398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                final ComponentName c = mCurrentVrModeComponent;
39498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mCurrentVrService.sendEvent(new PendingEvent() {
39598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    @Override
39698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    public void runEvent(IInterface service) throws RemoteException {
39798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        IVrListener l = (IVrListener) service;
39898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                        l.focusedActivityChanged(c);
39998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    }
40098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                });
40198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
40298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
40398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return validUserComponent;
40498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        } finally {
40598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Binder.restoreCallingIdentity(identity);
406c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        }
40798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
408c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
40998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    /**
41098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * Enable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given
41198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * component package and user.
41298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     *
41398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param component the component whose package should be enabled.
41498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param userId the user that owns the given component.
41598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     */
41698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void enableImpliedPermissionsLocked(ComponentName component, UserHandle userId) {
41798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mGuard) {
41898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            // Impossible
41998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            throw new IllegalStateException("Enabling permissions without disabling.");
420c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        }
42198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mGuard = true;
422c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
42398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
42498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
42598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String pName = component.getPackageName();
42698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (pm == null) {
42798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Slog.e(TAG, "Couldn't set implied permissions for " + pName +
42898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                ", PackageManager isn't running");
42998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
430e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
431e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
43298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ApplicationInfo info = null;
43398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        try {
43498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA);
43598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        } catch (NameNotFoundException e) {
43698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
43798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
43898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (info == null) {
43998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package.");
44098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
44198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
44298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
44398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!(info.isSystemApp() || info.isUpdatedSystemApp())) {
44498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return; // Application is not pre-installed, avoid setting implied permissions
44598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
44698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
44798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mWasDefaultGranted = true;
44898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
44998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        grantOverlayAccess(pName, userId);
45098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        grantNotificationPolicyAccess(pName);
45198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        grantNotificationListenerAccess(pName, userId);
452e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
453e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
45498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    /**
45598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * Disable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given
45698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * component package and user.
45798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     *
45898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param component the component whose package should be disabled.
45998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     * @param userId the user that owns the given component.
46098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk     */
46198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void disableImpliedPermissionsLocked(ComponentName component, UserHandle userId) {
46298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!mGuard) {
46398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            // Impossible
46498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            throw new IllegalStateException("Disabling permissions without enabling.");
46598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
46698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mGuard = false;
46798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
46898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
46998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
47098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (pm == null) {
47198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Slog.e(TAG, "Couldn't remove implied permissions for " + component +
47298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                ", PackageManager isn't running");
47398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
47498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
47598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
47698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String pName = component.getPackageName();
47798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mWasDefaultGranted) {
47898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            revokeOverlayAccess(userId);
47998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            revokeNotificationPolicyAccess(pName);
48098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            revokeNotificiationListenerAccess();
48198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mWasDefaultGranted = false;
48298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
48398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
48498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
48598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
48698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void grantOverlayAccess(String pkg, UserHandle userId) {
48798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
48898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        boolean prev = (PackageManager.PERMISSION_GRANTED ==
48998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg));
49098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousManageOverlayPackage = null;
49198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!prev) {
49298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW,
49398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    userId);
49498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousManageOverlayPackage = pkg;
49598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
49698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
49798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
49898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void revokeOverlayAccess(UserHandle userId) {
49998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
50098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mPreviousManageOverlayPackage != null) {
50198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            pm.revokeRuntimePermission(mPreviousManageOverlayPackage,
50298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId);
50398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousManageOverlayPackage = null;
50498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
50598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
50698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
50798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
50898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void grantNotificationPolicyAccess(String pkg) {
50998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
51098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg);
51198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousNotificationPolicyAccessPackage = null;
51298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (!prev) {
51398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            mPreviousNotificationPolicyAccessPackage = pkg;
51498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            nm.setNotificationPolicyAccessGranted(pkg, true);
51598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
51698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
51798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
51898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void revokeNotificationPolicyAccess(String pkg) {
51998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
52098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mPreviousNotificationPolicyAccessPackage != null) {
5210c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott            if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) {
5220c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott                // Remove any DND zen rules possibly created by the package.
5230c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott                nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage);
5240c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott                // Remove Notification Policy Access.
5250c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott                nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
5260c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott                mPreviousNotificationPolicyAccessPackage = null;
5270c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott            } else {
5280c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott                Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg);
5290c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott            }
53098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
53198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
53298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
53398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
53498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        PackageManager pm = mContext.getPackageManager();
53598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
53698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE,
53798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
53898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ContentResolver resolver = mContext.getContentResolver();
53998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
54098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<String> current = getCurrentNotifListeners(resolver);
54198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
54298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousToggledListenerSettings.clear();
54398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
54498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        for (ComponentName c : possibleServices) {
54598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            String flatName = c.flattenToString();
54698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (Objects.equals(c.getPackageName(), pkg)
54798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    && !current.contains(flatName)) {
54898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                mPreviousToggledListenerSettings.add(flatName);
54998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                current.add(flatName);
55098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
55198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
55298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
55398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (current.size() > 0) {
55498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            String flatSettings = formatSettings(current);
55598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
55698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                    flatSettings);
55798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
55898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
55998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
56098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private void revokeNotificiationListenerAccess() {
56198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (mPreviousToggledListenerSettings.isEmpty()) {
56298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return;
56398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
56498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
56598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ContentResolver resolver = mContext.getContentResolver();
56698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<String> current = getCurrentNotifListeners(resolver);
56798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
56898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        current.removeAll(mPreviousToggledListenerSettings);
56998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        mPreviousToggledListenerSettings.clear();
57098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
57198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String flatSettings = formatSettings(current);
57298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
57398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                flatSettings);
57498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
57598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
57698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
57798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        String flat = Settings.Secure.getString(resolver,
57898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
57998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
58098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        ArraySet<String> current = new ArraySet<>();
58198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (flat != null) {
58298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            String[] allowed = flat.split(":");
58398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            for (String s : allowed) {
58498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                current.add(s);
58598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
58698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
58798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        return current;
58898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
58998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
59098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    private static String formatSettings(Collection<String> c) {
59198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        if (c == null || c.isEmpty()) {
59298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            return "";
59398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
59498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
59598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        StringBuilder b = new StringBuilder();
59698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        boolean start = true;
59798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        for (String s : c) {
59898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if ("".equals(s)) {
59998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                continue;
60098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
60198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            if (!start) {
60298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk                b.append(':');
60398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            }
60498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            b.append(s);
60598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk            start = false;
60698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        }
60798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk        return b.toString();
60898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk    }
60998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
61098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
61198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk
612c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private void createAndConnectService(@NonNull ComponentName component, int userId) {
613c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        mCurrentVrService = VrManagerService.create(mContext, component, userId);
614c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        mCurrentVrService.connect();
615c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        Slog.i(TAG, "Connecting " + component + " for user " + userId);
616c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    }
617c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
618e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
619e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
620e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
621e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
622e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
623e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state of the VR mode.
62429931bc684bde6b430923122777684178ee2681cRuben Brunk     * @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
625e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
62629931bc684bde6b430923122777684178ee2681cRuben Brunk    private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
627e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (mVrModeEnabled != enabled) {
628e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mVrModeEnabled = enabled;
629e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
630e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Log mode change event.
631e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
632e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            setVrModeNative(mVrModeEnabled);
633e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
63429931bc684bde6b430923122777684178ee2681cRuben Brunk            updateOverlayStateLocked(exemptedComponent);
635e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            onVrModeChangedLocked();
636dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
637dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
638dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
639dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    /**
640dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     * Notify system services of VR mode change.
641e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
642e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
643dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     */
644dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private void onVrModeChangedLocked() {
645c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
646c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk                (mVrModeEnabled) ? 1 : 0, 0));
647dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
648e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
649e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
650e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Helper function for making ManagedApplicationService instances.
651e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
652e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static ManagedApplicationService create(@NonNull Context context,
653e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            @NonNull ComponentName component, int userId) {
654e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        return ManagedApplicationService.build(context, component, userId,
655e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
656e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                sBinderChecker);
657e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
658e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
659e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /*
660e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal calls.  These are callable from system services.
661e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
662e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
663e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
664c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            int userId, @NonNull ComponentName callingPackage) {
665e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
666c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            return updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
667e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
668e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
669e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
670c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
671e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
672c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            return mComponentObserver.isValid(targetPackageName, userId);
673e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
674e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
675e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
6768f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk    private boolean isCurrentVrListener(String packageName, int userId) {
6778f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        synchronized (mLock) {
6788f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            if (mCurrentVrService == null) {
6798f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk                return false;
6808f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            }
6818f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
6828f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk                    userId == mCurrentVrService.getUserId();
6838f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        }
6848f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk    }
6858f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk
686c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    /*
687c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk     * Implementation of IVrManager calls.
688c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk     */
689c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk
690c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private void addStateCallback(IVrStateCallbacks cb) {
691c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        mRemoteCallbacks.register(cb);
692e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
693e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
694c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private void removeStateCallback(IVrStateCallbacks cb) {
695c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk        mRemoteCallbacks.unregister(cb);
696e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
697e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
698c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk    private boolean getVrMode() {
699e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
700c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk            return mVrModeEnabled;
701e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
702e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
703dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk}
704