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; 198820f943e0254e188861ef4bc73a95cefc648942Ruben Brunkimport android.app.ActivityManager; 2047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.app.AppOpsManager; 2198576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.app.NotificationManager; 22e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.annotation.NonNull; 239906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.BroadcastReceiver; 24e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.content.ComponentName; 2598576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.ContentResolver; 2698576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.Context; 279906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.Intent; 289906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.IntentFilter; 2998576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.ApplicationInfo; 309906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.pm.FeatureInfo; 319906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport android.content.pm.PackageInfo; 3298576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager; 3398576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.content.pm.PackageManager.NameNotFoundException; 3447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.Binder; 35e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Handler; 3647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganovimport android.os.IBinder; 37e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.IInterface; 38e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.os.Looper; 39c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.os.Message; 40c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.os.RemoteCallbackList; 41c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport android.os.RemoteException; 4298576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.os.UserHandle; 43e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.provider.Settings; 4498576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport android.service.notification.NotificationListenerService; 45e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.IVrListener; 46c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.service.vr.IVrManager; 47c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunkimport android.service.vr.IVrStateCallbacks; 48e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport android.service.vr.VrListenerService; 49e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganovimport android.util.ArrayMap; 50dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.ArraySet; 51dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport android.util.Slog; 528820f943e0254e188861ef4bc73a95cefc648942Ruben Brunkimport android.util.SparseArray; 53e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.internal.R; 54e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganovimport com.android.server.LocalServices; 559906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport com.android.server.SystemConfig; 56dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport com.android.server.SystemService; 57c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport com.android.server.utils.ManagedApplicationService.PendingEvent; 58e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener; 59e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService; 60e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkimport com.android.server.utils.ManagedApplicationService.BinderChecker; 61dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 62dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandlerimport java.io.FileDescriptor; 63dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandlerimport java.io.PrintWriter; 6498576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.lang.StringBuilder; 652ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunkimport java.text.SimpleDateFormat; 662ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunkimport java.util.ArrayDeque; 67dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunkimport java.util.ArrayList; 6898576cf949a1ffbece3722451713aac01ed27968Ruben Brunkimport java.util.Collection; 692ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunkimport java.util.Date; 709906259202819794dd3ab1f60813f0c34e412efbCraig Donnerimport java.util.List; 71e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganovimport java.util.Map; 72c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunkimport java.util.Objects; 73dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 74dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk/** 75e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Service tracking whether VR mode is active, and notifying listening services of state changes. 76e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 77e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Services running in system server may modify the state of VrManagerService via the interface in 78e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the 79e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * interface given in VrStateListener. 80e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 81e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.: 82e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * hardware/libhardware/modules/vr 83e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 84e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * In general applications may enable or disable VR mode by calling 8598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to 8698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}. 87e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 88e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link android.service.vr.VrListenerService} 89e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrManagerInternal} 90e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @see {@link com.android.server.vr.VrStateListener} 91dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * 92e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @hide 93dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */ 94e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunkpublic class VrManagerService extends SystemService implements EnabledComponentChangeListener{ 95dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 96dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk public static final String TAG = "VrManagerService"; 97dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 98c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager"; 99c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 100b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private static final int PENDING_STATE_DELAY_MS = 300; 1012ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private static final int EVENT_LOG_SIZE = 32; 1028820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private static final int INVALID_APPOPS_MODE = -1; 103b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 104baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk private static native void initializeNative(); 105baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk private static native void setVrModeNative(boolean enabled); 106baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk 107dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk private final Object mLock = new Object(); 10847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov 10947d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov private final IBinder mOverlayToken = new Binder(); 11047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov 111e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // State protected by mLock 11298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean mVrModeEnabled; 113e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private EnabledComponentsObserver mComponentObserver; 114e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private ManagedApplicationService mCurrentVrService; 115e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private Context mContext; 116c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private ComponentName mCurrentVrModeComponent; 117c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private int mCurrentVrModeUser; 11898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean mWasDefaultGranted; 11998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean mGuard; 120c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks = 121c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk new RemoteCallbackList<>(); 1228820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE; 1238820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE; 124b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private VrState mPendingState; 1252ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE); 1268820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager(); 127e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 128c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private static final int MSG_VR_STATE_CHANGE = 0; 129b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private static final int MSG_PENDING_VR_STATE_CHANGE = 1; 130c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 131c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final Handler mHandler = new Handler() { 132c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk @Override 133c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void handleMessage(Message msg) { 134c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk switch(msg.what) { 135c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk case MSG_VR_STATE_CHANGE : { 136c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk boolean state = (msg.arg1 == 1); 137c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk int i = mRemoteCallbacks.beginBroadcast(); 138c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk while (i > 0) { 139c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk i--; 140c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk try { 141c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state); 142c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } catch (RemoteException e) { 143c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk // Noop 144c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 145c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 146c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.finishBroadcast(); 147c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } break; 148b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk case MSG_PENDING_VR_STATE_CHANGE : { 149b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk synchronized(mLock) { 150b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk VrManagerService.this.consumeAndApplyPendingStateLocked(); 151b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 152b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } break; 153c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk default : 154c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new IllegalStateException("Unknown message type: " + msg.what); 155c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 156c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 157c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk }; 158c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 159b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private static class VrState { 160b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final boolean enabled; 161b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final int userId; 162b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final ComponentName targetPackageName; 163b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk final ComponentName callingPackage; 1642ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk final long timestamp; 1652ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk final boolean defaultPermissionsGranted; 166b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 167b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk VrState(boolean enabled, ComponentName targetPackageName, int userId, 168b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk ComponentName callingPackage) { 169b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.enabled = enabled; 170b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.userId = userId; 171b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.targetPackageName = targetPackageName; 172b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk this.callingPackage = callingPackage; 1732ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.defaultPermissionsGranted = false; 1742ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.timestamp = System.currentTimeMillis(); 175b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 1762ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk 1772ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk VrState(boolean enabled, ComponentName targetPackageName, int userId, 1782ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ComponentName callingPackage, boolean defaultPermissionsGranted) { 1792ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.enabled = enabled; 1802ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.userId = userId; 1812ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.targetPackageName = targetPackageName; 1822ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.callingPackage = callingPackage; 1832ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.defaultPermissionsGranted = defaultPermissionsGranted; 1842ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk this.timestamp = System.currentTimeMillis(); 1852ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 1862ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 187b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 188e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private static final BinderChecker sBinderChecker = new BinderChecker() { 189e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 190e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public IInterface asInterface(IBinder binder) { 191e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return IVrListener.Stub.asInterface(binder); 192e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 193e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 194e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 195e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public boolean checkType(IInterface service) { 196e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return service instanceof IVrListener; 197e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 198e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk }; 199e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 2008820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private final class NotificationAccessManager { 2018820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>(); 202e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId = 203e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov new ArrayMap<>(); 2048820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 2058820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk public void update(Collection<String> packageNames) { 2068820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk int currentUserId = ActivityManager.getCurrentUser(); 2078820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 2088820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk ArraySet<String> allowed = mAllowedPackages.get(currentUserId); 2098820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk if (allowed == null) { 2108820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk allowed = new ArraySet<>(); 2118820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2128820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 213e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // Make sure we revoke notification access for listeners in other users 214e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov final int listenerCount = mNotificationAccessPackageToUserId.size(); 215e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov for (int i = listenerCount - 1; i >= 0; i--) { 216e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i); 217e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov if (grantUserId != currentUserId) { 218e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov String packageName = mNotificationAccessPackageToUserId.keyAt(i); 219e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov revokeNotificationListenerAccess(packageName, grantUserId); 220e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov revokeNotificationPolicyAccess(packageName); 221e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov mNotificationAccessPackageToUserId.removeAt(i); 222e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 223e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 224e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 2258820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk for (String pkg : allowed) { 2268820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk if (!packageNames.contains(pkg)) { 227e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov revokeNotificationListenerAccess(pkg, currentUserId); 2288820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk revokeNotificationPolicyAccess(pkg); 229e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov mNotificationAccessPackageToUserId.remove(pkg); 2308820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2318820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2328820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk for (String pkg : packageNames) { 2338820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk if (!allowed.contains(pkg)) { 2348820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk grantNotificationPolicyAccess(pkg); 235e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov grantNotificationListenerAccess(pkg, currentUserId); 236e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov mNotificationAccessPackageToUserId.put(pkg, currentUserId); 2378820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2388820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2398820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 2408820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk allowed.clear(); 2418820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk allowed.addAll(packageNames); 2428820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk mAllowedPackages.put(currentUserId, allowed); 2438820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2448820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2458820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 246e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 247e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Called when a user, package, or setting changes that could affect whether or not the 248e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * currently bound VrListenerService is changed. 249e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 250e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 251e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onEnabledComponentChanged() { 252e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 2538820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk int currentUser = ActivityManager.getCurrentUser(); 2548820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 2558820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk // Update listeners 2568820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser); 2578820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 2588820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk ArraySet<String> enabledPackages = new ArraySet<>(); 2598820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk for (ComponentName n : enabledListeners) { 2608820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk String pkg = n.getPackageName(); 2618820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk if (isDefaultAllowed(pkg)) { 2628820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk enabledPackages.add(n.getPackageName()); 2638820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2648820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 2658820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk mNotifAccessManager.update(enabledPackages); 2668820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 267e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mCurrentVrService == null) { 268e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return; // No active services 269e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 270e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 271b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk // If there is a pending state change, we'd better deal with that first 272b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk consumeAndApplyPendingStateLocked(); 273b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 274b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (mCurrentVrService == null) { 275b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk return; // No active services 276b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 277b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 278e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // There is an active service, update it if needed 279e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(), 280c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mCurrentVrService.getUserId(), null); 281e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 282e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 283dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 284c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final IVrManager mVrManager = new IVrManager.Stub() { 285c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 286dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 287c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void registerListener(IVrStateCallbacks cb) { 288c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); 289c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk if (cb == null) { 290c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new IllegalArgumentException("Callback binder object is null."); 291c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 292c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 293c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk VrManagerService.this.addStateCallback(cb); 294dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 295dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 296dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 297c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void unregisterListener(IVrStateCallbacks cb) { 298c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER); 299c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk if (cb == null) { 300c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new IllegalArgumentException("Callback binder object is null."); 301c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 302c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 303c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk VrManagerService.this.removeStateCallback(cb); 304dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 305dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 306dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 307c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public boolean getVrModeState() { 308c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return VrManagerService.this.getVrMode(); 309c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 310c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 311dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler @Override 312dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 313dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 314dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler != PackageManager.PERMISSION_GRANTED) { 315dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler pw.println("permission denied: can't dump VrManagerService from pid=" 316dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 317dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler return; 318dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler } 3192ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("********* Dump of VrManagerService *********"); 3202ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Previous state transitions:\n"); 3212ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk String tab = " "; 3222ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk dumpStateTransitions(pw); 3232ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("\n\nRemote Callbacks:"); 324dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array 325dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler while(i-->0) { 3262ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 327dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler pw.print(mRemoteCallbacks.getBroadcastItem(i)); 3282ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (i>0) pw.println(","); 329dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler } 330dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler mRemoteCallbacks.finishBroadcast(); 3312ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("\n"); 3322ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Installed VrListenerService components:"); 3332ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk int userId = mCurrentVrModeUser; 3342ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId); 3352ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (installed == null || installed.size() == 0) { 3362ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("None"); 3372ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } else { 3382ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk for (ComponentName n : installed) { 3392ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 3402ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println(n.flattenToString()); 3412ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 3422ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 3432ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Enabled VrListenerService components:"); 3442ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId); 3452ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (enabled == null || enabled.size() == 0) { 3462ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("None"); 3472ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } else { 3482ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk for (ComponentName n : enabled) { 3492ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 3502ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println(n.flattenToString()); 3512ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 3522ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 3532ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("\n"); 3542ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("********* End of VrManagerService Dump *********"); 355dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler } 356dc34df5d310245a268ee9ea3872a612c6f7950b5Dan Sandler 357c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk }; 358c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 359c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private void enforceCallerPermission(String permission) { 360c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk if (mContext.checkCallingOrSelfPermission(permission) 361c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk != PackageManager.PERMISSION_GRANTED) { 362c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk throw new SecurityException("Caller does not hold the permission " + permission); 3638f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 364c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk } 3658f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk 366c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk /** 367c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk * Implementation of VrManagerInternal. Callable only from system services. 368c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk */ 369c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private final class LocalService extends VrManagerInternal { 3708f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk @Override 371c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public void setVrMode(boolean enabled, ComponentName packageName, int userId, 372c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk ComponentName callingPackage) { 373af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, false); 374af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk } 375af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk 376af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk @Override 377af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk public void setVrModeImmediate(boolean enabled, ComponentName packageName, int userId, 378af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk ComponentName callingPackage) { 379af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, true); 380dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 381dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 382dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 383c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk public boolean isCurrentVrListener(String packageName, int userId) { 384c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return VrManagerService.this.isCurrentVrListener(packageName, userId); 385dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 386e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 387e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 388e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public int hasVrPackage(ComponentName packageName, int userId) { 389e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return VrManagerService.this.hasVrPackage(packageName, userId); 390e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 391dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 392dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 393dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk public VrManagerService(Context context) { 394dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk super(context); 395dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 396dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 397dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk @Override 398dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk public void onStart() { 399baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk synchronized(mLock) { 400baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk initializeNative(); 401e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mContext = getContext(); 402baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk } 403baa4b55b892041fc33f3acdf29de0676ab63c2f9Ruben Brunk 404dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk publishLocalService(VrManagerInternal.class, new LocalService()); 405c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder()); 4069906259202819794dd3ab1f60813f0c34e412efbCraig Donner 4079906259202819794dd3ab1f60813f0c34e412efbCraig Donner // If there are no VR packages installed on the device, then disable VR 4089906259202819794dd3ab1f60813f0c34e412efbCraig Donner // components, otherwise, enable them. 4099906259202819794dd3ab1f60813f0c34e412efbCraig Donner setEnabledStatusOfVrComponents(); 4109906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4119906259202819794dd3ab1f60813f0c34e412efbCraig Donner 4129906259202819794dd3ab1f60813f0c34e412efbCraig Donner private void setEnabledStatusOfVrComponents() { 4139906259202819794dd3ab1f60813f0c34e412efbCraig Donner ArraySet<ComponentName> vrComponents = SystemConfig.getInstance().getDefaultVrComponents(); 4149906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (vrComponents == null) { 4159906259202819794dd3ab1f60813f0c34e412efbCraig Donner return; 4169906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4179906259202819794dd3ab1f60813f0c34e412efbCraig Donner 4189906259202819794dd3ab1f60813f0c34e412efbCraig Donner // We only want to enable VR components if there is a VR package installed on the device. 4199906259202819794dd3ab1f60813f0c34e412efbCraig Donner // The VR components themselves do not quality as a VR package, so exclude them. 4209906259202819794dd3ab1f60813f0c34e412efbCraig Donner ArraySet<String> vrComponentPackageNames = new ArraySet<>(); 4219906259202819794dd3ab1f60813f0c34e412efbCraig Donner for (ComponentName componentName : vrComponents) { 4229906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames.add(componentName.getPackageName()); 4239906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4249906259202819794dd3ab1f60813f0c34e412efbCraig Donner 4259906259202819794dd3ab1f60813f0c34e412efbCraig Donner // Check to see if there are any packages on the device, other than the VR component 4269906259202819794dd3ab1f60813f0c34e412efbCraig Donner // packages. 4279906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager pm = mContext.getPackageManager(); 4289906259202819794dd3ab1f60813f0c34e412efbCraig Donner List<PackageInfo> packageInfos = pm.getInstalledPackages( 4299906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager.GET_CONFIGURATIONS); 4309906259202819794dd3ab1f60813f0c34e412efbCraig Donner boolean vrModeIsUsed = false; 4319906259202819794dd3ab1f60813f0c34e412efbCraig Donner for (PackageInfo packageInfo : packageInfos) { 4329906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (packageInfo != null && packageInfo.packageName != null && 4339906259202819794dd3ab1f60813f0c34e412efbCraig Donner pm.getApplicationEnabledSetting(packageInfo.packageName) == 4349906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { 4359906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrModeIsUsed = enableVrComponentsIfVrModeUsed(pm, packageInfo, 4369906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames, vrComponents); 4379906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (vrModeIsUsed) { 4389906259202819794dd3ab1f60813f0c34e412efbCraig Donner break; 4399906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4409906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4419906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4429906259202819794dd3ab1f60813f0c34e412efbCraig Donner 4439906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (!vrModeIsUsed) { 4449906259202819794dd3ab1f60813f0c34e412efbCraig Donner Slog.i(TAG, "No VR packages found, disabling VR components"); 445672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner setVrComponentsEnabledOrDisabled(vrComponents, false); 4469906259202819794dd3ab1f60813f0c34e412efbCraig Donner 4479906259202819794dd3ab1f60813f0c34e412efbCraig Donner // Register to receive an intent when a new package is installed, in case that package 4489906259202819794dd3ab1f60813f0c34e412efbCraig Donner // requires VR components. 4499906259202819794dd3ab1f60813f0c34e412efbCraig Donner IntentFilter intentFilter = new IntentFilter(); 4509906259202819794dd3ab1f60813f0c34e412efbCraig Donner intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 4519906259202819794dd3ab1f60813f0c34e412efbCraig Donner intentFilter.addDataScheme("package"); 4529906259202819794dd3ab1f60813f0c34e412efbCraig Donner mContext.registerReceiver(new BroadcastReceiver() { 4539906259202819794dd3ab1f60813f0c34e412efbCraig Donner @Override 4549906259202819794dd3ab1f60813f0c34e412efbCraig Donner public void onReceive(Context context, Intent intent) { 4559906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager pm = context.getPackageManager(); 4569906259202819794dd3ab1f60813f0c34e412efbCraig Donner final String packageName = intent.getData().getSchemeSpecificPart(); 4579906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (packageName != null) { 4589906259202819794dd3ab1f60813f0c34e412efbCraig Donner try { 4599906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageInfo packageInfo = pm.getPackageInfo(packageName, 4609906259202819794dd3ab1f60813f0c34e412efbCraig Donner PackageManager.GET_CONFIGURATIONS); 4619906259202819794dd3ab1f60813f0c34e412efbCraig Donner enableVrComponentsIfVrModeUsed(pm, packageInfo, 4629906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames, vrComponents); 4639906259202819794dd3ab1f60813f0c34e412efbCraig Donner } catch (NameNotFoundException e) { 4649906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4659906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4669906259202819794dd3ab1f60813f0c34e412efbCraig Donner }; 4679906259202819794dd3ab1f60813f0c34e412efbCraig Donner }, intentFilter); 4689906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4699906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 4709906259202819794dd3ab1f60813f0c34e412efbCraig Donner 471672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner private void setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents, 472672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner boolean enabled) { 473672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner int state = enabled ? 474672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager.COMPONENT_ENABLED_STATE_ENABLED : 475672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 476672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager pm = mContext.getPackageManager(); 477672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner for (ComponentName componentName : vrComponents) { 478672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner try { 479672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // Note that we must first check for the existance of the package before trying 480672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // to set its enabled state. This is to prevent PackageManager from throwing 481672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // an excepton if the package is not found (not just a NameNotFoundException 482672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner // exception). 483672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageInfo packageInfo = pm.getPackageInfo(componentName.getPackageName(), 484672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner PackageManager.GET_CONFIGURATIONS); 485672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner pm.setApplicationEnabledSetting(componentName.getPackageName(), state , 0); 486672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } catch (NameNotFoundException e) { 487672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } 488672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } 489672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner } 490672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner 4919906259202819794dd3ab1f60813f0c34e412efbCraig Donner private boolean enableVrComponentsIfVrModeUsed(PackageManager pm, PackageInfo packageInfo, 4929906259202819794dd3ab1f60813f0c34e412efbCraig Donner ArraySet<String> vrComponentPackageNames, ArraySet<ComponentName> vrComponents) { 4939906259202819794dd3ab1f60813f0c34e412efbCraig Donner boolean isVrComponent = vrComponents != null && 4949906259202819794dd3ab1f60813f0c34e412efbCraig Donner vrComponentPackageNames.contains(packageInfo.packageName); 4959906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (packageInfo != null && packageInfo.reqFeatures != null && !isVrComponent) { 4969906259202819794dd3ab1f60813f0c34e412efbCraig Donner for (FeatureInfo featureInfo : packageInfo.reqFeatures) { 4979906259202819794dd3ab1f60813f0c34e412efbCraig Donner if (featureInfo.name != null && 4989906259202819794dd3ab1f60813f0c34e412efbCraig Donner (featureInfo.name.equals(PackageManager.FEATURE_VR_MODE) || 4999906259202819794dd3ab1f60813f0c34e412efbCraig Donner featureInfo.name.equals(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE))) { 5009906259202819794dd3ab1f60813f0c34e412efbCraig Donner Slog.i(TAG, "VR package found, enabling VR components"); 501672afaa43b97d24c1f3aaf9722e53b70dbac8c54Craig Donner setVrComponentsEnabledOrDisabled(vrComponents, true); 5029906259202819794dd3ab1f60813f0c34e412efbCraig Donner return true; 5039906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 5049906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 5059906259202819794dd3ab1f60813f0c34e412efbCraig Donner } 5069906259202819794dd3ab1f60813f0c34e412efbCraig Donner return false; 507dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 508dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 509e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 510e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onBootPhase(int phase) { 5118507004a35a94e9bb4653dc049505aa54d1e6175Ruben Brunk if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 512e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 513e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Looper looper = Looper.getMainLooper(); 514e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Handler handler = new Handler(looper); 515e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>(); 516e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk listeners.add(this); 517e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver = EnabledComponentsObserver.build(mContext, handler, 518e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Settings.Secure.ENABLED_VR_LISTENERS, looper, 519e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk android.Manifest.permission.BIND_VR_LISTENER_SERVICE, 520e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk VrListenerService.SERVICE_INTERFACE, mLock, listeners); 521e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 522e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.rebuildAll(); 523e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 524e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 525e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 526e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 527e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 528e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onStartUser(int userHandle) { 529dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk synchronized (mLock) { 530e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 531dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 532dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 533dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 534e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 535e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onSwitchUser(int userHandle) { 536dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk synchronized (mLock) { 537e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 538e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 539e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 540e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 541e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 542e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 543e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onStopUser(int userHandle) { 544e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 545e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 546dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 547e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 548dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 549dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 550e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @Override 551e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk public void onCleanupUser(int userHandle) { 552dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk synchronized (mLock) { 553e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mComponentObserver.onUsersChanged(); 554dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 555dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 556dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 557e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) { 558e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class); 559e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 560e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // If user changed drop restrictions for the old user. 561e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov if (oldUserId != newUserId) { 562e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, 563e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov false, mOverlayToken, null, oldUserId); 564e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 565e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 566e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // Apply the restrictions for the current user based on vr state 567e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov String[] exemptions = (exemptedPackage == null) ? new String[0] : 568e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov new String[] { exemptedPackage }; 569e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 570e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, 571e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov mVrModeEnabled, mOverlayToken, exemptions, newUserId); 572e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 573e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 574e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId, 575e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov String oldVrServicePackage, int oldUserId) { 576e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // If VR state changed and we also have a VR service change. 577e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov if (Objects.equals(newVrServicePackage, oldVrServicePackage)) { 578e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov return; 579e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 58047d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 58147d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov try { 582e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // Set overlay exception state based on VR enabled and current service 583e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId); 58447d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } finally { 58547d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov Binder.restoreCallingIdentity(identity); 58647d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } 58747d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov } 58847d98de60bc5504271e027aef0b7ea218f0aaf59Svetoslav Ganov 589e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 590e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of 591e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * the currently selected VR listener service. If the component selected for the VR listener 592e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * service has changed, unbind the previous listener and bind the new listener (if enabled). 593e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 594e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Note: Must be called while holding {@code mLock}. 595e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 596e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param enabled new state for VR mode. 597e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param component new component to be bound as a VR listener. 598e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param userId user owning the component to be bound. 599c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk * @param calling the component currently using VR mode, or null to leave unchanged. 600e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 601e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @return {@code true} if the component/user combination specified is valid. 602e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 60398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component, 60498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk int userId, ComponentName calling) { 605c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 606c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk boolean sendUpdatedCaller = false; 60798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk final long identity = Binder.clearCallingIdentity(); 60898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk try { 609e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 61098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk boolean validUserComponent = (mComponentObserver.isValid(component, userId) == 61198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk EnabledComponentsObserver.NO_ERROR); 6122ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (!mVrModeEnabled && !enabled) { 6132ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk return validUserComponent; // Disabled -> Disabled transition does nothing. 6142ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 615e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 616e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov String oldVrServicePackage = mCurrentVrService != null 617e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov ? mCurrentVrService.getComponent().getPackageName() : null; 618e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov final int oldUserId = mCurrentVrModeUser; 619e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 62098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Always send mode change events. 621e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov changeVrModeLocked(enabled); 62229931bc684bde6b430923122777684178ee2681cRuben Brunk 62398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!enabled || !validUserComponent) { 62498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Unbind whatever is running 62598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService != null) { 626c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " + 62798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService.getUserId()); 62898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService.disconnect(); 62998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService = null; 63098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 63198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } else { 63298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService != null) { 63398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Unbind any running service that doesn't match the component/user selection 63498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService.disconnectIfNotMatching(component, userId)) { 63598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + 63698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk " for user " + mCurrentVrService.getUserId()); 63798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk createAndConnectService(component, userId); 63898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk sendUpdatedCaller = true; 63998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 64098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // The service with the correct component/user is bound 64198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } else { 64298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk // Nothing was previously running, bind a new service 643c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk createAndConnectService(component, userId); 644c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk sendUpdatedCaller = true; 645c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 64698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 64798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 648e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) { 64998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrModeComponent = calling; 650e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov sendUpdatedCaller = true; 651e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 652e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 653e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov if (mCurrentVrModeUser != userId) { 65498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrModeUser = userId; 655c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk sendUpdatedCaller = true; 656e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 65798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 658e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov String newVrServicePackage = mCurrentVrService != null 659e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov ? mCurrentVrService.getComponent().getPackageName() : null; 660e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov final int newUserId = mCurrentVrModeUser; 661e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 662e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // Update AppOps settings that change state when entering/exiting VR mode, or changing 663e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov // the current VrListenerService. 664e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov updateDependentAppOpsLocked(newVrServicePackage, newUserId, 665e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov oldVrServicePackage, oldUserId); 666e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 66798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (mCurrentVrService != null && sendUpdatedCaller) { 66898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk final ComponentName c = mCurrentVrModeComponent; 66998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk mCurrentVrService.sendEvent(new PendingEvent() { 67098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk @Override 67198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk public void runEvent(IInterface service) throws RemoteException { 67298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk IVrListener l = (IVrListener) service; 67398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk l.focusedActivityChanged(c); 67498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 67598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk }); 67698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 6772ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk logStateLocked(); 67898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 67998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return validUserComponent; 68098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } finally { 68198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk Binder.restoreCallingIdentity(identity); 682c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 68398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 684c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 6858820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk private boolean isDefaultAllowed(String packageName) { 6860568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner PackageManager pm = mContext.getPackageManager(); 6878820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 6888820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk ApplicationInfo info = null; 6898820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk try { 6908820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); 6918820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } catch (NameNotFoundException e) { 6928820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 6938820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 6948820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) { 6958820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk return false; 6960568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner } 6978820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk return true; 6980568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner } 6990568f28ac3ba83ec268b54d16a8b19c1fcaf9c89Craig Donner 70098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void grantNotificationPolicyAccess(String pkg) { 70198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk NotificationManager nm = mContext.getSystemService(NotificationManager.class); 7028820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk nm.setNotificationPolicyAccessGranted(pkg, true); 70398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 70498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 70598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private void revokeNotificationPolicyAccess(String pkg) { 70698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk NotificationManager nm = mContext.getSystemService(NotificationManager.class); 7078820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk // Remove any DND zen rules possibly created by the package. 7088820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk nm.removeAutomaticZenRules(pkg); 7098820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk // Remove Notification Policy Access. 7108820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk nm.setNotificationPolicyAccessGranted(pkg, false); 71198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 71298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 713e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private void grantNotificationListenerAccess(String pkg, int userId) { 71498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk PackageManager pm = mContext.getPackageManager(); 71598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm, 716e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov userId, NotificationListenerService.SERVICE_INTERFACE, 71798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE); 71898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ContentResolver resolver = mContext.getContentResolver(); 71998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 720e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov ArraySet<String> current = getNotificationListeners(resolver, userId); 72198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 72298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk for (ComponentName c : possibleServices) { 72398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flatName = c.flattenToString(); 72498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (Objects.equals(c.getPackageName(), pkg) 72598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk && !current.contains(flatName)) { 72698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk current.add(flatName); 72798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 72898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 72998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 73098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (current.size() > 0) { 73198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flatSettings = formatSettings(current); 732e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov Settings.Secure.putStringForUser(resolver, 733e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, 734e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov flatSettings, userId); 73598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 73698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 73798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 738e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private void revokeNotificationListenerAccess(String pkg, int userId) { 73998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ContentResolver resolver = mContext.getContentResolver(); 740e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 741e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov ArraySet<String> current = getNotificationListeners(resolver, userId); 74298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 7438820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk ArrayList<String> toRemove = new ArrayList<>(); 7448820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 7458820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk for (String c : current) { 7468820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk ComponentName component = ComponentName.unflattenFromString(c); 7478820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk if (component.getPackageName().equals(pkg)) { 7488820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk toRemove.add(c); 7498820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 7508820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk } 7518820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk 7528820f943e0254e188861ef4bc73a95cefc648942Ruben Brunk current.removeAll(toRemove); 75398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 75498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String flatSettings = formatSettings(current); 755e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov Settings.Secure.putStringForUser(resolver, 756e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, 757e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov flatSettings, userId); 758e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov } 759e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov 760e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private boolean isPermissionUserUpdated(String permission, String pkg, int userId) { 761e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov final int flags = mContext.getPackageManager().getPermissionFlags( 762e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov permission, pkg, new UserHandle(userId)); 763e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov return (flags & (PackageManager.FLAG_PERMISSION_USER_SET 764e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0; 76598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 76698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 767e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) { 768e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov String flat = Settings.Secure.getStringForUser(resolver, 769e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId); 77098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 77198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk ArraySet<String> current = new ArraySet<>(); 77298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (flat != null) { 77398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk String[] allowed = flat.split(":"); 77498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk for (String s : allowed) { 77598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk current.add(s); 77698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 77798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 77898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return current; 77998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 78098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 78198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk private static String formatSettings(Collection<String> c) { 78298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (c == null || c.isEmpty()) { 78398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return ""; 78498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 78598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 78698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk StringBuilder b = new StringBuilder(); 78798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk boolean start = true; 78898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk for (String s : c) { 78998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if ("".equals(s)) { 79098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk continue; 79198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 79298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk if (!start) { 79398576cf949a1ffbece3722451713aac01ed27968Ruben Brunk b.append(':'); 79498576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 79598576cf949a1ffbece3722451713aac01ed27968Ruben Brunk b.append(s); 79698576cf949a1ffbece3722451713aac01ed27968Ruben Brunk start = false; 79798576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 79898576cf949a1ffbece3722451713aac01ed27968Ruben Brunk return b.toString(); 79998576cf949a1ffbece3722451713aac01ed27968Ruben Brunk } 80098576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 80198576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 80298576cf949a1ffbece3722451713aac01ed27968Ruben Brunk 803c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk private void createAndConnectService(@NonNull ComponentName component, int userId) { 804c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mCurrentVrService = VrManagerService.create(mContext, component, userId); 805c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk mCurrentVrService.connect(); 806c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk Slog.i(TAG, "Connecting " + component + " for user " + userId); 807c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk } 808c7354fe2d4d73808929d2087f2d18ee3d8fa47fcRuben Brunk 809e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 810e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Send VR mode change callbacks to HAL and system services if mode has actually changed. 811e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 812e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Note: Must be called while holding {@code mLock}. 813e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * 814e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * @param enabled new state of the VR mode. 815e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 816e33f61319049810ae9cb318e2ba45e8a3449fb43Svetoslav Ganov private void changeVrModeLocked(boolean enabled) { 817e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk if (mVrModeEnabled != enabled) { 818e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk mVrModeEnabled = enabled; 819e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 820e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk // Log mode change event. 821e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled")); 822e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk setVrModeNative(mVrModeEnabled); 823e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 824e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk onVrModeChangedLocked(); 825dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 826dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 827dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk 828dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk /** 829dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk * Notify system services of VR mode change. 830e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * <p/> 831e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Note: Must be called while holding {@code mLock}. 832dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk */ 833dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk private void onVrModeChangedLocked() { 834c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE, 835c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk (mVrModeEnabled) ? 1 : 0, 0)); 836dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk } 837e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 838e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /** 839e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Helper function for making ManagedApplicationService instances. 840e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 841e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk private static ManagedApplicationService create(@NonNull Context context, 842e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk @NonNull ComponentName component, int userId) { 843e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk return ManagedApplicationService.build(context, component, userId, 844e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS, 845e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk sBinderChecker); 846e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 847e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 848b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private void consumeAndApplyPendingStateLocked() { 849b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (mPendingState != null) { 850b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk updateCurrentVrServiceLocked(mPendingState.enabled, 851b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState.targetPackageName, mPendingState.userId, 852b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState.callingPackage); 853b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState = null; 854b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 855b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 856b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 8572ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private void logStateLocked() { 8582ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk ComponentName currentBoundService = (mCurrentVrService == null) ? null : 8592ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mCurrentVrService.getComponent(); 8602ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser, 8612ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mCurrentVrModeComponent, mWasDefaultGranted); 8622ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (mLoggingDeque.size() == EVENT_LOG_SIZE) { 8632ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mLoggingDeque.removeFirst(); 8642ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8652ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk mLoggingDeque.add(current); 8662ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8672ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk 8682ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk private void dumpStateTransitions(PrintWriter pw) { 8692ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); 8702ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk String tab = " "; 8712ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (mLoggingDeque.size() == 0) { 8722ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8732ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("None"); 8742ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8752ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk for (VrState state : mLoggingDeque) { 8762ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(d.format(new Date(state.timestamp))); 8772ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8782ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("State changed to:"); 8792ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8802ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println((state.enabled) ? "ENABLED" : "DISABLED"); 8812ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (state.enabled) { 8822ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8832ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("User="); 8842ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println(state.userId); 8852ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8862ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("Current VR Activity="); 8872ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println((state.callingPackage == null) ? 8882ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk "None" : state.callingPackage.flattenToString()); 8892ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8902ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print("Bound VrListenerService="); 8912ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println((state.targetPackageName == null) ? 8922ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk "None" : state.targetPackageName.flattenToString()); 8932ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk if (state.defaultPermissionsGranted) { 8942ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.print(tab); 8952ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk pw.println("Default permissions granted to the bound VrListenerService."); 8962ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8972ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8982ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 8992ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk } 9002ff9c01975622ce7b0e1f7679f1337004dca7be9Ruben Brunk 901e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk /* 902e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk * Implementation of VrManagerInternal calls. These are callable from system services. 903e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk */ 904e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 905b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName, 906af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk int userId, @NonNull ComponentName callingPackage, boolean immediate) { 907b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 908e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 909b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 910af9f004f99d81bdc81a05e179ff04d6b3fcb1041Ruben Brunk if (!enabled && mCurrentVrService != null && !immediate) { 911b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls 912b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk // and service bind/unbind in case we are immediately switching to another VR app. 913b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk if (mPendingState == null) { 914b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE, 915b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk PENDING_STATE_DELAY_MS); 916b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 917b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 918b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState = new VrState(enabled, targetPackageName, userId, callingPackage); 919b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk return; 920b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } else { 921b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE); 922b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk mPendingState = null; 923b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk } 924b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk 925b56b72a8461dcc1a9dccd4c7019e2ecbf191fc1cRuben Brunk updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage); 926e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 927e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 928e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 929c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) { 930e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 931c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return mComponentObserver.isValid(targetPackageName, userId); 932e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 933e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 934e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 9358f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk private boolean isCurrentVrListener(String packageName, int userId) { 9368f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk synchronized (mLock) { 9378f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk if (mCurrentVrService == null) { 9388f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk return false; 9398f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 9408f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk return mCurrentVrService.getComponent().getPackageName().equals(packageName) && 9418f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk userId == mCurrentVrService.getUserId(); 9428f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 9438f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk } 9448f1d5cbabb3bc4ef61b9c2edc70fcfd5d75efec8Ruben Brunk 945c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk /* 946c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk * Implementation of IVrManager calls. 947c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk */ 948c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk 949c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private void addStateCallback(IVrStateCallbacks cb) { 950c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.register(cb); 951e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 952e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 953c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private void removeStateCallback(IVrStateCallbacks cb) { 954c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk mRemoteCallbacks.unregister(cb); 955e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 956e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk 957c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk private boolean getVrMode() { 958e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk synchronized (mLock) { 959c7be3beced4ade05466a4a77c003ea81c2429f74Ruben Brunk return mVrModeEnabled; 960e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 961e24b9a6cfa4d565d7f49c9ae8f3aeca737d93312Ruben Brunk } 962dd18a0b69537954d1cc34929a1386deb54f12b14Ruben Brunk} 963