Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaabcce6 authored by Ruben Brunk's avatar Ruben Brunk Committed by Android (Google) Code Review
Browse files

Merge "Set notification listener defaults for system VrListeners." into nyc-dev

parents 9bfc33f8 8820f943
Loading
Loading
Loading
Loading
+132 −75
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.server.vr;
package com.android.server.vr;


import android.Manifest;
import android.Manifest;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.NotificationManager;
import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -47,6 +48,7 @@ import android.service.vr.IVrStateCallbacks;
import android.service.vr.VrListenerService;
import android.service.vr.VrListenerService;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;


import com.android.internal.R;
import com.android.internal.R;
import com.android.server.SystemConfig;
import com.android.server.SystemConfig;
@@ -95,6 +97,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC


    private static final int PENDING_STATE_DELAY_MS = 300;
    private static final int PENDING_STATE_DELAY_MS = 300;
    private static final int EVENT_LOG_SIZE = 32;
    private static final int EVENT_LOG_SIZE = 32;
    private static final int INVALID_APPOPS_MODE = -1;


    private static native void initializeNative();
    private static native void initializeNative();
    private static native void setVrModeNative(boolean enabled);
    private static native void setVrModeNative(boolean enabled);
@@ -114,12 +117,11 @@ public class VrManagerService extends SystemService implements EnabledComponentC
    private boolean mGuard;
    private boolean mGuard;
    private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
    private final RemoteCallbackList<IVrStateCallbacks> mRemoteCallbacks =
            new RemoteCallbackList<>();
            new RemoteCallbackList<>();
    private final ArraySet<String> mPreviousToggledListenerSettings = new ArraySet<>();
    private int mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
    private String mPreviousNotificationPolicyAccessPackage;
    private int mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
    private String mPreviousCoarseLocationPackage;
    private String mPreviousManageOverlayPackage;
    private VrState mPendingState;
    private VrState mPendingState;
    private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
    private final ArrayDeque<VrState> mLoggingDeque = new ArrayDeque<>(EVENT_LOG_SIZE);
    private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();


    private static final int MSG_VR_STATE_CHANGE = 0;
    private static final int MSG_VR_STATE_CHANGE = 0;
    private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
    private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -193,6 +195,39 @@ public class VrManagerService extends SystemService implements EnabledComponentC
        }
        }
    };
    };


    private final class NotificationAccessManager {
        private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();

        public void update(Collection<String> packageNames) {
            int currentUserId = ActivityManager.getCurrentUser();

            UserHandle currentUserHandle = new UserHandle(currentUserId);

            ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
            if (allowed == null) {
                allowed = new ArraySet<>();
            }

            for (String pkg : allowed) {
                if (!packageNames.contains(pkg)) {
                    revokeNotificationListenerAccess(pkg);
                    revokeNotificationPolicyAccess(pkg);
                }
            }
            for (String pkg : packageNames) {
                if (!allowed.contains(pkg)) {
                    grantNotificationPolicyAccess(pkg);
                    grantNotificationListenerAccess(pkg, currentUserHandle);
                }
            }

            allowed.clear();
            allowed.addAll(packageNames);
            mAllowedPackages.put(currentUserId, allowed);
        }
    }


    /**
    /**
     * Called when a user, package, or setting changes that could affect whether or not the
     * Called when a user, package, or setting changes that could affect whether or not the
     * currently bound VrListenerService is changed.
     * currently bound VrListenerService is changed.
@@ -200,6 +235,20 @@ public class VrManagerService extends SystemService implements EnabledComponentC
    @Override
    @Override
    public void onEnabledComponentChanged() {
    public void onEnabledComponentChanged() {
        synchronized (mLock) {
        synchronized (mLock) {
            int currentUser = ActivityManager.getCurrentUser();

            // Update listeners
            ArraySet<ComponentName> enabledListeners = mComponentObserver.getEnabled(currentUser);

            ArraySet<String> enabledPackages = new ArraySet<>();
            for (ComponentName n : enabledListeners) {
                String pkg = n.getPackageName();
                if (isDefaultAllowed(pkg)) {
                    enabledPackages.add(n.getPackageName());
                }
            }
            mNotifAccessManager.update(enabledPackages);

            if (mCurrentVrService == null) {
            if (mCurrentVrService == null) {
                return; // No active services
                return; // No active services
            }
            }
@@ -616,21 +665,18 @@ public class VrManagerService extends SystemService implements EnabledComponentC
        } catch (NameNotFoundException e) {
        } catch (NameNotFoundException e) {
        }
        }


        if (info == null) {
        if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
            Slog.e(TAG, "Couldn't set implied permissions for " + pName + ", no such package.");
            return;
            return;
        }
        }


        if (!(info.isSystemApp() || info.isUpdatedSystemApp())) {
            return; // Application is not pre-installed, avoid setting implied permissions
        }

        mWasDefaultGranted = true;
        mWasDefaultGranted = true;

        AppOpsManager mgr = mContext.getSystemService(AppOpsManager.class);
        grantCoarseLocationAccess(pName, userId);
        if (mgr == null) {
        grantOverlayAccess(pName, userId);
            Slog.e(TAG, "No AppOpsManager, failed to set permissions for: " + pName);
        grantNotificationPolicyAccess(pName);
            return;
        grantNotificationListenerAccess(pName, userId);
        }
        grantCoarseLocationAccess(mgr, pName, info.uid);
        grantOverlayAccess(mgr, pName, info.uid);
    }
    }


    /**
    /**
@@ -657,80 +703,89 @@ public class VrManagerService extends SystemService implements EnabledComponentC


        String pName = component.getPackageName();
        String pName = component.getPackageName();
        if (mWasDefaultGranted) {
        if (mWasDefaultGranted) {
            revokeCoarseLocationAccess(userId);
            ApplicationInfo info = null;
            revokeOverlayAccess(userId);
            try {
            revokeNotificationPolicyAccess(pName);
                info = pm.getApplicationInfo(pName, PackageManager.GET_META_DATA);
            revokeNotificiationListenerAccess();
            } catch (NameNotFoundException e) {
            }

            if (info != null) {
                AppOpsManager mgr = mContext.getSystemService(AppOpsManager.class);
                if (mgr == null) {
                    Slog.e(TAG, "No AppOpsManager, failed to set permissions for: " + pName);
                    return;
                }
                revokeCoarseLocationAccess(mgr, pName, info.uid);
                revokeOverlayAccess(mgr, pName, info.uid);
            }
            mWasDefaultGranted = false;
            mWasDefaultGranted = false;
        }
        }


    }
    }


    private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
    private boolean isDefaultAllowed(String packageName) {
        PackageManager pm = mContext.getPackageManager();
        PackageManager pm = mContext.getPackageManager();
        boolean prev = (PackageManager.PERMISSION_GRANTED ==

                pm.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, pkg));
        ApplicationInfo info = null;
        mPreviousCoarseLocationPackage = null;
        try {
        if (!prev) {
            info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
            pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
        } catch (NameNotFoundException e) {
                    userId);
        }
            mPreviousCoarseLocationPackage = pkg;

        if (info == null || !(info.isSystemApp() || info.isUpdatedSystemApp())) {
            return false;
        }
        }
        return true;
    }
    }


    private void revokeCoarseLocationAccess(UserHandle userId) {
    private void grantCoarseLocationAccess(AppOpsManager mgr, String packageName, int uid) {
        PackageManager pm = mContext.getPackageManager();
        mPreviousCoarseLocationMode = mgr.checkOpNoThrow(AppOpsManager.OP_COARSE_LOCATION, uid,
        if (mPreviousCoarseLocationPackage != null) {
                packageName);
            pm.revokeRuntimePermission(mPreviousCoarseLocationPackage,

                    android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
        if (mPreviousCoarseLocationMode != AppOpsManager.MODE_ALLOWED) {
            mPreviousCoarseLocationPackage = null;
            mgr.setMode(AppOpsManager.OP_COARSE_LOCATION, uid, packageName,
                    AppOpsManager.MODE_ALLOWED);
        }
        }
    }
    }


    private void grantOverlayAccess(String pkg, UserHandle userId) {
    private void revokeCoarseLocationAccess(AppOpsManager mgr, String packageName, int uid) {
        PackageManager pm = mContext.getPackageManager();
        if (mPreviousCoarseLocationMode != AppOpsManager.MODE_ALLOWED) {
        boolean prev = (PackageManager.PERMISSION_GRANTED ==
            mgr.setMode(AppOpsManager.OP_COARSE_LOCATION, uid, packageName,
                pm.checkPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, pkg));
                    mPreviousCoarseLocationMode);
        mPreviousManageOverlayPackage = null;
            mPreviousCoarseLocationMode = INVALID_APPOPS_MODE;
        if (!prev) {
            pm.grantRuntimePermission(pkg, android.Manifest.permission.SYSTEM_ALERT_WINDOW,
                    userId);
            mPreviousManageOverlayPackage = pkg;
        }
        }
    }
    }


    private void revokeOverlayAccess(UserHandle userId) {
    private void grantOverlayAccess(AppOpsManager mgr, String packageName, int uid) {
        PackageManager pm = mContext.getPackageManager();

        if (mPreviousManageOverlayPackage != null) {
        mPreviousManageOverlayMode = mgr.checkOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid,
            pm.revokeRuntimePermission(mPreviousManageOverlayPackage,
                packageName);
                    android.Manifest.permission.SYSTEM_ALERT_WINDOW, userId);

            mPreviousManageOverlayPackage = null;
        if (mPreviousManageOverlayMode != AppOpsManager.MODE_ALLOWED) {
            mgr.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
                    AppOpsManager.MODE_ALLOWED);
        }
    }

    private void revokeOverlayAccess(AppOpsManager mgr, String packageName, int uid) {
        if (mPreviousManageOverlayMode != AppOpsManager.MODE_ALLOWED) {
            mgr.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName,
                    mPreviousManageOverlayMode);
            mPreviousManageOverlayMode = INVALID_APPOPS_MODE;
        }
        }
    }
    }


    private void grantNotificationPolicyAccess(String pkg) {
    private void grantNotificationPolicyAccess(String pkg) {
        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        boolean prev = nm.isNotificationPolicyAccessGrantedForPackage(pkg);
        mPreviousNotificationPolicyAccessPackage = null;
        if (!prev) {
            mPreviousNotificationPolicyAccessPackage = pkg;
        nm.setNotificationPolicyAccessGranted(pkg, true);
        nm.setNotificationPolicyAccessGranted(pkg, true);
    }
    }
    }


    private void revokeNotificationPolicyAccess(String pkg) {
    private void revokeNotificationPolicyAccess(String pkg) {
        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        if (mPreviousNotificationPolicyAccessPackage != null) {
            if (mPreviousNotificationPolicyAccessPackage.equals(pkg)) {
        // Remove any DND zen rules possibly created by the package.
        // Remove any DND zen rules possibly created by the package.
                nm.removeAutomaticZenRules(mPreviousNotificationPolicyAccessPackage);
        nm.removeAutomaticZenRules(pkg);
        // Remove Notification Policy Access.
        // Remove Notification Policy Access.
                nm.setNotificationPolicyAccessGranted(mPreviousNotificationPolicyAccessPackage, false);
        nm.setNotificationPolicyAccessGranted(pkg, false);
                mPreviousNotificationPolicyAccessPackage = null;
            } else {
                Slog.e(TAG, "Couldn't remove Notification Policy Access for package: " + pkg);
            }
        }
    }
    }


    private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
    private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
@@ -742,13 +797,10 @@ public class VrManagerService extends SystemService implements EnabledComponentC


        ArraySet<String> current = getCurrentNotifListeners(resolver);
        ArraySet<String> current = getCurrentNotifListeners(resolver);


        mPreviousToggledListenerSettings.clear();

        for (ComponentName c : possibleServices) {
        for (ComponentName c : possibleServices) {
            String flatName = c.flattenToString();
            String flatName = c.flattenToString();
            if (Objects.equals(c.getPackageName(), pkg)
            if (Objects.equals(c.getPackageName(), pkg)
                    && !current.contains(flatName)) {
                    && !current.contains(flatName)) {
                mPreviousToggledListenerSettings.add(flatName);
                current.add(flatName);
                current.add(flatName);
            }
            }
        }
        }
@@ -760,20 +812,25 @@ public class VrManagerService extends SystemService implements EnabledComponentC
        }
        }
    }
    }


    private void revokeNotificiationListenerAccess() {
    private void revokeNotificationListenerAccess(String pkg) {
        if (mPreviousToggledListenerSettings.isEmpty()) {
            return;
        }

        ContentResolver resolver = mContext.getContentResolver();
        ContentResolver resolver = mContext.getContentResolver();
        ArraySet<String> current = getCurrentNotifListeners(resolver);
        ArraySet<String> current = getCurrentNotifListeners(resolver);


        current.removeAll(mPreviousToggledListenerSettings);
        ArrayList<String> toRemove = new ArrayList<>();
        mPreviousToggledListenerSettings.clear();

        for (String c : current) {
            ComponentName component = ComponentName.unflattenFromString(c);
            if (component.getPackageName().equals(pkg)) {
                toRemove.add(c);
            }
        }

        current.removeAll(toRemove);


        String flatSettings = formatSettings(current);
        String flatSettings = formatSettings(current);
        Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
        Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
                flatSettings);
                flatSettings);

    }
    }


    private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
    private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {