blob: b937f9d4c6d83ce7a4052b6bf2cd45dc3e99e605 [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;
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -070024import android.app.Vr2dDisplayProperties;
Ruben Brunk98576cf2016-03-07 18:54:28 -080025import android.app.NotificationManager;
Ruben Brunke24b9a62016-02-16 21:38:24 -080026import android.annotation.NonNull;
Ruben Brunke24b9a62016-02-16 21:38:24 -080027import android.content.ComponentName;
Ruben Brunk98576cf2016-03-07 18:54:28 -080028import android.content.ContentResolver;
29import android.content.Context;
30import android.content.pm.ApplicationInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
Santos Cordon2f22da72017-02-27 17:24:44 -080033import android.hardware.display.DisplayManager;
Svetoslav Ganov47d98de2016-03-01 15:01:14 -080034import android.os.Binder;
Ruben Brunke24b9a62016-02-16 21:38:24 -080035import android.os.Handler;
Svetoslav Ganov47d98de2016-03-01 15:01:14 -080036import android.os.IBinder;
Ruben Brunke24b9a62016-02-16 21:38:24 -080037import android.os.IInterface;
38import android.os.Looper;
Ruben Brunkc7be3be2016-04-01 17:07:51 -070039import android.os.Message;
40import android.os.RemoteCallbackList;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080041import android.os.RemoteException;
Ruben Brunk98576cf2016-03-07 18:54:28 -080042import android.os.UserHandle;
Ruben Brunke24b9a62016-02-16 21:38:24 -080043import android.provider.Settings;
Ruben Brunk98576cf2016-03-07 18:54:28 -080044import android.service.notification.NotificationListenerService;
Steven Thomasb70845c2017-03-16 14:32:37 -070045import android.service.vr.IPersistentVrStateCallbacks;
Ruben Brunke24b9a62016-02-16 21:38:24 -080046import android.service.vr.IVrListener;
Ruben Brunkc7be3be2016-04-01 17:07:51 -070047import android.service.vr.IVrManager;
48import android.service.vr.IVrStateCallbacks;
Ruben Brunke24b9a62016-02-16 21:38:24 -080049import android.service.vr.VrListenerService;
Ruben Brunk1f4f26b2016-08-02 14:21:36 -070050import android.text.TextUtils;
Svetoslav Ganove33f6132016-06-01 16:25:31 -070051import android.util.ArrayMap;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080052import android.util.ArraySet;
53import android.util.Slog;
Ruben Brunk8820f942016-05-09 12:46:28 -070054import android.util.SparseArray;
Santos Cordonc14513d2016-12-14 14:52:59 -080055
Ruben Brunke24b9a62016-02-16 21:38:24 -080056import com.android.internal.R;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060057import com.android.internal.util.DumpUtils;
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -080058import com.android.server.LocalServices;
Craig Donner99062592016-04-14 21:45:19 -070059import com.android.server.SystemConfig;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080060import com.android.server.SystemService;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080061import com.android.server.utils.ManagedApplicationService.PendingEvent;
Ruben Brunke24b9a62016-02-16 21:38:24 -080062import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
63import com.android.server.utils.ManagedApplicationService;
64import com.android.server.utils.ManagedApplicationService.BinderChecker;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080065
Dan Sandlerdc34df52016-04-07 21:04:46 -040066import java.io.FileDescriptor;
67import java.io.PrintWriter;
Ruben Brunk98576cf2016-03-07 18:54:28 -080068import java.lang.StringBuilder;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070069import java.text.SimpleDateFormat;
70import java.util.ArrayDeque;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080071import java.util.ArrayList;
Ruben Brunk98576cf2016-03-07 18:54:28 -080072import java.util.Collection;
Ruben Brunk2ff9c012016-04-28 10:58:29 -070073import java.util.Date;
Ruben Brunkc7354fe2016-03-07 23:37:12 -080074import java.util.Objects;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080075
76/**
Ruben Brunke24b9a62016-02-16 21:38:24 -080077 * Service tracking whether VR mode is active, and notifying listening services of state changes.
78 * <p/>
79 * Services running in system server may modify the state of VrManagerService via the interface in
80 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
81 * interface given in VrStateListener.
82 * <p/>
83 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
84 * hardware/libhardware/modules/vr
85 * <p/>
86 * In general applications may enable or disable VR mode by calling
Ruben Brunk98576cf2016-03-07 18:54:28 -080087 * {@link android.app.Activity#setVrModeEnabled)}. An application may also implement a service to
88 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080089 *
Elliot Waite54de7742017-01-11 15:30:35 -080090 * @see android.service.vr.VrListenerService
91 * @see com.android.server.vr.VrManagerInternal
92 * @see com.android.server.vr.VrStateListener
Ruben Brunke24b9a62016-02-16 21:38:24 -080093 *
94 * @hide
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080095 */
Ruben Brunke24b9a62016-02-16 21:38:24 -080096public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080097
Ruben Brunkdd18a0b2015-12-04 16:16:31 -080098 public static final String TAG = "VrManagerService";
Joe Onorato82ba91d2017-04-27 16:18:05 -070099 static final boolean DBG = false;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800100
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700101 private static final int PENDING_STATE_DELAY_MS = 300;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700102 private static final int EVENT_LOG_SIZE = 32;
Ruben Brunk8820f942016-05-09 12:46:28 -0700103 private static final int INVALID_APPOPS_MODE = -1;
Ruben Brunk040484c2016-10-28 20:18:57 -0700104 /** Null set of sleep sleep flags. */
105 private static final int FLAG_NONE = 0;
106 /** Flag set when the device is not sleeping. */
107 private static final int FLAG_AWAKE = 1;
108 /** Flag set when the screen has been turned on. */
109 private static final int FLAG_SCREEN_ON = 2;
110 /** Flag indicating that all system sleep flags have been set.*/
111 private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700112
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800113 private static native void initializeNative();
114 private static native void setVrModeNative(boolean enabled);
115
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800116 private final Object mLock = new Object();
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800117
118 private final IBinder mOverlayToken = new Binder();
119
Ruben Brunke24b9a62016-02-16 21:38:24 -0800120 // State protected by mLock
Ruben Brunk040484c2016-10-28 20:18:57 -0700121 private boolean mVrModeAllowed;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800122 private boolean mVrModeEnabled;
Zak Cohen56345f42017-01-26 13:54:28 -0800123 private boolean mPersistentVrModeEnabled;
Ruben Brunke24b9a62016-02-16 21:38:24 -0800124 private EnabledComponentsObserver mComponentObserver;
125 private ManagedApplicationService mCurrentVrService;
Zak Cohen56345f42017-01-26 13:54:28 -0800126 private ComponentName mDefaultVrService;
Ruben Brunke24b9a62016-02-16 21:38:24 -0800127 private Context mContext;
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800128 private ComponentName mCurrentVrModeComponent;
129 private int mCurrentVrModeUser;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800130 private boolean mWasDefaultGranted;
131 private boolean mGuard;
Steven Thomasb70845c2017-03-16 14:32:37 -0700132 private final RemoteCallbackList<IVrStateCallbacks> mVrStateRemoteCallbacks =
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700133 new RemoteCallbackList<>();
Steven Thomasb70845c2017-03-16 14:32:37 -0700134 private final RemoteCallbackList<IPersistentVrStateCallbacks>
135 mPersistentVrStateRemoteCallbacks = new RemoteCallbackList<>();
Ruben Brunk8820f942016-05-09 12:46:28 -0700136 private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
137 private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700138 private VrState mPendingState;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700139 private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
Ruben Brunk8820f942016-05-09 12:46:28 -0700140 private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
Ruben Brunk040484c2016-10-28 20:18:57 -0700141 /** Tracks the state of the screen and keyguard UI.*/
Mark Urbanus72729f92017-02-17 12:00:54 -0800142 private int mSystemSleepFlags = FLAG_AWAKE;
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700143 private Vr2dDisplay mVr2dDisplay;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800144
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700145 private static final int MSG_VR_STATE_CHANGE = 0;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700146 private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
Zak Cohen732aeb02017-01-29 14:19:52 -0800147 private static final int MSG_PERSISTENT_VR_MODE_STATE_CHANGE = 2;
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700148
Ruben Brunk040484c2016-10-28 20:18:57 -0700149 /**
150 * Set whether VR mode may be enabled.
151 * <p/>
152 * If VR mode is not allowed to be enabled, calls to set VR mode will be cached. When VR mode
153 * is again allowed to be enabled, the most recent cached state will be applied.
154 *
155 * @param allowed {@code true} if calling any of the setVrMode methods may cause the device to
156 * enter VR mode.
157 */
158 private void setVrModeAllowedLocked(boolean allowed) {
159 if (mVrModeAllowed != allowed) {
160 mVrModeAllowed = allowed;
Joe Onorato82ba91d2017-04-27 16:18:05 -0700161 if (DBG) Slog.d(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
Ruben Brunk040484c2016-10-28 20:18:57 -0700162 if (mVrModeAllowed) {
163 consumeAndApplyPendingStateLocked();
164 } else {
Zak Cohen56345f42017-01-26 13:54:28 -0800165 // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
166 // exit persistent VR mode when screen is turned off.
Zak Cohen732aeb02017-01-29 14:19:52 -0800167 setPersistentModeAndNotifyListenersLocked(false);
Zak Cohen56345f42017-01-26 13:54:28 -0800168
Ruben Brunk040484c2016-10-28 20:18:57 -0700169 // Set pending state to current state.
170 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
171 ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
172 mCurrentVrService.getUserId(), mCurrentVrModeComponent)
173 : null;
174
175 // Unbind current VR service and do necessary callbacks.
176 updateCurrentVrServiceLocked(false, null, 0, null);
177 }
178 }
179 }
180
181 private void setSleepState(boolean isAsleep) {
182 synchronized(mLock) {
183
184 if (!isAsleep) {
185 mSystemSleepFlags |= FLAG_AWAKE;
186 } else {
187 mSystemSleepFlags &= ~FLAG_AWAKE;
188 }
189
190 setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
191 }
192 }
193
194 private void setScreenOn(boolean isScreenOn) {
195 synchronized(mLock) {
196 if (isScreenOn) {
197 mSystemSleepFlags |= FLAG_SCREEN_ON;
198 } else {
199 mSystemSleepFlags &= ~FLAG_SCREEN_ON;
200 }
201 setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
202 }
203 }
204
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700205 private final Handler mHandler = new Handler() {
206 @Override
207 public void handleMessage(Message msg) {
208 switch(msg.what) {
209 case MSG_VR_STATE_CHANGE : {
210 boolean state = (msg.arg1 == 1);
Steven Thomasb70845c2017-03-16 14:32:37 -0700211 int i = mVrStateRemoteCallbacks.beginBroadcast();
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700212 while (i > 0) {
213 i--;
214 try {
Steven Thomasb70845c2017-03-16 14:32:37 -0700215 mVrStateRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700216 } catch (RemoteException e) {
217 // Noop
218 }
219 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700220 mVrStateRemoteCallbacks.finishBroadcast();
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700221 } break;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700222 case MSG_PENDING_VR_STATE_CHANGE : {
223 synchronized(mLock) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700224 if (mVrModeAllowed) {
225 VrManagerService.this.consumeAndApplyPendingStateLocked();
226 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700227 }
228 } break;
Zak Cohen732aeb02017-01-29 14:19:52 -0800229 case MSG_PERSISTENT_VR_MODE_STATE_CHANGE : {
230 boolean state = (msg.arg1 == 1);
Steven Thomasb70845c2017-03-16 14:32:37 -0700231 int i = mPersistentVrStateRemoteCallbacks.beginBroadcast();
232 while (i > 0) {
233 i--;
234 try {
235 mPersistentVrStateRemoteCallbacks.getBroadcastItem(i)
236 .onPersistentVrStateChanged(state);
237 } catch (RemoteException e) {
238 // Noop
239 }
Zak Cohen732aeb02017-01-29 14:19:52 -0800240 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700241 mPersistentVrStateRemoteCallbacks.finishBroadcast();
Zak Cohen732aeb02017-01-29 14:19:52 -0800242 } break;
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700243 default :
244 throw new IllegalStateException("Unknown message type: " + msg.what);
245 }
246 }
247 };
248
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700249 private static class VrState {
250 final boolean enabled;
251 final int userId;
252 final ComponentName targetPackageName;
253 final ComponentName callingPackage;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700254 final long timestamp;
255 final boolean defaultPermissionsGranted;
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700256
257 VrState(boolean enabled, ComponentName targetPackageName, int userId,
258 ComponentName callingPackage) {
259 this.enabled = enabled;
260 this.userId = userId;
261 this.targetPackageName = targetPackageName;
262 this.callingPackage = callingPackage;
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700263 this.defaultPermissionsGranted = false;
264 this.timestamp = System.currentTimeMillis();
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700265 }
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700266
267 VrState(boolean enabled, ComponentName targetPackageName, int userId,
268 ComponentName callingPackage, boolean defaultPermissionsGranted) {
269 this.enabled = enabled;
270 this.userId = userId;
271 this.targetPackageName = targetPackageName;
272 this.callingPackage = callingPackage;
273 this.defaultPermissionsGranted = defaultPermissionsGranted;
274 this.timestamp = System.currentTimeMillis();
275 }
276 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700277
Ruben Brunke24b9a62016-02-16 21:38:24 -0800278 private static final BinderChecker sBinderChecker = new BinderChecker() {
279 @Override
280 public IInterface asInterface(IBinder binder) {
281 return IVrListener.Stub.asInterface(binder);
282 }
283
284 @Override
285 public boolean checkType(IInterface service) {
286 return service instanceof IVrListener;
287 }
288 };
289
Ruben Brunk8820f942016-05-09 12:46:28 -0700290 private final class NotificationAccessManager {
291 private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700292 private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
293 new ArrayMap<>();
Ruben Brunk8820f942016-05-09 12:46:28 -0700294
295 public void update(Collection<String> packageNames) {
296 int currentUserId = ActivityManager.getCurrentUser();
297
Ruben Brunk8820f942016-05-09 12:46:28 -0700298 ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
299 if (allowed == null) {
300 allowed = new ArraySet<>();
301 }
302
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700303 // Make sure we revoke notification access for listeners in other users
304 final int listenerCount = mNotificationAccessPackageToUserId.size();
305 for (int i = listenerCount - 1; i >= 0; i--) {
306 final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
307 if (grantUserId != currentUserId) {
308 String packageName = mNotificationAccessPackageToUserId.keyAt(i);
309 revokeNotificationListenerAccess(packageName, grantUserId);
310 revokeNotificationPolicyAccess(packageName);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000311 revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700312 mNotificationAccessPackageToUserId.removeAt(i);
313 }
314 }
315
Ruben Brunk8820f942016-05-09 12:46:28 -0700316 for (String pkg : allowed) {
317 if (!packageNames.contains(pkg)) {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700318 revokeNotificationListenerAccess(pkg, currentUserId);
Ruben Brunk8820f942016-05-09 12:46:28 -0700319 revokeNotificationPolicyAccess(pkg);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000320 revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700321 mNotificationAccessPackageToUserId.remove(pkg);
Ruben Brunk8820f942016-05-09 12:46:28 -0700322 }
323 }
324 for (String pkg : packageNames) {
325 if (!allowed.contains(pkg)) {
326 grantNotificationPolicyAccess(pkg);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700327 grantNotificationListenerAccess(pkg, currentUserId);
Craig Donnercae8cdf2016-07-28 22:39:05 +0000328 grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700329 mNotificationAccessPackageToUserId.put(pkg, currentUserId);
Ruben Brunk8820f942016-05-09 12:46:28 -0700330 }
331 }
332
333 allowed.clear();
334 allowed.addAll(packageNames);
335 mAllowedPackages.put(currentUserId, allowed);
336 }
337 }
338
Ruben Brunke24b9a62016-02-16 21:38:24 -0800339 /**
340 * Called when a user, package, or setting changes that could affect whether or not the
341 * currently bound VrListenerService is changed.
342 */
343 @Override
344 public void onEnabledComponentChanged() {
345 synchronized (mLock) {
Ruben Brunk8820f942016-05-09 12:46:28 -0700346 int currentUser = ActivityManager.getCurrentUser();
Ruben Brunk8820f942016-05-09 12:46:28 -0700347 // Update listeners
348 ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
349
350 ArraySet<String> enabledPackages = new ArraySet<>();
351 for (ComponentName n : enabledListeners) {
352 String pkg = n.getPackageName();
353 if (isDefaultAllowed(pkg)) {
354 enabledPackages.add(n.getPackageName());
355 }
356 }
357 mNotifAccessManager.update(enabledPackages);
358
Ruben Brunk040484c2016-10-28 20:18:57 -0700359 if (!mVrModeAllowed) {
360 return; // Don't do anything, we shouldn't be in VR mode.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800361 }
362
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700363 // If there is a pending state change, we'd better deal with that first
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800364 consumeAndApplyPendingStateLocked(false);
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700365
366 if (mCurrentVrService == null) {
367 return; // No active services
368 }
369
Ruben Brunke24b9a62016-02-16 21:38:24 -0800370 // There is an active service, update it if needed
371 updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
Alex Sakhartchouk6b1251f2017-05-17 12:34:53 -0400372 mCurrentVrService.getUserId(), mCurrentVrModeComponent);
Ruben Brunke24b9a62016-02-16 21:38:24 -0800373 }
374 }
375
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700376 private final IVrManager mVrManager = new IVrManager.Stub() {
377
378 @Override
379 public void registerListener(IVrStateCallbacks cb) {
380 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
381 if (cb == null) {
382 throw new IllegalArgumentException("Callback binder object is null.");
383 }
384
385 VrManagerService.this.addStateCallback(cb);
386 }
387
388 @Override
389 public void unregisterListener(IVrStateCallbacks cb) {
390 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
391 if (cb == null) {
392 throw new IllegalArgumentException("Callback binder object is null.");
393 }
394
395 VrManagerService.this.removeStateCallback(cb);
396 }
397
398 @Override
Steven Thomasb70845c2017-03-16 14:32:37 -0700399 public void registerPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
400 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
401 if (cb == null) {
402 throw new IllegalArgumentException("Callback binder object is null.");
403 }
404
405 VrManagerService.this.addPersistentStateCallback(cb);
406 }
407
408 @Override
409 public void unregisterPersistentVrStateListener(IPersistentVrStateCallbacks cb) {
410 enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
411 if (cb == null) {
412 throw new IllegalArgumentException("Callback binder object is null.");
413 }
414
415 VrManagerService.this.removePersistentStateCallback(cb);
416 }
417
418 @Override
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700419 public boolean getVrModeState() {
420 return VrManagerService.this.getVrMode();
421 }
422
Dan Sandlerdc34df52016-04-07 21:04:46 -0400423 @Override
Zak Cohen56345f42017-01-26 13:54:28 -0800424 public void setPersistentVrModeEnabled(boolean enabled) {
Craig Donner8deb67c2017-02-07 18:10:32 -0800425 enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
Zak Cohen56345f42017-01-26 13:54:28 -0800426 VrManagerService.this.setPersistentVrModeEnabled(enabled);
427 }
428
429 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700430 public void setVr2dDisplayProperties(
431 Vr2dDisplayProperties vr2dDisplayProp) {
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700432 enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700433 VrManagerService.this.setVr2dDisplayProperties(vr2dDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700434 }
435
436 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700437 public int getVr2dDisplayId() {
438 return VrManagerService.this.getVr2dDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -0800439 }
440
441 @Override
Dan Sandlerdc34df52016-04-07 21:04:46 -0400442 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600443 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
444
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700445 pw.println("********* Dump of VrManagerService *********");
Ruben Brunk040484c2016-10-28 20:18:57 -0700446 pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
Zak Cohen56345f42017-01-26 13:54:28 -0800447 pw.println("Persistent VR mode is currently: " +
448 ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700449 pw.println("Previous state transitions:\n");
450 String tab = " ";
451 dumpStateTransitions(pw);
452 pw.println("\n\nRemote Callbacks:");
Steven Thomasb70845c2017-03-16 14:32:37 -0700453 int i=mVrStateRemoteCallbacks.beginBroadcast(); // create the broadcast item array
Dan Sandlerdc34df52016-04-07 21:04:46 -0400454 while(i-->0) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700455 pw.print(tab);
Steven Thomasb70845c2017-03-16 14:32:37 -0700456 pw.print(mVrStateRemoteCallbacks.getBroadcastItem(i));
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700457 if (i>0) pw.println(",");
Dan Sandlerdc34df52016-04-07 21:04:46 -0400458 }
Steven Thomasb70845c2017-03-16 14:32:37 -0700459 mVrStateRemoteCallbacks.finishBroadcast();
460 pw.println("\n\nPersistent Vr State Remote Callbacks:");
461 i=mPersistentVrStateRemoteCallbacks.beginBroadcast();
462 while(i-->0) {
463 pw.print(tab);
464 pw.print(mPersistentVrStateRemoteCallbacks.getBroadcastItem(i));
465 if (i>0) pw.println(",");
466 }
467 mPersistentVrStateRemoteCallbacks.finishBroadcast();
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700468 pw.println("\n");
469 pw.println("Installed VrListenerService components:");
470 int userId = mCurrentVrModeUser;
471 ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
472 if (installed == null || installed.size() == 0) {
473 pw.println("None");
474 } else {
475 for (ComponentName n : installed) {
476 pw.print(tab);
477 pw.println(n.flattenToString());
478 }
479 }
480 pw.println("Enabled VrListenerService components:");
481 ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
482 if (enabled == null || enabled.size() == 0) {
483 pw.println("None");
484 } else {
485 for (ComponentName n : enabled) {
486 pw.print(tab);
487 pw.println(n.flattenToString());
488 }
489 }
490 pw.println("\n");
491 pw.println("********* End of VrManagerService Dump *********");
Dan Sandlerdc34df52016-04-07 21:04:46 -0400492 }
493
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700494 };
495
496 private void enforceCallerPermission(String permission) {
497 if (mContext.checkCallingOrSelfPermission(permission)
498 != PackageManager.PERMISSION_GRANTED) {
499 throw new SecurityException("Caller does not hold the permission " + permission);
500 }
501 }
502
Ruben Brunke24b9a62016-02-16 21:38:24 -0800503 /**
504 * Implementation of VrManagerInternal. Callable only from system services.
505 */
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800506 private final class LocalService extends VrManagerInternal {
507 @Override
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800508 public void setVrMode(boolean enabled, ComponentName packageName, int userId,
509 ComponentName callingPackage) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700510 VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
Ruben Brunkaf9f0042016-06-15 17:08:35 -0700511 }
512
513 @Override
Ruben Brunk040484c2016-10-28 20:18:57 -0700514 public void onSleepStateChanged(boolean isAsleep) {
515 VrManagerService.this.setSleepState(isAsleep);
516 }
517
518 @Override
519 public void onScreenStateChanged(boolean isScreenOn) {
520 VrManagerService.this.setScreenOn(isScreenOn);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800521 }
522
523 @Override
Ruben Brunk8f1d5cb2016-03-22 18:08:41 -0700524 public boolean isCurrentVrListener(String packageName, int userId) {
525 return VrManagerService.this.isCurrentVrListener(packageName, userId);
526 }
527
528 @Override
Ruben Brunke24b9a62016-02-16 21:38:24 -0800529 public int hasVrPackage(ComponentName packageName, int userId) {
530 return VrManagerService.this.hasVrPackage(packageName, userId);
531 }
Zak Cohen56345f42017-01-26 13:54:28 -0800532
533 @Override
534 public void setPersistentVrModeEnabled(boolean enabled) {
535 VrManagerService.this.setPersistentVrModeEnabled(enabled);
536 }
Zak Cohen732aeb02017-01-29 14:19:52 -0800537
538 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700539 public void setVr2dDisplayProperties(
540 Vr2dDisplayProperties compatDisplayProp) {
541 VrManagerService.this.setVr2dDisplayProperties(compatDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -0700542 }
543
544 @Override
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700545 public int getVr2dDisplayId() {
546 return VrManagerService.this.getVr2dDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -0800547 }
548
549 @Override
Steven Thomasb70845c2017-03-16 14:32:37 -0700550 public void addPersistentVrModeStateListener(IPersistentVrStateCallbacks listener) {
551 VrManagerService.this.addPersistentStateCallback(listener);
Zak Cohen732aeb02017-01-29 14:19:52 -0800552 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800553 }
554
555 public VrManagerService(Context context) {
556 super(context);
557 }
558
559 @Override
560 public void onStart() {
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800561 synchronized(mLock) {
562 initializeNative();
Ruben Brunke24b9a62016-02-16 21:38:24 -0800563 mContext = getContext();
Ruben Brunkbaa4b552016-02-02 16:27:37 -0800564 }
565
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800566 publishLocalService(VrManagerInternal.class, new LocalService());
Craig Donner8deb67c2017-02-07 18:10:32 -0800567 publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800568 }
569
Ruben Brunke24b9a62016-02-16 21:38:24 -0800570 @Override
571 public void onBootPhase(int phase) {
Ruben Brunk85070042016-03-21 12:10:38 -0700572 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Ruben Brunke24b9a62016-02-16 21:38:24 -0800573 synchronized (mLock) {
574 Looper looper = Looper.getMainLooper();
575 Handler handler = new Handler(looper);
576 ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
577 listeners.add(this);
578 mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
579 Settings.Secure.ENABLED_VR_LISTENERS, looper,
580 android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
581 VrListenerService.SERVICE_INTERFACE, mLock, listeners);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800582
Ruben Brunke24b9a62016-02-16 21:38:24 -0800583 mComponentObserver.rebuildAll();
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800584 }
Zak Cohen56345f42017-01-26 13:54:28 -0800585
586 //TODO: something more robust than picking the first one
587 ArraySet<ComponentName> defaultVrComponents =
588 SystemConfig.getInstance().getDefaultVrComponents();
589 if (defaultVrComponents.size() > 0) {
590 mDefaultVrService = defaultVrComponents.valueAt(0);
591 } else {
592 Slog.i(TAG, "No default vr listener service found.");
593 }
Santos Cordon2f22da72017-02-27 17:24:44 -0800594
595 DisplayManager dm =
596 (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
Karthik Ravi Shankar99493db2017-03-08 18:30:19 -0800597 ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -0700598 mVr2dDisplay = new Vr2dDisplay(dm, ami, mVrManager);
599 mVr2dDisplay.init(getContext());
Ruben Brunk040484c2016-10-28 20:18:57 -0700600 } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
601 synchronized (mLock) {
602 mVrModeAllowed = true;
603 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -0800604 }
605 }
606
Ruben Brunke24b9a62016-02-16 21:38:24 -0800607 @Override
608 public void onStartUser(int userHandle) {
609 synchronized (mLock) {
610 mComponentObserver.onUsersChanged();
611 }
612 }
613
614 @Override
615 public void onSwitchUser(int userHandle) {
616 synchronized (mLock) {
617 mComponentObserver.onUsersChanged();
618 }
619
620 }
621
622 @Override
623 public void onStopUser(int userHandle) {
624 synchronized (mLock) {
625 mComponentObserver.onUsersChanged();
626 }
627
628 }
629
630 @Override
631 public void onCleanupUser(int userHandle) {
632 synchronized (mLock) {
633 mComponentObserver.onUsersChanged();
634 }
635 }
636
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700637 private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
638 AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
639
640 // If user changed drop restrictions for the old user.
641 if (oldUserId != newUserId) {
642 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
643 false, mOverlayToken, null, oldUserId);
644 }
645
646 // Apply the restrictions for the current user based on vr state
647 String[] exemptions = (exemptedPackage == null) ? new String[0] :
648 new String[] { exemptedPackage };
649
650 appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
Ruben Brunk2781b412017-04-24 12:07:17 -0700651 mVrModeEnabled, mOverlayToken, exemptions, newUserId);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700652 }
653
654 private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
655 String oldVrServicePackage, int oldUserId) {
656 // If VR state changed and we also have a VR service change.
657 if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
658 return;
659 }
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800660 final long identity = Binder.clearCallingIdentity();
661 try {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700662 // Set overlay exception state based on VR enabled and current service
663 updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
Svetoslav Ganov47d98de2016-03-01 15:01:14 -0800664 } finally {
665 Binder.restoreCallingIdentity(identity);
666 }
667 }
668
Ruben Brunke24b9a62016-02-16 21:38:24 -0800669 /**
670 * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
671 * the currently selected VR listener service. If the component selected for the VR listener
672 * service has changed, unbind the previous listener and bind the new listener (if enabled).
673 * <p/>
674 * Note: Must be called while holding {@code mLock}.
675 *
676 * @param enabled new state for VR mode.
677 * @param component new component to be bound as a VR listener.
678 * @param userId user owning the component to be bound.
Alex Sakhartchouk6b1251f2017-05-17 12:34:53 -0400679 * @param calling the component currently using VR mode.
Ruben Brunke24b9a62016-02-16 21:38:24 -0800680 *
681 * @return {@code true} if the component/user combination specified is valid.
682 */
Ruben Brunk98576cf2016-03-07 18:54:28 -0800683 private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
684 int userId, ComponentName calling) {
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800685
686 boolean sendUpdatedCaller = false;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800687 final long identity = Binder.clearCallingIdentity();
688 try {
Ruben Brunke24b9a62016-02-16 21:38:24 -0800689
Ruben Brunk98576cf2016-03-07 18:54:28 -0800690 boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
691 EnabledComponentsObserver.NO_ERROR);
Ruben Brunk040484c2016-10-28 20:18:57 -0700692 boolean goingIntoVrMode = validUserComponent && enabled;
693 if (!mVrModeEnabled && !goingIntoVrMode) {
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700694 return validUserComponent; // Disabled -> Disabled transition does nothing.
695 }
Ruben Brunke24b9a62016-02-16 21:38:24 -0800696
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700697 String oldVrServicePackage = mCurrentVrService != null
698 ? mCurrentVrService.getComponent().getPackageName() : null;
699 final int oldUserId = mCurrentVrModeUser;
700
Ruben Brunk040484c2016-10-28 20:18:57 -0700701 // Notify system services and VR HAL of mode change.
702 changeVrModeLocked(goingIntoVrMode);
Ruben Brunk29931bc2016-03-11 00:24:26 -0800703
Ruben Brunk040484c2016-10-28 20:18:57 -0700704 boolean nothingChanged = false;
705 if (!goingIntoVrMode) {
706 // Not going into VR mode, unbind whatever is running
Ruben Brunk98576cf2016-03-07 18:54:28 -0800707 if (mCurrentVrService != null) {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800708 Slog.i(TAG, "Leaving VR mode, disconnecting "
709 + mCurrentVrService.getComponent() + " for user "
710 + mCurrentVrService.getUserId());
Ruben Brunk98576cf2016-03-07 18:54:28 -0800711 mCurrentVrService.disconnect();
Ruben Brunk98576cf2016-03-07 18:54:28 -0800712 mCurrentVrService = null;
Ruben Brunk040484c2016-10-28 20:18:57 -0700713 } else {
714 nothingChanged = true;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800715 }
716 } else {
Ruben Brunk040484c2016-10-28 20:18:57 -0700717 // Going into VR mode
Ruben Brunk98576cf2016-03-07 18:54:28 -0800718 if (mCurrentVrService != null) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700719 // Unbind any running service that doesn't match the latest component/user
720 // selection.
Ruben Brunk98576cf2016-03-07 18:54:28 -0800721 if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800722 Slog.i(TAG, "VR mode component changed to " + component
723 + ", disconnecting " + mCurrentVrService.getComponent()
724 + " for user " + mCurrentVrService.getUserId());
Ruben Brunk98576cf2016-03-07 18:54:28 -0800725 createAndConnectService(component, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800726 sendUpdatedCaller = true;
Ruben Brunk040484c2016-10-28 20:18:57 -0700727 } else {
728 nothingChanged = true;
Ruben Brunk98576cf2016-03-07 18:54:28 -0800729 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700730 // The service with the correct component/user is already bound, do nothing.
Ruben Brunk98576cf2016-03-07 18:54:28 -0800731 } else {
Ruben Brunk040484c2016-10-28 20:18:57 -0700732 // Nothing was previously running, bind a new service for the latest
733 // component/user selection.
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800734 createAndConnectService(component, userId);
735 sendUpdatedCaller = true;
736 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800737 }
738
Ruben Brunk666505e2017-05-04 16:54:46 -0700739 if ((calling != null || mPersistentVrModeEnabled)
740 && !Objects.equals(calling, mCurrentVrModeComponent)) {
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700741 sendUpdatedCaller = true;
742 }
Ruben Brunk7196a6b2017-03-22 15:43:24 -0700743 mCurrentVrModeComponent = calling;
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700744
745 if (mCurrentVrModeUser != userId) {
Ruben Brunk98576cf2016-03-07 18:54:28 -0800746 mCurrentVrModeUser = userId;
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800747 sendUpdatedCaller = true;
748 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800749
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700750 String newVrServicePackage = mCurrentVrService != null
751 ? mCurrentVrService.getComponent().getPackageName() : null;
752 final int newUserId = mCurrentVrModeUser;
753
754 // Update AppOps settings that change state when entering/exiting VR mode, or changing
755 // the current VrListenerService.
756 updateDependentAppOpsLocked(newVrServicePackage, newUserId,
757 oldVrServicePackage, oldUserId);
758
Ruben Brunk98576cf2016-03-07 18:54:28 -0800759 if (mCurrentVrService != null && sendUpdatedCaller) {
760 final ComponentName c = mCurrentVrModeComponent;
761 mCurrentVrService.sendEvent(new PendingEvent() {
762 @Override
763 public void runEvent(IInterface service) throws RemoteException {
764 IVrListener l = (IVrListener) service;
765 l.focusedActivityChanged(c);
766 }
767 });
768 }
Ruben Brunk040484c2016-10-28 20:18:57 -0700769
770 if (!nothingChanged) {
771 logStateLocked();
772 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800773
774 return validUserComponent;
775 } finally {
776 Binder.restoreCallingIdentity(identity);
777 }
778 }
779
Ruben Brunk8820f942016-05-09 12:46:28 -0700780 private boolean isDefaultAllowed(String packageName) {
Craig Donner0568f282016-04-11 13:02:44 -0700781 PackageManager pm = mContext.getPackageManager();
Ruben Brunk8820f942016-05-09 12:46:28 -0700782
783 ApplicationInfo info = null;
784 try {
785 info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
786 } catch (NameNotFoundException e) {
787 }
788
789 if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
790 return false;
791 }
792 return true;
793 }
794
Ruben Brunk98576cf2016-03-07 18:54:28 -0800795 private void grantNotificationPolicyAccess(String pkg) {
796 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk8820f942016-05-09 12:46:28 -0700797 nm.setNotificationPolicyAccessGranted(pkg, true);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800798 }
799
800 private void revokeNotificationPolicyAccess(String pkg) {
801 NotificationManager nm = mContext.getSystemService(NotificationManager.class);
Ruben Brunk8820f942016-05-09 12:46:28 -0700802 // Remove any DND zen rules possibly created by the package.
803 nm.removeAutomaticZenRules(pkg);
804 // Remove Notification Policy Access.
805 nm.setNotificationPolicyAccessGranted(pkg, false);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800806 }
807
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700808 private void grantNotificationListenerAccess(String pkg, int userId) {
Ruben Brunk98576cf2016-03-07 18:54:28 -0800809 PackageManager pm = mContext.getPackageManager();
810 ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700811 userId, NotificationListenerService.SERVICE_INTERFACE,
Ruben Brunk98576cf2016-03-07 18:54:28 -0800812 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
813 ContentResolver resolver = mContext.getContentResolver();
814
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700815 ArraySet<String> current = getNotificationListeners(resolver, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800816
Ruben Brunk98576cf2016-03-07 18:54:28 -0800817 for (ComponentName c : possibleServices) {
818 String flatName = c.flattenToString();
819 if (Objects.equals(c.getPackageName(), pkg)
820 && !current.contains(flatName)) {
Ruben Brunk98576cf2016-03-07 18:54:28 -0800821 current.add(flatName);
822 }
Ruben Brunke24b9a62016-02-16 21:38:24 -0800823 }
824
Ruben Brunk98576cf2016-03-07 18:54:28 -0800825 if (current.size() > 0) {
826 String flatSettings = formatSettings(current);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700827 Settings.Secure.putStringForUser(resolver,
828 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
829 flatSettings, userId);
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800830 }
Ruben Brunke24b9a62016-02-16 21:38:24 -0800831 }
832
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700833 private void revokeNotificationListenerAccess(String pkg, int userId) {
Ruben Brunk98576cf2016-03-07 18:54:28 -0800834 ContentResolver resolver = mContext.getContentResolver();
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700835
836 ArraySet<String> current = getNotificationListeners(resolver, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800837
Ruben Brunk8820f942016-05-09 12:46:28 -0700838 ArrayList<String> toRemove = new ArrayList<>();
839
840 for (String c : current) {
841 ComponentName component = ComponentName.unflattenFromString(c);
Ruben Brunk1f4f26b2016-08-02 14:21:36 -0700842 if (component != null && component.getPackageName().equals(pkg)) {
Ruben Brunk8820f942016-05-09 12:46:28 -0700843 toRemove.add(c);
844 }
845 }
846
847 current.removeAll(toRemove);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800848
849 String flatSettings = formatSettings(current);
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700850 Settings.Secure.putStringForUser(resolver,
851 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
852 flatSettings, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800853 }
854
Craig Donnercae8cdf2016-07-28 22:39:05 +0000855 private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
856 // Don't clobber the user if permission set in current state explicitly
857 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
Ruben Brunk12ab5e12016-11-10 15:27:30 -0800858 try {
859 mContext.getPackageManager().grantRuntimePermission(pkg,
860 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
861 } catch (IllegalArgumentException e) {
862 // Package was removed during update.
863 Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
864 + " was removed.");
865 }
Craig Donnercae8cdf2016-07-28 22:39:05 +0000866 }
867 }
868
869 private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
870 // Don't clobber the user if permission set in current state explicitly
871 if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
Ruben Brunk12ab5e12016-11-10 15:27:30 -0800872 try {
873 mContext.getPackageManager().revokeRuntimePermission(pkg,
874 Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
875 } catch (IllegalArgumentException e) {
876 // Package was removed during update.
877 Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
878 + " was removed.");
879 }
Craig Donnercae8cdf2016-07-28 22:39:05 +0000880 }
881 }
882
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700883 private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
884 final int flags = mContext.getPackageManager().getPermissionFlags(
885 permission, pkg, new UserHandle(userId));
886 return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
887 | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
888 }
889
890 private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
891 String flat = Settings.Secure.getStringForUser(resolver,
892 Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
Ruben Brunk98576cf2016-03-07 18:54:28 -0800893
894 ArraySet<String> current = new ArraySet<>();
895 if (flat != null) {
896 String[] allowed = flat.split(":");
897 for (String s : allowed) {
Ruben Brunk1f4f26b2016-08-02 14:21:36 -0700898 if (!TextUtils.isEmpty(s)) {
899 current.add(s);
900 }
Ruben Brunk98576cf2016-03-07 18:54:28 -0800901 }
902 }
903 return current;
904 }
905
906 private static String formatSettings(Collection<String> c) {
907 if (c == null || c.isEmpty()) {
908 return "";
909 }
910
911 StringBuilder b = new StringBuilder();
912 boolean start = true;
913 for (String s : c) {
914 if ("".equals(s)) {
915 continue;
916 }
917 if (!start) {
918 b.append(':');
919 }
920 b.append(s);
921 start = false;
922 }
923 return b.toString();
924 }
925
926
927
Ruben Brunkc7354fe2016-03-07 23:37:12 -0800928 private void createAndConnectService(@NonNull ComponentName component, int userId) {
929 mCurrentVrService = VrManagerService.create(mContext, component, userId);
930 mCurrentVrService.connect();
931 Slog.i(TAG, "Connecting " + component + " for user " + userId);
932 }
933
Ruben Brunke24b9a62016-02-16 21:38:24 -0800934 /**
935 * Send VR mode change callbacks to HAL and system services if mode has actually changed.
936 * <p/>
937 * Note: Must be called while holding {@code mLock}.
938 *
939 * @param enabled new state of the VR mode.
940 */
Svetoslav Ganove33f6132016-06-01 16:25:31 -0700941 private void changeVrModeLocked(boolean enabled) {
Ruben Brunke24b9a62016-02-16 21:38:24 -0800942 if (mVrModeEnabled != enabled) {
943 mVrModeEnabled = enabled;
944
945 // Log mode change event.
946 Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
947 setVrModeNative(mVrModeEnabled);
948
Ruben Brunke24b9a62016-02-16 21:38:24 -0800949 onVrModeChangedLocked();
950 }
951 }
952
953 /**
954 * Notify system services of VR mode change.
955 * <p/>
956 * Note: Must be called while holding {@code mLock}.
957 */
958 private void onVrModeChangedLocked() {
Ruben Brunkc7be3be2016-04-01 17:07:51 -0700959 mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
960 (mVrModeEnabled) ? 1 : 0, 0));
Ruben Brunke24b9a62016-02-16 21:38:24 -0800961 }
962
963 /**
964 * Helper function for making ManagedApplicationService instances.
965 */
966 private static ManagedApplicationService create(@NonNull Context context,
967 @NonNull ComponentName component, int userId) {
968 return ManagedApplicationService.build(context, component, userId,
969 R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
970 sBinderChecker);
971 }
972
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800973 /**
974 * Apply the pending VR state. If no state is pending, disconnect any currently bound
975 * VR listener service.
976 */
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700977 private void consumeAndApplyPendingStateLocked() {
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800978 consumeAndApplyPendingStateLocked(true);
979 }
980
981 /**
982 * Apply the pending VR state.
983 *
984 * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
985 * service will be disconnected if no state is pending. If this is {@code false} then the
986 * nothing will be changed when there is no pending state.
987 */
988 private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700989 if (mPendingState != null) {
990 updateCurrentVrServiceLocked(mPendingState.enabled,
991 mPendingState.targetPackageName, mPendingState.userId,
992 mPendingState.callingPackage);
993 mPendingState = null;
Ruben Brunk1ad4a2d2017-01-06 11:23:49 -0800994 } else if (disconnectIfNoPendingState) {
Ruben Brunk040484c2016-10-28 20:18:57 -0700995 updateCurrentVrServiceLocked(false, null, 0, null);
Ruben Brunkb56b72a2016-04-15 11:53:09 -0700996 }
997 }
998
Ruben Brunk2ff9c012016-04-28 10:58:29 -0700999 private void logStateLocked() {
1000 ComponentName currentBoundService = (mCurrentVrService == null) ? null :
1001 mCurrentVrService.getComponent();
1002 VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
1003 mCurrentVrModeComponent, mWasDefaultGranted);
1004 if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
1005 mLoggingDeque.removeFirst();
1006 }
1007 mLoggingDeque.add(current);
1008 }
1009
1010 private void dumpStateTransitions(PrintWriter pw) {
1011 SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
1012 String tab = " ";
1013 if (mLoggingDeque.size() == 0) {
1014 pw.print(tab);
1015 pw.println("None");
1016 }
1017 for (VrState state : mLoggingDeque) {
1018 pw.print(d.format(new Date(state.timestamp)));
1019 pw.print(tab);
1020 pw.print("State changed to:");
1021 pw.print(tab);
1022 pw.println((state.enabled) ? "ENABLED" : "DISABLED");
1023 if (state.enabled) {
1024 pw.print(tab);
1025 pw.print("User=");
1026 pw.println(state.userId);
1027 pw.print(tab);
1028 pw.print("Current VR Activity=");
1029 pw.println((state.callingPackage == null) ?
1030 "None" : state.callingPackage.flattenToString());
1031 pw.print(tab);
1032 pw.print("Bound VrListenerService=");
1033 pw.println((state.targetPackageName == null) ?
1034 "None" : state.targetPackageName.flattenToString());
1035 if (state.defaultPermissionsGranted) {
1036 pw.print(tab);
1037 pw.println("Default permissions granted to the bound VrListenerService.");
1038 }
1039 }
1040 }
1041 }
1042
Ruben Brunke24b9a62016-02-16 21:38:24 -08001043 /*
1044 * Implementation of VrManagerInternal calls. These are callable from system services.
1045 */
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001046 private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
Ruben Brunk040484c2016-10-28 20:18:57 -07001047 int userId, @NonNull ComponentName callingPackage) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001048
Ruben Brunke24b9a62016-02-16 21:38:24 -08001049 synchronized (mLock) {
Zak Cohen56345f42017-01-26 13:54:28 -08001050 VrState pending;
1051 ComponentName targetListener;
1052 ComponentName foregroundVrComponent;
1053
1054 // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
1055 // and the system default VR listener is used.
1056 boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
1057 if (!enabled && mPersistentVrModeEnabled) {
1058 targetListener = mDefaultVrService;
1059
1060 // Current foreground component isn't a VR one (in 2D app case)
1061 foregroundVrComponent = null;
1062 } else {
1063 targetListener = targetPackageName;
1064 foregroundVrComponent = callingPackage;
1065 }
1066 pending = new VrState(
1067 targetEnabledState, targetListener, userId, foregroundVrComponent);
1068
Ruben Brunk040484c2016-10-28 20:18:57 -07001069 if (!mVrModeAllowed) {
1070 // We're not allowed to be in VR mode. Make this state pending. This will be
1071 // applied the next time we are allowed to enter VR mode unless it is superseded by
1072 // another call.
1073 mPendingState = pending;
1074 return;
1075 }
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001076
Zak Cohen56345f42017-01-26 13:54:28 -08001077 if (!targetEnabledState && mCurrentVrService != null) {
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001078 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
1079 // and service bind/unbind in case we are immediately switching to another VR app.
1080 if (mPendingState == null) {
1081 mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
1082 PENDING_STATE_DELAY_MS);
1083 }
1084
Ruben Brunk040484c2016-10-28 20:18:57 -07001085 mPendingState = pending;
Ruben Brunkb56b72a2016-04-15 11:53:09 -07001086 return;
1087 } else {
1088 mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
1089 mPendingState = null;
1090 }
1091
Zak Cohen56345f42017-01-26 13:54:28 -08001092 updateCurrentVrServiceLocked(
1093 targetEnabledState, targetListener, userId, foregroundVrComponent);
1094 }
1095 }
1096
1097 private void setPersistentVrModeEnabled(boolean enabled) {
Zak Cohen732aeb02017-01-29 14:19:52 -08001098 synchronized(mLock) {
1099 setPersistentModeAndNotifyListenersLocked(enabled);
Zak Cohen56345f42017-01-26 13:54:28 -08001100 // Disabling persistent mode when not showing a VR should disable the overall vr mode.
1101 if (!enabled && mCurrentVrModeComponent == null) {
1102 setVrMode(false, null, 0, null);
1103 }
Ruben Brunke24b9a62016-02-16 21:38:24 -08001104 }
1105 }
1106
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001107 public void setVr2dDisplayProperties(
1108 Vr2dDisplayProperties compatDisplayProp) {
1109 if (mVr2dDisplay != null) {
1110 mVr2dDisplay.setVirtualDisplayProperties(compatDisplayProp);
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -07001111 return;
1112 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001113 Slog.w(TAG, "Vr2dDisplay is null!");
Karthik Ravi Shankarcdf9ce72017-04-12 15:31:20 -07001114 }
1115
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001116 private int getVr2dDisplayId() {
1117 if (mVr2dDisplay != null) {
1118 return mVr2dDisplay.getVirtualDisplayId();
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -08001119 }
Karthik Ravi Shankar2b9aaed2017-05-01 01:34:19 -07001120 Slog.w(TAG, "Vr2dDisplay is null!");
Karthik Ravi Shankar3a47ec22017-03-08 18:09:35 -08001121 return INVALID_DISPLAY;
1122 }
1123
Zak Cohen732aeb02017-01-29 14:19:52 -08001124 private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
1125 if (mPersistentVrModeEnabled == enabled) {
1126 return;
1127 }
1128 mPersistentVrModeEnabled = enabled;
1129
1130 mHandler.sendMessage(mHandler.obtainMessage(MSG_PERSISTENT_VR_MODE_STATE_CHANGE,
1131 (mPersistentVrModeEnabled) ? 1 : 0, 0));
1132 }
1133
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001134 private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001135 synchronized (mLock) {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001136 return mComponentObserver.isValid(targetPackageName, userId);
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001137 }
1138 }
1139
Ruben Brunk8f1d5cb2016-03-22 18:08:41 -07001140 private boolean isCurrentVrListener(String packageName, int userId) {
1141 synchronized (mLock) {
1142 if (mCurrentVrService == null) {
1143 return false;
1144 }
1145 return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
1146 userId == mCurrentVrService.getUserId();
1147 }
1148 }
1149
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001150 /*
1151 * Implementation of IVrManager calls.
1152 */
1153
1154 private void addStateCallback(IVrStateCallbacks cb) {
Steven Thomasb70845c2017-03-16 14:32:37 -07001155 mVrStateRemoteCallbacks.register(cb);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001156 }
1157
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001158 private void removeStateCallback(IVrStateCallbacks cb) {
Steven Thomasb70845c2017-03-16 14:32:37 -07001159 mVrStateRemoteCallbacks.unregister(cb);
1160 }
1161
1162 private void addPersistentStateCallback(IPersistentVrStateCallbacks cb) {
1163 mPersistentVrStateRemoteCallbacks.register(cb);
1164 }
1165
1166 private void removePersistentStateCallback(IPersistentVrStateCallbacks cb) {
1167 mPersistentVrStateRemoteCallbacks.unregister(cb);
Ruben Brunke24b9a62016-02-16 21:38:24 -08001168 }
1169
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001170 private boolean getVrMode() {
Ruben Brunke24b9a62016-02-16 21:38:24 -08001171 synchronized (mLock) {
Ruben Brunkc7be3be2016-04-01 17:07:51 -07001172 return mVrModeEnabled;
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001173 }
1174 }
Ruben Brunkdd18a0b2015-12-04 16:16:31 -08001175}