blob: b0fd248b2b39a5919f3e3fce3b05cf09712baffa [file] [log] [blame]
Ruben Brunke24b9a62016-02-16 21:38:24 -08001/**
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08002 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.vr;
17
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -080018import static android.view.Display.INVALID_DISPLAY;
19
Ruben Brunkc7be3be2016-04-01 17:07:51 -070020import android.Manifest;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -080021import android.app.ActivityManagerInternal;
Ruben Brunk8820f942016-05-09 12:46:28 -070022import android.app.ActivityManager;
Svetoslav Ganov47d98de2016-03-01 15:01:14 -080023import android.app.AppOpsManager;
Julia Reynoldsb852e562017-06-06 16:14:18 -040024import android.app.INotificationManager;
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -070025import android.app.Vr2dDisplayProperties;
Ruben Brunk98576cf2016-03-07 18:54:28 -080026import android.app.NotificationManager;
Ruben Brunke24b9a62016-02-16 21:38:24 -080027import android.annotation.NonNull;
Steven Thomas68cc84f2017-06-08 16:55:04 -070028import android.content.BroadcastReceiver;
Ruben Brunke24b9a62016-02-16 21:38:24 -080029import android.content.ComponentName;
Ruben Brunk98576cf2016-03-07 18:54:28 -080030import android.content.ContentResolver;
31import android.content.Context;
Steven Thomas68cc84f2017-06-08 16:55:04 -070032import android.content.Intent;
33import android.content.IntentFilter;
Ruben Brunk98576cf2016-03-07 18:54:28 -080034import android.content.pm.ApplicationInfo;
35import android.content.pm.PackageManager;
36import android.content.pm.PackageManager.NameNotFoundException;
Santos Cordon2f22da72017-02-27 17:24:44 -080037import android.hardware.display.DisplayManager;
Svetoslav Ganov47d98de2016-03-01 15:01:14 -080038import android.os.Binder;
Ruben Brunke24b9a62016-02-16 21:38:24 -080039import android.os.Handler;
Svetoslav Ganov47d98de2016-03-01 15:01:14 -080040import android.os.IBinder;
Ruben Brunke24b9a62016-02-16 21:38:24 -080041import android.os.IInterface;
42import android.os.Looper;
Ruben Brunkc7be3be2016-04-01 17:07:51 -070043import android.os.Message;
44import android.os.RemoteCallbackList;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080045import android.os.RemoteException;
Julia Reynoldsb852e562017-06-06 16:14:18 -040046import android.os.ServiceManager;
Steven Thomas68cc84f2017-06-08 16:55:04 -070047import android.os.SystemProperties;
Ruben Brunk98576cf2016-03-07 18:54:28 -080048import android.os.UserHandle;
Ruben Brunke24b9a62016-02-16 21:38:24 -080049import android.provider.Settings;
Ruben Brunk98576cf2016-03-07 18:54:28 -080050import android.service.notification.NotificationListenerService;
Steven Thomasb70845c2017-03-16 14:32:37 -070051import android.service.vr.IPersistentVrStateCallbacks;
Ruben Brunke24b9a62016-02-16 21:38:24 -080052import android.service.vr.IVrListener;
Ruben Brunkc7be3be2016-04-01 17:07:51 -070053import android.service.vr.IVrManager;
54import android.service.vr.IVrStateCallbacks;
Ruben Brunke24b9a62016-02-16 21:38:24 -080055import android.service.vr.VrListenerService;
Ruben Brunk1f4f26b2016-08-02 14:21:36 -070056import android.text.TextUtils;
Svetoslav Ganove33f6132016-06-01 16:25:31 -070057import android.util.ArrayMap;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080058import android.util.ArraySet;
59import android.util.Slog;
Ruben Brunk8820f942016-05-09 12:46:28 -070060import android.util.SparseArray;
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -070061import android.view.WindowManagerInternal;
Santos Cordonc14513d2016-12-14 14:52:59 -080062
Ruben Brunke24b9a62016-02-16 21:38:24 -080063import com.android.internal.R;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060064import com.android.internal.util.DumpUtils;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -080065import com.android.server.LocalServices;
Craig Donner99062592016-04-14 21:45:19 -070066import com.android.server.SystemConfig;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080067import com.android.server.SystemService;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080068import com.android.server.utils.ManagedApplicationService.PendingEvent;
Ruben Brunkd675f512017-10-03 15:39:41 -070069import com.android.server.utils.ManagedApplicationService.LogEvent;
70import com.android.server.utils.ManagedApplicationService.LogFormattable;
Ruben Brunke24b9a62016-02-16 21:38:24 -080071import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
72import com.android.server.utils.ManagedApplicationService;
73import com.android.server.utils.ManagedApplicationService.BinderChecker;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080074
Dan Sandlerdc34df52016-04-07 21:04:46 -040075import java.io.FileDescriptor;
76import java.io.PrintWriter;
Ruben Brunk98576cf2016-03-07 18:54:28 -080077import java.lang.StringBuilder;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070078import java.text.SimpleDateFormat;
Santos Cordone6d77232017-08-08 17:11:41 -070079import java.util.Arrays;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070080import java.util.ArrayDeque;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080081import java.util.ArrayList;
Ruben Brunk98576cf2016-03-07 18:54:28 -080082import java.util.Collection;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070083import java.util.Date;
Julia Reynoldsb852e562017-06-06 16:14:18 -040084import java.util.List;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080085import java.util.Objects;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080086
87/**
Ruben Brunke24b9a62016-02-16 21:38:24 -080088 * Service tracking whether VR mode is active, and notifying listening services of state changes.
89 * <p/>
90 * Services running in system server may modify the state of VrManagerService via the interface in
91 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
92 * interface given in VrStateListener.
93 * <p/>
94 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
95 * hardware/libhardware/modules/vr
96 * <p/>
97 * In general applications may enable or disable VR mode by calling
Ruben Brunk98576cf2016-03-07 18:54:28 -080098 * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to
99 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800100 *
Elliot Waite54de7742017-01-11 15:30:35 -0800101 * @see android.service.vr.VrListenerService
102 * @see com.android.server.vr.VrManagerInternal
103 * @see com.android.server.vr.VrStateListener
Ruben Brunke24b9a62016-02-16 21:38:24 -0800104 *
105 * @hide
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800106 */
Ruben Brunke24b9a62016-02-16 21:38:24 -0800107public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800108
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800109 public static final String TAG = "VrManagerService";
Joe Onorato82ba91d2017-04-27 16:18:05 -0700110 static final boolean DBG = false;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800111
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700112 private static final int PENDING_STATE_DELAY_MS = 300;
Ruben Brunkd675f512017-10-03 15:39:41 -0700113 private static final int EVENT_LOG_SIZE = 64;
Ruben Brunk8820f942016-05-09 12:46:28 -0700114 private static final int INVALID_APPOPS_MODE = -1;
Ruben Brunk040484c2016-10-28 20:18:57 -0700115 /** Null set of sleep sleep flags. */
116 private static final int FLAG_NONE = 0;
117 /** Flag set when the device is not sleeping. */
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700118 private static final int FLAG_AWAKE = 1 << 0;
Ruben Brunk040484c2016-10-28 20:18:57 -0700119 /** Flag set when the screen has been turned on. */
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700120 private static final int FLAG_SCREEN_ON = 1 << 1;
121 /** Flag set when the keyguard is not active. */
122 private static final int FLAG_KEYGUARD_UNLOCKED = 1 << 2;
Ruben Brunk040484c2016-10-28 20:18:57 -0700123 /** Flag indicating that all system sleep flags have been set.*/
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700124 private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON | FLAG_KEYGUARD_UNLOCKED;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700125
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800126 private static native void initializeNative();
127 private static native void setVrModeNative(boolean enabled);
128
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800129 private final Object mLock = new Object();
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800130
131 private final IBinder mOverlayToken = new Binder();
132
Ruben Brunke24b9a62016-02-16 21:38:24 -0800133 // State protected by mLock
Ruben Brunk040484c2016-10-28 20:18:57 -0700134 private boolean mVrModeAllowed;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800135 private boolean mVrModeEnabled;
Zak Cohen56345f42017-01-26 13:54:28 -0800136 private boolean mPersistentVrModeEnabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400137 private boolean mRunning2dInVr;
138 private int mVrAppProcessId;
Ruben Brunke24b9a62016-02-16 21:38:24 -0800139 private EnabledComponentsObserver mComponentObserver;
140 private ManagedApplicationService mCurrentVrService;
Ruben Brunk52ea6622017-10-02 23:51:25 -0700141 private ManagedApplicationService mCurrentVrCompositorService;
Zak Cohen56345f42017-01-26 13:54:28 -0800142 private ComponentName mDefaultVrService;
Ruben Brunke24b9a62016-02-16 21:38:24 -0800143 private Context mContext;
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800144 private ComponentName mCurrentVrModeComponent;
145 private int mCurrentVrModeUser;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800146 private boolean mWasDefaultGranted;
147 private boolean mGuard;
Steven Thomasb70845c2017-03-16 14:32:37 -0700148 private final RemoteCallbackList<IVrStateCallbacks> mVrStateRemoteCallbacks =
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700149 new RemoteCallbackList<>();
Steven Thomasb70845c2017-03-16 14:32:37 -0700150 private final RemoteCallbackList<IPersistentVrStateCallbacks>
151 mPersistentVrStateRemoteCallbacks = new RemoteCallbackList<>();
Ruben Brunk8820f942016-05-09 12:46:28 -0700152 private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
153 private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700154 private VrState mPendingState;
Ruben Brunkd675f512017-10-03 15:39:41 -0700155 private boolean mLogLimitHit;
156 private final ArrayDeque<LogFormattable> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
Ruben Brunk8820f942016-05-09 12:46:28 -0700157 private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400158 private INotificationManager mNotificationManager;
Ruben Brunk040484c2016-10-28 20:18:57 -0700159 /** Tracks the state of the screen and keyguard UI.*/
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700160 private int mSystemSleepFlags = FLAG_AWAKE | FLAG_KEYGUARD_UNLOCKED;
Steven Thomas68cc84f2017-06-08 16:55:04 -0700161 /**
162 * Set when ACTION_USER_UNLOCKED is fired. We shouldn't try to bind to the
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700163 * vr service before then. This gets set only once the first time the user unlocks the device
164 * and stays true thereafter.
Steven Thomas68cc84f2017-06-08 16:55:04 -0700165 */
166 private boolean mUserUnlocked;
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700167 private Vr2dDisplay mVr2dDisplay;
Steven Thomas68cc84f2017-06-08 16:55:04 -0700168 private boolean mBootsToVr;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800169
Ruben Brunkd675f512017-10-03 15:39:41 -0700170 // Handles events from the managed services (e.g. VrListenerService and any bound VR compositor
171 // service).
172 private final ManagedApplicationService.EventCallback mEventCallback
173 = new ManagedApplicationService.EventCallback() {
174 @Override
175 public void onServiceEvent(LogEvent event) {
176 logEvent(event);
177
178 ComponentName component = null;
179 synchronized (mLock) {
180 component = ((mCurrentVrService == null) ? null : mCurrentVrService.getComponent());
181 }
182
183 // If not on an AIO device and we permanently stopped trying to connect to the
184 // VrListenerService (or don't have one bound), leave persistent VR mode and VR mode.
185 if (!mBootsToVr && event.event == LogEvent.EVENT_STOPPED_PERMANENTLY &&
186 (component == null || component.equals(event.component))) {
187 Slog.e(TAG, "VrListenerSevice has died permanently, leaving system VR mode.");
188 // We're not a native VR device. Leave VR + persistent mode.
189 setPersistentVrModeEnabled(false);
190 }
191 }
192 };
193
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700194 private static final int MSG_VR_STATE_CHANGE = 0;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700195 private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
Zak Cohen732aeb02017-01-29 14:19:52 -0800196 private static final int MSG_PERSISTENT_VR_MODE_STATE_CHANGE = 2;
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700197
Ruben Brunk040484c2016-10-28 20:18:57 -0700198 /**
199 * Set whether VR mode may be enabled.
200 * <p/>
201 * If VR mode is not allowed to be enabled, calls to set VR mode will be cached. When VR mode
202 * is again allowed to be enabled, the most recent cached state will be applied.
203 *
Ruben Brunk040484c2016-10-28 20:18:57 -0700204 */
Steven Thomas68cc84f2017-06-08 16:55:04 -0700205 private void updateVrModeAllowedLocked() {
206 boolean allowed = mSystemSleepFlags == FLAG_ALL && mUserUnlocked;
Ruben Brunk040484c2016-10-28 20:18:57 -0700207 if (mVrModeAllowed != allowed) {
208 mVrModeAllowed = allowed;
Joe Onorato82ba91d2017-04-27 16:18:05 -0700209 if (DBG) Slog.d(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
Ruben Brunk040484c2016-10-28 20:18:57 -0700210 if (mVrModeAllowed) {
Steven Thomas68cc84f2017-06-08 16:55:04 -0700211 if (mBootsToVr) {
212 setPersistentVrModeEnabled(true);
213 }
Steven Thomas68cc84f2017-06-08 16:55:04 -0700214 if (mBootsToVr && !mVrModeEnabled) {
Albert Chaulk16d23972017-07-14 12:32:57 -0400215 setVrMode(true, mDefaultVrService, 0, -1, null);
Steven Thomas68cc84f2017-06-08 16:55:04 -0700216 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700217 } else {
Zak Cohen56345f42017-01-26 13:54:28 -0800218 // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
219 // exit persistent VR mode when screen is turned off.
Zak Cohen732aeb02017-01-29 14:19:52 -0800220 setPersistentModeAndNotifyListenersLocked(false);
Zak Cohen56345f42017-01-26 13:54:28 -0800221
Ruben Brunk040484c2016-10-28 20:18:57 -0700222 // Set pending state to current state.
223 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
Albert Chaulk16d23972017-07-14 12:32:57 -0400224 ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
225 mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
Ruben Brunk040484c2016-10-28 20:18:57 -0700226 : null;
227
228 // Unbind current VR service and do necessary callbacks.
Albert Chaulk16d23972017-07-14 12:32:57 -0400229 updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
Ruben Brunk040484c2016-10-28 20:18:57 -0700230 }
231 }
232 }
233
234 private void setSleepState(boolean isAsleep) {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700235 setSystemState(FLAG_AWAKE, !isAsleep);
Ruben Brunk040484c2016-10-28 20:18:57 -0700236 }
237
238 private void setScreenOn(boolean isScreenOn) {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700239 setSystemState(FLAG_SCREEN_ON, isScreenOn);
240 }
241
242 private void setKeyguardShowing(boolean isShowing) {
243 setSystemState(FLAG_KEYGUARD_UNLOCKED, !isShowing);
244 }
245
246 private void setSystemState(int flags, boolean isOn) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700247 synchronized(mLock) {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700248 int oldState = mSystemSleepFlags;
249 if (isOn) {
250 mSystemSleepFlags |= flags;
Ruben Brunk040484c2016-10-28 20:18:57 -0700251 } else {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700252 mSystemSleepFlags &= ~flags;
Ruben Brunk040484c2016-10-28 20:18:57 -0700253 }
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700254 if (oldState != mSystemSleepFlags) {
255 if (DBG) Slog.d(TAG, "System state: " + getStateAsString());
256 updateVrModeAllowedLocked();
257 }
Steven Thomas68cc84f2017-06-08 16:55:04 -0700258 }
259 }
260
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700261 private String getStateAsString() {
262 return new StringBuilder()
263 .append((mSystemSleepFlags & FLAG_AWAKE) != 0 ? "awake, " : "")
264 .append((mSystemSleepFlags & FLAG_SCREEN_ON) != 0 ? "screen_on, " : "")
265 .append((mSystemSleepFlags & FLAG_KEYGUARD_UNLOCKED) != 0 ? "keyguard_off" : "")
266 .toString();
267 }
268
Steven Thomas68cc84f2017-06-08 16:55:04 -0700269 private void setUserUnlocked() {
270 synchronized(mLock) {
271 mUserUnlocked = true;
272 updateVrModeAllowedLocked();
Ruben Brunk040484c2016-10-28 20:18:57 -0700273 }
274 }
275
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700276 private final Handler mHandler = new Handler() {
277 @Override
278 public void handleMessage(Message msg) {
279 switch(msg.what) {
280 case MSG_VR_STATE_CHANGE : {
281 boolean state = (msg.arg1 == 1);
Steven Thomasb70845c2017-03-16 14:32:37 -0700282 int i = mVrStateRemoteCallbacks.beginBroadcast();
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700283 while (i > 0) {
284 i--;
285 try {
Steven Thomasb70845c2017-03-16 14:32:37 -0700286 mVrStateRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700287 } catch (RemoteException e) {
288 // Noop
289 }
290 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700291 mVrStateRemoteCallbacks.finishBroadcast();
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700292 } break;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700293 case MSG_PENDING_VR_STATE_CHANGE : {
294 synchronized(mLock) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700295 if (mVrModeAllowed) {
296 VrManagerService.this.consumeAndApplyPendingStateLocked();
297 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700298 }
299 } break;
Zak Cohen732aeb02017-01-29 14:19:52 -0800300 case MSG_PERSISTENT_VR_MODE_STATE_CHANGE : {
301 boolean state = (msg.arg1 == 1);
Steven Thomasb70845c2017-03-16 14:32:37 -0700302 int i = mPersistentVrStateRemoteCallbacks.beginBroadcast();
303 while (i > 0) {
304 i--;
305 try {
306 mPersistentVrStateRemoteCallbacks.getBroadcastItem(i)
307 .onPersistentVrStateChanged(state);
308 } catch (RemoteException e) {
309 // Noop
310 }
Zak Cohen732aeb02017-01-29 14:19:52 -0800311 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700312 mPersistentVrStateRemoteCallbacks.finishBroadcast();
Zak Cohen732aeb02017-01-29 14:19:52 -0800313 } break;
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700314 default :
315 throw new IllegalStateException("Unknown message type: " + msg.what);
316 }
317 }
318 };
319
Ruben Brunkd675f512017-10-03 15:39:41 -0700320 // Event used to log when settings are changed for dumpsys logs.
321 private static class SettingEvent implements LogFormattable {
322 public final long timestamp;
323 public final String what;
324
325 SettingEvent(String what) {
326 this.timestamp = System.currentTimeMillis();
327 this.what = what;
328 }
329
330 @Override
331 public String toLogString(SimpleDateFormat dateFormat) {
332 return dateFormat.format(new Date(timestamp)) + " " + what;
333 }
334 }
335
336 // Event used to track changes of the primary on-screen VR activity.
337 private static class VrState implements LogFormattable {
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700338 final boolean enabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400339 final boolean running2dInVr;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700340 final int userId;
Albert Chaulk16d23972017-07-14 12:32:57 -0400341 final int processId;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700342 final ComponentName targetPackageName;
343 final ComponentName callingPackage;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700344 final long timestamp;
345 final boolean defaultPermissionsGranted;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700346
Albert Chaulk16d23972017-07-14 12:32:57 -0400347 VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
348 int processId, ComponentName callingPackage) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700349 this.enabled = enabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400350 this.running2dInVr = running2dInVr;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700351 this.userId = userId;
Albert Chaulk16d23972017-07-14 12:32:57 -0400352 this.processId = processId;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700353 this.targetPackageName = targetPackageName;
354 this.callingPackage = callingPackage;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700355 this.defaultPermissionsGranted = false;
356 this.timestamp = System.currentTimeMillis();
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700357 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700358
Albert Chaulk16d23972017-07-14 12:32:57 -0400359 VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
360 int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700361 this.enabled = enabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400362 this.running2dInVr = running2dInVr;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700363 this.userId = userId;
Albert Chaulk16d23972017-07-14 12:32:57 -0400364 this.processId = processId;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700365 this.targetPackageName = targetPackageName;
366 this.callingPackage = callingPackage;
367 this.defaultPermissionsGranted = defaultPermissionsGranted;
368 this.timestamp = System.currentTimeMillis();
369 }
Ruben Brunkd675f512017-10-03 15:39:41 -0700370
371 @Override
372 public String toLogString(SimpleDateFormat dateFormat) {
373 String tab = " ";
374 String newLine = "\n";
375 StringBuilder sb = new StringBuilder(dateFormat.format(new Date(timestamp)));
376 sb.append(tab);
377 sb.append("State changed to:");
378 sb.append(tab);
379 sb.append((enabled) ? "ENABLED" : "DISABLED");
380 sb.append(newLine);
381 if (enabled) {
382 sb.append(tab);
383 sb.append("User=");
384 sb.append(userId);
385 sb.append(newLine);
386 sb.append(tab);
387 sb.append("Current VR Activity=");
388 sb.append((callingPackage == null) ? "None" : callingPackage.flattenToString());
389 sb.append(newLine);
390 sb.append(tab);
391 sb.append("Bound VrListenerService=");
392 sb.append((targetPackageName == null) ? "None"
393 : targetPackageName.flattenToString());
394 sb.append(newLine);
395 if (defaultPermissionsGranted) {
396 sb.append(tab);
397 sb.append("Default permissions granted to the bound VrListenerService.");
398 sb.append(newLine);
399 }
400 }
401 return sb.toString();
402 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700403 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700404
Ruben Brunke24b9a62016-02-16 21:38:24 -0800405 private static final BinderChecker sBinderChecker = new BinderChecker() {
406 @Override
407 public IInterface asInterface(IBinder binder) {
408 return IVrListener.Stub.asInterface(binder);
409 }
410
411 @Override
412 public boolean checkType(IInterface service) {
413 return service instanceof IVrListener;
414 }
415 };
416
Ruben Brunk8820f942016-05-09 12:46:28 -0700417 private final class NotificationAccessManager {
418 private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700419 private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
420 new ArrayMap<>();
Ruben Brunk8820f942016-05-09 12:46:28 -0700421
422 public void update(Collection<String> packageNames) {
423 int currentUserId = ActivityManager.getCurrentUser();
424
Ruben Brunk8820f942016-05-09 12:46:28 -0700425 ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
426 if (allowed == null) {
427 allowed = new ArraySet<>();
428 }
429
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700430 // Make sure we revoke notification access for listeners in other users
431 final int listenerCount = mNotificationAccessPackageToUserId.size();
432 for (int i = listenerCount - 1; i >= 0; i--) {
433 final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
434 if (grantUserId != currentUserId) {
435 String packageName = mNotificationAccessPackageToUserId.keyAt(i);
436 revokeNotificationListenerAccess(packageName, grantUserId);
437 revokeNotificationPolicyAccess(packageName);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000438 revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700439 mNotificationAccessPackageToUserId.removeAt(i);
440 }
441 }
442
Ruben Brunk8820f942016-05-09 12:46:28 -0700443 for (String pkg : allowed) {
444 if (!packageNames.contains(pkg)) {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700445 revokeNotificationListenerAccess(pkg, currentUserId);
Ruben Brunk8820f942016-05-09 12:46:28 -0700446 revokeNotificationPolicyAccess(pkg);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000447 revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700448 mNotificationAccessPackageToUserId.remove(pkg);
Ruben Brunk8820f942016-05-09 12:46:28 -0700449 }
450 }
451 for (String pkg : packageNames) {
452 if (!allowed.contains(pkg)) {
453 grantNotificationPolicyAccess(pkg);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700454 grantNotificationListenerAccess(pkg, currentUserId);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000455 grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700456 mNotificationAccessPackageToUserId.put(pkg, currentUserId);
Ruben Brunk8820f942016-05-09 12:46:28 -0700457 }
458 }
459
460 allowed.clear();
461 allowed.addAll(packageNames);
462 mAllowedPackages.put(currentUserId, allowed);
463 }
464 }
465
Ruben Brunke24b9a62016-02-16 21:38:24 -0800466 /**
467 * Called when a user, package, or setting changes that could affect whether or not the
468 * currently bound VrListenerService is changed.
469 */
470 @Override
471 public void onEnabledComponentChanged() {
472 synchronized (mLock) {
Ruben Brunk8820f942016-05-09 12:46:28 -0700473 int currentUser = ActivityManager.getCurrentUser();
Ruben Brunk8820f942016-05-09 12:46:28 -0700474 // Update listeners
475 ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
476
477 ArraySet<String> enabledPackages = new ArraySet<>();
478 for (ComponentName n : enabledListeners) {
479 String pkg = n.getPackageName();
480 if (isDefaultAllowed(pkg)) {
481 enabledPackages.add(n.getPackageName());
482 }
483 }
484 mNotifAccessManager.update(enabledPackages);
485
Ruben Brunk040484c2016-10-28 20:18:57 -0700486 if (!mVrModeAllowed) {
487 return; // Don't do anything, we shouldn't be in VR mode.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800488 }
489
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700490 // If there is a pending state change, we'd better deal with that first
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800491 consumeAndApplyPendingStateLocked(false);
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700492
493 if (mCurrentVrService == null) {
494 return; // No active services
495 }
496
Ruben Brunke24b9a62016-02-16 21:38:24 -0800497 // There is an active service, update it if needed
Albert Chaulk16d23972017-07-14 12:32:57 -0400498 updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
499 mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
500 mVrAppProcessId, mCurrentVrModeComponent);
Ruben Brunke24b9a62016-02-16 21:38:24 -0800501 }
502 }
503
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700504 private final IVrManager mVrManager = new IVrManager.Stub() {
505
506 @Override
507 public void registerListener(IVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700508 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
509 Manifest.permission.ACCESS_VR_STATE);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700510 if (cb == null) {
511 throw new IllegalArgumentException("Callback binder object is null.");
512 }
513
514 VrManagerService.this.addStateCallback(cb);
515 }
516
517 @Override
518 public void unregisterListener(IVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700519 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
520 Manifest.permission.ACCESS_VR_STATE);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700521 if (cb == null) {
522 throw new IllegalArgumentException("Callback binder object is null.");
523 }
524
525 VrManagerService.this.removeStateCallback(cb);
526 }
527
528 @Override
Steven Thomasb70845c2017-03-16 14:32:37 -0700529 public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700530 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
531 Manifest.permission.ACCESS_VR_STATE);
Steven Thomasb70845c2017-03-16 14:32:37 -0700532 if (cb == null) {
533 throw new IllegalArgumentException("Callback binder object is null.");
534 }
535
536 VrManagerService.this.addPersistentStateCallback(cb);
537 }
538
539 @Override
540 public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700541 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
542 Manifest.permission.ACCESS_VR_STATE);
Steven Thomasb70845c2017-03-16 14:32:37 -0700543 if (cb == null) {
544 throw new IllegalArgumentException("Callback binder object is null.");
545 }
546
547 VrManagerService.this.removePersistentStateCallback(cb);
548 }
549
550 @Override
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700551 public boolean getVrModeState() {
Santos Cordone6d77232017-08-08 17:11:41 -0700552 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
553 Manifest.permission.ACCESS_VR_STATE);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700554 return VrManagerService.this.getVrMode();
555 }
556
Dan Sandlerdc34df52016-04-07 21:04:46 -0400557 @Override
Santos Cordone6d77232017-08-08 17:11:41 -0700558 public boolean getPersistentVrModeEnabled() {
559 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
560 Manifest.permission.ACCESS_VR_STATE);
561 return VrManagerService.this.getPersistentVrMode();
562 }
563
564 @Override
Zak Cohen56345f42017-01-26 13:54:28 -0800565 public void setPersistentVrModeEnabled(boolean enabled) {
Santos Cordone6d77232017-08-08 17:11:41 -0700566 enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
Zak Cohen56345f42017-01-26 13:54:28 -0800567 VrManagerService.this.setPersistentVrModeEnabled(enabled);
568 }
569
570 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700571 public void setVr2dDisplayProperties(
572 Vr2dDisplayProperties vr2dDisplayProp) {
Santos Cordone6d77232017-08-08 17:11:41 -0700573 enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700574 VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700575 }
576
577 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700578 public int getVr2dDisplayId() {
579 return VrManagerService.this.getVr2dDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -0800580 }
581
582 @Override
Ruben Brunk52ea6622017-10-02 23:51:25 -0700583 public void setAndBindCompositor(String componentName) {
584 enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
585 VrManagerService.this.setAndBindCompositor(
586 (componentName == null) ? null : ComponentName.unflattenFromString(componentName));
587 }
588
589 @Override
Dan Sandlerdc34df52016-04-07 21:04:46 -0400590 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600591 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
592
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700593 pw.println("********* Dump of VrManagerService *********");
Ruben Brunk040484c2016-10-28 20:18:57 -0700594 pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
Zak Cohen56345f42017-01-26 13:54:28 -0800595 pw.println("Persistent VR mode is currently: " +
596 ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
Ruben Brunkd675f512017-10-03 15:39:41 -0700597 pw.println("Currently bound VR listener service: "
Ruben Brunkb8449562017-10-05 13:30:47 -0700598 + ((mCurrentVrCompositorService == null)
Ruben Brunkd675f512017-10-03 15:39:41 -0700599 ? "None" : mCurrentVrCompositorService.getComponent().flattenToString()));
Ruben Brunk52ea6622017-10-02 23:51:25 -0700600 pw.println("Currently bound VR compositor service: "
601 + ((mCurrentVrCompositorService == null)
Ruben Brunkd675f512017-10-03 15:39:41 -0700602 ? "None" : mCurrentVrCompositorService.getComponent().flattenToString()));
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700603 pw.println("Previous state transitions:\n");
604 String tab = " ";
605 dumpStateTransitions(pw);
606 pw.println("\n\nRemote Callbacks:");
Steven Thomasb70845c2017-03-16 14:32:37 -0700607 int i=mVrStateRemoteCallbacks.beginBroadcast(); // create the broadcast item array
Dan Sandlerdc34df52016-04-07 21:04:46 -0400608 while(i-->0) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700609 pw.print(tab);
Steven Thomasb70845c2017-03-16 14:32:37 -0700610 pw.print(mVrStateRemoteCallbacks.getBroadcastItem(i));
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700611 if (i>0) pw.println(",");
Dan Sandlerdc34df52016-04-07 21:04:46 -0400612 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700613 mVrStateRemoteCallbacks.finishBroadcast();
614 pw.println("\n\nPersistent Vr State Remote Callbacks:");
615 i=mPersistentVrStateRemoteCallbacks.beginBroadcast();
616 while(i-->0) {
617 pw.print(tab);
618 pw.print(mPersistentVrStateRemoteCallbacks.getBroadcastItem(i));
619 if (i>0) pw.println(",");
620 }
621 mPersistentVrStateRemoteCallbacks.finishBroadcast();
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700622 pw.println("\n");
623 pw.println("Installed VrListenerService components:");
624 int userId = mCurrentVrModeUser;
625 ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
626 if (installed == null || installed.size() == 0) {
627 pw.println("None");
628 } else {
629 for (ComponentName n : installed) {
630 pw.print(tab);
631 pw.println(n.flattenToString());
632 }
633 }
634 pw.println("Enabled VrListenerService components:");
635 ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
636 if (enabled == null || enabled.size() == 0) {
637 pw.println("None");
638 } else {
639 for (ComponentName n : enabled) {
640 pw.print(tab);
641 pw.println(n.flattenToString());
642 }
643 }
644 pw.println("\n");
645 pw.println("********* End of VrManagerService Dump *********");
Dan Sandlerdc34df52016-04-07 21:04:46 -0400646 }
647
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700648 };
649
Santos Cordone6d77232017-08-08 17:11:41 -0700650 /**
651 * Enforces that at lease one of the specified permissions is held by the caller.
652 * Throws SecurityException if none of the specified permissions are held.
653 *
654 * @param permissions One or more permissions to check against.
655 */
656 private void enforceCallerPermissionAnyOf(String... permissions) {
657 for (String permission : permissions) {
658 if (mContext.checkCallingOrSelfPermission(permission)
659 == PackageManager.PERMISSION_GRANTED) {
660 return;
661 }
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700662 }
Santos Cordone6d77232017-08-08 17:11:41 -0700663 throw new SecurityException("Caller does not hold at least one of the permissions: "
664 + Arrays.toString(permissions));
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700665 }
666
Ruben Brunke24b9a62016-02-16 21:38:24 -0800667 /**
668 * Implementation of VrManagerInternal. Callable only from system services.
669 */
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800670 private final class LocalService extends VrManagerInternal {
671 @Override
Albert Chaulk16d23972017-07-14 12:32:57 -0400672 public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800673 ComponentName callingPackage) {
Albert Chaulk16d23972017-07-14 12:32:57 -0400674 VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
Ruben Brunkaf9f0042016-06-15 17:08:35 -0700675 }
676
677 @Override
Ruben Brunk040484c2016-10-28 20:18:57 -0700678 public void onSleepStateChanged(boolean isAsleep) {
679 VrManagerService.this.setSleepState(isAsleep);
680 }
681
682 @Override
683 public void onScreenStateChanged(boolean isScreenOn) {
684 VrManagerService.this.setScreenOn(isScreenOn);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800685 }
686
687 @Override
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700688 public void onKeyguardStateChanged(boolean isShowing) {
689 VrManagerService.this.setKeyguardShowing(isShowing);
690 }
691
692 @Override
Ruben Brunk8f1d5cb2016-03-22 18:08:41 -0700693 public boolean isCurrentVrListener(String packageName, int userId) {
694 return VrManagerService.this.isCurrentVrListener(packageName, userId);
695 }
696
697 @Override
Ruben Brunke24b9a62016-02-16 21:38:24 -0800698 public int hasVrPackage(ComponentName packageName, int userId) {
699 return VrManagerService.this.hasVrPackage(packageName, userId);
700 }
Zak Cohen56345f42017-01-26 13:54:28 -0800701
702 @Override
703 public void setPersistentVrModeEnabled(boolean enabled) {
704 VrManagerService.this.setPersistentVrModeEnabled(enabled);
705 }
Zak Cohen732aeb02017-01-29 14:19:52 -0800706
707 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700708 public void setVr2dDisplayProperties(
709 Vr2dDisplayProperties compatDisplayProp) {
710 VrManagerService.this.setVr2dDisplayProperties(compatDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700711 }
712
713 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700714 public int getVr2dDisplayId() {
715 return VrManagerService.this.getVr2dDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -0800716 }
717
718 @Override
Steven Thomasb70845c2017-03-16 14:32:37 -0700719 public void addPersistentVrModeStateListener(IPersistentVrStateCallbacks listener) {
720 VrManagerService.this.addPersistentStateCallback(listener);
Zak Cohen732aeb02017-01-29 14:19:52 -0800721 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800722 }
723
724 public VrManagerService(Context context) {
725 super(context);
726 }
727
728 @Override
729 public void onStart() {
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800730 synchronized(mLock) {
731 initializeNative();
Ruben Brunke24b9a62016-02-16 21:38:24 -0800732 mContext = getContext();
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800733 }
734
Steven Thomas68cc84f2017-06-08 16:55:04 -0700735 mBootsToVr = SystemProperties.getBoolean("ro.boot.vr", false);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800736 publishLocalService(VrManagerInternal.class, new LocalService());
Craig Donner8deb67c2017-02-07 18:10:32 -0800737 publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800738 }
739
Ruben Brunke24b9a62016-02-16 21:38:24 -0800740 @Override
741 public void onBootPhase(int phase) {
Ruben Brunk85070042016-03-21 12:10:38 -0700742 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Julia Reynoldsb852e562017-06-06 16:14:18 -0400743 mNotificationManager = INotificationManager.Stub.asInterface(
744 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800745 synchronized (mLock) {
746 Looper looper = Looper.getMainLooper();
747 Handler handler = new Handler(looper);
748 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
749 listeners.add(this);
750 mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
751 Settings.Secure.ENABLED_VR_LISTENERS, looper,
752 android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
753 VrListenerService.SERVICE_INTERFACE, mLock, listeners);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800754
Ruben Brunke24b9a62016-02-16 21:38:24 -0800755 mComponentObserver.rebuildAll();
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800756 }
Zak Cohen56345f42017-01-26 13:54:28 -0800757
758 //TODO: something more robust than picking the first one
759 ArraySet<ComponentName> defaultVrComponents =
760 SystemConfig.getInstance().getDefaultVrComponents();
761 if (defaultVrComponents.size() > 0) {
762 mDefaultVrService = defaultVrComponents.valueAt(0);
763 } else {
764 Slog.i(TAG, "No default vr listener service found.");
765 }
Santos Cordon2f22da72017-02-27 17:24:44 -0800766
767 DisplayManager dm =
768 (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700769 mVr2dDisplay = new Vr2dDisplay(
770 dm,
771 LocalServices.getService(ActivityManagerInternal.class),
772 LocalServices.getService(WindowManagerInternal.class),
773 mVrManager);
Santos Cordonc22c5632017-06-21 16:03:49 -0700774 mVr2dDisplay.init(getContext(), mBootsToVr);
Steven Thomas68cc84f2017-06-08 16:55:04 -0700775
776 IntentFilter intentFilter = new IntentFilter();
777 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
778 getContext().registerReceiver(new BroadcastReceiver() {
779 @Override
780 public void onReceive(Context context, Intent intent) {
781 if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
782 VrManagerService.this.setUserUnlocked();
783 }
784 }
785 }, intentFilter);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800786 }
787 }
788
Ruben Brunke24b9a62016-02-16 21:38:24 -0800789 @Override
790 public void onStartUser(int userHandle) {
791 synchronized (mLock) {
792 mComponentObserver.onUsersChanged();
793 }
794 }
795
796 @Override
797 public void onSwitchUser(int userHandle) {
798 synchronized (mLock) {
799 mComponentObserver.onUsersChanged();
800 }
801
802 }
803
804 @Override
805 public void onStopUser(int userHandle) {
806 synchronized (mLock) {
807 mComponentObserver.onUsersChanged();
808 }
809
810 }
811
812 @Override
813 public void onCleanupUser(int userHandle) {
814 synchronized (mLock) {
815 mComponentObserver.onUsersChanged();
816 }
817 }
818
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700819 private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
820 AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
821
822 // If user changed drop restrictions for the old user.
823 if (oldUserId != newUserId) {
824 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
825 false, mOverlayToken, null, oldUserId);
826 }
827
828 // Apply the restrictions for the current user based on vr state
829 String[] exemptions = (exemptedPackage == null) ? new String[0] :
830 new String[] { exemptedPackage };
831
832 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
Ruben Brunk2781b412017-04-24 12:07:17 -0700833 mVrModeEnabled, mOverlayToken, exemptions, newUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700834 }
835
836 private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
837 String oldVrServicePackage, int oldUserId) {
838 // If VR state changed and we also have a VR service change.
839 if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
840 return;
841 }
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800842 final long identity = Binder.clearCallingIdentity();
843 try {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700844 // Set overlay exception state based on VR enabled and current service
845 updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800846 } finally {
847 Binder.restoreCallingIdentity(identity);
848 }
849 }
850
Ruben Brunke24b9a62016-02-16 21:38:24 -0800851 /**
852 * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
853 * the currently selected VR listener service. If the component selected for the VR listener
854 * service has changed, unbind the previous listener and bind the new listener (if enabled).
855 * <p/>
856 * Note: Must be called while holding {@code mLock}.
857 *
858 * @param enabled new state for VR mode.
Albert Chaulk16d23972017-07-14 12:32:57 -0400859 * @param running2dInVr true if we have a top-level 2D intent.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800860 * @param component new component to be bound as a VR listener.
861 * @param userId user owning the component to be bound.
Albert Chaulk16d23972017-07-14 12:32:57 -0400862 * @param processId the process hosting the activity specified by calling.
863 * @param calling the component currently using VR mode or a 2D intent.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800864 *
865 * @return {@code true} if the component/user combination specified is valid.
866 */
Albert Chaulk16d23972017-07-14 12:32:57 -0400867 private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
868 @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800869
870 boolean sendUpdatedCaller = false;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800871 final long identity = Binder.clearCallingIdentity();
872 try {
Ruben Brunke24b9a62016-02-16 21:38:24 -0800873
Ruben Brunk98576cf2016-03-07 18:54:28 -0800874 boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
875 EnabledComponentsObserver.NO_ERROR);
Ruben Brunk040484c2016-10-28 20:18:57 -0700876 boolean goingIntoVrMode = validUserComponent && enabled;
877 if (!mVrModeEnabled && !goingIntoVrMode) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700878 return validUserComponent; // Disabled -> Disabled transition does nothing.
879 }
Ruben Brunke24b9a62016-02-16 21:38:24 -0800880
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700881 String oldVrServicePackage = mCurrentVrService != null
882 ? mCurrentVrService.getComponent().getPackageName() : null;
883 final int oldUserId = mCurrentVrModeUser;
884
Ruben Brunk040484c2016-10-28 20:18:57 -0700885 // Notify system services and VR HAL of mode change.
886 changeVrModeLocked(goingIntoVrMode);
Ruben Brunk29931bc2016-03-11 00:24:26 -0800887
Ruben Brunk040484c2016-10-28 20:18:57 -0700888 boolean nothingChanged = false;
889 if (!goingIntoVrMode) {
890 // Not going into VR mode, unbind whatever is running
Ruben Brunk98576cf2016-03-07 18:54:28 -0800891 if (mCurrentVrService != null) {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800892 Slog.i(TAG, "Leaving VR mode, disconnecting "
893 + mCurrentVrService.getComponent() + " for user "
894 + mCurrentVrService.getUserId());
Ruben Brunk98576cf2016-03-07 18:54:28 -0800895 mCurrentVrService.disconnect();
Ruben Brunk52ea6622017-10-02 23:51:25 -0700896 updateCompositorServiceLocked(UserHandle.USER_NULL, null);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800897 mCurrentVrService = null;
Ruben Brunk040484c2016-10-28 20:18:57 -0700898 } else {
899 nothingChanged = true;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800900 }
901 } else {
Ruben Brunk040484c2016-10-28 20:18:57 -0700902 // Going into VR mode
Ruben Brunk98576cf2016-03-07 18:54:28 -0800903 if (mCurrentVrService != null) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700904 // Unbind any running service that doesn't match the latest component/user
905 // selection.
Ruben Brunk98576cf2016-03-07 18:54:28 -0800906 if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800907 Slog.i(TAG, "VR mode component changed to " + component
908 + ", disconnecting " + mCurrentVrService.getComponent()
909 + " for user " + mCurrentVrService.getUserId());
Ruben Brunk52ea6622017-10-02 23:51:25 -0700910 updateCompositorServiceLocked(UserHandle.USER_NULL, null);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800911 createAndConnectService(component, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800912 sendUpdatedCaller = true;
Ruben Brunk040484c2016-10-28 20:18:57 -0700913 } else {
914 nothingChanged = true;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800915 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700916 // The service with the correct component/user is already bound, do nothing.
Ruben Brunk98576cf2016-03-07 18:54:28 -0800917 } else {
Ruben Brunk040484c2016-10-28 20:18:57 -0700918 // Nothing was previously running, bind a new service for the latest
919 // component/user selection.
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800920 createAndConnectService(component, userId);
921 sendUpdatedCaller = true;
922 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800923 }
924
Ruben Brunk666505e2017-05-04 16:54:46 -0700925 if ((calling != null || mPersistentVrModeEnabled)
Alex Sakhartchoukec4d3e42017-07-24 22:12:39 -0400926 && !Objects.equals(calling, mCurrentVrModeComponent)
927 || mRunning2dInVr != running2dInVr) {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700928 sendUpdatedCaller = true;
929 }
Ruben Brunk7196a6b2017-03-22 15:43:24 -0700930 mCurrentVrModeComponent = calling;
Albert Chaulk16d23972017-07-14 12:32:57 -0400931 mRunning2dInVr = running2dInVr;
932 mVrAppProcessId = processId;
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700933
934 if (mCurrentVrModeUser != userId) {
Ruben Brunk98576cf2016-03-07 18:54:28 -0800935 mCurrentVrModeUser = userId;
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800936 sendUpdatedCaller = true;
937 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800938
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700939 String newVrServicePackage = mCurrentVrService != null
940 ? mCurrentVrService.getComponent().getPackageName() : null;
941 final int newUserId = mCurrentVrModeUser;
942
943 // Update AppOps settings that change state when entering/exiting VR mode, or changing
944 // the current VrListenerService.
945 updateDependentAppOpsLocked(newVrServicePackage, newUserId,
946 oldVrServicePackage, oldUserId);
947
Ruben Brunk98576cf2016-03-07 18:54:28 -0800948 if (mCurrentVrService != null && sendUpdatedCaller) {
949 final ComponentName c = mCurrentVrModeComponent;
Albert Chaulk16d23972017-07-14 12:32:57 -0400950 final boolean b = running2dInVr;
951 final int pid = processId;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800952 mCurrentVrService.sendEvent(new PendingEvent() {
953 @Override
954 public void runEvent(IInterface service) throws RemoteException {
955 IVrListener l = (IVrListener) service;
Albert Chaulk16d23972017-07-14 12:32:57 -0400956 l.focusedActivityChanged(c, b, pid);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800957 }
958 });
959 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700960
961 if (!nothingChanged) {
962 logStateLocked();
963 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800964
965 return validUserComponent;
966 } finally {
967 Binder.restoreCallingIdentity(identity);
968 }
969 }
970
Ruben Brunk8820f942016-05-09 12:46:28 -0700971 private boolean isDefaultAllowed(String packageName) {
Craig Donner0568f282016-04-11 13:02:44 -0700972 PackageManager pm = mContext.getPackageManager();
Ruben Brunk8820f942016-05-09 12:46:28 -0700973
974 ApplicationInfo info = null;
975 try {
976 info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
977 } catch (NameNotFoundException e) {
978 }
979
980 if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
981 return false;
982 }
983 return true;
984 }
985
Ruben Brunk98576cf2016-03-07 18:54:28 -0800986 private void grantNotificationPolicyAccess(String pkg) {
987 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk8820f942016-05-09 12:46:28 -0700988 nm.setNotificationPolicyAccessGranted(pkg, true);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800989 }
990
991 private void revokeNotificationPolicyAccess(String pkg) {
992 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk8820f942016-05-09 12:46:28 -0700993 // Remove any DND zen rules possibly created by the package.
994 nm.removeAutomaticZenRules(pkg);
995 // Remove Notification Policy Access.
996 nm.setNotificationPolicyAccessGranted(pkg, false);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800997 }
998
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700999 private void grantNotificationListenerAccess(String pkg, int userId) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001000 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001001 PackageManager pm = mContext.getPackageManager();
1002 ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001003 userId, NotificationListenerService.SERVICE_INTERFACE,
Ruben Brunk98576cf2016-03-07 18:54:28 -08001004 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001005
Ruben Brunk98576cf2016-03-07 18:54:28 -08001006 for (ComponentName c : possibleServices) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001007 if (Objects.equals(c.getPackageName(), pkg)) {
1008 nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001009 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001010 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001011 }
1012
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001013 private void revokeNotificationListenerAccess(String pkg, int userId) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001014 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
1015 List<ComponentName> current = nm.getEnabledNotificationListeners(userId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001016
Julia Reynoldsb852e562017-06-06 16:14:18 -04001017 for (ComponentName component : current) {
Ruben Brunk1f4f26b2016-08-02 14:21:36 -07001018 if (component != null && component.getPackageName().equals(pkg)) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001019 nm.setNotificationListenerAccessGrantedForUser(component, userId, false);
Ruben Brunk8820f942016-05-09 12:46:28 -07001020 }
1021 }
Ruben Brunk98576cf2016-03-07 18:54:28 -08001022 }
1023
Craig Donnercae8cdf2016-07-28 22:39:05 +00001024 private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
1025 // Don't clobber the user if permission set in current state explicitly
1026 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
Ruben Brunk12ab5e12016-11-10 15:27:30 -08001027 try {
1028 mContext.getPackageManager().grantRuntimePermission(pkg,
1029 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
1030 } catch (IllegalArgumentException e) {
1031 // Package was removed during update.
1032 Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
1033 + " was removed.");
1034 }
Craig Donnercae8cdf2016-07-28 22:39:05 +00001035 }
1036 }
1037
1038 private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
1039 // Don't clobber the user if permission set in current state explicitly
1040 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
Ruben Brunk12ab5e12016-11-10 15:27:30 -08001041 try {
1042 mContext.getPackageManager().revokeRuntimePermission(pkg,
1043 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
1044 } catch (IllegalArgumentException e) {
1045 // Package was removed during update.
1046 Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
1047 + " was removed.");
1048 }
Craig Donnercae8cdf2016-07-28 22:39:05 +00001049 }
1050 }
1051
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001052 private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
1053 final int flags = mContext.getPackageManager().getPermissionFlags(
1054 permission, pkg, new UserHandle(userId));
1055 return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
1056 | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
1057 }
1058
1059 private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
1060 String flat = Settings.Secure.getStringForUser(resolver,
1061 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001062
1063 ArraySet<String> current = new ArraySet<>();
1064 if (flat != null) {
1065 String[] allowed = flat.split(":");
1066 for (String s : allowed) {
Ruben Brunk1f4f26b2016-08-02 14:21:36 -07001067 if (!TextUtils.isEmpty(s)) {
1068 current.add(s);
1069 }
Ruben Brunk98576cf2016-03-07 18:54:28 -08001070 }
1071 }
1072 return current;
1073 }
1074
1075 private static String formatSettings(Collection<String> c) {
1076 if (c == null || c.isEmpty()) {
1077 return "";
1078 }
1079
1080 StringBuilder b = new StringBuilder();
1081 boolean start = true;
1082 for (String s : c) {
1083 if ("".equals(s)) {
1084 continue;
1085 }
1086 if (!start) {
1087 b.append(':');
1088 }
1089 b.append(s);
1090 start = false;
1091 }
1092 return b.toString();
1093 }
1094
1095
1096
Ruben Brunkc7354fe2016-03-07 23:37:12 -08001097 private void createAndConnectService(@NonNull ComponentName component, int userId) {
Ruben Brunkd675f512017-10-03 15:39:41 -07001098 mCurrentVrService = createVrListenerService(component, userId);
Ruben Brunkc7354fe2016-03-07 23:37:12 -08001099 mCurrentVrService.connect();
1100 Slog.i(TAG, "Connecting " + component + " for user " + userId);
1101 }
1102
Ruben Brunke24b9a62016-02-16 21:38:24 -08001103 /**
1104 * Send VR mode change callbacks to HAL and system services if mode has actually changed.
1105 * <p/>
1106 * Note: Must be called while holding {@code mLock}.
1107 *
1108 * @param enabled new state of the VR mode.
1109 */
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001110 private void changeVrModeLocked(boolean enabled) {
Ruben Brunke24b9a62016-02-16 21:38:24 -08001111 if (mVrModeEnabled != enabled) {
1112 mVrModeEnabled = enabled;
1113
1114 // Log mode change event.
1115 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
1116 setVrModeNative(mVrModeEnabled);
1117
Ruben Brunke24b9a62016-02-16 21:38:24 -08001118 onVrModeChangedLocked();
1119 }
1120 }
1121
1122 /**
1123 * Notify system services of VR mode change.
1124 * <p/>
1125 * Note: Must be called while holding {@code mLock}.
1126 */
1127 private void onVrModeChangedLocked() {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001128 mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
1129 (mVrModeEnabled) ? 1 : 0, 0));
Ruben Brunke24b9a62016-02-16 21:38:24 -08001130 }
1131
1132 /**
Ruben Brunkd675f512017-10-03 15:39:41 -07001133 * Helper function for making ManagedApplicationService for VrListenerService instances.
Ruben Brunke24b9a62016-02-16 21:38:24 -08001134 */
Ruben Brunkd675f512017-10-03 15:39:41 -07001135 private ManagedApplicationService createVrListenerService(@NonNull ComponentName component,
1136 int userId) {
1137 int retryType = (mBootsToVr) ? ManagedApplicationService.RETRY_FOREVER
1138 : ManagedApplicationService.RETRY_NEVER;
1139 return ManagedApplicationService.build(mContext, component, userId,
Ruben Brunke24b9a62016-02-16 21:38:24 -08001140 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
Ruben Brunkd675f512017-10-03 15:39:41 -07001141 sBinderChecker, /*isImportant*/true, retryType, mHandler, mEventCallback);
1142 }
1143
1144 /**
1145 * Helper function for making ManagedApplicationService for VR Compositor instances.
1146 */
1147 private ManagedApplicationService createVrCompositorService(@NonNull ComponentName component,
1148 int userId) {
1149 int retryType = (mBootsToVr) ? ManagedApplicationService.RETRY_FOREVER
1150 : ManagedApplicationService.RETRY_BEST_EFFORT;
1151 return ManagedApplicationService.build(mContext, component, userId, /*clientLabel*/0,
1152 /*settingsAction*/null, /*binderChecker*/null, /*isImportant*/true, retryType,
1153 mHandler, /*disconnectCallback*/mEventCallback);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001154 }
1155
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -08001156 /**
1157 * Apply the pending VR state. If no state is pending, disconnect any currently bound
1158 * VR listener service.
1159 */
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001160 private void consumeAndApplyPendingStateLocked() {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -08001161 consumeAndApplyPendingStateLocked(true);
1162 }
1163
1164 /**
1165 * Apply the pending VR state.
1166 *
1167 * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
1168 * service will be disconnected if no state is pending. If this is {@code false} then the
1169 * nothing will be changed when there is no pending state.
1170 */
1171 private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001172 if (mPendingState != null) {
Albert Chaulk16d23972017-07-14 12:32:57 -04001173 updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
1174 mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001175 mPendingState.callingPackage);
1176 mPendingState = null;
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -08001177 } else if (disconnectIfNoPendingState) {
Albert Chaulk16d23972017-07-14 12:32:57 -04001178 updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001179 }
1180 }
1181
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001182 private void logStateLocked() {
1183 ComponentName currentBoundService = (mCurrentVrService == null) ? null :
Ruben Brunkd675f512017-10-03 15:39:41 -07001184 mCurrentVrService.getComponent();
1185 logEvent(new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
1186 mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted));
1187 }
1188
1189 private void logEvent(LogFormattable event) {
1190 synchronized (mLoggingDeque) {
1191 if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
1192 mLoggingDeque.removeFirst();
1193 mLogLimitHit = true;
1194 }
1195 mLoggingDeque.add(event);
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001196 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001197 }
1198
1199 private void dumpStateTransitions(PrintWriter pw) {
1200 SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
Ruben Brunkd675f512017-10-03 15:39:41 -07001201 synchronized (mLoggingDeque) {
1202 if (mLoggingDeque.size() == 0) {
1203 pw.print(" ");
1204 pw.println("None");
1205 }
1206
1207 if (mLogLimitHit) {
1208 pw.println("..."); // Indicates log overflow
1209 }
1210
1211 for (LogFormattable event : mLoggingDeque) {
1212 pw.println(event.toLogString(d));
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001213 }
1214 }
1215 }
1216
Ruben Brunke24b9a62016-02-16 21:38:24 -08001217 /*
1218 * Implementation of VrManagerInternal calls. These are callable from system services.
1219 */
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001220 private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
Albert Chaulk16d23972017-07-14 12:32:57 -04001221 int userId, int processId, @NonNull ComponentName callingPackage) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001222
Ruben Brunke24b9a62016-02-16 21:38:24 -08001223 synchronized (mLock) {
Zak Cohen56345f42017-01-26 13:54:28 -08001224 VrState pending;
1225 ComponentName targetListener;
Zak Cohen56345f42017-01-26 13:54:28 -08001226
1227 // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
1228 // and the system default VR listener is used.
1229 boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
Albert Chaulk16d23972017-07-14 12:32:57 -04001230 boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
1231 if (running2dInVr) {
Zak Cohen56345f42017-01-26 13:54:28 -08001232 targetListener = mDefaultVrService;
Zak Cohen56345f42017-01-26 13:54:28 -08001233 } else {
1234 targetListener = targetPackageName;
Zak Cohen56345f42017-01-26 13:54:28 -08001235 }
Albert Chaulk16d23972017-07-14 12:32:57 -04001236
1237 pending = new VrState(targetEnabledState, running2dInVr, targetListener,
1238 userId, processId, callingPackage);
Zak Cohen56345f42017-01-26 13:54:28 -08001239
Ruben Brunk040484c2016-10-28 20:18:57 -07001240 if (!mVrModeAllowed) {
1241 // We're not allowed to be in VR mode. Make this state pending. This will be
1242 // applied the next time we are allowed to enter VR mode unless it is superseded by
1243 // another call.
1244 mPendingState = pending;
1245 return;
1246 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001247
Zak Cohen56345f42017-01-26 13:54:28 -08001248 if (!targetEnabledState && mCurrentVrService != null) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001249 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
1250 // and service bind/unbind in case we are immediately switching to another VR app.
1251 if (mPendingState == null) {
1252 mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
1253 PENDING_STATE_DELAY_MS);
1254 }
1255
Ruben Brunk040484c2016-10-28 20:18:57 -07001256 mPendingState = pending;
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001257 return;
1258 } else {
1259 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
1260 mPendingState = null;
1261 }
1262
Albert Chaulk16d23972017-07-14 12:32:57 -04001263 updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
1264 userId, processId, callingPackage);
Zak Cohen56345f42017-01-26 13:54:28 -08001265 }
1266 }
1267
1268 private void setPersistentVrModeEnabled(boolean enabled) {
Zak Cohen732aeb02017-01-29 14:19:52 -08001269 synchronized(mLock) {
1270 setPersistentModeAndNotifyListenersLocked(enabled);
Alex Sakhartchouka26b4352017-07-25 17:08:43 -04001271 // Disabling persistent mode should disable the overall vr mode.
1272 if (!enabled) {
Albert Chaulk16d23972017-07-14 12:32:57 -04001273 setVrMode(false, null, 0, -1, null);
Zak Cohen56345f42017-01-26 13:54:28 -08001274 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001275 }
1276 }
1277
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001278 public void setVr2dDisplayProperties(
1279 Vr2dDisplayProperties compatDisplayProp) {
1280 if (mVr2dDisplay != null) {
1281 mVr2dDisplay.setVirtualDisplayProperties(compatDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -07001282 return;
1283 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001284 Slog.w(TAG, "Vr2dDisplay is null!");
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -07001285 }
1286
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001287 private int getVr2dDisplayId() {
1288 if (mVr2dDisplay != null) {
1289 return mVr2dDisplay.getVirtualDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -08001290 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001291 Slog.w(TAG, "Vr2dDisplay is null!");
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -08001292 return INVALID_DISPLAY;
1293 }
1294
Ruben Brunk52ea6622017-10-02 23:51:25 -07001295 private void setAndBindCompositor(ComponentName componentName) {
1296 final int userId = UserHandle.getCallingUserId();
1297 final long token = Binder.clearCallingIdentity();
1298 synchronized (mLock) {
1299 updateCompositorServiceLocked(userId, componentName);
1300 }
1301 Binder.restoreCallingIdentity(token);
1302 }
1303
1304 private void updateCompositorServiceLocked(int userId, ComponentName componentName) {
1305 if (mCurrentVrCompositorService != null
1306 && mCurrentVrCompositorService.disconnectIfNotMatching(componentName, userId)) {
Ruben Brunkd675f512017-10-03 15:39:41 -07001307 Slog.i(TAG, "Disconnecting compositor service: "
1308 + mCurrentVrCompositorService.getComponent());
Ruben Brunk52ea6622017-10-02 23:51:25 -07001309 // Check if existing service matches the requested one, if not (or if the requested
1310 // component is null) disconnect it.
1311 mCurrentVrCompositorService = null;
1312 }
1313
1314 if (componentName != null && mCurrentVrCompositorService == null) {
1315 // We don't have an existing service matching the requested component, so attempt to
1316 // connect one.
Ruben Brunkd675f512017-10-03 15:39:41 -07001317 Slog.i(TAG, "Connecting compositor service: " + componentName);
1318 mCurrentVrCompositorService = createVrCompositorService(componentName, userId);
Ruben Brunk52ea6622017-10-02 23:51:25 -07001319 mCurrentVrCompositorService.connect();
1320 }
1321 }
1322
Zak Cohen732aeb02017-01-29 14:19:52 -08001323 private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
1324 if (mPersistentVrModeEnabled == enabled) {
1325 return;
1326 }
Ruben Brunkd675f512017-10-03 15:39:41 -07001327 String eventName = "Persistent VR mode " + ((enabled) ? "enabled" : "disabled");
1328 Slog.i(TAG, eventName);
1329 logEvent(new SettingEvent(eventName));
Zak Cohen732aeb02017-01-29 14:19:52 -08001330 mPersistentVrModeEnabled = enabled;
1331
1332 mHandler.sendMessage(mHandler.obtainMessage(MSG_PERSISTENT_VR_MODE_STATE_CHANGE,
1333 (mPersistentVrModeEnabled) ? 1 : 0, 0));
1334 }
1335
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001336 private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001337 synchronized (mLock) {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001338 return mComponentObserver.isValid(targetPackageName, userId);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001339 }
1340 }
1341
Ruben Brunk8f1d5cb2016-03-22 18:08:41 -07001342 private boolean isCurrentVrListener(String packageName, int userId) {
1343 synchronized (mLock) {
1344 if (mCurrentVrService == null) {
1345 return false;
1346 }
1347 return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
1348 userId == mCurrentVrService.getUserId();
1349 }
1350 }
1351
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001352 /*
1353 * Implementation of IVrManager calls.
1354 */
1355
1356 private void addStateCallback(IVrStateCallbacks cb) {
Steven Thomasb70845c2017-03-16 14:32:37 -07001357 mVrStateRemoteCallbacks.register(cb);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001358 }
1359
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001360 private void removeStateCallback(IVrStateCallbacks cb) {
Steven Thomasb70845c2017-03-16 14:32:37 -07001361 mVrStateRemoteCallbacks.unregister(cb);
1362 }
1363
1364 private void addPersistentStateCallback(IPersistentVrStateCallbacks cb) {
1365 mPersistentVrStateRemoteCallbacks.register(cb);
1366 }
1367
1368 private void removePersistentStateCallback(IPersistentVrStateCallbacks cb) {
1369 mPersistentVrStateRemoteCallbacks.unregister(cb);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001370 }
1371
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001372 private boolean getVrMode() {
Ruben Brunke24b9a62016-02-16 21:38:24 -08001373 synchronized (mLock) {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001374 return mVrModeEnabled;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001375 }
1376 }
Santos Cordone6d77232017-08-08 17:11:41 -07001377
1378 private boolean getPersistentVrMode() {
1379 synchronized (mLock) {
1380 return mPersistentVrModeEnabled;
1381 }
1382 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001383}