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