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