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

Commit 5a9da780 authored by Gustav Sennton's avatar Gustav Sennton Committed by Android (Google) Code Review
Browse files

Merge "Move SSIN sys ui flags from Settings.Global to DeviceConfig."

parents 4ed935a5 8fa7e952
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ package com.android.internal.config.sysui;
 */
public final class SystemUiDeviceConfigFlags {

    // Flags related to NotificationAssistant

    /**
     * Whether the Notification Assistant should generate replies for notifications.
     */
@@ -45,5 +47,39 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions";

    // Flags related to Smart Suggestions - these are read in SmartReplyConstants.

    /** (boolean) Whether to enable smart suggestions in notifications. */
    public static final String SSIN_ENABLED = "ssin_enabled";

    /**
     * (boolean) Whether apps need to target at least P to provide their own smart replies (this
     * doesn't apply to actions!).
     */
    public static final String SSIN_REQUIRES_TARGETING_P = "ssin_requires_targeting_p";

    /**
     * (int) The number of times we'll try to find a better line-break for double-line smart
     * suggestion buttons.
     */
    public static final String SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS =
            "ssin_max_squeeze_remeasure_attempts";

    /** (boolean) Whether to let the user edit smart replies before sending. */
    public static final String SSIN_EDIT_CHOICES_BEFORE_SENDING =
            "ssin_edit_choices_before_sending";

    /** (boolean) Whether smart suggestions should be enabled in heads-up notifications. */
    public static final String SSIN_SHOW_IN_HEADS_UP = "ssin_show_in_heads_up";

    /** (int) Minimum number of system generated replies to show in a notification. */
    public static final String SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES =
            "ssin_min_num_system_generated_replies";

    /**
     * (int) Maximum number of actions to show in a notification, -1 if there shouldn't be a limit
     */
    public static final String SSIN_MAX_NUM_ACTIONS = "ssin_max_num_actions";

    private SystemUiDeviceConfigFlags() { }
}
+79 −37
Original line number Diff line number Diff line
@@ -21,13 +21,14 @@ import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import android.app.RemoteInput;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.provider.DeviceConfig;
import android.text.TextUtils;
import android.util.KeyValueListParser;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;

import javax.inject.Inject;
@@ -35,20 +36,10 @@ import javax.inject.Named;
import javax.inject.Singleton;

@Singleton
public final class SmartReplyConstants extends ContentObserver {
public final class SmartReplyConstants {

    private static final String TAG = "SmartReplyConstants";

    private static final String KEY_ENABLED = "enabled";
    private static final String KEY_REQUIRES_TARGETING_P = "requires_targeting_p";
    private static final String KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS =
            "max_squeeze_remeasure_attempts";
    private static final String KEY_EDIT_CHOICES_BEFORE_SENDING =
            "edit_choices_before_sending";
    private static final String KEY_SHOW_IN_HEADS_UP = "show_in_heads_up";
    private static final String KEY_MIN_NUM_REPLIES = "min_num_system_generated_replies";
    private static final String KEY_MAX_NUM_ACTIONS = "max_num_actions";

    private final boolean mDefaultEnabled;
    private final boolean mDefaultRequiresP;
    private final int mDefaultMaxSqueezeRemeasureAttempts;
@@ -69,13 +60,13 @@ public final class SmartReplyConstants extends ContentObserver {
    private volatile int mMinNumSystemGeneratedReplies;
    private volatile int mMaxNumActions;

    private final Handler mHandler;
    private final Context mContext;
    private final KeyValueListParser mParser = new KeyValueListParser(',');

    @Inject
    public SmartReplyConstants(@Named(MAIN_HANDLER_NAME) Handler handler, Context context) {
        super(handler);

        mHandler = handler;
        mContext = context;
        final Resources resources = mContext.getResources();
        mDefaultEnabled = resources.getBoolean(
@@ -93,35 +84,86 @@ public final class SmartReplyConstants extends ContentObserver {
        mDefaultMaxNumActions = resources.getInteger(
                R.integer.config_smart_replies_in_notifications_max_num_actions);

        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS),
                false, this);
        registerDeviceConfigListener();
        updateConstants();
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
    private void registerDeviceConfigListener() {
        DeviceConfig.addOnPropertyChangedListener(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                this::postToHandler,
                this::onDeviceConfigPropertyChanged);
    }

    private void postToHandler(Runnable r) {
        this.mHandler.post(r);
    }

    @VisibleForTesting
    void onDeviceConfigPropertyChanged(String namespace, String name, String value) {
        if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
            Log.e(TAG, "Received update from DeviceConfig for unrelated namespace: "
                    + namespace + " " + name + "=" + value);
            return;
        }

        updateConstants();
    }

    private void updateConstants() {
        synchronized (SmartReplyConstants.this) {
            mEnabled = readDeviceConfigBooleanOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_ENABLED,
                    mDefaultEnabled);
            mRequiresTargetingP = readDeviceConfigBooleanOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P,
                    mDefaultRequiresP);
            mMaxSqueezeRemeasureAttempts = readDeviceConfigIntegerOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS,
                    mDefaultMaxSqueezeRemeasureAttempts);
            mEditChoicesBeforeSending = readDeviceConfigBooleanOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING,
                    mDefaultEditChoicesBeforeSending);
            mShowInHeadsUp = readDeviceConfigBooleanOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP,
                    mDefaultShowInHeadsUp);
            mMinNumSystemGeneratedReplies = readDeviceConfigIntegerOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES,
                    mDefaultMinNumSystemGeneratedReplies);
            mMaxNumActions = readDeviceConfigIntegerOrDefaultIfEmpty(
                    SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS,
                    mDefaultMaxNumActions);
        }
    }

    private static boolean readDeviceConfigBooleanOrDefaultIfEmpty(String propertyName,
            boolean defaultValue) {
        String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI, propertyName);
        if (TextUtils.isEmpty(value)) {
            return defaultValue;
        }
        if ("true".equals(value)) {
            return true;
        }
        if ("false".equals(value)) {
            return false;
        }
        // For invalid configs we return the default value.
        return defaultValue;
    }

    private static int readDeviceConfigIntegerOrDefaultIfEmpty(String propertyName,
            int defaultValue) {
        String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI, propertyName);
        if (TextUtils.isEmpty(value)) {
            return defaultValue;
        }
        try {
                mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
                        Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "Bad smart reply constants", e);
            }
            mEnabled = mParser.getBoolean(KEY_ENABLED, mDefaultEnabled);
            mRequiresTargetingP = mParser.getBoolean(KEY_REQUIRES_TARGETING_P, mDefaultRequiresP);
            mMaxSqueezeRemeasureAttempts = mParser.getInt(
                    KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS, mDefaultMaxSqueezeRemeasureAttempts);
            mEditChoicesBeforeSending = mParser.getBoolean(
                    KEY_EDIT_CHOICES_BEFORE_SENDING, mDefaultEditChoicesBeforeSending);
            mShowInHeadsUp = mParser.getBoolean(KEY_SHOW_IN_HEADS_UP, mDefaultShowInHeadsUp);
            mMinNumSystemGeneratedReplies =
                    mParser.getInt(KEY_MIN_NUM_REPLIES, mDefaultMinNumSystemGeneratedReplies);
            mMaxNumActions = mParser.getInt(KEY_MAX_NUM_ACTIONS, mDefaultMaxNumActions);
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            Log.e(TAG, "Tried to read an integer flag, property name="
                    + propertyName + ", value=" + value);
            return defaultValue;
        }
    }

