1/**
2 * 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
18import android.Manifest;
19import android.app.ActivityManager;
20import android.app.AppOpsManager;
21import android.app.NotificationManager;
22import android.annotation.NonNull;
23import android.content.BroadcastReceiver;
24import android.content.ComponentName;
25import android.content.ContentResolver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.content.pm.ApplicationInfo;
30import android.content.pm.FeatureInfo;
31import android.content.pm.PackageInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.PackageManager.NameNotFoundException;
34import android.os.Binder;
35import android.os.Handler;
36import android.os.IBinder;
37import android.os.IInterface;
38import android.os.Looper;
39import android.os.Message;
40import android.os.RemoteCallbackList;
41import android.os.RemoteException;
42import android.os.UserHandle;
43import android.provider.Settings;
44import android.service.notification.NotificationListenerService;
45import android.service.vr.IVrListener;
46import android.service.vr.IVrManager;
47import android.service.vr.IVrStateCallbacks;
48import android.service.vr.VrListenerService;
49import android.util.ArrayMap;
50import android.util.ArraySet;
51import android.util.Slog;
52import android.util.SparseArray;
53import com.android.internal.R;
54import com.android.server.LocalServices;
55import com.android.server.SystemConfig;
56import com.android.server.SystemService;
57import com.android.server.utils.ManagedApplicationService.PendingEvent;
58import com.android.server.vr.EnabledComponentsObserver.EnabledComponentChangeListener;
59import com.android.server.utils.ManagedApplicationService;
60import com.android.server.utils.ManagedApplicationService.BinderChecker;
61
62import java.io.FileDescriptor;
63import java.io.PrintWriter;
64import java.lang.StringBuilder;
65import java.text.SimpleDateFormat;
66import java.util.ArrayDeque;
67import java.util.ArrayList;
68import java.util.Collection;
69import java.util.Date;
70import java.util.List;
71import java.util.Map;
72import java.util.Objects;
73
74/**
75 * Service tracking whether VR mode is active, and notifying listening services of state changes.
76 * <p/>
77 * Services running in system server may modify the state of VrManagerService via the interface in
78 * VrManagerInternal, and may register to receive callbacks when the system VR mode changes via the
79 * interface given in VrStateListener.
80 * <p/>
81 * Device vendors may choose to receive VR state changes by implementing the VR mode HAL, e.g.:
82 *  hardware/libhardware/modules/vr
83 * <p/>
84 * In general applications may enable or disable VR mode by calling
85 * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
86 * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
87 *
88 * @see {@link android.service.vr.VrListenerService}
89 * @see {@link com.android.server.vr.VrManagerInternal}
90 * @see {@link com.android.server.vr.VrStateListener}
91 *
92 * @hide
93 */
94public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
95
96    public static final String TAG = "VrManagerService";
97
98    public static final String VR_MANAGER_BINDER_SERVICE = "vrmanager";
99
100    private static final int PENDING_STATE_DELAY_MS = 300;
101    private static final int EVENT_LOG_SIZE = 32;
102    private static final int INVALID_APPOPS_MODE = -1;
103
104    private static native void initializeNative();
105    private static native void setVrModeNative(boolean enabled);
106
107    private final Object mLock = new Object();
108
109    private final IBinder mOverlayToken = new Binder();
110
111    // State protected by mLock
112    private boolean mVrModeEnabled;
113    private EnabledComponentsObserver mComponentObserver;
114    private ManagedApplicationService mCurrentVrService;
115    private Context mContext;
116    private ComponentName mCurrentVrModeComponent;
117    private int mCurrentVrModeUser;
118    private boolean mWasDefaultGranted;
119    private boolean mGuard;
120    private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
121            new RemoteCallbackList<>();
122    private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
123    private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
124    private VrState mPendingState;
125    private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
126    private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
127
128    private static final int MSG_VR_STATE_CHANGE = 0;
129    private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
130
131    private final Handler mHandler = new Handler() {
132        @Override
133        public void handleMessage(Message msg) {
134            switch(msg.what) {
135                case MSG_VR_STATE_CHANGE : {
136                    boolean state = (msg.arg1 == 1);
137                    int i = mRemoteCallbacks.beginBroadcast();
138                    while (i > 0) {
139                        i--;
140                        try {
141                            mRemoteCallbacks.getBroadcastItem(i).onVrStateChanged(state);
142                        } catch (RemoteException e) {
143                            // Noop
144                        }
145                    }
146                    mRemoteCallbacks.finishBroadcast();
147                } break;
148                case MSG_PENDING_VR_STATE_CHANGE : {
149                    synchronized(mLock) {
150                        VrManagerService.this.consumeAndApplyPendingStateLocked();
151                    }
152                } break;
153                default :
154                    throw new IllegalStateException("Unknown message type: " + msg.what);
155            }
156        }
157    };
158
159    private static class VrState {
160        final boolean enabled;
161        final int userId;
162        final ComponentName targetPackageName;
163        final ComponentName callingPackage;
164        final long timestamp;
165        final boolean defaultPermissionsGranted;
166
167        VrState(boolean enabled, ComponentName targetPackageName, int userId,
168                ComponentName callingPackage) {
169            this.enabled = enabled;
170            this.userId = userId;
171            this.targetPackageName = targetPackageName;
172            this.callingPackage = callingPackage;
173            this.defaultPermissionsGranted = false;
174            this.timestamp = System.currentTimeMillis();
175        }
176
177        VrState(boolean enabled, ComponentName targetPackageName, int userId,
178            ComponentName callingPackage, boolean defaultPermissionsGranted) {
179            this.enabled = enabled;
180            this.userId = userId;
181            this.targetPackageName = targetPackageName;
182            this.callingPackage = callingPackage;
183            this.defaultPermissionsGranted = defaultPermissionsGranted;
184            this.timestamp = System.currentTimeMillis();
185        }
186    }
187
188    private static final BinderChecker sBinderChecker = new BinderChecker() {
189        @Override
190        public IInterface asInterface(IBinder binder) {
191            return IVrListener.Stub.asInterface(binder);
192        }
193
194        @Override
195        public boolean checkType(IInterface service) {
196            return service instanceof IVrListener;
197        }
198    };
199
200    private final class NotificationAccessManager {
201        private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
202        private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
203                new ArrayMap<>();
204
205        public void update(Collection<String> packageNames) {
206            int currentUserId = ActivityManager.getCurrentUser();
207
208            ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
209            if (allowed == null) {
210                allowed = new ArraySet<>();
211            }
212
213            // Make sure we revoke notification access for listeners in other users
214            final int listenerCount = mNotificationAccessPackageToUserId.size();
215            for (int i = listenerCount - 1; i >= 0; i--) {
216                final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
217                if (grantUserId != currentUserId) {
218                    String packageName = mNotificationAccessPackageToUserId.keyAt(i);
219                    revokeNotificationListenerAccess(packageName, grantUserId);
220                    revokeNotificationPolicyAccess(packageName);
221                    mNotificationAccessPackageToUserId.removeAt(i);
222                }
223            }
224
225            for (String pkg : allowed) {
226                if (!packageNames.contains(pkg)) {
227                    revokeNotificationListenerAccess(pkg, currentUserId);
228                    revokeNotificationPolicyAccess(pkg);
229                    mNotificationAccessPackageToUserId.remove(pkg);
230                }
231            }
232            for (String pkg : packageNames) {
233                if (!allowed.contains(pkg)) {
234                    grantNotificationPolicyAccess(pkg);
235                    grantNotificationListenerAccess(pkg, currentUserId);
236                    mNotificationAccessPackageToUserId.put(pkg, currentUserId);
237                }
238            }
239
240            allowed.clear();
241            allowed.addAll(packageNames);
242            mAllowedPackages.put(currentUserId, allowed);
243        }
244    }
245
246    /**
247     * Called when a user, package, or setting changes that could affect whether or not the
248     * currently bound VrListenerService is changed.
249     */
250    @Override
251    public void onEnabledComponentChanged() {
252        synchronized (mLock) {
253            int currentUser = ActivityManager.getCurrentUser();
254
255            // Update listeners
256            ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);
257
258            ArraySet<String> enabledPackages = new ArraySet<>();
259            for (ComponentName n : enabledListeners) {
260                String pkg = n.getPackageName();
261                if (isDefaultAllowed(pkg)) {
262                    enabledPackages.add(n.getPackageName());
263                }
264            }
265            mNotifAccessManager.update(enabledPackages);
266
267            if (mCurrentVrService == null) {
268                return; // No active services
269            }
270
271            // If there is a pending state change, we'd better deal with that first
272            consumeAndApplyPendingStateLocked();
273
274            if (mCurrentVrService == null) {
275                return; // No active services
276            }
277
278            // There is an active service, update it if needed
279            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
280                    mCurrentVrService.getUserId(), null);
281        }
282    }
283
284    private final IVrManager mVrManager = new IVrManager.Stub() {
285
286        @Override
287        public void registerListener(IVrStateCallbacks cb) {
288            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
289            if (cb == null) {
290                throw new IllegalArgumentException("Callback binder object is null.");
291            }
292
293            VrManagerService.this.addStateCallback(cb);
294        }
295
296        @Override
297        public void unregisterListener(IVrStateCallbacks cb) {
298            enforceCallerPermission(Manifest.permission.ACCESS_VR_MANAGER);
299            if (cb == null) {
300                throw new IllegalArgumentException("Callback binder object is null.");
301            }
302
303            VrManagerService.this.removeStateCallback(cb);
304        }
305
306        @Override
307        public boolean getVrModeState() {
308            return VrManagerService.this.getVrMode();
309        }
310
311        @Override
312        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
313            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
314                    != PackageManager.PERMISSION_GRANTED) {
315                pw.println("permission denied: can't dump VrManagerService from pid="
316                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
317                return;
318            }
319            pw.println("********* Dump of VrManagerService *********");
320            pw.println("Previous state transitions:\n");
321            String tab = "  ";
322            dumpStateTransitions(pw);
323            pw.println("\n\nRemote Callbacks:");
324            int i=mRemoteCallbacks.beginBroadcast(); // create the broadcast item array
325            while(i-->0) {
326                pw.print(tab);
327                pw.print(mRemoteCallbacks.getBroadcastItem(i));
328                if (i>0) pw.println(",");
329            }
330            mRemoteCallbacks.finishBroadcast();
331            pw.println("\n");
332            pw.println("Installed VrListenerService components:");
333            int userId = mCurrentVrModeUser;
334            ArraySet<ComponentName> installed = mComponentObserver.getInstalled(userId);
335            if (installed == null || installed.size() == 0) {
336                pw.println("None");
337            } else {
338                for (ComponentName n : installed) {
339                    pw.print(tab);
340                    pw.println(n.flattenToString());
341                }
342            }
343            pw.println("Enabled VrListenerService components:");
344            ArraySet<ComponentName> enabled = mComponentObserver.getEnabled(userId);
345            if (enabled == null || enabled.size() == 0) {
346                pw.println("None");
347            } else {
348                for (ComponentName n : enabled) {
349                    pw.print(tab);
350                    pw.println(n.flattenToString());
351                }
352            }
353            pw.println("\n");
354            pw.println("********* End of VrManagerService Dump *********");
355        }
356
357    };
358
359    private void enforceCallerPermission(String permission) {
360        if (mContext.checkCallingOrSelfPermission(permission)
361                != PackageManager.PERMISSION_GRANTED) {
362            throw new SecurityException("Caller does not hold the permission " + permission);
363        }
364    }
365
366    /**
367     * Implementation of VrManagerInternal.  Callable only from system services.
368     */
369    private final class LocalService extends VrManagerInternal {
370        @Override
371        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
372                ComponentName callingPackage) {
373            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, false);
374        }
375
376        @Override
377        public void setVrModeImmediate(boolean enabled, ComponentName packageName, int userId,
378                ComponentName callingPackage) {
379            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, true);
380        }
381
382        @Override
383        public boolean isCurrentVrListener(String packageName, int userId) {
384            return VrManagerService.this.isCurrentVrListener(packageName, userId);
385        }
386
387        @Override
388        public int hasVrPackage(ComponentName packageName, int userId) {
389            return VrManagerService.this.hasVrPackage(packageName, userId);
390        }
391    }
392
393    public VrManagerService(Context context) {
394        super(context);
395    }
396
397    @Override
398    public void onStart() {
399        synchronized(mLock) {
400            initializeNative();
401            mContext = getContext();
402        }
403
404        publishLocalService(VrManagerInternal.class, new LocalService());
405        publishBinderService(VR_MANAGER_BINDER_SERVICE, mVrManager.asBinder());
406
407        // If there are no VR packages installed on the device, then disable VR
408        // components, otherwise, enable them.
409        setEnabledStatusOfVrComponents();
410    }
411
412    private void setEnabledStatusOfVrComponents() {
413        ArraySet<ComponentName> vrComponents = SystemConfig.getInstance().getDefaultVrComponents();
414        if (vrComponents == null) {
415           return;
416        }
417
418        // We only want to enable VR components if there is a VR package installed on the device.
419        // The VR components themselves do not quality as a VR package, so exclude them.
420        ArraySet<String> vrComponentPackageNames = new ArraySet<>();
421        for (ComponentName componentName : vrComponents) {
422            vrComponentPackageNames.add(componentName.getPackageName());
423        }
424
425        // Check to see if there are any packages on the device, other than the VR component
426        // packages.
427        PackageManager pm = mContext.getPackageManager();
428        List<PackageInfo> packageInfos = pm.getInstalledPackages(
429                PackageManager.GET_CONFIGURATIONS);
430        boolean vrModeIsUsed = false;
431        for (PackageInfo packageInfo : packageInfos) {
432            if (packageInfo != null && packageInfo.packageName != null &&
433                    pm.getApplicationEnabledSetting(packageInfo.packageName) ==
434                            PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
435                vrModeIsUsed = enableVrComponentsIfVrModeUsed(pm, packageInfo,
436                        vrComponentPackageNames, vrComponents);
437                if (vrModeIsUsed) {
438                    break;
439                }
440            }
441        }
442
443        if (!vrModeIsUsed) {
444            Slog.i(TAG, "No VR packages found, disabling VR components");
445            setVrComponentsEnabledOrDisabled(vrComponents, false);
446
447            // Register to receive an intent when a new package is installed, in case that package
448            // requires VR components.
449            IntentFilter intentFilter = new IntentFilter();
450            intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
451            intentFilter.addDataScheme("package");
452            mContext.registerReceiver(new BroadcastReceiver() {
453                @Override
454                public void onReceive(Context context, Intent intent) {
455                    PackageManager pm = context.getPackageManager();
456                    final String packageName = intent.getData().getSchemeSpecificPart();
457                    if (packageName != null) {
458                        try {
459                            PackageInfo packageInfo = pm.getPackageInfo(packageName,
460                                    PackageManager.GET_CONFIGURATIONS);
461                            enableVrComponentsIfVrModeUsed(pm, packageInfo,
462                                    vrComponentPackageNames, vrComponents);
463                        } catch (NameNotFoundException e) {
464                        }
465                    }
466                };
467            }, intentFilter);
468        }
469    }
470
471    private void setVrComponentsEnabledOrDisabled(ArraySet<ComponentName> vrComponents,
472            boolean enabled) {
473        int state = enabled ?
474                PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
475                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
476        PackageManager pm = mContext.getPackageManager();
477        for (ComponentName componentName : vrComponents) {
478            try {
479                // Note that we must first check for the existance of the package before trying
480                // to set its enabled state.  This is to prevent PackageManager from throwing
481                // an excepton if the package is not found (not just a NameNotFoundException
482                // exception).
483                PackageInfo packageInfo = pm.getPackageInfo(componentName.getPackageName(),
484                        PackageManager.GET_CONFIGURATIONS);
485                pm.setApplicationEnabledSetting(componentName.getPackageName(), state , 0);
486            } catch (NameNotFoundException e) {
487            }
488        }
489    }
490
491    private boolean enableVrComponentsIfVrModeUsed(PackageManager pm, PackageInfo packageInfo,
492            ArraySet<String> vrComponentPackageNames, ArraySet<ComponentName> vrComponents) {
493        boolean isVrComponent = vrComponents != null &&
494                vrComponentPackageNames.contains(packageInfo.packageName);
495        if (packageInfo != null && packageInfo.reqFeatures != null && !isVrComponent) {
496            for (FeatureInfo featureInfo : packageInfo.reqFeatures) {
497                if (featureInfo.name != null &&
498                    (featureInfo.name.equals(PackageManager.FEATURE_VR_MODE) ||
499                     featureInfo.name.equals(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE))) {
500                    Slog.i(TAG, "VR package found, enabling VR components");
501                    setVrComponentsEnabledOrDisabled(vrComponents, true);
502                    return true;
503                }
504            }
505        }
506        return false;
507    }
508
509    @Override
510    public void onBootPhase(int phase) {
511        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
512            synchronized (mLock) {
513                Looper looper = Looper.getMainLooper();
514                Handler handler = new Handler(looper);
515                ArrayList<EnabledComponentChangeListener> listeners = new ArrayList<>();
516                listeners.add(this);
517                mComponentObserver = EnabledComponentsObserver.build(mContext, handler,
518                        Settings.Secure.ENABLED_VR_LISTENERS, looper,
519                        android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
520                        VrListenerService.SERVICE_INTERFACE, mLock, listeners);
521
522                mComponentObserver.rebuildAll();
523            }
524        }
525    }
526
527    @Override
528    public void onStartUser(int userHandle) {
529        synchronized (mLock) {
530            mComponentObserver.onUsersChanged();
531        }
532    }
533
534    @Override
535    public void onSwitchUser(int userHandle) {
536        synchronized (mLock) {
537            mComponentObserver.onUsersChanged();
538        }
539
540    }
541
542    @Override
543    public void onStopUser(int userHandle) {
544        synchronized (mLock) {
545            mComponentObserver.onUsersChanged();
546        }
547
548    }
549
550    @Override
551    public void onCleanupUser(int userHandle) {
552        synchronized (mLock) {
553            mComponentObserver.onUsersChanged();
554        }
555    }
556
557    private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
558        AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
559
560        // If user changed drop restrictions for the old user.
561        if (oldUserId != newUserId) {
562            appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
563                    false, mOverlayToken, null, oldUserId);
564        }
565
566        // Apply the restrictions for the current user based on vr state
567        String[] exemptions = (exemptedPackage == null) ? new String[0] :
568                new String[] { exemptedPackage };
569
570        appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
571                mVrModeEnabled, mOverlayToken, exemptions, newUserId);
572    }
573
574    private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
575            String oldVrServicePackage, int oldUserId) {
576        // If VR state changed and we also have a VR service change.
577        if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
578            return;
579        }
580        final long identity = Binder.clearCallingIdentity();
581        try {
582            // Set overlay exception state based on VR enabled and current service
583            updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
584        } finally {
585            Binder.restoreCallingIdentity(identity);
586        }
587    }
588
589    /**
590     * Send VR mode changes (if the mode state has changed), and update the bound/unbound state of
591     * the currently selected VR listener service.  If the component selected for the VR listener
592     * service has changed, unbind the previous listener and bind the new listener (if enabled).
593     * <p/>
594     * Note: Must be called while holding {@code mLock}.
595     *
596     * @param enabled new state for VR mode.
597     * @param component new component to be bound as a VR listener.
598     * @param userId user owning the component to be bound.
599     * @param calling the component currently using VR mode, or null to leave unchanged.
600     *
601     * @return {@code true} if the component/user combination specified is valid.
602     */
603    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
604            int userId, ComponentName calling) {
605
606        boolean sendUpdatedCaller = false;
607        final long identity = Binder.clearCallingIdentity();
608        try {
609
610            boolean validUserComponent = (mComponentObserver.isValid(component, userId) ==
611                    EnabledComponentsObserver.NO_ERROR);
612            if (!mVrModeEnabled && !enabled) {
613                return validUserComponent; // Disabled -> Disabled transition does nothing.
614            }
615
616            String oldVrServicePackage = mCurrentVrService != null
617                    ? mCurrentVrService.getComponent().getPackageName() : null;
618            final int oldUserId = mCurrentVrModeUser;
619
620            // Always send mode change events.
621            changeVrModeLocked(enabled);
622
623            if (!enabled || !validUserComponent) {
624                // Unbind whatever is running
625                if (mCurrentVrService != null) {
626                    Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() + " for user " +
627                            mCurrentVrService.getUserId());
628                    mCurrentVrService.disconnect();
629                    mCurrentVrService = null;
630                }
631            } else {
632                if (mCurrentVrService != null) {
633                    // Unbind any running service that doesn't match the component/user selection
634                    if (mCurrentVrService.disconnectIfNotMatching(component, userId)) {
635                        Slog.i(TAG, "Disconnecting " + mCurrentVrService.getComponent() +
636                                " for user " + mCurrentVrService.getUserId());
637                        createAndConnectService(component, userId);
638                        sendUpdatedCaller = true;
639                    }
640                    // The service with the correct component/user is bound
641                } else {
642                    // Nothing was previously running, bind a new service
643                    createAndConnectService(component, userId);
644                    sendUpdatedCaller = true;
645                }
646            }
647
648            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
649                mCurrentVrModeComponent = calling;
650                sendUpdatedCaller = true;
651            }
652
653            if (mCurrentVrModeUser != userId) {
654                mCurrentVrModeUser = userId;
655                sendUpdatedCaller = true;
656            }
657
658            String newVrServicePackage = mCurrentVrService != null
659                    ? mCurrentVrService.getComponent().getPackageName() : null;
660            final int newUserId = mCurrentVrModeUser;
661
662            // Update AppOps settings that change state when entering/exiting VR mode, or changing
663            // the current VrListenerService.
664            updateDependentAppOpsLocked(newVrServicePackage, newUserId,
665                    oldVrServicePackage, oldUserId);
666
667            if (mCurrentVrService != null && sendUpdatedCaller) {
668                final ComponentName c = mCurrentVrModeComponent;
669                mCurrentVrService.sendEvent(new PendingEvent() {
670                    @Override
671                    public void runEvent(IInterface service) throws RemoteException {
672                        IVrListener l = (IVrListener) service;
673                        l.focusedActivityChanged(c);
674                    }
675                });
676            }
677            logStateLocked();
678
679            return validUserComponent;
680        } finally {
681            Binder.restoreCallingIdentity(identity);
682        }
683    }
684
685    private boolean isDefaultAllowed(String packageName) {
686        PackageManager pm = mContext.getPackageManager();
687
688        ApplicationInfo info = null;
689        try {
690            info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
691        } catch (NameNotFoundException e) {
692        }
693
694        if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
695            return false;
696        }
697        return true;
698    }
699
700    private void grantNotificationPolicyAccess(String pkg) {
701        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
702        nm.setNotificationPolicyAccessGranted(pkg, true);
703    }
704
705    private void revokeNotificationPolicyAccess(String pkg) {
706        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
707        // Remove any DND zen rules possibly created by the package.
708        nm.removeAutomaticZenRules(pkg);
709        // Remove Notification Policy Access.
710        nm.setNotificationPolicyAccessGranted(pkg, false);
711    }
712
713    private void grantNotificationListenerAccess(String pkg, int userId) {
714        PackageManager pm = mContext.getPackageManager();
715        ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
716                userId, NotificationListenerService.SERVICE_INTERFACE,
717                android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
718        ContentResolver resolver = mContext.getContentResolver();
719
720        ArraySet<String> current = getNotificationListeners(resolver, userId);
721
722        for (ComponentName c : possibleServices) {
723            String flatName = c.flattenToString();
724            if (Objects.equals(c.getPackageName(), pkg)
725                    && !current.contains(flatName)) {
726                current.add(flatName);
727            }
728        }
729
730        if (current.size() > 0) {
731            String flatSettings = formatSettings(current);
732            Settings.Secure.putStringForUser(resolver,
733                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
734                    flatSettings, userId);
735        }
736    }
737
738    private void revokeNotificationListenerAccess(String pkg, int userId) {
739        ContentResolver resolver = mContext.getContentResolver();
740
741        ArraySet<String> current = getNotificationListeners(resolver, userId);
742
743        ArrayList<String> toRemove = new ArrayList<>();
744
745        for (String c : current) {
746            ComponentName component = ComponentName.unflattenFromString(c);
747            if (component.getPackageName().equals(pkg)) {
748                toRemove.add(c);
749            }
750        }
751
752        current.removeAll(toRemove);
753
754        String flatSettings = formatSettings(current);
755        Settings.Secure.putStringForUser(resolver,
756                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
757                flatSettings, userId);
758    }
759
760    private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
761        final int flags = mContext.getPackageManager().getPermissionFlags(
762                permission, pkg, new UserHandle(userId));
763        return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
764                | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
765    }
766
767    private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
768        String flat = Settings.Secure.getStringForUser(resolver,
769                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
770
771        ArraySet<String> current = new ArraySet<>();
772        if (flat != null) {
773            String[] allowed = flat.split(":");
774            for (String s : allowed) {
775                current.add(s);
776            }
777        }
778        return current;
779    }
780
781    private static String formatSettings(Collection<String> c) {
782        if (c == null || c.isEmpty()) {
783            return "";
784        }
785
786        StringBuilder b = new StringBuilder();
787        boolean start = true;
788        for (String s : c) {
789            if ("".equals(s)) {
790                continue;
791            }
792            if (!start) {
793                b.append(':');
794            }
795            b.append(s);
796            start = false;
797        }
798        return b.toString();
799    }
800
801
802
803    private void createAndConnectService(@NonNull ComponentName component, int userId) {
804        mCurrentVrService = VrManagerService.create(mContext, component, userId);
805        mCurrentVrService.connect();
806        Slog.i(TAG, "Connecting " + component + " for user " + userId);
807    }
808
809    /**
810     * Send VR mode change callbacks to HAL and system services if mode has actually changed.
811     * <p/>
812     * Note: Must be called while holding {@code mLock}.
813     *
814     * @param enabled new state of the VR mode.
815     */
816    private void changeVrModeLocked(boolean enabled) {
817        if (mVrModeEnabled != enabled) {
818            mVrModeEnabled = enabled;
819
820            // Log mode change event.
821            Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
822            setVrModeNative(mVrModeEnabled);
823
824            onVrModeChangedLocked();
825        }
826    }
827
828    /**
829     * Notify system services of VR mode change.
830     * <p/>
831     * Note: Must be called while holding {@code mLock}.
832     */
833    private void onVrModeChangedLocked() {
834        mHandler.sendMessage(mHandler.obtainMessage(MSG_VR_STATE_CHANGE,
835                (mVrModeEnabled) ? 1 : 0, 0));
836    }
837
838    /**
839     * Helper function for making ManagedApplicationService instances.
840     */
841    private static ManagedApplicationService create(@NonNull Context context,
842            @NonNull ComponentName component, int userId) {
843        return ManagedApplicationService.build(context, component, userId,
844                R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS,
845                sBinderChecker);
846    }
847
848    private void consumeAndApplyPendingStateLocked() {
849        if (mPendingState != null) {
850            updateCurrentVrServiceLocked(mPendingState.enabled,
851                    mPendingState.targetPackageName, mPendingState.userId,
852                    mPendingState.callingPackage);
853            mPendingState = null;
854        }
855    }
856
857    private void logStateLocked() {
858        ComponentName currentBoundService = (mCurrentVrService == null) ? null :
859            mCurrentVrService.getComponent();
860        VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
861            mCurrentVrModeComponent, mWasDefaultGranted);
862        if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
863            mLoggingDeque.removeFirst();
864        }
865        mLoggingDeque.add(current);
866    }
867
868    private void dumpStateTransitions(PrintWriter pw) {
869        SimpleDateFormat d = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
870        String tab = "  ";
871        if (mLoggingDeque.size() == 0) {
872            pw.print(tab);
873            pw.println("None");
874        }
875        for (VrState state : mLoggingDeque) {
876            pw.print(d.format(new Date(state.timestamp)));
877            pw.print(tab);
878            pw.print("State changed to:");
879            pw.print(tab);
880            pw.println((state.enabled) ? "ENABLED" : "DISABLED");
881            if (state.enabled) {
882                pw.print(tab);
883                pw.print("User=");
884                pw.println(state.userId);
885                pw.print(tab);
886                pw.print("Current VR Activity=");
887                pw.println((state.callingPackage == null) ?
888                    "None" : state.callingPackage.flattenToString());
889                pw.print(tab);
890                pw.print("Bound VrListenerService=");
891                pw.println((state.targetPackageName == null) ?
892                    "None" : state.targetPackageName.flattenToString());
893                if (state.defaultPermissionsGranted) {
894                    pw.print(tab);
895                    pw.println("Default permissions granted to the bound VrListenerService.");
896                }
897            }
898        }
899    }
900
901    /*
902     * Implementation of VrManagerInternal calls.  These are callable from system services.
903     */
904
905    private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
906            int userId, @NonNull ComponentName callingPackage, boolean immediate) {
907
908        synchronized (mLock) {
909
910            if (!enabled && mCurrentVrService != null && !immediate) {
911                // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
912                // and service bind/unbind in case we are immediately switching to another VR app.
913                if (mPendingState == null) {
914                    mHandler.sendEmptyMessageDelayed(MSG_PENDING_VR_STATE_CHANGE,
915                            PENDING_STATE_DELAY_MS);
916                }
917
918                mPendingState = new VrState(enabled, targetPackageName, userId, callingPackage);
919                return;
920            } else {
921                mHandler.removeMessages(MSG_PENDING_VR_STATE_CHANGE);
922                mPendingState = null;
923            }
924
925            updateCurrentVrServiceLocked(enabled, targetPackageName, userId, callingPackage);
926        }
927    }
928
929    private int hasVrPackage(@NonNull ComponentName targetPackageName, int userId) {
930        synchronized (mLock) {
931            return mComponentObserver.isValid(targetPackageName, userId);
932        }
933    }
934
935    private boolean isCurrentVrListener(String packageName, int userId) {
936        synchronized (mLock) {
937            if (mCurrentVrService == null) {
938                return false;
939            }
940            return mCurrentVrService.getComponent().getPackageName().equals(packageName) &&
941                    userId == mCurrentVrService.getUserId();
942        }
943    }
944
945    /*
946     * Implementation of IVrManager calls.
947     */
948
949    private void addStateCallback(IVrStateCallbacks cb) {
950        mRemoteCallbacks.register(cb);
951    }
952
953    private void removeStateCallback(IVrStateCallbacks cb) {
954        mRemoteCallbacks.unregister(cb);
955    }
956
957    private boolean getVrMode() {
958        synchronized (mLock) {
959            return mVrModeEnabled;
960        }
961    }
962}
963