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

Commit 4a447963 authored by Jay Aliomer's avatar Jay Aliomer Committed by Android (Google) Code Review
Browse files

Merge "Clear notifications deletes configs"

parents 053c2ebe 4204f256
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.notification.NotificationManagerService.DumpFilter;

import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -80,6 +83,39 @@ public class ConditionProviders extends ManagedServices {
        return mSystemConditionProviders;
    }

    @Override
    protected ArrayMap<Boolean, ArrayList<ComponentName>>
            resetComponents(String packageName, int userId) {
        resetPackage(packageName, userId);
        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
        changes.put(true, new ArrayList<>(0));
        changes.put(false, new ArrayList<>(0));
        return changes;
    }

    /**
     *  @return true if the passed package is enabled. false otherwise
     */
    boolean resetPackage(String packageName, int userId) {
        boolean isAllowed = super.isPackageOrComponentAllowed(packageName, userId);
        boolean isDefault = super.isDefaultComponentOrPackage(packageName);
        if (!isAllowed && isDefault) {
            setPackageOrComponentEnabled(packageName, userId, true, true);
        }
        if (isAllowed && !isDefault) {
            setPackageOrComponentEnabled(packageName, userId, true, false);
        }
        return !isAllowed && isDefault;
    }

    @Override
    void writeDefaults(XmlSerializer out) throws IOException {
        synchronized (mDefaultsLock) {
            String defaults = String.join(ENABLED_SERVICES_SEPARATOR, mDefaultPackages);
            out.attribute(null, ATT_DEFAULTS, defaults);
        }
    }

    @Override
    protected Config getConfig() {
        final Config c = new Config();
+148 −2
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ abstract public class ManagedServices {
    static final String ATT_USER_ID = "user";
    static final String ATT_IS_PRIMARY = "primary";
    static final String ATT_VERSION = "version";
    static final String ATT_DEFAULTS = "defaults";

    static final int DB_VERSION = 1;

@@ -128,6 +129,10 @@ abstract public class ManagedServices {
     */
    private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>();
    private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>();
    // we need these packages to be protected because classes that inherit from it need to see it
    protected final Object mDefaultsLock = new Object();
    protected final ArraySet<ComponentName> mDefaultComponents = new ArraySet<>();
    protected final ArraySet<String> mDefaultPackages = new ArraySet<>();

    // lists the component names of all enabled (and therefore potentially connected)
    // app services for current profiles.
@@ -179,6 +184,112 @@ abstract public class ManagedServices {
        }
    }

    protected void addDefaultComponentOrPackage(String packageOrComponent) {
        if (packageOrComponent != null) {
            synchronized (mDefaultsLock) {
                ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
                if (cn == null) {
                    mDefaultPackages.add(packageOrComponent);
                } else {
                    mDefaultPackages.add(cn.getPackageName());
                    mDefaultComponents.add(cn);
                }
            }
        }
    }

    boolean isDefaultComponentOrPackage(String packageOrComponent) {
        synchronized (mDefaultsLock) {
            ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
            if (cn == null) {
                return mDefaultPackages.contains(packageOrComponent);
            } else {
                return mDefaultComponents.contains(cn);
            }
        }
    }

    ArraySet<ComponentName> getDefaultComponents() {
        synchronized (mDefaultsLock) {
            return new ArraySet<>(mDefaultComponents);
        }
    }

    ArraySet<String> getDefaultPackages() {
        synchronized (mDefaultsLock) {
            return new ArraySet<>(mDefaultPackages);
        }
    }

    /**
     * When resetting a package, we need to enable default components that belong to that packages
     * we also need to disable components that are not default to return the managed service state
     * to when a new android device is first turned on for that package.
     *
     * @param packageName package to reset.
     * @param userId the android user id
     * @return a list of components that were permitted
     */
    @NonNull
    ArrayMap<Boolean, ArrayList<ComponentName>> resetComponents(String packageName, int userId) {
        // components that we want to enable
        ArrayList<ComponentName> componentsToEnable =
                new ArrayList<>(mDefaultComponents.size());

        // components that were removed
        ArrayList<ComponentName> disabledComponents =
                new ArrayList<>(mDefaultComponents.size());

        // all components that are enabled now
        ArraySet<ComponentName> enabledComponents =
                new ArraySet<>(getAllowedComponents(userId));

        boolean changed = false;

        synchronized (mDefaultsLock) {
            // record all components that are enabled but should not be by default
            for (int i = 0; i < mDefaultComponents.size() && enabledComponents.size() > 0; i++) {
                ComponentName currentDefault = mDefaultComponents.valueAt(i);
                if (packageName.equals(currentDefault.getPackageName())
                        && !enabledComponents.contains(currentDefault)) {
                    componentsToEnable.add(currentDefault);
                }
            }
            synchronized (mApproved) {
                final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(
                        userId);
                if (approvedByType != null) {
                    final int M = approvedByType.size();
                    for (int j = 0; j < M; j++) {
                        final ArraySet<String> approved = approvedByType.valueAt(j);
                        for (int i = 0; i < enabledComponents.size(); i++) {
                            ComponentName currentComponent = enabledComponents.valueAt(i);
                            if (packageName.equals(currentComponent.getPackageName())
                                    && !mDefaultComponents.contains(currentComponent)) {
                                if (approved.remove(currentComponent.flattenToString())) {
                                    disabledComponents.add(currentComponent);
                                    changed = true;
                                }
                            }
                        }
                        for (int i = 0; i < componentsToEnable.size(); i++) {
                            ComponentName candidate = componentsToEnable.get(i);
                            changed |= approved.add(candidate.flattenToString());
                        }
                    }

                }
            }
        }
        if (changed) rebindServices(false, USER_ALL);

        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
        changes.put(true, componentsToEnable);
        changes.put(false, disabledComponents);

        return changes;
    }

    protected int getBindFlags() {
        return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
    }
@@ -310,11 +421,24 @@ abstract public class ManagedServices {
        }
    }

    void writeDefaults(XmlSerializer out) throws IOException {
        synchronized (mDefaultsLock) {
            List<String> componentStrings = new ArrayList<>(mDefaultComponents.size());
            for (int i = 0; i < mDefaultComponents.size(); i++) {
                componentStrings.add(mDefaultComponents.valueAt(i).flattenToString());
            }
            String defaults = String.join(ENABLED_SERVICES_SEPARATOR, componentStrings);
            out.attribute(null, ATT_DEFAULTS, defaults);
        }
    }

    public void writeXml(XmlSerializer out, boolean forBackup, int userId) throws IOException {
        out.startTag(null, getConfig().xmlTag);

        out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION));

        writeDefaults(out);

        if (forBackup) {
            trimApprovedListsAccordingToInstalledServices(userId);
        }
