VrManagerService.java revision 8f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8
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;
2247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.Binder;
23e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler;
2447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.IBinder;
25e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface;
26e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Looper;
27c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport android.os.RemoteException;
28e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings;
29e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.IVrListener;
30e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.VrListenerService;
31dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.ArraySet;
32dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.Slog;
33dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
34e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.internal.R;
35dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport com.android.server.SystemService;
36c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport com.android.server.utils.ManagedApplicationService.PendingEvent;
37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
38e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService;
39e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService.BinderChecker;
40dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
41dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport java.util.ArrayList;
42c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport java.util.Objects;
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;
82c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private ComponentName mCurrentVrModeComponent;
83c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private int mCurrentVrModeUser;
84e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
85e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static final BinderChecker sBinderChecker = new BinderChecker() {
86e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
87e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public IInterface asInterface(IBinder binder) {
88e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return IVrListener.Stub.asInterface(binder);
89e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
90e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
91e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
92e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public boolean checkType(IInterface service) {
93e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return service instanceof IVrListener;
94e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
95e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    };
96e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
97e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
98e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Called when a user, package, or setting changes that could affect whether or not the
99e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * currently bound VrListenerService is changed.
100e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
101e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
102e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onEnabledComponentChanged() {
103e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
104e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService == null) {
105e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                return; // No active services
106e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
107e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
108e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // There is an active service, update it if needed
109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
110c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    mCurrentVrService.getUserId(), null);
111e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
112e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
113dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
114e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
115e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal.  Callable only from system services.
116e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
117dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private final class LocalService extends VrManagerInternal {
118dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
119dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public boolean isInVrMode() {
120dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            return VrManagerService.this.getVrMode();
121dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
122dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
123dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
124c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
125c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                ComponentName callingPackage) {
126c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
127dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
128dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
129dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
1308f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        public boolean isCurrentVrListener(String packageName, int userId) {
1318f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            return VrManagerService.this.isCurrentVrListener(packageName, userId);
1328f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        }
1338f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk
1348f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        @Override
135dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public void registerListener(VrStateListener listener) {
136dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            VrManagerService.this.addListener(listener);
137dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
138dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
139dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        @Override
140dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        public void unregisterListener(VrStateListener listener) {
141dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            VrManagerService.this.removeListener(listener);
142dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
143e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
144e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        @Override
145e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        public int hasVrPackage(ComponentName packageName, int userId) {
146e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return VrManagerService.this.hasVrPackage(packageName, userId);
147e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
148dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
149dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
150dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public VrManagerService(Context context) {
151dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        super(context);
152dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
153dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
154dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    @Override
155dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    public void onStart() {
156baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        synchronized(mLock) {
157baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk            initializeNative();
158e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mContext = getContext();
159baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk        }
160baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk
161dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        publishLocalService(VrManagerInternal.class, new LocalService());
162dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
163dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
164e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
165e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onBootPhase(int phase) {
1668507004a35a94e9bb4653dc049505aa54d1e6175Ruben Brunk        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
167e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            synchronized (mLock) {
168e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Looper looper = Looper.getMainLooper();
169e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Handler handler = new Handler(looper);
170e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
171e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                listeners.add(this);
172e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
173e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
174e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
175e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
176e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
177e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mComponentObserver.rebuildAll();
178e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
179e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
180e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
181e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
182e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
183e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStartUser(int userHandle) {
184dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
185e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
186dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
187dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
188dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
189e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
190e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onSwitchUser(int userHandle) {
191dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
192e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
193e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
194e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
195e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
196e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
197e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
198e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onStopUser(int userHandle) {
199e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
200e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
201dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
202e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
203dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
204dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
205e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    @Override
206e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    public void onCleanupUser(int userHandle) {
207dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        synchronized (mLock) {
208e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mComponentObserver.onUsersChanged();
209dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
210dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
211dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
21229931bc684bde6b430923122777684178ee2681cRuben Brunk    private void updateOverlayStateLocked(ComponentName exemptedComponent) {
21347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        final long identity = Binder.clearCallingIdentity();
21447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        try {
21547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
21647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            if (appOpsManager != null) {
21729931bc684bde6b430923122777684178ee2681cRuben Brunk                String[] exemptions = (exemptedComponent == null) ? new String[0] :
21829931bc684bde6b430923122777684178ee2681cRuben Brunk                        new String[] { exemptedComponent.getPackageName() };
21929931bc684bde6b430923122777684178ee2681cRuben Brunk
22047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov                appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
22129931bc684bde6b430923122777684178ee2681cRuben Brunk                        mVrModeEnabled, mOverlayToken, exemptions);
22247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            }
22347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        } finally {
22447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov            Binder.restoreCallingIdentity(identity);
22547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov        }
22647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov    }
22747d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov
228e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
229e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
230e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * the currently selected VR listener service.  If the component selected for the VR listener
231e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * service has changed, unbind the previous listener and bind the new listener (if enabled).
232e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
233e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
234e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
235e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state for VR mode.
236e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param component new component to be bound as a VR listener.
237e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param userId user owning the component to be bound.
238c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk     * @param calling the component currently using VR mode, or null to leave unchanged.
239e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
240e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @return {@code true} if the component/user combination specified is valid.
241e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
242e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean updateCurrentVrServiceLocked(boolean enabled,
243c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            @NonNull ComponentName component, int userId, ComponentName calling) {
244c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
245c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        boolean sendUpdatedCaller = false;
246e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
247e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
248e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                EnabledComponentsObserver.NO_ERROR);
249e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
25029931bc684bde6b430923122777684178ee2681cRuben Brunk        // Always send mode change events.
25129931bc684bde6b430923122777684178ee2681cRuben Brunk        changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
25229931bc684bde6b430923122777684178ee2681cRuben Brunk
253e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (!enabled || !validUserComponent) {
254e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Unbind whatever is running
255e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            if (mCurrentVrService != null) {
256e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
257e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        mCurrentVrService.getUserId());
258e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mCurrentVrService.disconnect();
259e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                mCurrentVrService = null;
260e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
261c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        } else {
262c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            if (mCurrentVrService != null) {
263c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                // Unbind any running service that doesn't match the component/user selection
264c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
265c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
266e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                        mCurrentVrService.getUserId());
267c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    createAndConnectService(component, userId);
268c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    sendUpdatedCaller = true;
269c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                }
270c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                // The service with the correct component/user is bound
271c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            } else {
272c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                // Nothing was previously running, bind a new service
273c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                createAndConnectService(component, userId);
274c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                sendUpdatedCaller = true;
275e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            }
276c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        }
277c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
278c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent))  {
279c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            mCurrentVrModeComponent = calling;
280c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            mCurrentVrModeUser = userId;
281c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            sendUpdatedCaller = true;
282c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        }
283c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
284c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        if (mCurrentVrService != null && sendUpdatedCaller) {
285c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            final ComponentName c = mCurrentVrModeComponent;
286c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            mCurrentVrService.sendEvent(new PendingEvent() {
287c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                @Override
288c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                public void runEvent(IInterface service) throws RemoteException {
289c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    IVrListener l = (IVrListener) service;
290c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                    l.focusedActivityChanged(c);
291c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk                }
292c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            });
293e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
294e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
295e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        return validUserComponent;
296e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
297e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
298c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    private void createAndConnectService(@NonNull ComponentName component, int userId) {
299c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        mCurrentVrService = VrManagerService.create(mContext, component, userId);
300c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        mCurrentVrService.connect();
301c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk        Slog.i(TAG, "Connecting " + component + " for user " + userId);
302c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk    }
303c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk
304e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
305e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
306e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
307e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
308e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     *
309e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * @param enabled new state of the VR mode.
31029931bc684bde6b430923122777684178ee2681cRuben Brunk     * @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
311e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
31229931bc684bde6b430923122777684178ee2681cRuben Brunk    private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
313e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        if (mVrModeEnabled != enabled) {
314e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mVrModeEnabled = enabled;
315e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
316e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            // Log mode change event.
317e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
318e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            setVrModeNative(mVrModeEnabled);
319e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
32029931bc684bde6b430923122777684178ee2681cRuben Brunk            updateOverlayStateLocked(exemptedComponent);
321e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            onVrModeChangedLocked();
322dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
323dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
324dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk
325dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    /**
326dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     * Notify system services of VR mode change.
327e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * <p/>
328e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Note: Must be called while holding {@code mLock}.
329dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk     */
330dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    private void onVrModeChangedLocked() {
331dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        for (VrStateListener l : mListeners) {
332dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk            l.onVrStateChanged(mVrModeEnabled);
333dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk        }
334dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk    }
335e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
336e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /**
337e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Helper function for making ManagedApplicationService instances.
338e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
339e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private static ManagedApplicationService create(@NonNull Context context,
340e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            @NonNull ComponentName component, int userId) {
341e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        return ManagedApplicationService.build(context, component, userId,
342e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
343e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk                sBinderChecker);
344e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
345e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
346e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    /*
347e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     * Implementation of VrManagerInternal calls.  These are callable from system services.
348e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk     */
349e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
350e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
351c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            int userId, @NonNull ComponentName callingPackage) {
352e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
353c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk            return updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
354e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
355e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
356e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
357e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private boolean getVrMode() {
358e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
359e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return mVrModeEnabled;
360e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
361e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
362e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
3638f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk    private boolean isCurrentVrListener(String packageName, int userId) {
3648f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        synchronized (mLock) {
3658f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            if (mCurrentVrService == null) {
3668f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk                return false;
3678f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            }
3688f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk            return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
3698f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk                    userId == mCurrentVrService.getUserId();
3708f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk        }
3718f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk    }
3728f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk
373e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void addListener(VrStateListener listener) {
374e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
375e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mListeners.add(listener);
376e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
377e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
378e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
379e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private void removeListener(VrStateListener listener) {
380e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
381e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            mListeners.remove(listener);
382e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
383e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
384e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk
385e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
386e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        synchronized (mLock) {
387e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk            return mComponentObserver.isValid(targetPackageName, userId);
388e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk        }
389e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk    }
390dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk}
391