+59 −32
Original line number Diff line number Diff line
@@ -23,15 +23,17 @@ import static junit.framework.Assert.assertTrue;
import android.app.RemoteInput;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.provider.DeviceConfig;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableResources;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,7 +49,7 @@ public class SmartReplyConstantsTest extends SysuiTestCase {

    @Before
    public void setUp() {
        overrideSetting(null); // No config.
        resetAllDeviceConfigFlags();
        TestableResources resources = mContext.getOrCreateTestableResources();
        resources.addOverride(R.bool.config_smart_replies_in_notifications_enabled, true);
        resources.addOverride(
@@ -58,9 +60,16 @@ public class SmartReplyConstantsTest extends SysuiTestCase {
        resources.addOverride(
                R.integer.config_smart_replies_in_notifications_min_num_system_generated_replies,
                2);
        resources.addOverride(
                R.integer.config_smart_replies_in_notifications_max_num_actions, -1);
        mConstants = new SmartReplyConstants(Handler.createAsync(Looper.myLooper()), mContext);
    }

    @After
    public void tearDown() {
        resetAllDeviceConfigFlags();
    }

    @Test
    public void testIsEnabledWithNoConfig() {
        assertTrue(mConstants.isEnabled());
@@ -68,25 +77,25 @@ public class SmartReplyConstantsTest extends SysuiTestCase {

    @Test
    public void testIsEnabledWithInvalidConfig() {
        overrideSetting("invalid config");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_ENABLED, "invalid config");
        triggerConstantsOnChange();
        assertTrue(mConstants.isEnabled());
    }

    @Test
    public void testIsEnabledWithValidConfig() {
        overrideSetting("enabled=false,max_squeeze_remeasure_attempts=5");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_ENABLED, "false");
        triggerConstantsOnChange();
        assertFalse(mConstants.isEnabled());
    }

    @Test
    public void testRequiresTargetingPConfig() {
        overrideSetting("enabled=true,requires_targeting_p=false");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, "false");
        triggerConstantsOnChange();
        assertEquals(false, mConstants.requiresTargetingP());

        overrideSetting("enabled=true");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, "");
        triggerConstantsOnChange();
        assertEquals(true, mConstants.requiresTargetingP());
    }
@@ -99,21 +108,21 @@ public class SmartReplyConstantsTest extends SysuiTestCase {

    @Test
    public void testGetMaxSqueezeRemeasureAttemptsWithInvalidConfig() {
        overrideSetting("invalid config");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS,
                "invalid config");
        triggerConstantsOnChange();
        assertEquals(7, mConstants.getMaxSqueezeRemeasureAttempts());
    }

    @Test
    public void testGetMaxSqueezeRemeasureAttemptsWithValidConfig() {
        overrideSetting("enabled=false,max_squeeze_remeasure_attempts=5");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS, "5");
        triggerConstantsOnChange();
        assertEquals(5, mConstants.getMaxSqueezeRemeasureAttempts());
    }

    @Test
    public void testGetEffectiveEditChoicesBeforeSendingWithNoConfig() {
        overrideSetting("enabled=true");
        triggerConstantsOnChange();
        assertFalse(
                mConstants.getEffectiveEditChoicesBeforeSending(
@@ -128,7 +137,7 @@ public class SmartReplyConstantsTest extends SysuiTestCase {

    @Test
    public void testGetEffectiveEditChoicesBeforeSendingWithEnabledConfig() {
        overrideSetting("enabled=true,edit_choices_before_sending=true");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING, "true");
        triggerConstantsOnChange();
        assertTrue(
                mConstants.getEffectiveEditChoicesBeforeSending(
@@ -143,7 +152,7 @@ public class SmartReplyConstantsTest extends SysuiTestCase {

    @Test
    public void testGetEffectiveEditChoicesBeforeSendingWithDisabledConfig() {
        overrideSetting("enabled=true,edit_choices_before_sending=false");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING, "false");
        triggerConstantsOnChange();
        assertFalse(
                mConstants.getEffectiveEditChoicesBeforeSending(
@@ -164,53 +173,71 @@ public class SmartReplyConstantsTest extends SysuiTestCase {

    @Test
    public void testShowInHeadsUpEnabled() {
        overrideSetting("enabled=true,show_in_heads_up=true");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, "true");
        triggerConstantsOnChange();
        assertTrue(mConstants.getShowInHeadsUp());
    }

    @Test
    public void testShowInHeadsUpDisabled() {
        overrideSetting("enabled=true,show_in_heads_up=false");
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, "false");
        triggerConstantsOnChange();
        assertFalse(mConstants.getShowInHeadsUp());
    }

    @Test
    public void testMaxNumActionsWithNoConfig() {
    public void testGetMinNumSystemGeneratedRepliesWithNoConfig() {
        assertTrue(mConstants.isEnabled());
        assertEquals(-1, mConstants.getMaxNumActions());
        assertEquals(2, mConstants.getMinNumSystemGeneratedReplies());
    }

    @Test
    public void testMaxNumActionsSet() {
        overrideSetting("enabled=true,max_num_actions=10");
    public void testGetMinNumSystemGeneratedRepliesWithValidConfig() {
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES, "5");
        triggerConstantsOnChange();
        assertEquals(10, mConstants.getMaxNumActions());
    }

    private void overrideSetting(String flags) {
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS, flags);
        assertEquals(5, mConstants.getMinNumSystemGeneratedReplies());
    }

    @Test
    public void testGetMinNumSystemGeneratedRepliesWithNoConfig() {
    public void testMaxNumActionsWithNoConfig() {
        assertTrue(mConstants.isEnabled());
        assertEquals(2, mConstants.getMinNumSystemGeneratedReplies());
        assertEquals(-1, mConstants.getMaxNumActions());
    }

    @Test
    public void testGetMinNumSystemGeneratedRepliesWithValidConfig() {
        overrideSetting("enabled=true,min_num_system_generated_replies=5");
    public void testMaxNumActionsSet() {
        overrideSetting(SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS, "10");
        triggerConstantsOnChange();
        assertEquals(5, mConstants.getMinNumSystemGeneratedReplies());
        assertEquals(10, mConstants.getMaxNumActions());
    }

    private void overrideSetting(String propertyName, String value) {
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                propertyName, value, false /* makeDefault */);
    }

    private void triggerConstantsOnChange() {
        // Since Settings.Global is mocked in TestableContext, we need to manually trigger the
        // content observer.
        mConstants.onChange(false,
                Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
        mConstants.onDeviceConfigPropertyChanged(DeviceConfig.NAMESPACE_SYSTEMUI,
                "" /* name */, "" /* value */);
    }

    private void resetAllDeviceConfigFlags() {
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_ENABLED, "", false /* makeDefault */);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_REQUIRES_TARGETING_P, "", false /* makeDefault */);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_MAX_SQUEEZE_REMEASURE_ATTEMPTS, "",
                false /* makeDefault */);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_EDIT_CHOICES_BEFORE_SENDING, "",
                false /* makeDefault */);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_SHOW_IN_HEADS_UP, "", false /* makeDefault */);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_MIN_NUM_SYSTEM_GENERATED_REPLIES, "",
                false /* makeDefault */);
        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.SSIN_MAX_NUM_ACTIONS, "", false /* makeDefault */);
    }
}