VrManagerService.java revision 2ff9c01975622ce7b0e1f7679f1337004dca7be9
1e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk/** 2dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Copyright (C) 2015 The Android Open Source Project 3dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * 4dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * you may not use this file except in compliance with the License. 6dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * You may obtain a copy of the License at 7dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * 8dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * 10dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * See the License for the specific language governing permissions and 14dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * limitations under the License. 15dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */ 16dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkpackage com.android.server.vr; 17dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 18c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.Manifest; 1947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.app.AppOpsManager; 2098576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.app.NotificationManager; 21e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull; 229906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.BroadcastReceiver; 23e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ComponentName; 2498576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.ContentResolver; 2598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.Context; 269906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.Intent; 279906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.IntentFilter; 2898576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.ApplicationInfo; 299906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.pm.FeatureInfo; 309906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.pm.PackageInfo; 3198576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager; 3298576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager.NameNotFoundException; 3347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.Binder; 34e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler; 3547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.IBinder; 36e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface; 37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Looper; 38c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.os.Message; 39c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.os.RemoteCallbackList; 40c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport android.os.RemoteException; 4198576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.os.UserHandle; 42e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings; 4398576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.service.notification.NotificationListenerService; 44e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.IVrListener; 45c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.service.vr.IVrManager; 46c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.service.vr.IVrStateCallbacks; 47e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.VrListenerService; 48dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.ArraySet; 49dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.Slog; 50dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 51e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.internal.R; 529906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport com.android.server.SystemConfig; 53dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport com.android.server.SystemService; 54c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport com.android.server.utils.ManagedApplicationService.PendingEvent; 55e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener; 56e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService; 57e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService.BinderChecker; 58dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 59dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandlerimport java.io.FileDescriptor; 60dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandlerimport java.io.PrintWriter; 6198576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.lang.StringBuilder; 622ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunkimport java.text.SimpleDateFormat; 632ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunkimport java.util.ArrayDeque; 64dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport java.util.ArrayList; 6598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.util.Collection; 662ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunkimport java.util.Date; 679906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport java.util.List; 68c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport java.util.Objects; 69dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 70dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk/** 71e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Service tracking whether VR mode is active, and notifying listening services of state changes. 72e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 73e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Services running in system server may modify the state of VrManagerService via the interface in 74e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the 75e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * interface given in VrStateListener. 76e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 77e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.: 78e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * hardware/libhardware/modules/vr 79e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 80e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * In general applications may enable or disable VR mode by calling 8198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to 8298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}. 83e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 84e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link android.service.vr.VrListenerService} 85e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrManagerInternal} 86e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrStateListener} 87dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * 88e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide 89dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */ 90e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class VrManagerService extends SystemService implements EnabledComponentChangeListener{ 91dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 92dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk public static final String TAG = "VrManagerService"; 93dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 94c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager"; 95c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 96b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private static final int PENDING_STATE_DELAY_MS = 300; 972ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private static final int EVENT_LOG_SIZE = 32; 98b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 99baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk private static native void initializeNative(); 100baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk private static native void setVrModeNative(boolean enabled); 101baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk 102dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk private final Object mLock = new Object(); 10347d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov 10447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov private final IBinder mOverlayToken = new Binder(); 10547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov 106e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // State protected by mLock 10798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean mVrModeEnabled; 108e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private EnabledComponentsObserver mComponentObserver; 109e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private ManagedApplicationService mCurrentVrService; 110e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private Context mContext; 111c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private ComponentName mCurrentVrModeComponent; 112c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private int mCurrentVrModeUser; 11398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean mWasDefaultGranted; 11498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean mGuard; 115c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks = 116c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk new RemoteCallbackList<>(); 11798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>(); 11898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private String mPreviousNotificationPolicyAccessPackage; 1190568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner private String mPreviousCoarseLocationPackage; 12098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private String mPreviousManageOverlayPackage; 121b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private VrState mPendingState; 1222ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE); 123e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 124c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private static final int MSG_VR_STATE_CHANGE = 0; 125b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private static final int MSG_PENDING_VR_STATE_CHANGE = 1; 126c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 127c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final Handler mHandler = new Handler() { 128c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk @Override 129c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void handleMessage(Message msg) { 130c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk switch(msg.what) { 131c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk case MSG_VR_STATE_CHANGE : { 132c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk boolean state = (msg.arg1 == 1); 133c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk int i = mRemoteCallbacks.beginBroadcast(); 134c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk while (i > 0) { 135c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk i--; 136c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk try { 137c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state); 138c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } catch (RemoteException e) { 139c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk // Noop 140c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 141c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 142c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.finishBroadcast(); 143c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } break; 144b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk case MSG_PENDING_VR_STATE_CHANGE : { 145b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk synchronized(mLock) { 146b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk VrManagerService.this.consumeAndApplyPendingStateLocked(); 147b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 148b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } break; 149c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk default : 150c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new IllegalStateException("Unknown message type: " + msg.what); 151c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 152c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 153c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk }; 154c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 155b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private static class VrState { 156b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final boolean enabled; 157b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final int userId; 158b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final ComponentName targetPackageName; 159b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final ComponentName callingPackage; 1602ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk final long timestamp; 1612ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk final boolean defaultPermissionsGranted; 162b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 163b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk VrState(boolean enabled, ComponentName targetPackageName, int userId, 164b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk ComponentName callingPackage) { 165b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.enabled = enabled; 166b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.userId = userId; 167b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.targetPackageName = targetPackageName; 168b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.callingPackage = callingPackage; 1692ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.defaultPermissionsGranted = false; 1702ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.timestamp = System.currentTimeMillis(); 171b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 1722ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk 1732ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk VrState(boolean enabled, ComponentName targetPackageName, int userId, 1742ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ComponentName callingPackage, boolean defaultPermissionsGranted) { 1752ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.enabled = enabled; 1762ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.userId = userId; 1772ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.targetPackageName = targetPackageName; 1782ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.callingPackage = callingPackage; 1792ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.defaultPermissionsGranted = defaultPermissionsGranted; 1802ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.timestamp = System.currentTimeMillis(); 1812ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 1822ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 183b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 184e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private static final BinderChecker sBinderChecker = new BinderChecker() { 185e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 186e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public IInterface asInterface(IBinder binder) { 187e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return IVrListener.Stub.asInterface(binder); 188e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 189e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 190e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 191e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public boolean checkType(IInterface service) { 192e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return service instanceof IVrListener; 193e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 194e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk }; 195e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 196e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 197e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Called when a user, package, or setting changes that could affect whether or not the 198e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * currently bound VrListenerService is changed. 199e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 200e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 201e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onEnabledComponentChanged() { 202e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 203e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mCurrentVrService == null) { 204e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return; // No active services 205e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 206e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 207b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk // If there is a pending state change, we'd better deal with that first 208b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk consumeAndApplyPendingStateLocked(); 209b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 210b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (mCurrentVrService == null) { 211b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk return; // No active services 212b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 213b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 214e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // There is an active service, update it if needed 215e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(), 216c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mCurrentVrService.getUserId(), null); 217e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 218e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 219dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 220c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final IVrManager mVrManager = new IVrManager.Stub() { 221c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 222dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 223c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void registerListener(IVrStateCallbacks cb) { 224c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); 225c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk if (cb == null) { 226c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new IllegalArgumentException("Callback binder object is null."); 227c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 228c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 229c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk VrManagerService.this.addStateCallback(cb); 230dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 231dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 232dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 233c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void unregisterListener(IVrStateCallbacks cb) { 234c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); 235c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk if (cb == null) { 236c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new IllegalArgumentException("Callback binder object is null."); 237c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 238c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 239c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk VrManagerService.this.removeStateCallback(cb); 240dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 241dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 242dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 243c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public boolean getVrModeState() { 244c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return VrManagerService.this.getVrMode(); 245c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 246c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 247dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler @Override 248dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 249dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 250dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler != PackageManager.PERMISSION_GRANTED) { 251dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler pw.println("permission denied: can't dump VrManagerService from pid=" 252dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 253dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler return; 254dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler } 2552ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("********* Dump of VrManagerService *********"); 2562ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Previous state transitions:\n"); 2572ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk String tab = " "; 2582ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk dumpStateTransitions(pw); 2592ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("\n\nRemote Callbacks:"); 260dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array 261dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler while(i-->0) { 2622ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 263dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler pw.print(mRemoteCallbacks.getBroadcastItem(i)); 2642ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (i>0) pw.println(","); 265dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler } 266dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler mRemoteCallbacks.finishBroadcast(); 2672ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("\n"); 2682ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Installed VrListenerService components:"); 2692ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk int userId = mCurrentVrModeUser; 2702ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId); 2712ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (installed == null || installed.size() == 0) { 2722ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("None"); 2732ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } else { 2742ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk for (ComponentName n : installed) { 2752ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 2762ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println(n.flattenToString()); 2772ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 2782ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 2792ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Enabled VrListenerService components:"); 2802ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId); 2812ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (enabled == null || enabled.size() == 0) { 2822ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("None"); 2832ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } else { 2842ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk for (ComponentName n : enabled) { 2852ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 2862ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println(n.flattenToString()); 2872ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 2882ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 2892ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("\n"); 2902ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("********* End of VrManagerService Dump *********"); 291dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler } 292dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler 293c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk }; 294c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 295c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private void enforceCallerPermission(String permission) { 296c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk if (mContext.checkCallingOrSelfPermission(permission) 297c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk != PackageManager.PERMISSION_GRANTED) { 298c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new SecurityException("Caller does not hold the permission " + permission); 2998f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 300c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 3018f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk 302c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk /** 303c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk * Implementation of VrManagerInternal. Callable only from system services. 304c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk */ 305c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final class LocalService extends VrManagerInternal { 3068f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk @Override 307c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void setVrMode(boolean enabled, ComponentName packageName, int userId, 308c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk ComponentName callingPackage) { 309c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage); 310dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 311dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 312dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 313c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public boolean isCurrentVrListener(String packageName, int userId) { 314c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return VrManagerService.this.isCurrentVrListener(packageName, userId); 315dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 316e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 317e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 318e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public int hasVrPackage(ComponentName packageName, int userId) { 319e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return VrManagerService.this.hasVrPackage(packageName, userId); 320e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 321dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 322dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 323dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk public VrManagerService(Context context) { 324dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk super(context); 325dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 326dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 327dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 328dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk public void onStart() { 329baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk synchronized(mLock) { 330baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk initializeNative(); 331e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext = getContext(); 332baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk } 333baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk 334dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk publishLocalService(VrManagerInternal.class, new LocalService()); 335c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder()); 3369906259202819794dd3ab1f60813f0c34e412efbCraig Donner 3379906259202819794dd3ab1f60813f0c34e412efbCraig Donner // If there are no VR packages installed on the device, then disable VR 3389906259202819794dd3ab1f60813f0c34e412efbCraig Donner // components, otherwise, enable them. 3399906259202819794dd3ab1f60813f0c34e412efbCraig Donner setEnabledStatusOfVrComponents(); 3409906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3419906259202819794dd3ab1f60813f0c34e412efbCraig Donner 3429906259202819794dd3ab1f60813f0c34e412efbCraig Donner private void setEnabledStatusOfVrComponents() { 3439906259202819794dd3ab1f60813f0c34e412efbCraig Donner ArraySet<ComponentName> vrComponents = SystemConfig.getInstance().getDefaultVrComponents(); 3449906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (vrComponents == null) { 3459906259202819794dd3ab1f60813f0c34e412efbCraig Donner return; 3469906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3479906259202819794dd3ab1f60813f0c34e412efbCraig Donner 3489906259202819794dd3ab1f60813f0c34e412efbCraig Donner // We only want to enable VR components if there is a VR package installed on the device. 3499906259202819794dd3ab1f60813f0c34e412efbCraig Donner // The VR components themselves do not quality as a VR package, so exclude them. 3509906259202819794dd3ab1f60813f0c34e412efbCraig Donner ArraySet<String> vrComponentPackageNames = new ArraySet<>(); 3519906259202819794dd3ab1f60813f0c34e412efbCraig Donner for (ComponentName componentName : vrComponents) { 3529906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames.add(componentName.getPackageName()); 3539906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3549906259202819794dd3ab1f60813f0c34e412efbCraig Donner 3559906259202819794dd3ab1f60813f0c34e412efbCraig Donner // Check to see if there are any packages on the device, other than the VR component 3569906259202819794dd3ab1f60813f0c34e412efbCraig Donner // packages. 3579906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager pm = mContext.getPackageManager(); 3589906259202819794dd3ab1f60813f0c34e412efbCraig Donner List<PackageInfo> packageInfos = pm.getInstalledPackages( 3599906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager.GET_CONFIGURATIONS); 3609906259202819794dd3ab1f60813f0c34e412efbCraig Donner boolean vrModeIsUsed = false; 3619906259202819794dd3ab1f60813f0c34e412efbCraig Donner for (PackageInfo packageInfo : packageInfos) { 3629906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (packageInfo != null && packageInfo.packageName != null && 3639906259202819794dd3ab1f60813f0c34e412efbCraig Donner pm.getApplicationEnabledSetting(packageInfo.packageName) == 3649906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 3659906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrModeIsUsed = enableVrComponentsIfVrModeUsed(pm, packageInfo, 3669906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames, vrComponents); 3679906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (vrModeIsUsed) { 3689906259202819794dd3ab1f60813f0c34e412efbCraig Donner break; 3699906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3709906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3719906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3729906259202819794dd3ab1f60813f0c34e412efbCraig Donner 3739906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (!vrModeIsUsed) { 3749906259202819794dd3ab1f60813f0c34e412efbCraig Donner Slog.i(TAG, "No VR packages found, disabling VR components"); 375672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner setVrComponentsEnabledOrDisabled(vrComponents, false); 3769906259202819794dd3ab1f60813f0c34e412efbCraig Donner 3779906259202819794dd3ab1f60813f0c34e412efbCraig Donner // Register to receive an intent when a new package is installed, in case that package 3789906259202819794dd3ab1f60813f0c34e412efbCraig Donner // requires VR components. 3799906259202819794dd3ab1f60813f0c34e412efbCraig Donner IntentFilter intentFilter = new IntentFilter(); 3809906259202819794dd3ab1f60813f0c34e412efbCraig Donner intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 3819906259202819794dd3ab1f60813f0c34e412efbCraig Donner intentFilter.addDataScheme("package"); 3829906259202819794dd3ab1f60813f0c34e412efbCraig Donner mContext.registerReceiver(new BroadcastReceiver() { 3839906259202819794dd3ab1f60813f0c34e412efbCraig Donner @Override 3849906259202819794dd3ab1f60813f0c34e412efbCraig Donner public void onReceive(Context context, Intent intent) { 3859906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager pm = context.getPackageManager(); 3869906259202819794dd3ab1f60813f0c34e412efbCraig Donner final String packageName = intent.getData().getSchemeSpecificPart(); 3879906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (packageName != null) { 3889906259202819794dd3ab1f60813f0c34e412efbCraig Donner try { 3899906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageInfo packageInfo = pm.getPackageInfo(packageName, 3909906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager.GET_CONFIGURATIONS); 3919906259202819794dd3ab1f60813f0c34e412efbCraig Donner enableVrComponentsIfVrModeUsed(pm, packageInfo, 3929906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames, vrComponents); 3939906259202819794dd3ab1f60813f0c34e412efbCraig Donner } catch (NameNotFoundException e) { 3949906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3959906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3969906259202819794dd3ab1f60813f0c34e412efbCraig Donner }; 3979906259202819794dd3ab1f60813f0c34e412efbCraig Donner }, intentFilter); 3989906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 3999906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4009906259202819794dd3ab1f60813f0c34e412efbCraig Donner 401672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner private void setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents, 402672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner boolean enabled) { 403672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner int state = enabled ? 404672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 405672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 406672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager pm = mContext.getPackageManager(); 407672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner for (ComponentName componentName : vrComponents) { 408672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner try { 409672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // Note that we must first check for the existance of the package before trying 410672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // to set its enabled state. This is to prevent PackageManager from throwing 411672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // an excepton if the package is not found (not just a NameNotFoundException 412672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // exception). 413672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageInfo packageInfo = pm.getPackageInfo(componentName.getPackageName(), 414672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager.GET_CONFIGURATIONS); 415672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner pm.setApplicationEnabledSetting(componentName.getPackageName(), state , 0); 416672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } catch (NameNotFoundException e) { 417672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } 418672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } 419672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } 420672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner 4219906259202819794dd3ab1f60813f0c34e412efbCraig Donner private boolean enableVrComponentsIfVrModeUsed(PackageManager pm, PackageInfo packageInfo, 4229906259202819794dd3ab1f60813f0c34e412efbCraig Donner ArraySet<String> vrComponentPackageNames, ArraySet<ComponentName> vrComponents) { 4239906259202819794dd3ab1f60813f0c34e412efbCraig Donner boolean isVrComponent = vrComponents != null && 4249906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames.contains(packageInfo.packageName); 4259906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (packageInfo != null && packageInfo.reqFeatures != null && !isVrComponent) { 4269906259202819794dd3ab1f60813f0c34e412efbCraig Donner for (FeatureInfo featureInfo : packageInfo.reqFeatures) { 4279906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (featureInfo.name != null && 4289906259202819794dd3ab1f60813f0c34e412efbCraig Donner (featureInfo.name.equals(PackageManager.FEATURE_VR_MODE) || 4299906259202819794dd3ab1f60813f0c34e412efbCraig Donner featureInfo.name.equals(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE))) { 4309906259202819794dd3ab1f60813f0c34e412efbCraig Donner Slog.i(TAG, "VR package found, enabling VR components"); 431672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner setVrComponentsEnabledOrDisabled(vrComponents, true); 4329906259202819794dd3ab1f60813f0c34e412efbCraig Donner return true; 4339906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4349906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4359906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4369906259202819794dd3ab1f60813f0c34e412efbCraig Donner return false; 437dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 438dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 439e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 440e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onBootPhase(int phase) { 4418507004a35a94e9bb4653dc049505aa54d1e6175Ruben Brunk if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 442e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 443e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Looper looper = Looper.getMainLooper(); 444e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Handler handler = new Handler(looper); 445e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>(); 446e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk listeners.add(this); 447e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver = EnabledComponentsObserver.build(mContext, handler, 448e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Settings.Secure.ENABLED_VR_LISTENERS, looper, 449e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk android.Manifest.permission.BIND_VR_LISTENER_SERVICE, 450e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk VrListenerService.SERVICE_INTERFACE, mLock, listeners); 451e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 452e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.rebuildAll(); 453e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 454e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 455e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 456e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 457e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 458e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onStartUser(int userHandle) { 459dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk synchronized (mLock) { 460e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 461dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 462dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 463dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 464e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 465e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onSwitchUser(int userHandle) { 466dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk synchronized (mLock) { 467e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 468e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 469e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 470e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 471e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 472e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 473e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onStopUser(int userHandle) { 474e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 475e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 476dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 477e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 478dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 479dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 480e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 481e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onCleanupUser(int userHandle) { 482dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk synchronized (mLock) { 483e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 484dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 485dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 486dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 48729931bc684bde6b430923122777684178ee2681cRuben Brunk private void updateOverlayStateLocked(ComponentName exemptedComponent) { 48847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 48947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov try { 49047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class); 49147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov if (appOpsManager != null) { 49229931bc684bde6b430923122777684178ee2681cRuben Brunk String[] exemptions = (exemptedComponent == null) ? new String[0] : 49329931bc684bde6b430923122777684178ee2681cRuben Brunk new String[] { exemptedComponent.getPackageName() }; 49429931bc684bde6b430923122777684178ee2681cRuben Brunk 49547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, 49629931bc684bde6b430923122777684178ee2681cRuben Brunk mVrModeEnabled, mOverlayToken, exemptions); 49747d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } 49847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } finally { 49947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov Binder.restoreCallingIdentity(identity); 50047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } 50147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } 50247d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov 503e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 504e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of 505e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * the currently selected VR listener service. If the component selected for the VR listener 506e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * service has changed, unbind the previous listener and bind the new listener (if enabled). 507e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 508e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Note: Must be called while holding {@code mLock}. 509e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 510e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param enabled new state for VR mode. 511e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param component new component to be bound as a VR listener. 512e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param userId user owning the component to be bound. 513c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk * @param calling the component currently using VR mode, or null to leave unchanged. 514e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 515e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return {@code true} if the component/user combination specified is valid. 516e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 51798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component, 51898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk int userId, ComponentName calling) { 519c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 520c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk boolean sendUpdatedCaller = false; 52198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk final long identity = Binder.clearCallingIdentity(); 52298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk try { 523e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 52498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk boolean validUserComponent = (mComponentObserver.isValid(component, userId) == 52598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk EnabledComponentsObserver.NO_ERROR); 5262ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (!mVrModeEnabled && !enabled) { 5272ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk return validUserComponent; // Disabled -> Disabled transition does nothing. 5282ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 529e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 53098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Always send mode change events. 53198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null); 53229931bc684bde6b430923122777684178ee2681cRuben Brunk 53398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!enabled || !validUserComponent) { 53498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Unbind whatever is running 53598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService != null) { 536c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " + 53798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService.getUserId()); 53898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService.disconnect(); 53998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk disableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 54098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk new UserHandle(mCurrentVrService.getUserId())); 54198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService = null; 54298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 54398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } else { 54498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService != null) { 54598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Unbind any running service that doesn't match the component/user selection 54698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService.disconnectIfNotMatching(component, userId)) { 54798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + 54898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk " for user " + mCurrentVrService.getUserId()); 54998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk disableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 55098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk new UserHandle(mCurrentVrService.getUserId())); 55198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk createAndConnectService(component, userId); 55298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk enableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 55398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk new UserHandle(mCurrentVrService.getUserId())); 55498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk sendUpdatedCaller = true; 55598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 55698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // The service with the correct component/user is bound 55798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } else { 55898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Nothing was previously running, bind a new service 559c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk createAndConnectService(component, userId); 56098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk enableImpliedPermissionsLocked(mCurrentVrService.getComponent(), 56198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk new UserHandle(mCurrentVrService.getUserId())); 562c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk sendUpdatedCaller = true; 563c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 56498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 56598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 56698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) { 56798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrModeComponent = calling; 56898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrModeUser = userId; 569c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk sendUpdatedCaller = true; 570e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 57198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 57298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService != null && sendUpdatedCaller) { 57398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk final ComponentName c = mCurrentVrModeComponent; 57498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService.sendEvent(new PendingEvent() { 57598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk @Override 57698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk public void runEvent(IInterface service) throws RemoteException { 57798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk IVrListener l = (IVrListener) service; 57898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk l.focusedActivityChanged(c); 57998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 58098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk }); 58198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 5822ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk logStateLocked(); 58398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 58498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return validUserComponent; 58598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } finally { 58698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Binder.restoreCallingIdentity(identity); 587c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 58898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 589c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 59098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk /** 59198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * Enable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given 59298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * component package and user. 59398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * 59498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * @param component the component whose package should be enabled. 59598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * @param userId the user that owns the given component. 59698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk */ 59798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void enableImpliedPermissionsLocked(ComponentName component, UserHandle userId) { 59898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mGuard) { 59998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Impossible 60098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk throw new IllegalStateException("Enabling permissions without disabling."); 601c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 60298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mGuard = true; 603c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 60498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk PackageManager pm = mContext.getPackageManager(); 60598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 60698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String pName = component.getPackageName(); 60798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (pm == null) { 60898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Slog.e(TAG, "Couldn't set implied permissions for " + pName + 60998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ", PackageManager isn't running"); 61098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return; 611e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 612e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 61398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ApplicationInfo info = null; 61498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk try { 61598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA); 61698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } catch (NameNotFoundException e) { 61798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 61898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 61998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (info == null) { 62098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package."); 62198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return; 62298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 62398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 62498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!(info.isSystemApp() || info.isUpdatedSystemApp())) { 62598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return; // Application is not pre-installed, avoid setting implied permissions 62698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 62798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 62898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mWasDefaultGranted = true; 62998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 6300568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner grantCoarseLocationAccess(pName, userId); 63198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk grantOverlayAccess(pName, userId); 63298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk grantNotificationPolicyAccess(pName); 63398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk grantNotificationListenerAccess(pName, userId); 634e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 635e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 63698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk /** 63798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * Disable the permission given in {@link #IMPLIED_VR_LISTENER_PERMISSIONS} for the given 63898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * component package and user. 63998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * 64098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * @param component the component whose package should be disabled. 64198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * @param userId the user that owns the given component. 64298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk */ 64398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void disableImpliedPermissionsLocked(ComponentName component, UserHandle userId) { 64498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!mGuard) { 64598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Impossible 64698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk throw new IllegalStateException("Disabling permissions without enabling."); 64798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 64898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mGuard = false; 64998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 65098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk PackageManager pm = mContext.getPackageManager(); 65198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 65298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (pm == null) { 65398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Slog.e(TAG, "Couldn't remove implied permissions for " + component + 65498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ", PackageManager isn't running"); 65598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return; 65698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 65798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 65898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String pName = component.getPackageName(); 65998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mWasDefaultGranted) { 6600568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner revokeCoarseLocationAccess(userId); 66198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk revokeOverlayAccess(userId); 66298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk revokeNotificationPolicyAccess(pName); 66398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk revokeNotificiationListenerAccess(); 66498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mWasDefaultGranted = false; 66598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 66698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 66798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 66898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 6690568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner private void grantCoarseLocationAccess(String pkg, UserHandle userId) { 6700568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner PackageManager pm = mContext.getPackageManager(); 6710568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner boolean prev = (PackageManager.PERMISSION_GRANTED == 6720568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner pm.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, pkg)); 6730568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner mPreviousCoarseLocationPackage = null; 6740568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner if (!prev) { 6750568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION, 6760568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner userId); 6770568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner mPreviousCoarseLocationPackage = pkg; 6780568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner } 6790568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner } 6800568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner 6810568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner private void revokeCoarseLocationAccess(UserHandle userId) { 6820568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner PackageManager pm = mContext.getPackageManager(); 6830568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner if (mPreviousCoarseLocationPackage != null) { 6840568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner pm.revokeRuntimePermission(mPreviousCoarseLocationPackage, 6850568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner android.Manifest.permission.ACCESS_COARSE_LOCATION, userId); 6860568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner mPreviousCoarseLocationPackage = null; 6870568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner } 6880568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner } 6890568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner 69098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void grantOverlayAccess(String pkg, UserHandle userId) { 69198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk PackageManager pm = mContext.getPackageManager(); 69298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk boolean prev = (PackageManager.PERMISSION_GRANTED == 69398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg)); 69498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousManageOverlayPackage = null; 69598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!prev) { 69698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW, 69798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk userId); 69898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousManageOverlayPackage = pkg; 69998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 70098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 70198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 70298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void revokeOverlayAccess(UserHandle userId) { 70398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk PackageManager pm = mContext.getPackageManager(); 70498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mPreviousManageOverlayPackage != null) { 70598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk pm.revokeRuntimePermission(mPreviousManageOverlayPackage, 70698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId); 70798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousManageOverlayPackage = null; 70898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 70998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 71098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 71198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void grantNotificationPolicyAccess(String pkg) { 71298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk NotificationManager nm = mContext.getSystemService(NotificationManager.class); 71398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg); 71498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousNotificationPolicyAccessPackage = null; 71598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!prev) { 71698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousNotificationPolicyAccessPackage = pkg; 71798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk nm.setNotificationPolicyAccessGranted(pkg, true); 71898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 71998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 72098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 72198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void revokeNotificationPolicyAccess(String pkg) { 72298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk NotificationManager nm = mContext.getSystemService(NotificationManager.class); 72398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mPreviousNotificationPolicyAccessPackage != null) { 7240c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) { 7250c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott // Remove any DND zen rules possibly created by the package. 7260c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage); 7270c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott // Remove Notification Policy Access. 7280c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false); 7290c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott mPreviousNotificationPolicyAccessPackage = null; 7300c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott } else { 7310c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg); 7320c9ac648190a3f0e850d4fe376002f7a11654a87Ariana Mott } 73398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 73498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 73598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 73698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void grantNotificationListenerAccess(String pkg, UserHandle userId) { 73798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk PackageManager pm = mContext.getPackageManager(); 73898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm, 73998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE, 74098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); 74198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ContentResolver resolver = mContext.getContentResolver(); 74298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 74398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ArraySet<String> current = getCurrentNotifListeners(resolver); 74498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 74598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousToggledListenerSettings.clear(); 74698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 74798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk for (ComponentName c : possibleServices) { 74898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flatName = c.flattenToString(); 74998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (Objects.equals(c.getPackageName(), pkg) 75098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk && !current.contains(flatName)) { 75198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousToggledListenerSettings.add(flatName); 75298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk current.add(flatName); 75398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 75498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 75598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 75698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (current.size() > 0) { 75798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flatSettings = formatSettings(current); 75898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, 75998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk flatSettings); 76098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 76198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 76298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 76398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void revokeNotificiationListenerAccess() { 76498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mPreviousToggledListenerSettings.isEmpty()) { 76598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return; 76698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 76798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 76898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ContentResolver resolver = mContext.getContentResolver(); 76998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ArraySet<String> current = getCurrentNotifListeners(resolver); 77098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 77198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk current.removeAll(mPreviousToggledListenerSettings); 77298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mPreviousToggledListenerSettings.clear(); 77398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 77498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flatSettings = formatSettings(current); 77598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, 77698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk flatSettings); 77798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 77898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 77998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) { 78098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flat = Settings.Secure.getString(resolver, 78198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Settings.Secure.ENABLED_NOTIFICATION_LISTENERS); 78298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 78398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ArraySet<String> current = new ArraySet<>(); 78498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (flat != null) { 78598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String[] allowed = flat.split(":"); 78698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk for (String s : allowed) { 78798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk current.add(s); 78898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 78998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 79098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return current; 79198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 79298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 79398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private static String formatSettings(Collection<String> c) { 79498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (c == null || c.isEmpty()) { 79598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return ""; 79698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 79798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 79898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk StringBuilder b = new StringBuilder(); 79998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk boolean start = true; 80098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk for (String s : c) { 80198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if ("".equals(s)) { 80298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk continue; 80398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 80498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!start) { 80598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk b.append(':'); 80698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 80798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk b.append(s); 80898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk start = false; 80998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 81098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return b.toString(); 81198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 81298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 81398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 81498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 815c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private void createAndConnectService(@NonNull ComponentName component, int userId) { 816c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mCurrentVrService = VrManagerService.create(mContext, component, userId); 817c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mCurrentVrService.connect(); 818c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk Slog.i(TAG, "Connecting " + component + " for user " + userId); 819c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 820c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 821e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 822e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Send VR mode change callbacks to HAL and system services if mode has actually changed. 823e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 824e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Note: Must be called while holding {@code mLock}. 825e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 826e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param enabled new state of the VR mode. 82729931bc684bde6b430923122777684178ee2681cRuben Brunk * @param exemptedComponent a component to exempt from AppOps restrictions for overlays. 828e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 82929931bc684bde6b430923122777684178ee2681cRuben Brunk private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) { 830e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mVrModeEnabled != enabled) { 831e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mVrModeEnabled = enabled; 832e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 833e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // Log mode change event. 834e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled")); 835e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk setVrModeNative(mVrModeEnabled); 836e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 83729931bc684bde6b430923122777684178ee2681cRuben Brunk updateOverlayStateLocked(exemptedComponent); 838e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk onVrModeChangedLocked(); 839dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 840dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 841dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 842dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk /** 843dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Notify system services of VR mode change. 844e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 845e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Note: Must be called while holding {@code mLock}. 846dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */ 847dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk private void onVrModeChangedLocked() { 848c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE, 849c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk (mVrModeEnabled) ? 1 : 0, 0)); 850dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 851e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 852e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 853e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Helper function for making ManagedApplicationService instances. 854e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 855e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private static ManagedApplicationService create(@NonNull Context context, 856e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @NonNull ComponentName component, int userId) { 857e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return ManagedApplicationService.build(context, component, userId, 858e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS, 859e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk sBinderChecker); 860e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 861e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 862b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private void consumeAndApplyPendingStateLocked() { 863b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (mPendingState != null) { 864b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk updateCurrentVrServiceLocked(mPendingState.enabled, 865b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState.targetPackageName, mPendingState.userId, 866b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState.callingPackage); 867b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState = null; 868b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 869b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 870b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 8712ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private void logStateLocked() { 8722ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ComponentName currentBoundService = (mCurrentVrService == null) ? null : 8732ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mCurrentVrService.getComponent(); 8742ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser, 8752ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mCurrentVrModeComponent, mWasDefaultGranted); 8762ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (mLoggingDeque.size() == EVENT_LOG_SIZE) { 8772ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mLoggingDeque.removeFirst(); 8782ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8792ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mLoggingDeque.add(current); 8802ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8812ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk 8822ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private void dumpStateTransitions(PrintWriter pw) { 8832ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); 8842ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk String tab = " "; 8852ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (mLoggingDeque.size() == 0) { 8862ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8872ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("None"); 8882ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8892ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk for (VrState state : mLoggingDeque) { 8902ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(d.format(new Date(state.timestamp))); 8912ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8922ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("State changed to:"); 8932ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8942ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println((state.enabled) ? "ENABLED" : "DISABLED"); 8952ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (state.enabled) { 8962ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8972ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("User="); 8982ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println(state.userId); 8992ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 9002ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("Current VR Activity="); 9012ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println((state.callingPackage == null) ? 9022ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk "None" : state.callingPackage.flattenToString()); 9032ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 9042ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("Bound VrListenerService="); 9052ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println((state.targetPackageName == null) ? 9062ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk "None" : state.targetPackageName.flattenToString()); 9072ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (state.defaultPermissionsGranted) { 9082ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 9092ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Default permissions granted to the bound VrListenerService."); 9102ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 9112ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 9122ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 9132ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 9142ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk 915e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /* 916e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Implementation of VrManagerInternal calls. These are callable from system services. 917e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 918e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 919b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName, 920c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk int userId, @NonNull ComponentName callingPackage) { 921b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 922e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 923b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 924b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (!enabled && mCurrentVrService != null) { 925b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls 926b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk // and service bind/unbind in case we are immediately switching to another VR app. 927b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (mPendingState == null) { 928b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE, 929b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk PENDING_STATE_DELAY_MS); 930b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 931b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 932b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState = new VrState(enabled, targetPackageName, userId, callingPackage); 933b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk return; 934b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } else { 935b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE); 936b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState = null; 937b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 938b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 939b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage); 940e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 941e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 942e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 943c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) { 944e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 945c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return mComponentObserver.isValid(targetPackageName, userId); 946e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 947e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 948e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 9498f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk private boolean isCurrentVrListener(String packageName, int userId) { 9508f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk synchronized (mLock) { 9518f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk if (mCurrentVrService == null) { 9528f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk return false; 9538f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 9548f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk return mCurrentVrService.getComponent().getPackageName().equals(packageName) && 9558f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk userId == mCurrentVrService.getUserId(); 9568f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 9578f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 9588f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk 959c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk /* 960c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk * Implementation of IVrManager calls. 961c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk */ 962c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 963c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private void addStateCallback(IVrStateCallbacks cb) { 964c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.register(cb); 965e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 966e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 967c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private void removeStateCallback(IVrStateCallbacks cb) { 968c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.unregister(cb); 969e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 970e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 971c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private boolean getVrMode() { 972e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 973c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return mVrModeEnabled; 974e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 975e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 976dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk} 977