VrManagerService.java revision 2ec8d8403ea13f77dd2a1fe9f11fff084ba85cea
1dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/**
2dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Copyright (C) 2015 The Android Open Source Project
3dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
4dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * you may not use this file except in compliance with the License.
6dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * You may obtain a copy of the License at
7dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
8dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
10dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software
11dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * See the License for the specific language governing permissions and
14dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * limitations under the License.
15dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu */
16dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhupackage com.android.server.vr;
17dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
18dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.Manifest;
19dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.app.ActivityManager;
20dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.app.AppOpsManager;
21dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.app.NotificationManager;
22dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.annotation.NonNull;
23dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.content.ComponentName;
24dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.content.ContentResolver;
25dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.content.Context;
26dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.content.pm.ApplicationInfo;
27dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.content.pm.PackageManager;
28dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.content.pm.PackageManager.NameNotFoundException;
29dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.Binder;
30dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.Handler;
31dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.IBinder;
32dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.IInterface;
3336e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhuimport android.os.Looper;
34dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.Message;
35dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.RemoteCallbackList;
36dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.RemoteException;
37dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.os.UserHandle;
38dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.provider.Settings;
39dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.service.notification.NotificationListenerService;
40dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.service.vr.IVrListener;
41dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.service.vr.IVrManager;
42dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.service.vr.IVrStateCallbacks;
43dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.service.vr.VrListenerService;
44dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.text.TextUtils;
45dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.util.ArrayMap;
46dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.util.ArraySet;
47dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.util.Slog;
48dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport android.util.SparseArray;
49dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
50dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.internal.R;
51dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.server.SystemConfig;
52dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.server.SystemService;
53dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.server.utils.ManagedApplicationService.PendingEvent;
54dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
55dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.server.utils.ManagedApplicationService;
56dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport com.android.server.utils.ManagedApplicationService.BinderChecker;
57dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
58dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.FileDescriptor;
59dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.io.PrintWriter;
60dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.lang.StringBuilder;
61dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.text.SimpleDateFormat;
62dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.ArrayDeque;
63dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.ArrayList;
64dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Collection;
65dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Date;
66dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhuimport java.util.Objects;
67dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
68dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu/**
69dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Service tracking whether VR mode is active, and notifying listening services of state changes.
70dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
71dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Services running in system server may modify the state of VrManagerService via the interface in
72dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
73dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * interface given in VrStateListener.
74dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
75dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
76dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *  hardware/libhardware/modules/vr
77dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * <p/>
78dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * In general applications may enable or disable VR mode by calling
79dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
80dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
81dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu *
82dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu * @see android.service.vr.VrListenerService
8336e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu * @see com.android.server.vr.VrManagerInternal
8436e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu * @see com.android.server.vr.VrStateListener
8536e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu *
8636e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu * @hide
8736e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu */
8836e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhupublic class VrManagerService extends SystemService implements EnabledComponentChangeListener{
8936e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu
9036e04c3847e93ccf4c3e0cde617eecea72c2605dTeng-Hui Zhu    public static final String TAG = "VrManagerService";
91dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
92dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int PENDING_STATE_DELAY_MS = 300;
93dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int EVENT_LOG_SIZE = 32;
94dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int INVALID_APPOPS_MODE = -1;
95dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    /** Null set of sleep sleep flags. */
96dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int FLAG_NONE = 0;
97dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    /** Flag set when the device is not sleeping. */
98dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int FLAG_AWAKE = 1;
99dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    /** Flag set when the screen has been turned on. */
100dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int FLAG_SCREEN_ON = 2;
101dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    /** Flag indicating that all system sleep flags have been set.*/
102dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int FLAG_ALL = FLAG_AWAKE | FLAG_SCREEN_ON;
103dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
104dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static native void initializeNative();
105dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static native void setVrModeNative(boolean enabled);
106dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
107dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private final Object mLock = new Object();
108dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
109dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private final IBinder mOverlayToken = new Binder();
110dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
111dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    // State protected by mLock
112dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private boolean mVrModeAllowed;
113dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private boolean mVrModeEnabled;
114dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private boolean mPersistentVrModeEnabled;
115dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private EnabledComponentsObserver mComponentObserver;
116dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private ManagedApplicationService mCurrentVrService;
117dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private ComponentName mDefaultVrService;
118dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private Context mContext;
119dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private ComponentName mCurrentVrModeComponent;
120dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private int mCurrentVrModeUser;
121dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private boolean mWasDefaultGranted;
122dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private boolean mGuard;
123dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
124dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            new RemoteCallbackList<>();
125dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private final ArrayList<PersistentVrStateListener> mPersistentVrStateListeners =
126dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu            new ArrayList<>();
127dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
128dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
129dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private VrState mPendingState;
130dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
131dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
132dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    /** Tracks the state of the screen and keyguard UI.*/
133dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private int mSystemSleepFlags = FLAG_NONE;
134dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
135dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int MSG_VR_STATE_CHANGE = 0;
136dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
137dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    private static final int MSG_PERSISTENT_VR_MODE_STATE_CHANGE = 2;
138dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu
139dd9eb897ee7c7b507cbdcf80263bb4b5de6966bfTeng-Hui Zhu    /**
140     * Set whether VR mode may be enabled.
141     * <p/>
142     * If VR mode is not allowed to be enabled, calls to set VR mode will be cached.  When VR mode
143     * is again allowed to be enabled, the most recent cached state will be applied.
144     *
145     * @param allowed {@code true} if calling any of the setVrMode methods may cause the device to
146     *   enter VR mode.
147     */
148    private void setVrModeAllowedLocked(boolean allowed) {
149        if (mVrModeAllowed != allowed) {
150            mVrModeAllowed = allowed;
151            Slog.i(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
152            if (mVrModeAllowed) {
153                consumeAndApplyPendingStateLocked();
154            } else {
155                // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
156                // exit persistent VR mode when screen is turned off.
157                setPersistentModeAndNotifyListenersLocked(false);
158
159                // Set pending state to current state.
160                mPendingState = (mVrModeEnabled && mCurrentVrService != null)
161                    ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
162                        mCurrentVrService.getUserId(), mCurrentVrModeComponent)
163                    : null;
164
165                // Unbind current VR service and do necessary callbacks.
166                updateCurrentVrServiceLocked(false, null, 0, null);
167            }
168        }
169    }
170
171    private void setSleepState(boolean isAsleep) {
172        synchronized(mLock) {
173
174            if (!isAsleep) {
175                mSystemSleepFlags |= FLAG_AWAKE;
176            } else {
177                mSystemSleepFlags &= ~FLAG_AWAKE;
178            }
179
180            setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
181        }
182    }
183
184    private void setScreenOn(boolean isScreenOn) {
185        synchronized(mLock) {
186            if (isScreenOn) {
187                mSystemSleepFlags |= FLAG_SCREEN_ON;
188            } else {
189                mSystemSleepFlags &= ~FLAG_SCREEN_ON;
190            }
191            setVrModeAllowedLocked(mSystemSleepFlags == FLAG_ALL);
192        }
193    }
194
195    private final Handler mHandler = new Handler() {
196        @Override
197        public void handleMessage(Message msg) {
198            switch(msg.what) {
199                case MSG_VR_STATE_CHANGE : {
200                    boolean state = (msg.arg1 == 1);
201                    int i = mRemoteCallbacks.beginBroadcast();
202                    while (i > 0) {
203                        i--;
204                        try {
205                            mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
206                        } catch (RemoteException e) {
207                            // Noop
208                        }
209                    }
210                    mRemoteCallbacks.finishBroadcast();
211                } break;
212                case MSG_PENDING_VR_STATE_CHANGE : {
213                    synchronized(mLock) {
214                        if (mVrModeAllowed) {
215                           VrManagerService.this.consumeAndApplyPendingStateLocked();
216                        }
217                    }
218                } break;
219                case MSG_PERSISTENT_VR_MODE_STATE_CHANGE : {
220                    boolean state = (msg.arg1 == 1);
221                    for (int i = 0; i < mPersistentVrStateListeners.size(); i++) {
222                        mPersistentVrStateListeners.get(i).onPersistentVrStateChanged(
223                                state);
224                    }
225                } break;
226                default :
227                    throw new IllegalStateException("Unknown message type: " + msg.what);
228            }
229        }
230    };
231
232    private static class VrState {
233        final boolean enabled;
234        final int userId;
235        final ComponentName targetPackageName;
236        final ComponentName callingPackage;
237        final long timestamp;
238        final boolean defaultPermissionsGranted;
239
240        VrState(boolean enabled, ComponentName targetPackageName, int userId,
241                ComponentName callingPackage) {
242            this.enabled = enabled;
243            this.userId = userId;
244            this.targetPackageName = targetPackageName;
245            this.callingPackage = callingPackage;
246            this.defaultPermissionsGranted = false;
247            this.timestamp = System.currentTimeMillis();
248        }
249
250        VrState(boolean enabled, ComponentName targetPackageName, int userId,
251            ComponentName callingPackage, boolean defaultPermissionsGranted) {
252            this.enabled = enabled;
253            this.userId = userId;
254            this.targetPackageName = targetPackageName;
255            this.callingPackage = callingPackage;
256            this.defaultPermissionsGranted = defaultPermissionsGranted;
257            this.timestamp = System.currentTimeMillis();
258        }
259    }
260
261    private static final BinderChecker sBinderChecker = new BinderChecker() {
262        @Override
263        public IInterface asInterface(IBinder binder) {
264            return IVrListener.Stub.asInterface(binder);
265        }
266
267        @Override
268        public boolean checkType(IInterface service) {
269            return service instanceof IVrListener;
270        }
271    };
272
273    private final class NotificationAccessManager {
274        private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
275        private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
276                new ArrayMap<>();
277
278        public void update(Collection<String> packageNames) {
279            int currentUserId = ActivityManager.getCurrentUser();
280
281            ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
282            if (allowed == null) {
283                allowed = new ArraySet<>();
284            }
285
286            // Make sure we revoke notification access for listeners in other users
287            final int listenerCount = mNotificationAccessPackageToUserId.size();
288            for (int i = listenerCount - 1; i >= 0; i--) {
289                final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
290                if (grantUserId != currentUserId) {
291                    String packageName = mNotificationAccessPackageToUserId.keyAt(i);
292                    revokeNotificationListenerAccess(packageName, grantUserId);
293                    revokeNotificationPolicyAccess(packageName);
294                    revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
295                    mNotificationAccessPackageToUserId.removeAt(i);
296                }
297            }
298
299            for (String pkg : allowed) {
300                if (!packageNames.contains(pkg)) {
301                    revokeNotificationListenerAccess(pkg, currentUserId);
302                    revokeNotificationPolicyAccess(pkg);
303                    revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
304                    mNotificationAccessPackageToUserId.remove(pkg);
305                }
306            }
307            for (String pkg : packageNames) {
308                if (!allowed.contains(pkg)) {
309                    grantNotificationPolicyAccess(pkg);
310                    grantNotificationListenerAccess(pkg, currentUserId);
311                    grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
312                    mNotificationAccessPackageToUserId.put(pkg, currentUserId);
313                }
314            }
315
316            allowed.clear();
317            allowed.addAll(packageNames);
318            mAllowedPackages.put(currentUserId, allowed);
319        }
320    }
321
322    /**
323     * Called when a user, package, or setting changes that could affect whether or not the
324     * currently bound VrListenerService is changed.
325     */
326    @Override
327    public void onEnabledComponentChanged() {
328        synchronized (mLock) {
329            int currentUser = ActivityManager.getCurrentUser();
330            // Update listeners
331            ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
332
333            ArraySet<String> enabledPackages = new ArraySet<>();
334            for (ComponentName n : enabledListeners) {
335                String pkg = n.getPackageName();
336                if (isDefaultAllowed(pkg)) {
337                    enabledPackages.add(n.getPackageName());
338                }
339            }
340            mNotifAccessManager.update(enabledPackages);
341
342            if (!mVrModeAllowed) {
343                return; // Don't do anything, we shouldn't be in VR mode.
344            }
345
346            // If there is a pending state change, we'd better deal with that first
347            consumeAndApplyPendingStateLocked(false);
348
349            if (mCurrentVrService == null) {
350                return; // No active services
351            }
352
353            // There is an active service, update it if needed
354            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
355                    mCurrentVrService.getUserId(), null);
356        }
357    }
358
359    private final IVrManager mVrManager = new IVrManager.Stub() {
360
361        @Override
362        public void registerListener(IVrStateCallbacks cb) {
363            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
364            if (cb == null) {
365                throw new IllegalArgumentException("Callback binder object is null.");
366            }
367
368            VrManagerService.this.addStateCallback(cb);
369        }
370
371        @Override
372        public void unregisterListener(IVrStateCallbacks cb) {
373            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
374            if (cb == null) {
375                throw new IllegalArgumentException("Callback binder object is null.");
376            }
377
378            VrManagerService.this.removeStateCallback(cb);
379        }
380
381        @Override
382        public boolean getVrModeState() {
383            return VrManagerService.this.getVrMode();
384        }
385
386        @Override
387        public void setPersistentVrModeEnabled(boolean enabled) {
388            enforceCallerPermission(Manifest.permission.RESTRICTED_VR_ACCESS);
389            VrManagerService.this.setPersistentVrModeEnabled(enabled);
390        }
391
392        @Override
393        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
394            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
395                    != PackageManager.PERMISSION_GRANTED) {
396                pw.println("Permission Denial: can't dump VrManagerService from pid="
397                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
398                return;
399            }
400            pw.println("********* Dump of VrManagerService *********");
401            pw.println("VR mode is currently: " + ((mVrModeAllowed) ? "allowed" : "disallowed"));
402            pw.println("Persistent VR mode is currently: " +
403                    ((mPersistentVrModeEnabled) ? "enabled" : "disabled"));
404            pw.println("Previous state transitions:\n");
405            String tab = "  ";
406            dumpStateTransitions(pw);
407            pw.println("\n\nRemote Callbacks:");
408            int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
409            while(i-->0) {
410                pw.print(tab);
411                pw.print(mRemoteCallbacks.getBroadcastItem(i));
412                if (i>0) pw.println(",");
413            }
414            mRemoteCallbacks.finishBroadcast();
415            pw.println("\n");
416            pw.println("Installed VrListenerService components:");
417            int userId = mCurrentVrModeUser;
418            ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
419            if (installed == null || installed.size() == 0) {
420                pw.println("None");
421            } else {
422                for (ComponentName n : installed) {
423                    pw.print(tab);
424                    pw.println(n.flattenToString());
425                }
426            }
427            pw.println("Enabled VrListenerService components:");
428            ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
429            if (enabled == null || enabled.size() == 0) {
430                pw.println("None");
431            } else {
432                for (ComponentName n : enabled) {
433                    pw.print(tab);
434                    pw.println(n.flattenToString());
435                }
436            }
437            pw.println("Attached persistent mode listeners:");
438            if (mPersistentVrStateListeners == null ||
439                    mPersistentVrStateListeners.size() == 0) {
440                pw.println("None");
441            } else {
442                for (PersistentVrStateListener l : mPersistentVrStateListeners) {
443                    pw.print(tab);
444                    pw.println("listener: " + l);
445                }
446            }
447            pw.println("\n");
448            pw.println("********* End of VrManagerService Dump *********");
449        }
450
451    };
452
453    private void enforceCallerPermission(String permission) {
454        if (mContext.checkCallingOrSelfPermission(permission)
455                != PackageManager.PERMISSION_GRANTED) {
456            throw new SecurityException("Caller does not hold the permission " + permission);
457        }
458    }
459
460    /**
461     * Implementation of VrManagerInternal.  Callable only from system services.
462     */
463    private final class LocalService extends VrManagerInternal {
464        @Override
465        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
466                ComponentName callingPackage) {
467            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
468        }
469
470        @Override
471        public void onSleepStateChanged(boolean isAsleep) {
472            VrManagerService.this.setSleepState(isAsleep);
473        }
474
475        @Override
476        public void onScreenStateChanged(boolean isScreenOn) {
477            VrManagerService.this.setScreenOn(isScreenOn);
478        }
479
480        @Override
481        public boolean isCurrentVrListener(String packageName, int userId) {
482            return VrManagerService.this.isCurrentVrListener(packageName, userId);
483        }
484
485        @Override
486        public int hasVrPackage(ComponentName packageName, int userId) {
487            return VrManagerService.this.hasVrPackage(packageName, userId);
488        }
489
490        @Override
491        public void setPersistentVrModeEnabled(boolean enabled) {
492            VrManagerService.this.setPersistentVrModeEnabled(enabled);
493        }
494
495        @Override
496        public void addPersistentVrModeStateListener(PersistentVrStateListener listener) {
497            VrManagerService.this.addPersistentVrModeStateListener(listener);
498        }
499    }
500
501    public VrManagerService(Context context) {
502        super(context);
503    }
504
505    @Override
506    public void onStart() {
507        synchronized(mLock) {
508            initializeNative();
509            mContext = getContext();
510        }
511
512        publishLocalService(VrManagerInternal.class, new LocalService());
513        publishBinderService(Context.VR_SERVICE, mVrManager.asBinder());
514    }
515
516    @Override
517    public void onBootPhase(int phase) {
518        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
519            synchronized (mLock) {
520                Looper looper = Looper.getMainLooper();
521                Handler handler = new Handler(looper);
522                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
523                listeners.add(this);
524                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
525                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
526                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
527                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
528
529                mComponentObserver.rebuildAll();
530            }
531
532            //TODO: something more robust than picking the first one
533            ArraySet<ComponentName> defaultVrComponents =
534                    SystemConfig.getInstance().getDefaultVrComponents();
535            if (defaultVrComponents.size() > 0) {
536                mDefaultVrService = defaultVrComponents.valueAt(0);
537            } else {
538                Slog.i(TAG, "No default vr listener service found.");
539            }
540        } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
541            synchronized (mLock) {
542                mVrModeAllowed = true;
543            }
544        }
545    }
546
547    @Override
548    public void onStartUser(int userHandle) {
549        synchronized (mLock) {
550            mComponentObserver.onUsersChanged();
551        }
552    }
553
554    @Override
555    public void onSwitchUser(int userHandle) {
556        synchronized (mLock) {
557            mComponentObserver.onUsersChanged();
558        }
559
560    }
561
562    @Override
563    public void onStopUser(int userHandle) {
564        synchronized (mLock) {
565            mComponentObserver.onUsersChanged();
566        }
567
568    }
569
570    @Override
571    public void onCleanupUser(int userHandle) {
572        synchronized (mLock) {
573            mComponentObserver.onUsersChanged();
574        }
575    }
576
577    private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
578        AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
579
580        // If user changed drop restrictions for the old user.
581        if (oldUserId != newUserId) {
582            appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
583                    false, mOverlayToken, null, oldUserId);
584        }
585
586        if (!mVrModeEnabled) {
587            return;
588        }
589
590        // Apply the restrictions for the current user based on vr state
591        String[] exemptions = (exemptedPackage == null) ? new String[0] :
592                new String[] { exemptedPackage };
593
594        appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
595                true, mOverlayToken, exemptions, newUserId);
596    }
597
598    private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
599            String oldVrServicePackage, int oldUserId) {
600        // If VR state changed and we also have a VR service change.
601        if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
602            return;
603        }
604        final long identity = Binder.clearCallingIdentity();
605        try {
606            // Set overlay exception state based on VR enabled and current service
607            updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
608        } finally {
609            Binder.restoreCallingIdentity(identity);
610        }
611    }
612
613    /**
614     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
615     * the currently selected VR listener service.  If the component selected for the VR listener
616     * service has changed, unbind the previous listener and bind the new listener (if enabled).
617     * <p/>
618     * Note: Must be called while holding {@code mLock}.
619     *
620     * @param enabled new state for VR mode.
621     * @param component new component to be bound as a VR listener.
622     * @param userId user owning the component to be bound.
623     * @param calling the component currently using VR mode, or null to leave unchanged.
624     *
625     * @return {@code true} if the component/user combination specified is valid.
626     */
627    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
628            int userId, ComponentName calling) {
629
630        boolean sendUpdatedCaller = false;
631        final long identity = Binder.clearCallingIdentity();
632        try {
633
634            boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
635                    EnabledComponentsObserver.NO_ERROR);
636            boolean goingIntoVrMode = validUserComponent && enabled;
637            if (!mVrModeEnabled && !goingIntoVrMode) {
638                return validUserComponent; // Disabled -> Disabled transition does nothing.
639            }
640
641            String oldVrServicePackage = mCurrentVrService != null
642                    ? mCurrentVrService.getComponent().getPackageName() : null;
643            final int oldUserId = mCurrentVrModeUser;
644
645            // Notify system services and VR HAL of mode change.
646            changeVrModeLocked(goingIntoVrMode);
647
648            boolean nothingChanged = false;
649            if (!goingIntoVrMode) {
650                // Not going into VR mode, unbind whatever is running
651                if (mCurrentVrService != null) {
652                    Slog.i(TAG, "Leaving VR mode, disconnecting "
653                        + mCurrentVrService.getComponent() + " for user "
654                        + mCurrentVrService.getUserId());
655                    mCurrentVrService.disconnect();
656                    mCurrentVrService = null;
657                } else {
658                    nothingChanged = true;
659                }
660            } else {
661                // Going into VR mode
662                if (mCurrentVrService != null) {
663                    // Unbind any running service that doesn't match the latest component/user
664                    // selection.
665                    if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
666                        Slog.i(TAG, "VR mode component changed to " + component
667                            + ", disconnecting " + mCurrentVrService.getComponent()
668                            + " for user " + mCurrentVrService.getUserId());
669                        createAndConnectService(component, userId);
670                        sendUpdatedCaller = true;
671                    } else {
672                        nothingChanged = true;
673                    }
674                    // The service with the correct component/user is already bound, do nothing.
675                } else {
676                    // Nothing was previously running, bind a new service for the latest
677                    // component/user selection.
678                    createAndConnectService(component, userId);
679                    sendUpdatedCaller = true;
680                }
681            }
682
683            mCurrentVrModeComponent = calling;
684            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
685                sendUpdatedCaller = true;
686            }
687
688            if (mCurrentVrModeUser != userId) {
689                mCurrentVrModeUser = userId;
690                sendUpdatedCaller = true;
691            }
692
693            String newVrServicePackage = mCurrentVrService != null
694                    ? mCurrentVrService.getComponent().getPackageName() : null;
695            final int newUserId = mCurrentVrModeUser;
696
697            // Update AppOps settings that change state when entering/exiting VR mode, or changing
698            // the current VrListenerService.
699            updateDependentAppOpsLocked(newVrServicePackage, newUserId,
700                    oldVrServicePackage, oldUserId);
701
702            if (mCurrentVrService != null && sendUpdatedCaller) {
703                final ComponentName c = mCurrentVrModeComponent;
704                mCurrentVrService.sendEvent(new PendingEvent() {
705                    @Override
706                    public void runEvent(IInterface service) throws RemoteException {
707                        IVrListener l = (IVrListener) service;
708                        l.focusedActivityChanged(c);
709                    }
710                });
711            }
712
713            if (!nothingChanged) {
714                logStateLocked();
715            }
716
717            return validUserComponent;
718        } finally {
719            Binder.restoreCallingIdentity(identity);
720        }
721    }
722
723    private boolean isDefaultAllowed(String packageName) {
724        PackageManager pm = mContext.getPackageManager();
725
726        ApplicationInfo info = null;
727        try {
728            info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
729        } catch (NameNotFoundException e) {
730        }
731
732        if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
733            return false;
734        }
735        return true;
736    }
737
738    private void grantNotificationPolicyAccess(String pkg) {
739        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
740        nm.setNotificationPolicyAccessGranted(pkg, true);
741    }
742
743    private void revokeNotificationPolicyAccess(String pkg) {
744        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
745        // Remove any DND zen rules possibly created by the package.
746        nm.removeAutomaticZenRules(pkg);
747        // Remove Notification Policy Access.
748        nm.setNotificationPolicyAccessGranted(pkg, false);
749    }
750
751    private void grantNotificationListenerAccess(String pkg, int userId) {
752        PackageManager pm = mContext.getPackageManager();
753        ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
754                userId, NotificationListenerService.SERVICE_INTERFACE,
755                android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
756        ContentResolver resolver = mContext.getContentResolver();
757
758        ArraySet<String> current = getNotificationListeners(resolver, userId);
759
760        for (ComponentName c : possibleServices) {
761            String flatName = c.flattenToString();
762            if (Objects.equals(c.getPackageName(), pkg)
763                    && !current.contains(flatName)) {
764                current.add(flatName);
765            }
766        }
767
768        if (current.size() > 0) {
769            String flatSettings = formatSettings(current);
770            Settings.Secure.putStringForUser(resolver,
771                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
772                    flatSettings, userId);
773        }
774    }
775
776    private void revokeNotificationListenerAccess(String pkg, int userId) {
777        ContentResolver resolver = mContext.getContentResolver();
778
779        ArraySet<String> current = getNotificationListeners(resolver, userId);
780
781        ArrayList<String> toRemove = new ArrayList<>();
782
783        for (String c : current) {
784            ComponentName component = ComponentName.unflattenFromString(c);
785            if (component != null && component.getPackageName().equals(pkg)) {
786                toRemove.add(c);
787            }
788        }
789
790        current.removeAll(toRemove);
791
792        String flatSettings = formatSettings(current);
793        Settings.Secure.putStringForUser(resolver,
794                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
795                flatSettings, userId);
796    }
797
798    private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
799        // Don't clobber the user if permission set in current state explicitly
800        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
801            try {
802                mContext.getPackageManager().grantRuntimePermission(pkg,
803                        Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
804            } catch (IllegalArgumentException e) {
805                // Package was removed during update.
806                Slog.w(TAG, "Could not grant coarse location permission, package " + pkg
807                    + " was removed.");
808            }
809        }
810    }
811
812    private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
813        // Don't clobber the user if permission set in current state explicitly
814        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
815            try {
816                mContext.getPackageManager().revokeRuntimePermission(pkg,
817                        Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
818            } catch (IllegalArgumentException e) {
819                // Package was removed during update.
820                Slog.w(TAG, "Could not revoke coarse location permission, package " + pkg
821                    + " was removed.");
822            }
823        }
824    }
825
826    private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
827        final int flags = mContext.getPackageManager().getPermissionFlags(
828                permission, pkg, new UserHandle(userId));
829        return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
830                | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
831    }
832
833    private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
834        String flat = Settings.Secure.getStringForUser(resolver,
835                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
836
837        ArraySet<String> current = new ArraySet<>();
838        if (flat != null) {
839            String[] allowed = flat.split(":");
840            for (String s : allowed) {
841                if (!TextUtils.isEmpty(s)) {
842                    current.add(s);
843                }
844            }
845        }
846        return current;
847    }
848
849    private static String formatSettings(Collection<String> c) {
850        if (c == null || c.isEmpty()) {
851            return "";
852        }
853
854        StringBuilder b = new StringBuilder();
855        boolean start = true;
856        for (String s : c) {
857            if ("".equals(s)) {
858                continue;
859            }
860            if (!start) {
861                b.append(':');
862            }
863            b.append(s);
864            start = false;
865        }
866        return b.toString();
867    }
868
869
870
871    private void createAndConnectService(@NonNull ComponentName component, int userId) {
872        mCurrentVrService = VrManagerService.create(mContext, component, userId);
873        mCurrentVrService.connect();
874        Slog.i(TAG, "Connecting " + component + " for user " + userId);
875    }
876
877    /**
878     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
879     * <p/>
880     * Note: Must be called while holding {@code mLock}.
881     *
882     * @param enabled new state of the VR mode.
883     */
884    private void changeVrModeLocked(boolean enabled) {
885        if (mVrModeEnabled != enabled) {
886            mVrModeEnabled = enabled;
887
888            // Log mode change event.
889            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
890            setVrModeNative(mVrModeEnabled);
891
892            onVrModeChangedLocked();
893        }
894    }
895
896    /**
897     * Notify system services of VR mode change.
898     * <p/>
899     * Note: Must be called while holding {@code mLock}.
900     */
901    private void onVrModeChangedLocked() {
902        mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
903                (mVrModeEnabled) ? 1 : 0, 0));
904    }
905
906    /**
907     * Helper function for making ManagedApplicationService instances.
908     */
909    private static ManagedApplicationService create(@NonNull Context context,
910            @NonNull ComponentName component, int userId) {
911        return ManagedApplicationService.build(context, component, userId,
912                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
913                sBinderChecker);
914    }
915
916    /**
917     * Apply the pending VR state. If no state is pending, disconnect any currently bound
918     * VR listener service.
919     */
920    private void consumeAndApplyPendingStateLocked() {
921        consumeAndApplyPendingStateLocked(true);
922    }
923
924    /**
925     * Apply the pending VR state.
926     *
927     * @param disconnectIfNoPendingState if {@code true}, then any currently bound VR listener
928     *     service will be disconnected if no state is pending. If this is {@code false} then the
929     *     nothing will be changed when there is no pending state.
930     */
931    private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
932        if (mPendingState != null) {
933            updateCurrentVrServiceLocked(mPendingState.enabled,
934                    mPendingState.targetPackageName, mPendingState.userId,
935                    mPendingState.callingPackage);
936            mPendingState = null;
937        } else if (disconnectIfNoPendingState) {
938            updateCurrentVrServiceLocked(false, null, 0, null);
939        }
940    }
941
942    private void logStateLocked() {
943        ComponentName currentBoundService = (mCurrentVrService == null) ? null :
944            mCurrentVrService.getComponent();
945        VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
946            mCurrentVrModeComponent, mWasDefaultGranted);
947        if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
948            mLoggingDeque.removeFirst();
949        }
950        mLoggingDeque.add(current);
951    }
952
953    private void dumpStateTransitions(PrintWriter pw) {
954        SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
955        String tab = "  ";
956        if (mLoggingDeque.size() == 0) {
957            pw.print(tab);
958            pw.println("None");
959        }
960        for (VrState state : mLoggingDeque) {
961            pw.print(d.format(new Date(state.timestamp)));
962            pw.print(tab);
963            pw.print("State changed to:");
964            pw.print(tab);
965            pw.println((state.enabled) ? "ENABLED" : "DISABLED");
966            if (state.enabled) {
967                pw.print(tab);
968                pw.print("User=");
969                pw.println(state.userId);
970                pw.print(tab);
971                pw.print("Current VR Activity=");
972                pw.println((state.callingPackage == null) ?
973                    "None" : state.callingPackage.flattenToString());
974                pw.print(tab);
975                pw.print("Bound VrListenerService=");
976                pw.println((state.targetPackageName == null) ?
977                    "None" : state.targetPackageName.flattenToString());
978                if (state.defaultPermissionsGranted) {
979                    pw.print(tab);
980                    pw.println("Default permissions granted to the bound VrListenerService.");
981                }
982            }
983        }
984    }
985
986    /*
987     * Implementation of VrManagerInternal calls.  These are callable from system services.
988     */
989    private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
990            int userId, @NonNull ComponentName callingPackage) {
991
992        synchronized (mLock) {
993            VrState pending;
994            ComponentName targetListener;
995            ComponentName foregroundVrComponent;
996
997            // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
998            // and the system default VR listener is used.
999            boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
1000            if (!enabled && mPersistentVrModeEnabled) {
1001                targetListener = mDefaultVrService;
1002
1003                // Current foreground component isn't a VR one (in 2D app case)
1004                foregroundVrComponent = null;
1005            } else {
1006                targetListener = targetPackageName;
1007                foregroundVrComponent = callingPackage;
1008            }
1009            pending = new VrState(
1010                    targetEnabledState, targetListener, userId, foregroundVrComponent);
1011
1012            if (!mVrModeAllowed) {
1013                // We're not allowed to be in VR mode.  Make this state pending.  This will be
1014                // applied the next time we are allowed to enter VR mode unless it is superseded by
1015                // another call.
1016                mPendingState = pending;
1017                return;
1018            }
1019
1020            if (!targetEnabledState && mCurrentVrService != null) {
1021                // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
1022                // and service bind/unbind in case we are immediately switching to another VR app.
1023                if (mPendingState == null) {
1024                    mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
1025                            PENDING_STATE_DELAY_MS);
1026                }
1027
1028                mPendingState = pending;
1029                return;
1030            } else {
1031                mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
1032                mPendingState = null;
1033            }
1034
1035            updateCurrentVrServiceLocked(
1036                    targetEnabledState, targetListener, userId, foregroundVrComponent);
1037        }
1038    }
1039
1040    private void setPersistentVrModeEnabled(boolean enabled) {
1041        synchronized(mLock) {
1042            setPersistentModeAndNotifyListenersLocked(enabled);
1043            // Disabling persistent mode when not showing a VR should disable the overall vr mode.
1044            if (!enabled && mCurrentVrModeComponent == null) {
1045                setVrMode(false, null, 0, null);
1046            }
1047        }
1048    }
1049
1050    private void setPersistentModeAndNotifyListenersLocked(boolean enabled) {
1051        if (mPersistentVrModeEnabled == enabled) {
1052            return;
1053        }
1054        mPersistentVrModeEnabled = enabled;
1055
1056        mHandler.sendMessage(mHandler.obtainMessage(MSG_PERSISTENT_VR_MODE_STATE_CHANGE,
1057                (mPersistentVrModeEnabled) ? 1 : 0, 0));
1058    }
1059
1060    private void addPersistentVrModeStateListener(PersistentVrStateListener listener) {
1061        synchronized (mLock) {
1062            mPersistentVrStateListeners.add(listener);
1063        }
1064    }
1065
1066    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
1067        synchronized (mLock) {
1068            return mComponentObserver.isValid(targetPackageName, userId);
1069        }
1070    }
1071
1072    private boolean isCurrentVrListener(String packageName, int userId) {
1073        synchronized (mLock) {
1074            if (mCurrentVrService == null) {
1075                return false;
1076            }
1077            return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
1078                    userId == mCurrentVrService.getUserId();
1079        }
1080    }
1081
1082    /*
1083     * Implementation of IVrManager calls.
1084     */
1085
1086    private void addStateCallback(IVrStateCallbacks cb) {
1087        mRemoteCallbacks.register(cb);
1088    }
1089
1090    private void removeStateCallback(IVrStateCallbacks cb) {
1091        mRemoteCallbacks.unregister(cb);
1092    }
1093
1094    private boolean getVrMode() {
1095        synchronized (mLock) {
1096            return mVrModeEnabled;
1097        }
1098    }
1099}
1100