VrManagerService.java revision e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312
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;
19e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull;
20dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.content.Context;
21e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ComponentName;
22dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.content.Intent;
23dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.content.pm.PackageManager;
2447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.Binder;
25e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler;
2647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.IBinder;
27e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface;
28e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Looper;
29dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.os.UserHandle;
30e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings;
31e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.IVrListener;
32e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.VrListenerService;
33dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.ArraySet;
34dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.Slog;
35dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
36e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.internal.R;
37dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport com.android.server.SystemService;
38e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
39e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService;
40e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService.BinderChecker;
41dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
42dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport java.util.ArrayList;
43e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport java.util.Set;
44dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
45dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk/**
46e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Service tracking whether VR mode is active, and notifying listening services of state changes.
47e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
48e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Services running in system server may modify the state of VrManagerService via the interface in
49e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
50e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * interface given in VrStateListener.
51e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
52e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
53e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk *  hardware/libhardware/modules/vr
54e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/>
55e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * In general applications may enable or disable VR mode by calling
56e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * {@link android.app.Activity#setVrMode)}.  An application may also implement a service to be run
57e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * while in VR mode by implementing {@link android.service.vr.VrListenerService}.
58e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk *
59e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link android.service.vr.VrListenerService}
60e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrManagerInternal}
61e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrStateListener}
62dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk *
63e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide
64dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */
65e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class VrManagerService extends SystemService implements EnabledComponentChangeListener{
66dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
67dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public static final String TAG = "VrManagerService";
68dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
69baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk    private static native void initializeNative();
70baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk    private static native void setVrModeNative(boolean enabled);
71baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
72dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private final Object mLock = new Object();
7347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
7447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    private final IBinder mOverlayToken = new Binder();
7547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
76e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    // State protected by mLock
77dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private boolean mVrModeEnabled = false;
78e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private final Set<VrStateListener> mListeners = new ArraySet<>();
79e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private EnabledComponentsObserver mComponentObserver;
80e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private ManagedApplicationService mCurrentVrService;
81e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private Context mContext;
82e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
83e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static final BinderChecker sBinderChecker = new BinderChecker() {
84e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
85e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public IInterface asInterface(IBinder binder) {
86e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return IVrListener.Stub.asInterface(binder);
87e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
88e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
89e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
90e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public boolean checkType(IInterface service) {
91e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return service instanceof IVrListener;
92e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
93e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    };
94e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
95e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
96e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Called when a user, package, or setting changes that could affect whether or not the
97e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * currently bound VrListenerService is changed.
98e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
99e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
100e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onEnabledComponentChanged() {
101e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
102e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService == null) {
103e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                return; // No active services
104e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
105e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
106e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // There is an active service, update it if needed
107e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
108e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                    mCurrentVrService.getUserId());
109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
110e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
111dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
112e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
113e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal.  Callable only from system services.
114e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
115dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private final class LocalService extends VrManagerInternal {
116dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
117dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public boolean isInVrMode() {
118dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            return VrManagerService.this.getVrMode();
119dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
120dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
121dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
122e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public void setVrMode(boolean enabled, ComponentName packageName, int userId) {
123e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            VrManagerService.this.setVrMode(enabled, packageName, userId);
124dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
125dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
126dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
127dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public void registerListener(VrStateListener listener) {
128dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            VrManagerService.this.addListener(listener);
129dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
130dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
131dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
132dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public void unregisterListener(VrStateListener listener) {
133dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            VrManagerService.this.removeListener(listener);
134dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
135e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
136e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
137e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public int hasVrPackage(ComponentName packageName, int userId) {
138e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return VrManagerService.this.hasVrPackage(packageName, userId);
139e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
140dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
141dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
142dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public VrManagerService(Context context) {
143dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        super(context);
144dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
145dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
146dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    @Override
147dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public void onStart() {
148baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        synchronized(mLock) {
149baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk            initializeNative();
150e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mContext = getContext();
151baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        }
152baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
153dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        publishLocalService(VrManagerInternal.class, new LocalService());
154dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
155dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
156e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
157e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onBootPhase(int phase) {
158e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
159e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            synchronized (mLock) {
160e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Looper looper = Looper.getMainLooper();
161e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Handler handler = new Handler(looper);
162e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
163e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                listeners.add(this);
164e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
165e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
166e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
167e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
168e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
169e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver.rebuildAll();
170e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
171e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
172e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
173e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
174e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
175e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStartUser(int userHandle) {
176dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
177e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
178dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
179dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
180dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
181e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
182e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onSwitchUser(int userHandle) {
183dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
184e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
185e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
186e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
187e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
188e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
189e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
190e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStopUser(int userHandle) {
191e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
192e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
193dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
194e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
195dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
196dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
197e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
198e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onCleanupUser(int userHandle) {
199dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
200e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
201dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
202dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
203dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
20447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    private void updateOverlayStateLocked() {
20547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        final long identity = Binder.clearCallingIdentity();
20647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        try {
20747d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
20847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            if (appOpsManager != null) {
20947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov                appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
21047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov                        mVrModeEnabled, mOverlayToken);
21147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            }
21247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        } finally {
21347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            Binder.restoreCallingIdentity(identity);
21447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        }
21547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    }
21647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
217e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
218e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
219e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * the currently selected VR listener service.  If the component selected for the VR listener
220e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * service has changed, unbind the previous listener and bind the new listener (if enabled).
221e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
222e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
223e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
224e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state for VR mode.
225e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param component new component to be bound as a VR listener.
226e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param userId user owning the component to be bound.
227e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
228e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @return {@code true} if the component/user combination specified is valid.
229e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
230e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean updateCurrentVrServiceLocked(boolean enabled,
231e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            @NonNull ComponentName component, int userId) {
232e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
233e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        // Always send mode change events.
234e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        changeVrModeLocked(enabled);
235e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
236e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
237e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                EnabledComponentsObserver.NO_ERROR);
238e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
239e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (!enabled || !validUserComponent) {
240e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Unbind whatever is running
241e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService != null) {
242e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
243e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        mCurrentVrService.getUserId());
244e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mCurrentVrService.disconnect();
245e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mCurrentVrService = null;
246e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
247e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return validUserComponent;
248e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
249e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
250e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (mCurrentVrService != null) {
251e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Unbind any running service that doesn't match the component/user selection
252e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
253e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
254e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        mCurrentVrService.getUserId());
255e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mCurrentVrService = VrManagerService.create(mContext, component, userId);
256e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mCurrentVrService.connect();
257e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Slog.i(TAG, "Connecting " + mCurrentVrService.getComponent() + " for user " +
258e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        mCurrentVrService.getUserId());
259e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
260e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // The service with the correct component/user is bound
261e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        } else {
262e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Nothing was previously running, bind a new service
263e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mCurrentVrService = VrManagerService.create(mContext, component, userId);
264e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mCurrentVrService.connect();
265e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            Slog.i(TAG, "Connecting " + mCurrentVrService.getComponent() + " for user " +
266e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                    mCurrentVrService.getUserId());
267e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
268e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
269e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        return validUserComponent;
270e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
271e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
272e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
273e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
274e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
275e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
276e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
277e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state of the VR mode.
278e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
279e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void changeVrModeLocked(boolean enabled) {
280e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (mVrModeEnabled != enabled) {
281e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mVrModeEnabled = enabled;
282e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
283e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Log mode change event.
284e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
285e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            setVrModeNative(mVrModeEnabled);
286e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
287e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            updateOverlayStateLocked();
288e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            onVrModeChangedLocked();
289dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
290dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
291dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
292dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    /**
293dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     * Notify system services of VR mode change.
294e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
295e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
296dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     */
297dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private void onVrModeChangedLocked() {
298dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        for (VrStateListener l : mListeners) {
299dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            l.onVrStateChanged(mVrModeEnabled);
300dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
301dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
302e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
303e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
304e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Helper function for making ManagedApplicationService instances.
305e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
306e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static ManagedApplicationService create(@NonNull Context context,
307e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            @NonNull ComponentName component, int userId) {
308e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        return ManagedApplicationService.build(context, component, userId,
309e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
310e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                sBinderChecker);
311e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
312e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
313e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /*
314e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal calls.  These are callable from system services.
315e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
316e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
317e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
318e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            int userId) {
319e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
320e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return updateCurrentVrServiceLocked(enabled, targetPackageName, userId);
321e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
322e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
323e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
324e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean getVrMode() {
325e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
326e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return mVrModeEnabled;
327e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
328e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
329e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
330e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void addListener(VrStateListener listener) {
331e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
332e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mListeners.add(listener);
333e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
334e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
335e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
336e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void removeListener(VrStateListener listener) {
337e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
338e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mListeners.remove(listener);
339e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
340e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
341e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
342e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
343e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
344e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return mComponentObserver.isValid(targetPackageName, userId);
345e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
346e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
347dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk}
348