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