@@ -378,6 +502,27 @@ abstract public class ManagedServices {
        loadAllowedComponentsFromSettings();
    }

    void readDefaults(XmlPullParser parser) {
        String defaultComponents = XmlUtils.readStringAttribute(parser, ATT_DEFAULTS);
        if (defaultComponents == null) {
            return;
        }
        String[] components = defaultComponents.split(ENABLED_SERVICES_SEPARATOR);
        synchronized (mDefaultsLock) {
            for (int i = 0; i < components.length; i++) {
                if (!TextUtils.isEmpty(components[i])) {
                    ComponentName cn = ComponentName.unflattenFromString(components[i]);
                    if (cn != null) {
                        mDefaultPackages.add(cn.getPackageName());
                        mDefaultComponents.add(cn);
                    } else {
                        mDefaultPackages.add(components[i]);
                    }
                }
            }
        }
    }

    public void readXml(
            XmlPullParser parser,
            TriPredicate<String, Integer, String> allowedManagedServicePackages,
@@ -386,6 +531,7 @@ abstract public class ManagedServices {
            throws XmlPullParserException, IOException {
        // read grants
        int type;
        readDefaults(parser);
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
            String tag = parser.getName();
            if (type == XmlPullParser.END_TAG
@@ -785,9 +931,9 @@ abstract public class ManagedServices {
        return queryPackageForServices(packageName, 0, userId);
    }

    protected Set<ComponentName> queryPackageForServices(String packageName, int extraFlags,
    protected ArraySet<ComponentName> queryPackageForServices(String packageName, int extraFlags,
            int userId) {
        Set<ComponentName> installed = new ArraySet<>();
        ArraySet<ComponentName> installed = new ArraySet<>();
        final PackageManager pm = mContext.getPackageManager();
        Intent queryIntent = new Intent(mConfig.serviceInterface);
        if (!TextUtils.isEmpty(packageName)) {
+128 −53
Original line number Diff line number Diff line
@@ -356,7 +356,6 @@ public class NotificationManagerService extends SystemService {
    private static final int REQUEST_CODE_TIMEOUT = 1;
    private static final String SCHEME_TIMEOUT = "timeout";
    private static final String EXTRA_KEY = "key";

    private IActivityManager mAm;
    private ActivityManager mActivityManager;
    private IPackageManager mPackageManager;
@@ -524,24 +523,21 @@ public class NotificationManagerService extends SystemService {

    }

    protected void readDefaultApprovedServices(int userId) {

    void loadDefaultApprovedServices(int userId) {
        String defaultListenerAccess = getContext().getResources().getString(
                com.android.internal.R.string.config_defaultListenerAccessPackages);
        if (defaultListenerAccess != null) {
            for (String whitelisted :
                    defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)) {
                // Gather all notification listener components for candidate pkgs.
                Set<ComponentName> approvedListeners =
                        mListeners.queryPackageForServices(whitelisted,
            String[] listeners =
                    defaultListenerAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
            for (int i = 0; i < listeners.length; i++) {
                ArraySet<ComponentName> approvedListeners =
                        mListeners.queryPackageForServices(listeners[i],
                                MATCH_DIRECT_BOOT_AWARE
                                        | MATCH_DIRECT_BOOT_UNAWARE, userId);
                for (ComponentName cn : approvedListeners) {
                    try {
                        getBinderService().setNotificationListenerAccessGrantedForUser(cn,
                                    userId, true);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                for (int k = 0; k < approvedListeners.size(); k++) {
                    ComponentName cn = approvedListeners.valueAt(k);
                    mListeners.addDefaultComponentOrPackage(cn.flattenToString());
                }
            }
        }
@@ -549,44 +545,84 @@ public class NotificationManagerService extends SystemService {
        String defaultDndAccess = getContext().getResources().getString(
                com.android.internal.R.string.config_defaultDndAccessPackages);
        if (defaultDndAccess != null) {
            for (String whitelisted :
                    defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR)) {
                try {
                    getBinderService().setNotificationPolicyAccessGranted(whitelisted, true);
                } catch (RemoteException e) {
                    e.printStackTrace();
            String[] dnds = defaultDndAccess.split(ManagedServices.ENABLED_SERVICES_SEPARATOR);
            for (int i = 0; i < dnds.length; i++) {
                mConditionProviders.addDefaultComponentOrPackage(dnds[i]);
            }
        }


        ArraySet<String> assistants = new ArraySet<>();
        String deviceAssistant = DeviceConfig.getProperty(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
        if (deviceAssistant != null) {
            assistants.addAll(Arrays.asList(deviceAssistant.split(
                    ManagedServices.ENABLED_SERVICES_SEPARATOR)));
        }
        assistants.addAll(Arrays.asList(getContext().getResources().getString(
                com.android.internal.R.string.config_defaultAssistantAccessComponent)
                .split(ManagedServices.ENABLED_SERVICES_SEPARATOR)));
        for (int i = 0; i < assistants.size(); i++) {
            String cnString = assistants.valueAt(i);
            mAssistants.addDefaultComponentOrPackage(cnString);
        }
    }

    protected void allowDefaultApprovedServices(int userId) {

        ArraySet<ComponentName> defaultListeners = mListeners.getDefaultComponents();
        for (int i = 0; i < defaultListeners.size(); i++) {
            ComponentName cn = defaultListeners.valueAt(i);
            allowNotificationListener(userId, cn);
        }

        ArraySet<String> defaultDnds = mConditionProviders.getDefaultPackages();
        for (int i = 0; i < defaultDnds.size(); i++) {
            allowDndPackage(defaultDnds.valueAt(i));
        }

        setDefaultAssistantForUser(userId);
    }

    protected void setDefaultAssistantForUser(int userId) {
        List<ComponentName> validAssistants = new ArrayList<>(
                mAssistants.queryPackageForServices(
                        null, MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId));
        ArraySet<ComponentName> defaults = mAssistants.getDefaultComponents();
        // We should have only one default assistant by default
        // allowAssistant should execute once in practice
        for (int i = 0; i < defaults.size(); i++) {
            ComponentName cn = defaults.valueAt(i);
            if (allowAssistant(userId, cn)) return;
        }
    }

        List<String> candidateStrs = new ArrayList<>();
        candidateStrs.add(DeviceConfig.getProperty(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE));
        candidateStrs.add(getContext().getResources().getString(
                com.android.internal.R.string.config_defaultAssistantAccessComponent));
    private void allowDndPackage(String packageName) {
        try {
            getBinderService().setNotificationPolicyAccessGranted(packageName, true);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

        for (String candidateStr : candidateStrs) {
            if (TextUtils.isEmpty(candidateStr)) {
                continue;
    private void allowNotificationListener(int userId, ComponentName cn) {

        try {
            getBinderService().setNotificationListenerAccessGrantedForUser(cn,
                        userId, true);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
            ComponentName candidate = ComponentName.unflattenFromString(candidateStr);

    private boolean allowAssistant(int userId, ComponentName candidate) {
        Set<ComponentName> validAssistants =
                mAssistants.queryPackageForServices(
                        null,
                        MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
        if (candidate != null && validAssistants.contains(candidate)) {
            setNotificationAssistantAccessGrantedForUserInternal(candidate, userId, true);
                Slog.d(TAG, String.format("Set default NAS to be %s in %d", candidateStr, userId));
                return;
            } else {
                Slog.w(TAG, "Invalid default NAS config is found: " + candidateStr);
            }
            return true;
        }
        return false;
    }

    void readPolicyXml(InputStream stream, boolean forRestore, int userId)
@@ -656,7 +692,8 @@ public class NotificationManagerService extends SystemService {
            } catch (FileNotFoundException e) {
                // No data yet
                // Load default managed services approvals
                readDefaultApprovedServices(USER_SYSTEM);
                loadDefaultApprovedServices(USER_SYSTEM);
                allowDefaultApprovedServices(USER_SYSTEM);
            } catch (IOException e) {
                Log.wtf(TAG, "Unable to read notification policy", e);
            } catch (NumberFormatException e) {
@@ -1363,7 +1400,7 @@ public class NotificationManagerService extends SystemService {
                if (userId != USER_NULL) {
                    mUserProfiles.updateCache(context);
                    if (!mUserProfiles.isManagedProfile(userId)) {
                        readDefaultApprovedServices(userId);
                        allowDefaultApprovedServices(userId);
                    }
                }
            } else if (action.equals(Intent.ACTION_USER_REMOVED)) {
@@ -1741,7 +1778,6 @@ public class NotificationManagerService extends SystemService {

        mPolicyFile = policyFile;
        loadPolicyFile();

        mStatusBar = getLocalService(StatusBarManagerInternal.class);
        if (mStatusBar != null) {
            mStatusBar.setNotificationDelegate(mNotificationDelegate);
@@ -2957,21 +2993,52 @@ public class NotificationManagerService extends SystemService {

        @Override
        public void clearData(String packageName, int uid, boolean fromApp) throws RemoteException {
            boolean packagesChanged = false;
            checkCallerIsSystem();

            // Cancel posted notifications
            final int userId = UserHandle.getUserId(uid);
            cancelAllNotificationsInt(MY_UID, MY_PID, packageName, null, 0, 0, true,
                    UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);

            final String[] packages = new String[] {packageName};
            final int[] uids = new int[] {uid};
            // Zen
            packagesChanged |=
                    mConditionProviders.resetPackage(packageName, userId);

            // Listener & assistant
            mListeners.onPackagesChanged(true, packages, uids);
            mAssistants.onPackagesChanged(true, packages, uids);
            // Listener
            ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
                    mListeners.resetComponents(packageName, userId);
            packagesChanged |= changedListeners.get(true).size() > 0
                    || changedListeners.get(false).size() > 0;

            // Zen
            mConditionProviders.onPackagesChanged(true, packages, uids);
            // When a listener is enabled, we enable the dnd package as a secondary
            for (int i = 0; i < changedListeners.get(true).size(); i++) {
                mConditionProviders.setPackageOrComponentEnabled(
                        changedListeners.get(true).get(i).getPackageName(),
                        userId, false, true);
            }

            // Assistant
            ArrayMap<Boolean, ArrayList<ComponentName>> changedAssistants =
                    mAssistants.resetComponents(packageName, userId);
            packagesChanged |= changedAssistants.get(true).size() > 0
                    || changedAssistants.get(false).size() > 0;

            // we want only one assistant enabled
            for (int i = 1; i < changedAssistants.get(true).size(); i++) {
                mAssistants.setPackageOrComponentEnabled(
                        changedAssistants.get(true).get(i).flattenToString(),
                        userId, true, false);
            }

            // When the default assistant is enabled, we enable the dnd package as a secondary
            if (changedAssistants.get(true).size() > 0) {
                //we want only one assistant active
                mConditionProviders
                        .setPackageOrComponentEnabled(
                                changedAssistants.get(true).get(0).getPackageName(),
                                userId, false, true);

            }

            // Snoozing
            mSnoozeHelper.clearData(UserHandle.getUserId(uid), packageName);
@@ -2981,6 +3048,14 @@ public class NotificationManagerService extends SystemService {
                mPreferencesHelper.clearData(packageName, uid);
            }

            if (packagesChanged) {
                getContext().sendBroadcastAsUser(new Intent(
                                ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
                                .setPackage(packageName)
                                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT),
                        UserHandle.of(userId), null);
            }

            handleSavePolicyFile();
        }

+143 −2

File changed.

Preview size limit exceeded, changes collapsed.

+76 −4

File changed.

Preview size limit exceeded, changes collapsed.