blob: 45689ce73c9f2cc9f7af7551766fd318333c75d4 [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;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070021import android.annotation.NonNull;
Ruben Brunk8820f942016-05-09 12:46:28 -070022import android.app.ActivityManager;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070023import android.app.ActivityManagerInternal;
Svetoslav Ganov47d98de2016-03-01 15:01:14 -080024import android.app.AppOpsManager;
Julia Reynoldsb852e562017-06-06 16:14:18 -040025import android.app.INotificationManager;
Ruben Brunk98576cf2016-03-07 18:54:28 -080026import android.app.NotificationManager;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070027import android.app.Vr2dDisplayProperties;
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;
Santos Cordonc14513d2016-12-14 14:52:59 -080061
Ruben Brunke24b9a62016-02-16 21:38:24 -080062import com.android.internal.R;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060063import com.android.internal.util.DumpUtils;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070064import com.android.server.FgThread;
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 Brunke24b9a62016-02-16 21:38:24 -080068import com.android.server.utils.ManagedApplicationService;
69import com.android.server.utils.ManagedApplicationService.BinderChecker;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070070import com.android.server.utils.ManagedApplicationService.LogEvent;
71import com.android.server.utils.ManagedApplicationService.LogFormattable;
72import com.android.server.utils.ManagedApplicationService.PendingEvent;
73import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
74import com.android.server.wm.ActivityTaskManagerInternal;
75import com.android.server.wm.ActivityTaskManagerInternal.ScreenObserver;
76import com.android.server.wm.WindowManagerInternal;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080077
Dan Sandlerdc34df52016-04-07 21:04:46 -040078import java.io.FileDescriptor;
79import java.io.PrintWriter;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070080import java.text.SimpleDateFormat;
81import java.util.ArrayDeque;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080082import java.util.ArrayList;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070083import java.util.Arrays;
Ruben Brunk98576cf2016-03-07 18:54:28 -080084import java.util.Collection;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070085import java.util.Date;
Julia Reynoldsb852e562017-06-06 16:14:18 -040086import java.util.List;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080087import java.util.Objects;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080088
89/**
Ruben Brunke24b9a62016-02-16 21:38:24 -080090 * Service tracking whether VR mode is active, and notifying listening services of state changes.
91 * <p/>
92 * Services running in system server may modify the state of VrManagerService via the interface in
93 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
94 * interface given in VrStateListener.
95 * <p/>
96 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
97 * hardware/libhardware/modules/vr
98 * <p/>
99 * In general applications may enable or disable VR mode by calling
Ruben Brunk98576cf2016-03-07 18:54:28 -0800100 * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to
101 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800102 *
Elliot Waite54de7742017-01-11 15:30:35 -0800103 * @see android.service.vr.VrListenerService
104 * @see com.android.server.vr.VrManagerInternal
105 * @see com.android.server.vr.VrStateListener
Ruben Brunke24b9a62016-02-16 21:38:24 -0800106 *
107 * @hide
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800108 */
Jeff Sharkey9765e442017-12-14 22:15:14 -0700109public class VrManagerService extends SystemService
110 implements EnabledComponentChangeListener, ScreenObserver {
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800111
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800112 public static final String TAG = "VrManagerService";
Joe Onorato82ba91d2017-04-27 16:18:05 -0700113 static final boolean DBG = false;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800114
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700115 private static final int PENDING_STATE_DELAY_MS = 300;
Ruben Brunkd675f512017-10-03 15:39:41 -0700116 private static final int EVENT_LOG_SIZE = 64;
Ruben Brunk8820f942016-05-09 12:46:28 -0700117 private static final int INVALID_APPOPS_MODE = -1;
Ruben Brunk040484c2016-10-28 20:18:57 -0700118 /** Null set of sleep sleep flags. */
119 private static final int FLAG_NONE = 0;
120 /** Flag set when the device is not sleeping. */
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700121 private static final int FLAG_AWAKE = 1 << 0;
Ruben Brunk040484c2016-10-28 20:18:57 -0700122 /** Flag set when the screen has been turned on. */
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700123 private static final int FLAG_SCREEN_ON = 1 << 1;
124 /** Flag set when the keyguard is not active. */
125 private static final int FLAG_KEYGUARD_UNLOCKED = 1 << 2;
Ruben Brunk040484c2016-10-28 20:18:57 -0700126 /** Flag indicating that all system sleep flags have been set.*/
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700127 private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON | FLAG_KEYGUARD_UNLOCKED;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700128
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800129 private static native void initializeNative();
130 private static native void setVrModeNative(boolean enabled);
131
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800132 private final Object mLock = new Object();
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800133
134 private final IBinder mOverlayToken = new Binder();
135
Ruben Brunke24b9a62016-02-16 21:38:24 -0800136 // State protected by mLock
Ruben Brunk040484c2016-10-28 20:18:57 -0700137 private boolean mVrModeAllowed;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800138 private boolean mVrModeEnabled;
Zak Cohen56345f42017-01-26 13:54:28 -0800139 private boolean mPersistentVrModeEnabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400140 private boolean mRunning2dInVr;
141 private int mVrAppProcessId;
Ruben Brunke24b9a62016-02-16 21:38:24 -0800142 private EnabledComponentsObserver mComponentObserver;
143 private ManagedApplicationService mCurrentVrService;
Ruben Brunk52ea6622017-10-02 23:51:25 -0700144 private ManagedApplicationService mCurrentVrCompositorService;
Zak Cohen56345f42017-01-26 13:54:28 -0800145 private ComponentName mDefaultVrService;
Ruben Brunke24b9a62016-02-16 21:38:24 -0800146 private Context mContext;
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800147 private ComponentName mCurrentVrModeComponent;
148 private int mCurrentVrModeUser;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800149 private boolean mWasDefaultGranted;
150 private boolean mGuard;
Steven Thomasb70845c2017-03-16 14:32:37 -0700151 private final RemoteCallbackList<IVrStateCallbacks> mVrStateRemoteCallbacks =
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700152 new RemoteCallbackList<>();
Steven Thomasb70845c2017-03-16 14:32:37 -0700153 private final RemoteCallbackList<IPersistentVrStateCallbacks>
154 mPersistentVrStateRemoteCallbacks = new RemoteCallbackList<>();
Ruben Brunk8820f942016-05-09 12:46:28 -0700155 private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
156 private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700157 private VrState mPendingState;
Ruben Brunkd675f512017-10-03 15:39:41 -0700158 private boolean mLogLimitHit;
159 private final ArrayDeque<LogFormattable> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
Ruben Brunk8820f942016-05-09 12:46:28 -0700160 private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
Julia Reynoldsb852e562017-06-06 16:14:18 -0400161 private INotificationManager mNotificationManager;
Ruben Brunk040484c2016-10-28 20:18:57 -0700162 /** Tracks the state of the screen and keyguard UI.*/
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700163 private int mSystemSleepFlags = FLAG_AWAKE | FLAG_KEYGUARD_UNLOCKED;
Steven Thomas68cc84f2017-06-08 16:55:04 -0700164 /**
165 * Set when ACTION_USER_UNLOCKED is fired. We shouldn't try to bind to the
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700166 * vr service before then. This gets set only once the first time the user unlocks the device
167 * and stays true thereafter.
Steven Thomas68cc84f2017-06-08 16:55:04 -0700168 */
169 private boolean mUserUnlocked;
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700170 private Vr2dDisplay mVr2dDisplay;
Steven Thomas68cc84f2017-06-08 16:55:04 -0700171 private boolean mBootsToVr;
Steven Thomas1356ec92017-09-07 11:26:38 -0700172 private boolean mStandby;
173 private boolean mUseStandbyToExitVrMode;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800174
Ruben Brunkd675f512017-10-03 15:39:41 -0700175 // Handles events from the managed services (e.g. VrListenerService and any bound VR compositor
176 // service).
177 private final ManagedApplicationService.EventCallback mEventCallback
178 = new ManagedApplicationService.EventCallback() {
179 @Override
180 public void onServiceEvent(LogEvent event) {
181 logEvent(event);
182
183 ComponentName component = null;
184 synchronized (mLock) {
185 component = ((mCurrentVrService == null) ? null : mCurrentVrService.getComponent());
Steven Thomas9aedfb12017-12-06 19:41:07 -0800186
187 // If the VrCore main service was disconnected or the binding died we'll rebind
188 // automatically. Call focusedActivityChanged() once we rebind.
189 if (component != null && component.equals(event.component) &&
190 (event.event == LogEvent.EVENT_DISCONNECTED ||
191 event.event == LogEvent.EVENT_BINDING_DIED)) {
192 callFocusedActivityChangedLocked();
193 }
Ruben Brunkd675f512017-10-03 15:39:41 -0700194 }
195
196 // If not on an AIO device and we permanently stopped trying to connect to the
197 // VrListenerService (or don't have one bound), leave persistent VR mode and VR mode.
198 if (!mBootsToVr && event.event == LogEvent.EVENT_STOPPED_PERMANENTLY &&
199 (component == null || component.equals(event.component))) {
200 Slog.e(TAG, "VrListenerSevice has died permanently, leaving system VR mode.");
201 // We're not a native VR device. Leave VR + persistent mode.
202 setPersistentVrModeEnabled(false);
203 }
204 }
205 };
206
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700207 private static final int MSG_VR_STATE_CHANGE = 0;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700208 private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
Zak Cohen732aeb02017-01-29 14:19:52 -0800209 private static final int MSG_PERSISTENT_VR_MODE_STATE_CHANGE = 2;
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700210
Ruben Brunk040484c2016-10-28 20:18:57 -0700211 /**
212 * Set whether VR mode may be enabled.
213 * <p/>
214 * If VR mode is not allowed to be enabled, calls to set VR mode will be cached. When VR mode
215 * is again allowed to be enabled, the most recent cached state will be applied.
216 *
Ruben Brunk040484c2016-10-28 20:18:57 -0700217 */
Steven Thomas68cc84f2017-06-08 16:55:04 -0700218 private void updateVrModeAllowedLocked() {
Steven Thomas1356ec92017-09-07 11:26:38 -0700219 boolean ignoreSleepFlags = mBootsToVr && mUseStandbyToExitVrMode;
220 boolean disallowedByStandby = mStandby && mUseStandbyToExitVrMode;
221 boolean allowed = (mSystemSleepFlags == FLAG_ALL || ignoreSleepFlags) && mUserUnlocked
222 && !disallowedByStandby;
Ruben Brunk040484c2016-10-28 20:18:57 -0700223 if (mVrModeAllowed != allowed) {
224 mVrModeAllowed = allowed;
Joe Onorato82ba91d2017-04-27 16:18:05 -0700225 if (DBG) Slog.d(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
Ruben Brunk040484c2016-10-28 20:18:57 -0700226 if (mVrModeAllowed) {
Steven Thomas68cc84f2017-06-08 16:55:04 -0700227 if (mBootsToVr) {
228 setPersistentVrModeEnabled(true);
229 }
Steven Thomas68cc84f2017-06-08 16:55:04 -0700230 if (mBootsToVr && !mVrModeEnabled) {
Albert Chaulk16d23972017-07-14 12:32:57 -0400231 setVrMode(true, mDefaultVrService, 0, -1, null);
Steven Thomas68cc84f2017-06-08 16:55:04 -0700232 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700233 } else {
Zak Cohen56345f42017-01-26 13:54:28 -0800234 // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
235 // exit persistent VR mode when screen is turned off.
Zak Cohen732aeb02017-01-29 14:19:52 -0800236 setPersistentModeAndNotifyListenersLocked(false);
Zak Cohen56345f42017-01-26 13:54:28 -0800237
Ruben Brunk040484c2016-10-28 20:18:57 -0700238 // Set pending state to current state.
239 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
Albert Chaulk16d23972017-07-14 12:32:57 -0400240 ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
241 mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
Ruben Brunk040484c2016-10-28 20:18:57 -0700242 : null;
243
244 // Unbind current VR service and do necessary callbacks.
Albert Chaulk16d23972017-07-14 12:32:57 -0400245 updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
Ruben Brunk040484c2016-10-28 20:18:57 -0700246 }
247 }
248 }
249
Ruben Brunk040484c2016-10-28 20:18:57 -0700250 private void setScreenOn(boolean isScreenOn) {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700251 setSystemState(FLAG_SCREEN_ON, isScreenOn);
252 }
253
Jeff Sharkey9765e442017-12-14 22:15:14 -0700254 @Override
255 public void onAwakeStateChanged(boolean isAwake) {
256 setSystemState(FLAG_AWAKE, isAwake);
257 }
258
259 @Override
260 public void onKeyguardStateChanged(boolean isShowing) {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700261 setSystemState(FLAG_KEYGUARD_UNLOCKED, !isShowing);
262 }
263
264 private void setSystemState(int flags, boolean isOn) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700265 synchronized(mLock) {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700266 int oldState = mSystemSleepFlags;
267 if (isOn) {
268 mSystemSleepFlags |= flags;
Ruben Brunk040484c2016-10-28 20:18:57 -0700269 } else {
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700270 mSystemSleepFlags &= ~flags;
Ruben Brunk040484c2016-10-28 20:18:57 -0700271 }
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700272 if (oldState != mSystemSleepFlags) {
273 if (DBG) Slog.d(TAG, "System state: " + getStateAsString());
274 updateVrModeAllowedLocked();
275 }
Steven Thomas68cc84f2017-06-08 16:55:04 -0700276 }
277 }
278
Santos Cordonb5cbecb2017-10-05 11:31:15 -0700279 private String getStateAsString() {
280 return new StringBuilder()
281 .append((mSystemSleepFlags & FLAG_AWAKE) != 0 ? "awake, " : "")
282 .append((mSystemSleepFlags & FLAG_SCREEN_ON) != 0 ? "screen_on, " : "")
283 .append((mSystemSleepFlags & FLAG_KEYGUARD_UNLOCKED) != 0 ? "keyguard_off" : "")
284 .toString();
285 }
286
Steven Thomas68cc84f2017-06-08 16:55:04 -0700287 private void setUserUnlocked() {
288 synchronized(mLock) {
289 mUserUnlocked = true;
290 updateVrModeAllowedLocked();
Ruben Brunk040484c2016-10-28 20:18:57 -0700291 }
292 }
293
Steven Thomas1356ec92017-09-07 11:26:38 -0700294 private void setStandbyEnabled(boolean standby) {
295 synchronized(mLock) {
296 if (!mBootsToVr) {
297 Slog.e(TAG, "Attempting to set standby mode on a non-standalone device");
298 return;
299 }
300 mStandby = standby;
301 updateVrModeAllowedLocked();
302 }
303 }
304
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700305 private final Handler mHandler = new Handler() {
306 @Override
307 public void handleMessage(Message msg) {
308 switch(msg.what) {
309 case MSG_VR_STATE_CHANGE : {
310 boolean state = (msg.arg1 == 1);
Steven Thomasb70845c2017-03-16 14:32:37 -0700311 int i = mVrStateRemoteCallbacks.beginBroadcast();
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700312 while (i > 0) {
313 i--;
314 try {
Steven Thomasb70845c2017-03-16 14:32:37 -0700315 mVrStateRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700316 } catch (RemoteException e) {
317 // Noop
318 }
319 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700320 mVrStateRemoteCallbacks.finishBroadcast();
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700321 } break;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700322 case MSG_PENDING_VR_STATE_CHANGE : {
323 synchronized(mLock) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700324 if (mVrModeAllowed) {
325 VrManagerService.this.consumeAndApplyPendingStateLocked();
326 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700327 }
328 } break;
Zak Cohen732aeb02017-01-29 14:19:52 -0800329 case MSG_PERSISTENT_VR_MODE_STATE_CHANGE : {
330 boolean state = (msg.arg1 == 1);
Steven Thomasb70845c2017-03-16 14:32:37 -0700331 int i = mPersistentVrStateRemoteCallbacks.beginBroadcast();
332 while (i > 0) {
333 i--;
334 try {
335 mPersistentVrStateRemoteCallbacks.getBroadcastItem(i)
336 .onPersistentVrStateChanged(state);
337 } catch (RemoteException e) {
338 // Noop
339 }
Zak Cohen732aeb02017-01-29 14:19:52 -0800340 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700341 mPersistentVrStateRemoteCallbacks.finishBroadcast();
Zak Cohen732aeb02017-01-29 14:19:52 -0800342 } break;
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700343 default :
344 throw new IllegalStateException("Unknown message type: " + msg.what);
345 }
346 }
347 };
348
Ruben Brunkd675f512017-10-03 15:39:41 -0700349 // Event used to log when settings are changed for dumpsys logs.
350 private static class SettingEvent implements LogFormattable {
351 public final long timestamp;
352 public final String what;
353
354 SettingEvent(String what) {
355 this.timestamp = System.currentTimeMillis();
356 this.what = what;
357 }
358
359 @Override
360 public String toLogString(SimpleDateFormat dateFormat) {
361 return dateFormat.format(new Date(timestamp)) + " " + what;
362 }
363 }
364
365 // Event used to track changes of the primary on-screen VR activity.
366 private static class VrState implements LogFormattable {
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700367 final boolean enabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400368 final boolean running2dInVr;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700369 final int userId;
Albert Chaulk16d23972017-07-14 12:32:57 -0400370 final int processId;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700371 final ComponentName targetPackageName;
372 final ComponentName callingPackage;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700373 final long timestamp;
374 final boolean defaultPermissionsGranted;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700375
Albert Chaulk16d23972017-07-14 12:32:57 -0400376 VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
377 int processId, ComponentName callingPackage) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700378 this.enabled = enabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400379 this.running2dInVr = running2dInVr;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700380 this.userId = userId;
Albert Chaulk16d23972017-07-14 12:32:57 -0400381 this.processId = processId;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700382 this.targetPackageName = targetPackageName;
383 this.callingPackage = callingPackage;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700384 this.defaultPermissionsGranted = false;
385 this.timestamp = System.currentTimeMillis();
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700386 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700387
Albert Chaulk16d23972017-07-14 12:32:57 -0400388 VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
389 int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700390 this.enabled = enabled;
Albert Chaulk16d23972017-07-14 12:32:57 -0400391 this.running2dInVr = running2dInVr;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700392 this.userId = userId;
Albert Chaulk16d23972017-07-14 12:32:57 -0400393 this.processId = processId;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700394 this.targetPackageName = targetPackageName;
395 this.callingPackage = callingPackage;
396 this.defaultPermissionsGranted = defaultPermissionsGranted;
397 this.timestamp = System.currentTimeMillis();
398 }
Ruben Brunkd675f512017-10-03 15:39:41 -0700399
400 @Override
401 public String toLogString(SimpleDateFormat dateFormat) {
402 String tab = " ";
403 String newLine = "\n";
404 StringBuilder sb = new StringBuilder(dateFormat.format(new Date(timestamp)));
405 sb.append(tab);
406 sb.append("State changed to:");
407 sb.append(tab);
408 sb.append((enabled) ? "ENABLED" : "DISABLED");
409 sb.append(newLine);
410 if (enabled) {
411 sb.append(tab);
412 sb.append("User=");
413 sb.append(userId);
414 sb.append(newLine);
415 sb.append(tab);
416 sb.append("Current VR Activity=");
417 sb.append((callingPackage == null) ? "None" : callingPackage.flattenToString());
418 sb.append(newLine);
419 sb.append(tab);
420 sb.append("Bound VrListenerService=");
421 sb.append((targetPackageName == null) ? "None"
422 : targetPackageName.flattenToString());
423 sb.append(newLine);
424 if (defaultPermissionsGranted) {
425 sb.append(tab);
426 sb.append("Default permissions granted to the bound VrListenerService.");
427 sb.append(newLine);
428 }
429 }
430 return sb.toString();
431 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700432 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700433
Ruben Brunke24b9a62016-02-16 21:38:24 -0800434 private static final BinderChecker sBinderChecker = new BinderChecker() {
435 @Override
436 public IInterface asInterface(IBinder binder) {
437 return IVrListener.Stub.asInterface(binder);
438 }
439
440 @Override
441 public boolean checkType(IInterface service) {
442 return service instanceof IVrListener;
443 }
444 };
445
Ruben Brunk8820f942016-05-09 12:46:28 -0700446 private final class NotificationAccessManager {
447 private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700448 private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
449 new ArrayMap<>();
Ruben Brunk8820f942016-05-09 12:46:28 -0700450
451 public void update(Collection<String> packageNames) {
452 int currentUserId = ActivityManager.getCurrentUser();
453
Ruben Brunk8820f942016-05-09 12:46:28 -0700454 ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
455 if (allowed == null) {
456 allowed = new ArraySet<>();
457 }
458
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700459 // Make sure we revoke notification access for listeners in other users
460 final int listenerCount = mNotificationAccessPackageToUserId.size();
461 for (int i = listenerCount - 1; i >= 0; i--) {
462 final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
463 if (grantUserId != currentUserId) {
464 String packageName = mNotificationAccessPackageToUserId.keyAt(i);
465 revokeNotificationListenerAccess(packageName, grantUserId);
466 revokeNotificationPolicyAccess(packageName);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000467 revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700468 mNotificationAccessPackageToUserId.removeAt(i);
469 }
470 }
471
Ruben Brunk8820f942016-05-09 12:46:28 -0700472 for (String pkg : allowed) {
473 if (!packageNames.contains(pkg)) {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700474 revokeNotificationListenerAccess(pkg, currentUserId);
Ruben Brunk8820f942016-05-09 12:46:28 -0700475 revokeNotificationPolicyAccess(pkg);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000476 revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700477 mNotificationAccessPackageToUserId.remove(pkg);
Ruben Brunk8820f942016-05-09 12:46:28 -0700478 }
479 }
480 for (String pkg : packageNames) {
481 if (!allowed.contains(pkg)) {
482 grantNotificationPolicyAccess(pkg);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700483 grantNotificationListenerAccess(pkg, currentUserId);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000484 grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700485 mNotificationAccessPackageToUserId.put(pkg, currentUserId);
Ruben Brunk8820f942016-05-09 12:46:28 -0700486 }
487 }
488
489 allowed.clear();
490 allowed.addAll(packageNames);
491 mAllowedPackages.put(currentUserId, allowed);
492 }
493 }
494
Ruben Brunke24b9a62016-02-16 21:38:24 -0800495 /**
496 * Called when a user, package, or setting changes that could affect whether or not the
497 * currently bound VrListenerService is changed.
498 */
499 @Override
500 public void onEnabledComponentChanged() {
501 synchronized (mLock) {
Ruben Brunk8820f942016-05-09 12:46:28 -0700502 int currentUser = ActivityManager.getCurrentUser();
Ruben Brunk8820f942016-05-09 12:46:28 -0700503 // Update listeners
504 ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
505
506 ArraySet<String> enabledPackages = new ArraySet<>();
507 for (ComponentName n : enabledListeners) {
508 String pkg = n.getPackageName();
509 if (isDefaultAllowed(pkg)) {
510 enabledPackages.add(n.getPackageName());
511 }
512 }
513 mNotifAccessManager.update(enabledPackages);
514
Ruben Brunk040484c2016-10-28 20:18:57 -0700515 if (!mVrModeAllowed) {
516 return; // Don't do anything, we shouldn't be in VR mode.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800517 }
518
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700519 // If there is a pending state change, we'd better deal with that first
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800520 consumeAndApplyPendingStateLocked(false);
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700521
522 if (mCurrentVrService == null) {
523 return; // No active services
524 }
525
Ruben Brunke24b9a62016-02-16 21:38:24 -0800526 // There is an active service, update it if needed
Albert Chaulk16d23972017-07-14 12:32:57 -0400527 updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
528 mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
529 mVrAppProcessId, mCurrentVrModeComponent);
Ruben Brunke24b9a62016-02-16 21:38:24 -0800530 }
531 }
532
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700533 private final IVrManager mVrManager = new IVrManager.Stub() {
534
535 @Override
536 public void registerListener(IVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700537 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
538 Manifest.permission.ACCESS_VR_STATE);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700539 if (cb == null) {
540 throw new IllegalArgumentException("Callback binder object is null.");
541 }
542
543 VrManagerService.this.addStateCallback(cb);
544 }
545
546 @Override
547 public void unregisterListener(IVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700548 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
549 Manifest.permission.ACCESS_VR_STATE);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700550 if (cb == null) {
551 throw new IllegalArgumentException("Callback binder object is null.");
552 }
553
554 VrManagerService.this.removeStateCallback(cb);
555 }
556
557 @Override
Steven Thomasb70845c2017-03-16 14:32:37 -0700558 public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700559 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
560 Manifest.permission.ACCESS_VR_STATE);
Steven Thomasb70845c2017-03-16 14:32:37 -0700561 if (cb == null) {
562 throw new IllegalArgumentException("Callback binder object is null.");
563 }
564
565 VrManagerService.this.addPersistentStateCallback(cb);
566 }
567
568 @Override
569 public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
Santos Cordone6d77232017-08-08 17:11:41 -0700570 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
571 Manifest.permission.ACCESS_VR_STATE);
Steven Thomasb70845c2017-03-16 14:32:37 -0700572 if (cb == null) {
573 throw new IllegalArgumentException("Callback binder object is null.");
574 }
575
576 VrManagerService.this.removePersistentStateCallback(cb);
577 }
578
579 @Override
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700580 public boolean getVrModeState() {
Santos Cordone6d77232017-08-08 17:11:41 -0700581 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
582 Manifest.permission.ACCESS_VR_STATE);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700583 return VrManagerService.this.getVrMode();
584 }
585
Dan Sandlerdc34df52016-04-07 21:04:46 -0400586 @Override
Santos Cordone6d77232017-08-08 17:11:41 -0700587 public boolean getPersistentVrModeEnabled() {
588 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER,
589 Manifest.permission.ACCESS_VR_STATE);
590 return VrManagerService.this.getPersistentVrMode();
591 }
592
593 @Override
Zak Cohen56345f42017-01-26 13:54:28 -0800594 public void setPersistentVrModeEnabled(boolean enabled) {
Santos Cordone6d77232017-08-08 17:11:41 -0700595 enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
Zak Cohen56345f42017-01-26 13:54:28 -0800596 VrManagerService.this.setPersistentVrModeEnabled(enabled);
597 }
598
599 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700600 public void setVr2dDisplayProperties(
601 Vr2dDisplayProperties vr2dDisplayProp) {
Santos Cordone6d77232017-08-08 17:11:41 -0700602 enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700603 VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700604 }
605
606 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700607 public int getVr2dDisplayId() {
608 return VrManagerService.this.getVr2dDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -0800609 }
610
611 @Override
Ruben Brunk52ea6622017-10-02 23:51:25 -0700612 public void setAndBindCompositor(String componentName) {
613 enforceCallerPermissionAnyOf(Manifest.permission.RESTRICTED_VR_ACCESS);
614 VrManagerService.this.setAndBindCompositor(
615 (componentName == null) ? null : ComponentName.unflattenFromString(componentName));
616 }
617
618 @Override
Steven Thomas1356ec92017-09-07 11:26:38 -0700619 public void setStandbyEnabled(boolean standby) {
620 enforceCallerPermissionAnyOf(Manifest.permission.ACCESS_VR_MANAGER);
621 VrManagerService.this.setStandbyEnabled(standby);
622 }
623
624 @Override
Dan Sandlerdc34df52016-04-07 21:04:46 -0400625 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600626 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
627
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700628 pw.println("********* Dump of VrManagerService *********");
Ruben Brunk040484c2016-10-28 20:18:57 -0700629 pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
Zak Cohen56345f42017-01-26 13:54:28 -0800630 pw.println("Persistent VR mode is currently: " +
631 ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
Ruben Brunkd675f512017-10-03 15:39:41 -0700632 pw.println("Currently bound VR listener service: "
Ruben Brunka25b93c2017-10-05 19:41:42 -0700633 + ((mCurrentVrService == null)
634 ? "None" : mCurrentVrService.getComponent().flattenToString()));
Ruben Brunk52ea6622017-10-02 23:51:25 -0700635 pw.println("Currently bound VR compositor service: "
636 + ((mCurrentVrCompositorService == null)
Ruben Brunkd675f512017-10-03 15:39:41 -0700637 ? "None" : mCurrentVrCompositorService.getComponent().flattenToString()));
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700638 pw.println("Previous state transitions:\n");
639 String tab = " ";
640 dumpStateTransitions(pw);
641 pw.println("\n\nRemote Callbacks:");
Steven Thomasb70845c2017-03-16 14:32:37 -0700642 int i=mVrStateRemoteCallbacks.beginBroadcast(); // create the broadcast item array
Dan Sandlerdc34df52016-04-07 21:04:46 -0400643 while(i-->0) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700644 pw.print(tab);
Steven Thomasb70845c2017-03-16 14:32:37 -0700645 pw.print(mVrStateRemoteCallbacks.getBroadcastItem(i));
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700646 if (i>0) pw.println(",");
Dan Sandlerdc34df52016-04-07 21:04:46 -0400647 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700648 mVrStateRemoteCallbacks.finishBroadcast();
649 pw.println("\n\nPersistent Vr State Remote Callbacks:");
650 i=mPersistentVrStateRemoteCallbacks.beginBroadcast();
651 while(i-->0) {
652 pw.print(tab);
653 pw.print(mPersistentVrStateRemoteCallbacks.getBroadcastItem(i));
654 if (i>0) pw.println(",");
655 }
656 mPersistentVrStateRemoteCallbacks.finishBroadcast();
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700657 pw.println("\n");
658 pw.println("Installed VrListenerService components:");
659 int userId = mCurrentVrModeUser;
660 ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
661 if (installed == null || installed.size() == 0) {
662 pw.println("None");
663 } else {
664 for (ComponentName n : installed) {
665 pw.print(tab);
666 pw.println(n.flattenToString());
667 }
668 }
669 pw.println("Enabled VrListenerService components:");
670 ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
671 if (enabled == null || enabled.size() == 0) {
672 pw.println("None");
673 } else {
674 for (ComponentName n : enabled) {
675 pw.print(tab);
676 pw.println(n.flattenToString());
677 }
678 }
679 pw.println("\n");
680 pw.println("********* End of VrManagerService Dump *********");
Dan Sandlerdc34df52016-04-07 21:04:46 -0400681 }
682
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700683 };
684
Santos Cordone6d77232017-08-08 17:11:41 -0700685 /**
686 * Enforces that at lease one of the specified permissions is held by the caller.
687 * Throws SecurityException if none of the specified permissions are held.
688 *
689 * @param permissions One or more permissions to check against.
690 */
691 private void enforceCallerPermissionAnyOf(String... permissions) {
692 for (String permission : permissions) {
693 if (mContext.checkCallingOrSelfPermission(permission)
694 == PackageManager.PERMISSION_GRANTED) {
695 return;
696 }
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700697 }
Santos Cordone6d77232017-08-08 17:11:41 -0700698 throw new SecurityException("Caller does not hold at least one of the permissions: "
699 + Arrays.toString(permissions));
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700700 }
701
Ruben Brunke24b9a62016-02-16 21:38:24 -0800702 /**
703 * Implementation of VrManagerInternal. Callable only from system services.
704 */
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800705 private final class LocalService extends VrManagerInternal {
706 @Override
Albert Chaulk16d23972017-07-14 12:32:57 -0400707 public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800708 ComponentName callingPackage) {
Albert Chaulk16d23972017-07-14 12:32:57 -0400709 VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
Ruben Brunkaf9f0042016-06-15 17:08:35 -0700710 }
711
712 @Override
Ruben Brunk040484c2016-10-28 20:18:57 -0700713 public void onScreenStateChanged(boolean isScreenOn) {
714 VrManagerService.this.setScreenOn(isScreenOn);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800715 }
716
717 @Override
Ruben Brunk8f1d5cb2016-03-22 18:08:41 -0700718 public boolean isCurrentVrListener(String packageName, int userId) {
719 return VrManagerService.this.isCurrentVrListener(packageName, userId);
720 }
721
722 @Override
Ruben Brunke24b9a62016-02-16 21:38:24 -0800723 public int hasVrPackage(ComponentName packageName, int userId) {
724 return VrManagerService.this.hasVrPackage(packageName, userId);
725 }
Zak Cohen56345f42017-01-26 13:54:28 -0800726
727 @Override
728 public void setPersistentVrModeEnabled(boolean enabled) {
729 VrManagerService.this.setPersistentVrModeEnabled(enabled);
730 }
Zak Cohen732aeb02017-01-29 14:19:52 -0800731
732 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700733 public void setVr2dDisplayProperties(
734 Vr2dDisplayProperties compatDisplayProp) {
735 VrManagerService.this.setVr2dDisplayProperties(compatDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700736 }
737
738 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700739 public int getVr2dDisplayId() {
740 return VrManagerService.this.getVr2dDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -0800741 }
742
743 @Override
Steven Thomasb70845c2017-03-16 14:32:37 -0700744 public void addPersistentVrModeStateListener(IPersistentVrStateCallbacks listener) {
745 VrManagerService.this.addPersistentStateCallback(listener);
Zak Cohen732aeb02017-01-29 14:19:52 -0800746 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800747 }
748
749 public VrManagerService(Context context) {
750 super(context);
751 }
752
753 @Override
754 public void onStart() {
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800755 synchronized(mLock) {
756 initializeNative();
Ruben Brunke24b9a62016-02-16 21:38:24 -0800757 mContext = getContext();
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800758 }
759
Steven Thomas68cc84f2017-06-08 16:55:04 -0700760 mBootsToVr = SystemProperties.getBoolean("ro.boot.vr", false);
Steven Thomas1356ec92017-09-07 11:26:38 -0700761 mUseStandbyToExitVrMode = mBootsToVr
Steven Thomasd007c462017-11-13 16:31:37 -0800762 && SystemProperties.getBoolean("persist.vr.use_standby_to_exit_vr_mode", true);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800763 publishLocalService(VrManagerInternal.class, new LocalService());
Craig Donner8deb67c2017-02-07 18:10:32 -0800764 publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800765 }
766
Ruben Brunke24b9a62016-02-16 21:38:24 -0800767 @Override
768 public void onBootPhase(int phase) {
Ruben Brunk85070042016-03-21 12:10:38 -0700769 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700770 LocalServices.getService(ActivityTaskManagerInternal.class)
Jeff Sharkey9765e442017-12-14 22:15:14 -0700771 .registerScreenObserver(this);
772
Julia Reynoldsb852e562017-06-06 16:14:18 -0400773 mNotificationManager = INotificationManager.Stub.asInterface(
774 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800775 synchronized (mLock) {
776 Looper looper = Looper.getMainLooper();
777 Handler handler = new Handler(looper);
778 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
779 listeners.add(this);
780 mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
781 Settings.Secure.ENABLED_VR_LISTENERS, looper,
782 android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
783 VrListenerService.SERVICE_INTERFACE, mLock, listeners);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800784
Ruben Brunke24b9a62016-02-16 21:38:24 -0800785 mComponentObserver.rebuildAll();
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800786 }
Zak Cohen56345f42017-01-26 13:54:28 -0800787
788 //TODO: something more robust than picking the first one
789 ArraySet<ComponentName> defaultVrComponents =
790 SystemConfig.getInstance().getDefaultVrComponents();
791 if (defaultVrComponents.size() > 0) {
792 mDefaultVrService = defaultVrComponents.valueAt(0);
793 } else {
794 Slog.i(TAG, "No default vr listener service found.");
795 }
Santos Cordon2f22da72017-02-27 17:24:44 -0800796
797 DisplayManager dm =
798 (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
Tarandeep Singhe1cfcf42017-07-10 18:50:00 -0700799 mVr2dDisplay = new Vr2dDisplay(
800 dm,
801 LocalServices.getService(ActivityManagerInternal.class),
802 LocalServices.getService(WindowManagerInternal.class),
803 mVrManager);
Santos Cordonc22c5632017-06-21 16:03:49 -0700804 mVr2dDisplay.init(getContext(), mBootsToVr);
Steven Thomas68cc84f2017-06-08 16:55:04 -0700805
806 IntentFilter intentFilter = new IntentFilter();
807 intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
808 getContext().registerReceiver(new BroadcastReceiver() {
809 @Override
810 public void onReceive(Context context, Intent intent) {
811 if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
812 VrManagerService.this.setUserUnlocked();
813 }
814 }
815 }, intentFilter);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800816 }
817 }
818
Ruben Brunke24b9a62016-02-16 21:38:24 -0800819 @Override
820 public void onStartUser(int userHandle) {
821 synchronized (mLock) {
822 mComponentObserver.onUsersChanged();
823 }
824 }
825
826 @Override
827 public void onSwitchUser(int userHandle) {
Fyodor Kupolovab781c22017-12-19 16:44:26 -0800828 FgThread.getHandler().post(() -> {
829 synchronized (mLock) {
830 mComponentObserver.onUsersChanged();
831 }
832 });
Ruben Brunke24b9a62016-02-16 21:38:24 -0800833
834 }
835
836 @Override
837 public void onStopUser(int userHandle) {
838 synchronized (mLock) {
839 mComponentObserver.onUsersChanged();
840 }
841
842 }
843
844 @Override
845 public void onCleanupUser(int userHandle) {
846 synchronized (mLock) {
847 mComponentObserver.onUsersChanged();
848 }
849 }
850
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700851 private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
852 AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
853
854 // If user changed drop restrictions for the old user.
855 if (oldUserId != newUserId) {
856 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
857 false, mOverlayToken, null, oldUserId);
858 }
859
860 // Apply the restrictions for the current user based on vr state
861 String[] exemptions = (exemptedPackage == null) ? new String[0] :
862 new String[] { exemptedPackage };
863
864 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
Ruben Brunk2781b412017-04-24 12:07:17 -0700865 mVrModeEnabled, mOverlayToken, exemptions, newUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700866 }
867
868 private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
869 String oldVrServicePackage, int oldUserId) {
870 // If VR state changed and we also have a VR service change.
871 if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
872 return;
873 }
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800874 final long identity = Binder.clearCallingIdentity();
875 try {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700876 // Set overlay exception state based on VR enabled and current service
877 updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800878 } finally {
879 Binder.restoreCallingIdentity(identity);
880 }
881 }
882
Ruben Brunke24b9a62016-02-16 21:38:24 -0800883 /**
884 * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
885 * the currently selected VR listener service. If the component selected for the VR listener
886 * service has changed, unbind the previous listener and bind the new listener (if enabled).
887 * <p/>
888 * Note: Must be called while holding {@code mLock}.
889 *
890 * @param enabled new state for VR mode.
Albert Chaulk16d23972017-07-14 12:32:57 -0400891 * @param running2dInVr true if we have a top-level 2D intent.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800892 * @param component new component to be bound as a VR listener.
893 * @param userId user owning the component to be bound.
Albert Chaulk16d23972017-07-14 12:32:57 -0400894 * @param processId the process hosting the activity specified by calling.
895 * @param calling the component currently using VR mode or a 2D intent.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800896 *
897 * @return {@code true} if the component/user combination specified is valid.
898 */
Albert Chaulk16d23972017-07-14 12:32:57 -0400899 private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
900 @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800901
902 boolean sendUpdatedCaller = false;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800903 final long identity = Binder.clearCallingIdentity();
904 try {
Ruben Brunke24b9a62016-02-16 21:38:24 -0800905
Ruben Brunk98576cf2016-03-07 18:54:28 -0800906 boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
907 EnabledComponentsObserver.NO_ERROR);
Ruben Brunk040484c2016-10-28 20:18:57 -0700908 boolean goingIntoVrMode = validUserComponent && enabled;
909 if (!mVrModeEnabled && !goingIntoVrMode) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700910 return validUserComponent; // Disabled -> Disabled transition does nothing.
911 }
Ruben Brunke24b9a62016-02-16 21:38:24 -0800912
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700913 String oldVrServicePackage = mCurrentVrService != null
914 ? mCurrentVrService.getComponent().getPackageName() : null;
915 final int oldUserId = mCurrentVrModeUser;
916
Ruben Brunk040484c2016-10-28 20:18:57 -0700917 // Notify system services and VR HAL of mode change.
918 changeVrModeLocked(goingIntoVrMode);
Ruben Brunk29931bc2016-03-11 00:24:26 -0800919
Ruben Brunk040484c2016-10-28 20:18:57 -0700920 boolean nothingChanged = false;
921 if (!goingIntoVrMode) {
922 // Not going into VR mode, unbind whatever is running
Ruben Brunk98576cf2016-03-07 18:54:28 -0800923 if (mCurrentVrService != null) {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800924 Slog.i(TAG, "Leaving VR mode, disconnecting "
925 + mCurrentVrService.getComponent() + " for user "
926 + mCurrentVrService.getUserId());
Ruben Brunk98576cf2016-03-07 18:54:28 -0800927 mCurrentVrService.disconnect();
Ruben Brunk52ea6622017-10-02 23:51:25 -0700928 updateCompositorServiceLocked(UserHandle.USER_NULL, null);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800929 mCurrentVrService = null;
Ruben Brunk040484c2016-10-28 20:18:57 -0700930 } else {
931 nothingChanged = true;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800932 }
933 } else {
Ruben Brunk040484c2016-10-28 20:18:57 -0700934 // Going into VR mode
Ruben Brunk98576cf2016-03-07 18:54:28 -0800935 if (mCurrentVrService != null) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700936 // Unbind any running service that doesn't match the latest component/user
937 // selection.
Ruben Brunk98576cf2016-03-07 18:54:28 -0800938 if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800939 Slog.i(TAG, "VR mode component changed to " + component
940 + ", disconnecting " + mCurrentVrService.getComponent()
941 + " for user " + mCurrentVrService.getUserId());
Ruben Brunk52ea6622017-10-02 23:51:25 -0700942 updateCompositorServiceLocked(UserHandle.USER_NULL, null);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800943 createAndConnectService(component, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800944 sendUpdatedCaller = true;
Ruben Brunk040484c2016-10-28 20:18:57 -0700945 } else {
946 nothingChanged = true;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800947 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700948 // The service with the correct component/user is already bound, do nothing.
Ruben Brunk98576cf2016-03-07 18:54:28 -0800949 } else {
Ruben Brunk040484c2016-10-28 20:18:57 -0700950 // Nothing was previously running, bind a new service for the latest
951 // component/user selection.
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800952 createAndConnectService(component, userId);
953 sendUpdatedCaller = true;
954 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800955 }
956
Ruben Brunk666505e2017-05-04 16:54:46 -0700957 if ((calling != null || mPersistentVrModeEnabled)
Alex Sakhartchoukec4d3e42017-07-24 22:12:39 -0400958 && !Objects.equals(calling, mCurrentVrModeComponent)
959 || mRunning2dInVr != running2dInVr) {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700960 sendUpdatedCaller = true;
961 }
Ruben Brunk7196a6b2017-03-22 15:43:24 -0700962 mCurrentVrModeComponent = calling;
Albert Chaulk16d23972017-07-14 12:32:57 -0400963 mRunning2dInVr = running2dInVr;
964 mVrAppProcessId = processId;
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700965
966 if (mCurrentVrModeUser != userId) {
Ruben Brunk98576cf2016-03-07 18:54:28 -0800967 mCurrentVrModeUser = userId;
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800968 sendUpdatedCaller = true;
969 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800970
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700971 String newVrServicePackage = mCurrentVrService != null
972 ? mCurrentVrService.getComponent().getPackageName() : null;
973 final int newUserId = mCurrentVrModeUser;
974
975 // Update AppOps settings that change state when entering/exiting VR mode, or changing
976 // the current VrListenerService.
977 updateDependentAppOpsLocked(newVrServicePackage, newUserId,
978 oldVrServicePackage, oldUserId);
979
Ruben Brunk98576cf2016-03-07 18:54:28 -0800980 if (mCurrentVrService != null && sendUpdatedCaller) {
Steven Thomas9aedfb12017-12-06 19:41:07 -0800981 callFocusedActivityChangedLocked();
Ruben Brunk98576cf2016-03-07 18:54:28 -0800982 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700983
984 if (!nothingChanged) {
985 logStateLocked();
986 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800987
988 return validUserComponent;
989 } finally {
990 Binder.restoreCallingIdentity(identity);
991 }
992 }
993
Steven Thomas9aedfb12017-12-06 19:41:07 -0800994 private void callFocusedActivityChangedLocked() {
995 final ComponentName c = mCurrentVrModeComponent;
996 final boolean b = mRunning2dInVr;
997 final int pid = mVrAppProcessId;
998 mCurrentVrService.sendEvent(new PendingEvent() {
999 @Override
1000 public void runEvent(IInterface service) throws RemoteException {
1001 // Under specific (and unlikely) timing scenarios, when VrCore
1002 // crashes and is rebound, focusedActivityChanged() may be
1003 // called a 2nd time with the same arguments. IVrListeners
1004 // should make sure to handle that scenario gracefully.
1005 IVrListener l = (IVrListener) service;
1006 l.focusedActivityChanged(c, b, pid);
1007 }
1008 });
1009 }
1010
Ruben Brunk8820f942016-05-09 12:46:28 -07001011 private boolean isDefaultAllowed(String packageName) {
Craig Donner0568f282016-04-11 13:02:44 -07001012 PackageManager pm = mContext.getPackageManager();
Ruben Brunk8820f942016-05-09 12:46:28 -07001013
1014 ApplicationInfo info = null;
1015 try {
1016 info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
1017 } catch (NameNotFoundException e) {
1018 }
1019
1020 if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
1021 return false;
1022 }
1023 return true;
1024 }
1025
Ruben Brunk98576cf2016-03-07 18:54:28 -08001026 private void grantNotificationPolicyAccess(String pkg) {
1027 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk8820f942016-05-09 12:46:28 -07001028 nm.setNotificationPolicyAccessGranted(pkg, true);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001029 }
1030
1031 private void revokeNotificationPolicyAccess(String pkg) {
1032 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk8820f942016-05-09 12:46:28 -07001033 // Remove any DND zen rules possibly created by the package.
1034 nm.removeAutomaticZenRules(pkg);
1035 // Remove Notification Policy Access.
1036 nm.setNotificationPolicyAccessGranted(pkg, false);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001037 }
1038
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001039 private void grantNotificationListenerAccess(String pkg, int userId) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001040 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001041 PackageManager pm = mContext.getPackageManager();
1042 ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001043 userId, NotificationListenerService.SERVICE_INTERFACE,
Ruben Brunk98576cf2016-03-07 18:54:28 -08001044 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001045
Ruben Brunk98576cf2016-03-07 18:54:28 -08001046 for (ComponentName c : possibleServices) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001047 if (Objects.equals(c.getPackageName(), pkg)) {
1048 nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001049 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001050 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001051 }
1052
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001053 private void revokeNotificationListenerAccess(String pkg, int userId) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001054 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
1055 List<ComponentName> current = nm.getEnabledNotificationListeners(userId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001056
Julia Reynoldsb852e562017-06-06 16:14:18 -04001057 for (ComponentName component : current) {
Ruben Brunk1f4f26b2016-08-02 14:21:36 -07001058 if (component != null && component.getPackageName().equals(pkg)) {
Julia Reynoldsb852e562017-06-06 16:14:18 -04001059 nm.setNotificationListenerAccessGrantedForUser(component, userId, false);
Ruben Brunk8820f942016-05-09 12:46:28 -07001060 }
1061 }
Ruben Brunk98576cf2016-03-07 18:54:28 -08001062 }
1063
Craig Donnercae8cdf2016-07-28 22:39:05 +00001064 private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
1065 // Don't clobber the user if permission set in current state explicitly
1066 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
Ruben Brunk12ab5e12016-11-10 15:27:30 -08001067 try {
1068 mContext.getPackageManager().grantRuntimePermission(pkg,
1069 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
1070 } catch (IllegalArgumentException e) {
1071 // Package was removed during update.
1072 Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
1073 + " was removed.");
1074 }
Craig Donnercae8cdf2016-07-28 22:39:05 +00001075 }
1076 }
1077
1078 private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
1079 // Don't clobber the user if permission set in current state explicitly
1080 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
Ruben Brunk12ab5e12016-11-10 15:27:30 -08001081 try {
1082 mContext.getPackageManager().revokeRuntimePermission(pkg,
1083 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
1084 } catch (IllegalArgumentException e) {
1085 // Package was removed during update.
1086 Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
1087 + " was removed.");
1088 }
Craig Donnercae8cdf2016-07-28 22:39:05 +00001089 }
1090 }
1091
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001092 private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
1093 final int flags = mContext.getPackageManager().getPermissionFlags(
1094 permission, pkg, new UserHandle(userId));
1095 return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
1096 | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
1097 }
1098
1099 private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
1100 String flat = Settings.Secure.getStringForUser(resolver,
1101 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -08001102
1103 ArraySet<String> current = new ArraySet<>();
1104 if (flat != null) {
1105 String[] allowed = flat.split(":");
1106 for (String s : allowed) {
Ruben Brunk1f4f26b2016-08-02 14:21:36 -07001107 if (!TextUtils.isEmpty(s)) {
1108 current.add(s);
1109 }
Ruben Brunk98576cf2016-03-07 18:54:28 -08001110 }
1111 }
1112 return current;
1113 }
1114
1115 private static String formatSettings(Collection<String> c) {
1116 if (c == null || c.isEmpty()) {
1117 return "";
1118 }
1119
1120 StringBuilder b = new StringBuilder();
1121 boolean start = true;
1122 for (String s : c) {
1123 if ("".equals(s)) {
1124 continue;
1125 }
1126 if (!start) {
1127 b.append(':');
1128 }
1129 b.append(s);
1130 start = false;
1131 }
1132 return b.toString();
1133 }
1134
1135
1136
Ruben Brunkc7354fe2016-03-07 23:37:12 -08001137 private void createAndConnectService(@NonNull ComponentName component, int userId) {
Ruben Brunkd675f512017-10-03 15:39:41 -07001138 mCurrentVrService = createVrListenerService(component, userId);
Ruben Brunkc7354fe2016-03-07 23:37:12 -08001139 mCurrentVrService.connect();
1140 Slog.i(TAG, "Connecting " + component + " for user " + userId);
1141 }
1142
Ruben Brunke24b9a62016-02-16 21:38:24 -08001143 /**
1144 * Send VR mode change callbacks to HAL and system services if mode has actually changed.
1145 * <p/>
1146 * Note: Must be called while holding {@code mLock}.
1147 *
1148 * @param enabled new state of the VR mode.
1149 */
Svetoslav Ganove33f6132016-06-01 16:25:31 -07001150 private void changeVrModeLocked(boolean enabled) {
Ruben Brunke24b9a62016-02-16 21:38:24 -08001151 if (mVrModeEnabled != enabled) {
1152 mVrModeEnabled = enabled;
1153
1154 // Log mode change event.
1155 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
1156 setVrModeNative(mVrModeEnabled);
1157
Ruben Brunke24b9a62016-02-16 21:38:24 -08001158 onVrModeChangedLocked();
1159 }
1160 }
1161
1162 /**
1163 * Notify system services of VR mode change.
1164 * <p/>
1165 * Note: Must be called while holding {@code mLock}.
1166 */
1167 private void onVrModeChangedLocked() {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001168 mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
1169 (mVrModeEnabled) ? 1 : 0, 0));
Ruben Brunke24b9a62016-02-16 21:38:24 -08001170 }
1171
1172 /**
Ruben Brunkd675f512017-10-03 15:39:41 -07001173 * Helper function for making ManagedApplicationService for VrListenerService instances.
Ruben Brunke24b9a62016-02-16 21:38:24 -08001174 */
Ruben Brunkd675f512017-10-03 15:39:41 -07001175 private ManagedApplicationService createVrListenerService(@NonNull ComponentName component,
1176 int userId) {
1177 int retryType = (mBootsToVr) ? ManagedApplicationService.RETRY_FOREVER
1178 : ManagedApplicationService.RETRY_NEVER;
1179 return ManagedApplicationService.build(mContext, component, userId,
Ruben Brunke24b9a62016-02-16 21:38:24 -08001180 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
Ruben Brunkd675f512017-10-03 15:39:41 -07001181 sBinderChecker, /*isImportant*/true, retryType, mHandler, mEventCallback);
1182 }
1183
1184 /**
1185 * Helper function for making ManagedApplicationService for VR Compositor instances.
1186 */
1187 private ManagedApplicationService createVrCompositorService(@NonNull ComponentName component,
1188 int userId) {
1189 int retryType = (mBootsToVr) ? ManagedApplicationService.RETRY_FOREVER
1190 : ManagedApplicationService.RETRY_BEST_EFFORT;
1191 return ManagedApplicationService.build(mContext, component, userId, /*clientLabel*/0,
1192 /*settingsAction*/null, /*binderChecker*/null, /*isImportant*/true, retryType,
1193 mHandler, /*disconnectCallback*/mEventCallback);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001194 }
1195
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -08001196 /**
1197 * Apply the pending VR state. If no state is pending, disconnect any currently bound
1198 * VR listener service.
1199 */
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001200 private void consumeAndApplyPendingStateLocked() {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -08001201 consumeAndApplyPendingStateLocked(true);
1202 }
1203
1204 /**
1205 * Apply the pending VR state.
1206 *
1207 * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
1208 * service will be disconnected if no state is pending. If this is {@code false} then the
1209 * nothing will be changed when there is no pending state.
1210 */
1211 private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001212 if (mPendingState != null) {
Albert Chaulk16d23972017-07-14 12:32:57 -04001213 updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
1214 mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001215 mPendingState.callingPackage);
1216 mPendingState = null;
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -08001217 } else if (disconnectIfNoPendingState) {
Albert Chaulk16d23972017-07-14 12:32:57 -04001218 updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001219 }
1220 }
1221
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001222 private void logStateLocked() {
1223 ComponentName currentBoundService = (mCurrentVrService == null) ? null :
Ruben Brunkd675f512017-10-03 15:39:41 -07001224 mCurrentVrService.getComponent();
1225 logEvent(new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
1226 mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted));
1227 }
1228
1229 private void logEvent(LogFormattable event) {
1230 synchronized (mLoggingDeque) {
1231 if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
1232 mLoggingDeque.removeFirst();
1233 mLogLimitHit = true;
1234 }
1235 mLoggingDeque.add(event);
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001236 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001237 }
1238
1239 private void dumpStateTransitions(PrintWriter pw) {
1240 SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
Ruben Brunkd675f512017-10-03 15:39:41 -07001241 synchronized (mLoggingDeque) {
1242 if (mLoggingDeque.size() == 0) {
1243 pw.print(" ");
1244 pw.println("None");
1245 }
1246
1247 if (mLogLimitHit) {
1248 pw.println("..."); // Indicates log overflow
1249 }
1250
1251 for (LogFormattable event : mLoggingDeque) {
1252 pw.println(event.toLogString(d));
Ruben Brunk2ff9c012016-04-28 10:58:29 -07001253 }
1254 }
1255 }
1256
Ruben Brunke24b9a62016-02-16 21:38:24 -08001257 /*
1258 * Implementation of VrManagerInternal calls. These are callable from system services.
1259 */
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001260 private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
Albert Chaulk16d23972017-07-14 12:32:57 -04001261 int userId, int processId, @NonNull ComponentName callingPackage) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001262
Ruben Brunke24b9a62016-02-16 21:38:24 -08001263 synchronized (mLock) {
Zak Cohen56345f42017-01-26 13:54:28 -08001264 VrState pending;
1265 ComponentName targetListener;
Zak Cohen56345f42017-01-26 13:54:28 -08001266
1267 // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
1268 // and the system default VR listener is used.
1269 boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
Albert Chaulk16d23972017-07-14 12:32:57 -04001270 boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
1271 if (running2dInVr) {
Zak Cohen56345f42017-01-26 13:54:28 -08001272 targetListener = mDefaultVrService;
Zak Cohen56345f42017-01-26 13:54:28 -08001273 } else {
1274 targetListener = targetPackageName;
Zak Cohen56345f42017-01-26 13:54:28 -08001275 }
Albert Chaulk16d23972017-07-14 12:32:57 -04001276
1277 pending = new VrState(targetEnabledState, running2dInVr, targetListener,
1278 userId, processId, callingPackage);
Zak Cohen56345f42017-01-26 13:54:28 -08001279
Ruben Brunk040484c2016-10-28 20:18:57 -07001280 if (!mVrModeAllowed) {
1281 // We're not allowed to be in VR mode. Make this state pending. This will be
1282 // applied the next time we are allowed to enter VR mode unless it is superseded by
1283 // another call.
1284 mPendingState = pending;
1285 return;
1286 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001287
Zak Cohen56345f42017-01-26 13:54:28 -08001288 if (!targetEnabledState && mCurrentVrService != null) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001289 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
1290 // and service bind/unbind in case we are immediately switching to another VR app.
1291 if (mPendingState == null) {
1292 mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
1293 PENDING_STATE_DELAY_MS);
1294 }
1295
Ruben Brunk040484c2016-10-28 20:18:57 -07001296 mPendingState = pending;
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001297 return;
1298 } else {
1299 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
1300 mPendingState = null;
1301 }
1302
Albert Chaulk16d23972017-07-14 12:32:57 -04001303 updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
1304 userId, processId, callingPackage);
Zak Cohen56345f42017-01-26 13:54:28 -08001305 }
1306 }
1307
1308 private void setPersistentVrModeEnabled(boolean enabled) {
Zak Cohen732aeb02017-01-29 14:19:52 -08001309 synchronized(mLock) {
1310 setPersistentModeAndNotifyListenersLocked(enabled);
Alex Sakhartchouka26b4352017-07-25 17:08:43 -04001311 // Disabling persistent mode should disable the overall vr mode.
1312 if (!enabled) {
Albert Chaulk16d23972017-07-14 12:32:57 -04001313 setVrMode(false, null, 0, -1, null);
Zak Cohen56345f42017-01-26 13:54:28 -08001314 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001315 }
1316 }
1317
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001318 public void setVr2dDisplayProperties(
1319 Vr2dDisplayProperties compatDisplayProp) {
minxia2936ad32018-05-01 18:08:34 -07001320 final long token = Binder.clearCallingIdentity();
1321 try {
1322 if (mVr2dDisplay != null) {
1323 mVr2dDisplay.setVirtualDisplayProperties(compatDisplayProp);
1324 return;
1325 }
1326 } finally {
1327 Binder.restoreCallingIdentity(token);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -07001328 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001329 Slog.w(TAG, "Vr2dDisplay is null!");
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -07001330 }
1331
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001332 private int getVr2dDisplayId() {
1333 if (mVr2dDisplay != null) {
1334 return mVr2dDisplay.getVirtualDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -08001335 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001336 Slog.w(TAG, "Vr2dDisplay is null!");
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -08001337 return INVALID_DISPLAY;
1338 }
1339
Ruben Brunk52ea6622017-10-02 23:51:25 -07001340 private void setAndBindCompositor(ComponentName componentName) {
1341 final int userId = UserHandle.getCallingUserId();
1342 final long token = Binder.clearCallingIdentity();
minxia2936ad32018-05-01 18:08:34 -07001343 try {
1344 synchronized (mLock) {
1345 updateCompositorServiceLocked(userId, componentName);
1346 }
1347 } finally {
1348 Binder.restoreCallingIdentity(token);
Ruben Brunk52ea6622017-10-02 23:51:25 -07001349 }
Ruben Brunk52ea6622017-10-02 23:51:25 -07001350 }
1351
1352 private void updateCompositorServiceLocked(int userId, ComponentName componentName) {
1353 if (mCurrentVrCompositorService != null
1354 && mCurrentVrCompositorService.disconnectIfNotMatching(componentName, userId)) {
Ruben Brunkd675f512017-10-03 15:39:41 -07001355 Slog.i(TAG, "Disconnecting compositor service: "
1356 + mCurrentVrCompositorService.getComponent());
Ruben Brunk52ea6622017-10-02 23:51:25 -07001357 // Check if existing service matches the requested one, if not (or if the requested
1358 // component is null) disconnect it.
1359 mCurrentVrCompositorService = null;
1360 }
1361
1362 if (componentName != null && mCurrentVrCompositorService == null) {
1363 // We don't have an existing service matching the requested component, so attempt to
1364 // connect one.
Ruben Brunkd675f512017-10-03 15:39:41 -07001365 Slog.i(TAG, "Connecting compositor service: " + componentName);
1366 mCurrentVrCompositorService = createVrCompositorService(componentName, userId);
Ruben Brunk52ea6622017-10-02 23:51:25 -07001367 mCurrentVrCompositorService.connect();
1368 }
1369 }
1370
Zak Cohen732aeb02017-01-29 14:19:52 -08001371 private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
1372 if (mPersistentVrModeEnabled == enabled) {
1373 return;
1374 }
Ruben Brunkd675f512017-10-03 15:39:41 -07001375 String eventName = "Persistent VR mode " + ((enabled) ? "enabled" : "disabled");
1376 Slog.i(TAG, eventName);
1377 logEvent(new SettingEvent(eventName));
Zak Cohen732aeb02017-01-29 14:19:52 -08001378 mPersistentVrModeEnabled = enabled;
1379
1380 mHandler.sendMessage(mHandler.obtainMessage(MSG_PERSISTENT_VR_MODE_STATE_CHANGE,
1381 (mPersistentVrModeEnabled) ? 1 : 0, 0));
1382 }
1383
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001384 private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001385 synchronized (mLock) {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001386 return mComponentObserver.isValid(targetPackageName, userId);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001387 }
1388 }
1389
Ruben Brunk8f1d5cb2016-03-22 18:08:41 -07001390 private boolean isCurrentVrListener(String packageName, int userId) {
1391 synchronized (mLock) {
1392 if (mCurrentVrService == null) {
1393 return false;
1394 }
1395 return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
1396 userId == mCurrentVrService.getUserId();
1397 }
1398 }
1399
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001400 /*
1401 * Implementation of IVrManager calls.
1402 */
1403
1404 private void addStateCallback(IVrStateCallbacks cb) {
Steven Thomasb70845c2017-03-16 14:32:37 -07001405 mVrStateRemoteCallbacks.register(cb);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001406 }
1407
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001408 private void removeStateCallback(IVrStateCallbacks cb) {
Steven Thomasb70845c2017-03-16 14:32:37 -07001409 mVrStateRemoteCallbacks.unregister(cb);
1410 }
1411
1412 private void addPersistentStateCallback(IPersistentVrStateCallbacks cb) {
1413 mPersistentVrStateRemoteCallbacks.register(cb);
1414 }
1415
1416 private void removePersistentStateCallback(IPersistentVrStateCallbacks cb) {
1417 mPersistentVrStateRemoteCallbacks.unregister(cb);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001418 }
1419
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001420 private boolean getVrMode() {
Ruben Brunke24b9a62016-02-16 21:38:24 -08001421 synchronized (mLock) {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001422 return mVrModeEnabled;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001423 }
1424 }
Santos Cordone6d77232017-08-08 17:11:41 -07001425
1426 private boolean getPersistentVrMode() {
1427 synchronized (mLock) {
1428 return mPersistentVrModeEnabled;
1429 }
1430 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001431}