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

Commit f6a6597f authored by Chloris Kuo's avatar Chloris Kuo
Browse files

Fix bug: NAS set to none will be reset to default after the second

reboot

Bug: 185725135
Test: atest NotificationAssistantsTest, ManagedServicesTest,
NotificationManagedServiceTest

Change-Id: I63ba2a4e6fc1e9ac4612231af25c55fb66b0991e
parent 5743bb3b
Loading
Loading
Loading
Loading
+39 −10
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ abstract public class ManagedServices {
    protected static final String ENABLED_SERVICES_SEPARATOR = ":";
    private static final String DB_VERSION_1 = "1";
    private static final String DB_VERSION_2 = "2";
    private static final String DB_VERSION_3 = "3";


    /**
@@ -113,8 +114,9 @@ abstract public class ManagedServices {
    static final String ATT_VERSION = "version";
    static final String ATT_DEFAULTS = "defaults";
    static final String ATT_USER_SET = "user_set_services";
    static final String ATT_USER_CHANGED = "user_changed";

    static final int DB_VERSION = 3;
    static final int DB_VERSION = 4;

    static final int APPROVAL_BY_PACKAGE = 0;
    static final int APPROVAL_BY_COMPONENT = 1;
@@ -160,6 +162,8 @@ abstract public class ManagedServices {
    @GuardedBy("mApproved")
    protected ArrayMap<Integer, ArraySet<String>> mUserSetServices = new ArrayMap<>();

    protected ArrayMap<Integer, Boolean> mIsUserChanged = new ArrayMap<>();

    // True if approved services are stored in xml, not settings.
    private boolean mUseXml;

@@ -338,6 +342,7 @@ abstract public class ManagedServices {
            for (int i = 0; i < N; i++) {
                final int userId = mApproved.keyAt(i);
                final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
                final Boolean userChanged = mIsUserChanged.get(userId);
                if (approvedByType != null) {
                    final int M = approvedByType.size();
                    for (int j = 0; j < M; j++) {
@@ -345,16 +350,20 @@ abstract public class ManagedServices {
                        final ArraySet<String> approved = approvedByType.valueAt(j);
                        if (approvedByType != null && approvedByType.size() > 0) {
                            pw.println("      " + String.join(ENABLED_SERVICES_SEPARATOR, approved)
                                    + " (user: " + userId + " isPrimary: " + isPrimary + ")");
                                    + " (user: " + userId + " isPrimary: " + isPrimary
                                    + (userChanged == null ? "" : " isUserChanged: "
                                    + userChanged) + ")");
                        }
                    }
                }
            }

            pw.println("    Has user set:");
            Set<Integer> userIds = mUserSetServices.keySet();
            for (int userId : userIds) {
                pw.println("      userId=" + userId + " value=" + mUserSetServices.get(userId));
                if (mIsUserChanged.get(userId) == null) {
                    pw.println("      userId=" + userId + " value="
                            + (mUserSetServices.get(userId)));
                }
            }
        }

@@ -489,13 +498,14 @@ abstract public class ManagedServices {
                    continue;
                }
                final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
                final Boolean isUserChanged = mIsUserChanged.get(approvedUserId);
                if (approvedByType != null) {
                    final int M = approvedByType.size();
                    for (int j = 0; j < M; j++) {
                        final boolean isPrimary = approvedByType.keyAt(j);
                        final Set<String> approved = approvedByType.valueAt(j);
                        final Set<String> userSet = mUserSetServices.get(approvedUserId);
                        if (approved != null || userSet != null) {
                        if (approved != null || userSet != null || isUserChanged != null) {
                            String allowedItems = approved == null
                                    ? ""
                                    : String.join(ENABLED_SERVICES_SEPARATOR, approved);
@@ -503,7 +513,9 @@ abstract public class ManagedServices {
                            out.attribute(null, ATT_APPROVED_LIST, allowedItems);
                            out.attributeInt(null, ATT_USER_ID, approvedUserId);
                            out.attributeBoolean(null, ATT_IS_PRIMARY, isPrimary);
                            if (userSet != null) {
                            if (isUserChanged != null) {
                                out.attributeBoolean(null, ATT_USER_CHANGED, isUserChanged);
                            } else if (userSet != null) {
                                String userSetItems =
                                        String.join(ENABLED_SERVICES_SEPARATOR, userSet);
                                out.attribute(null, ATT_USER_SET, userSetItems);
@@ -618,12 +630,21 @@ abstract public class ManagedServices {
                            ? userId : parser.getAttributeInt(null, ATT_USER_ID, 0);
                    final boolean isPrimary =
                            parser.getAttributeBoolean(null, ATT_IS_PRIMARY, true);
                    final String userSet = XmlUtils.readStringAttribute(parser, ATT_USER_SET);

                    final String isUserChanged = XmlUtils.readStringAttribute(parser,
                            ATT_USER_CHANGED);
                    String userSetComponent = null;
                    if (isUserChanged == null) {
                        userSetComponent = XmlUtils.readStringAttribute(parser, ATT_USER_SET);
                    } else {
                        mIsUserChanged.put(resolvedUserId, Boolean.valueOf(isUserChanged));
                    }
                    readExtraAttributes(tag, parser, resolvedUserId);
                    if (allowedManagedServicePackages == null || allowedManagedServicePackages.test(
                            getPackageName(approved), resolvedUserId, getRequiredPermission())) {
                            getPackageName(approved), resolvedUserId, getRequiredPermission())
                            || approved.isEmpty()) {
                        if (mUm.getUserInfo(resolvedUserId) != null) {
                            addApprovedList(approved, resolvedUserId, isPrimary, userSet);
                            addApprovedList(approved, resolvedUserId, isPrimary, userSetComponent);
                        }
                        mUseXml = true;
                    }
@@ -634,10 +655,16 @@ abstract public class ManagedServices {
        }
        boolean isOldVersion = TextUtils.isEmpty(version)
                || DB_VERSION_1.equals(version)
                || DB_VERSION_2.equals(version);
                || DB_VERSION_2.equals(version)
                || DB_VERSION_3.equals(version);
        boolean needUpgradeUserset = DB_VERSION_3.equals(version);
        if (isOldVersion) {
            upgradeDefaultsXmlVersion();
        }
        if (needUpgradeUserset) {
            upgradeUserSet();
        }

        rebindServices(false, USER_ALL);
    }

@@ -666,6 +693,8 @@ abstract public class ManagedServices {
        }
    }

    protected void upgradeUserSet() {};

    /**
     * Read extra attributes in the {@link #TAG_MANAGED_SERVICES} tag.
     */
+11 −40
Original line number Diff line number Diff line
@@ -106,7 +106,6 @@ import static android.service.notification.NotificationListenerService.TRIM_FULL
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;

import static com.android.internal.util.CollectionUtils.emptyIfNull;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
@@ -324,7 +323,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
@@ -9428,6 +9426,14 @@ public class NotificationManagerService extends SystemService {
            return mDefaultFromConfig;
        }

        @Override
        protected void upgradeUserSet() {
            for (int userId: mApproved.keySet()) {
                ArraySet<String> userSetServices = mUserSetServices.get(userId);
                mIsUserChanged.put(userId, (userSetServices != null && userSetServices.size() > 0));
            }
        }

        public NotificationAssistants(Context context, Object lock, UserProfiles up,
                IPackageManager pm) {
            super(context, lock, up, pm);
@@ -9602,47 +9608,12 @@ public class NotificationManagerService extends SystemService {
        }

        boolean hasUserSet(int userId) {
            synchronized (mLock) {
                ArraySet<String> userSetServices = mUserSetServices.get(userId);
                if (userSetServices == null) {
                    // Legacy case - no data means user-set, unless no assistant is set
                    return !mApproved.isEmpty();
                }
                Map<Boolean, ArraySet<String>> approvedByType = emptyIfNull(mApproved.get(userId));
                return userSetServices.containsAll(emptyIfNull(approvedByType.get(true)))
                        && userSetServices.containsAll(emptyIfNull(approvedByType.get(false)));
            }
            Boolean userSet = mIsUserChanged.get(userId);
            return (userSet != null && userSet);
        }

        void setUserSet(int userId, boolean set) {
            synchronized (mLock) {
                ArraySet<String> userSetServices = new ArraySet<>();
                if (set) {
                    ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
                    if (approvedByType != null) {
                        for (int i = 0; i < approvedByType.size(); i++) {
                            userSetServices.addAll(approvedByType.valueAt(i));
                        }
                    }
                }
                mUserSetServices.put(userId, userSetServices);
            }
        }

        @Override
        protected void readExtraAttributes(String tag, TypedXmlPullParser parser, int userId)
                throws IOException {
            // TODO: this logic looks broken, since it's trying to convert a
            // list into a boolean; for now we preserve the old parsing behavior
            // to avoid a performance regression, but someone should investigate
            final String value = parser.getAttributeValue(null, ATT_USER_SET);
            final boolean userSet;
            if (TextUtils.isEmpty(value)) {
                userSet = false;
            } else {
                userSet = Boolean.parseBoolean(value);
            }
            setUserSet(userId, userSet);
            mIsUserChanged.put(userId, set);
        }

        private void notifyCapabilitiesChanged(final ManagedServiceInfo info) {
+34 −4
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
    private String mVersionString;
    private final Set<ComponentName> mDefaults = new ArraySet();
    private ManagedServices mService;
    private String mUserSetString;

    private static final String SETTING = "setting";
    private static final String SECONDARY_SETTING = "secondary_setting";
@@ -138,7 +139,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
        profileIds.add(13);
        when(mUserProfiles.getCurrentProfileIds()).thenReturn(profileIds);

        mVersionString = "2";
        mVersionString = "4";
        mExpectedPrimary = new ArrayMap<>();
        mExpectedSecondary = new ArrayMap<>();
        mExpectedPrimaryPackages = new ArrayMap<>();
@@ -1363,6 +1364,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
    public void loadDefaults_noVersionWithDefaults() throws Exception {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        mVersionString = null;
        loadXml(mService);
        assertEquals(mService.getDefaultComponents(), mDefaults);
    }
@@ -1421,12 +1423,34 @@ public class ManagedServicesTest extends UiServiceTestCase {
        resetComponentsAndPackages();
        mDefaults.add(new ComponentName("default", "class"));
        mDefaultsString = "xml/class";
        mVersionString = String.valueOf(mService.DB_VERSION);
        loadXml(mService);
        assertEquals(mService.getDefaultComponents(),
                new ArraySet(Arrays.asList(new ComponentName("xml", "class"))));
    }

    @Test
    public void upgradeUserSet_versionThree() throws Exception {
        resetComponentsAndPackages();

        List<UserInfo> users = new ArrayList<>();
        users.add(new UserInfo(98, "98", 0));
        users.add(new UserInfo(99, "99", 0));
        for (UserInfo user : users) {
            when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
        }

        mDefaultsString = "xml/class";
        mVersionString = "3";
        mUserSetString = "xml/class";
        loadXml(mService);

        //Test services without overriding upgradeUserSet() remain unchanged
        assertEquals(new ArraySet(Arrays.asList(mUserSetString)),
                mService.mUserSetServices.get(98));
        assertEquals(new ArraySet(Arrays.asList(mUserSetString)),
                mService.mUserSetServices.get(99));
        assertEquals(new ArrayMap(), mService.mIsUserChanged);
    }

    private void resetComponentsAndPackages() {
        ArrayMap<Integer, ArrayMap<Integer, String>> empty = new ArrayMap(1);
@@ -1468,11 +1492,17 @@ public class ManagedServicesTest extends UiServiceTestCase {
        xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                        + ManagedServices.ATT_USER_ID + "=\"99\" "
                        + ManagedServices.ATT_IS_PRIMARY + "=\"true\" "
                        + ManagedServices.ATT_APPROVED_LIST + "=\"990\" />\n");
                        + ManagedServices.ATT_APPROVED_LIST + "=\"990\" "
                        + (mUserSetString != null ? ManagedServices.ATT_USER_SET + "=\""
                        + mUserSetString + "\" " : "")
                        + "/>\n");
        xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
                + ManagedServices.ATT_USER_ID + "=\"98\" "
                + ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
                + ManagedServices.ATT_APPROVED_LIST + "=\"981\" />\n");
                + ManagedServices.ATT_APPROVED_LIST + "=\"981\" "
                + (mUserSetString != null ? ManagedServices.ATT_USER_SET + "=\""
                + mUserSetString + "\" " : "")
                + " />\n");
        xml.append("</" + xmlTag + ">");

        return xml.toString();
+46 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.server.notification;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertNull;
@@ -41,11 +42,13 @@ import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.testing.TestableContext;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.TypedXmlPullParser;
import android.util.Xml;

import com.android.internal.util.function.TriPredicate;
import com.android.server.UiServiceTestCase;
import com.android.server.notification.NotificationManagerService.NotificationAssistants;

@@ -131,6 +134,49 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
        verify(mNm, times(mUm.getUsers().size())).setDefaultAssistantForUser(anyInt());
    }

    @Test
    public void testReadXml_userDisabled() throws Exception {
        String xml = "<enabled_assistants version=\"4\" defaults=\"b/b\">"
                + "<service_listing approved=\"\" user=\"0\" primary=\"true\""
                + "user_changed=\"true\"/>"
                + "</enabled_assistants>";

        final TypedXmlPullParser parser = Xml.newFastPullParser();
        parser.setInput(new BufferedInputStream(
                new ByteArrayInputStream(xml.toString().getBytes())), null);
        TriPredicate<String, Integer, String> allowedManagedServicePackages =
                mNm::canUseManagedServices;

        parser.nextTag();
        mAssistants.readXml(parser, allowedManagedServicePackages, false, UserHandle.USER_ALL);

        ArrayMap<Boolean, ArraySet<String>> approved = mAssistants.mApproved.get(0);

        // approved should not be null
        assertNotNull(approved);
        assertEquals(new ArraySet<>(), approved.get(true));
    }

    @Test
    public void testReadXml_upgradeUserSet() throws Exception {
        String xml = "<enabled_assistants version=\"3\" defaults=\"b/b\">"
                + "<service_listing approved=\"\" user=\"0\" primary=\"true\""
                + "user_set_services=\"b/b\"/>"
                + "</enabled_assistants>";

        final TypedXmlPullParser parser = Xml.newFastPullParser();
        parser.setInput(new BufferedInputStream(
                new ByteArrayInputStream(xml.toString().getBytes())), null);
        TriPredicate<String, Integer, String> allowedManagedServicePackages =
                mNm::canUseManagedServices;

        parser.nextTag();
        mAssistants.readXml(parser, allowedManagedServicePackages, false, UserHandle.USER_ALL);

        verify(mAssistants, times(1)).upgradeUserSet();
        assertTrue(mAssistants.mIsUserChanged.get(0));
    }

    @Test
    public void testXmlUpgradeExistingApprovedComponents() throws Exception {
        String xml = "<enabled_assistants version=\"2\" defaults=\"b\\b\">"