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

Commit 13cc6eb7 authored by Gustav Sennton's avatar Gustav Sennton
Browse files

Add flags to control generation of Smart Suggestions in Notifications

Add flags to the notification_assistant DeviceConfig namespace to
control smart suggestions generation for notifications.

The existing flag in Settings.Global
SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS will be removed in a follow-up.

Bug: 120792826
Test: atest AssistantSettingsTest
Test: play around with 'adb shell device_config put
notification_assistant notification_assistant_generate_replies X', and
'adb shell device_config put
notification_assistant notification_assistant_generate_actions X', where
X is false or true.
Change-Id: I0252bff48f053aab4b81d74147579416b28c515a
parent a9b062d0
Loading
Loading
Loading
Loading
+76 −16
Original line number Diff line number Diff line
@@ -20,8 +20,11 @@ import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.KeyValueListParser;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

@@ -29,6 +32,7 @@ import com.android.internal.annotations.VisibleForTesting;
 * Observes the settings for {@link Assistant}.
 */
final class AssistantSettings extends ContentObserver {
    private static final String LOG_TAG = "AssistantSettings";
    public static Factory FACTORY = AssistantSettings::createAndRegister;
    private static final boolean DEFAULT_GENERATE_REPLIES = true;
    private static final boolean DEFAULT_GENERATE_ACTIONS = true;
@@ -39,19 +43,33 @@ final class AssistantSettings extends ContentObserver {
    private static final Uri DISMISS_TO_VIEW_RATIO_LIMIT_URI =
            Settings.Global.getUriFor(
                    Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT);
    private static final Uri SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS_URI =
            Settings.Global.getUriFor(
                    Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS);
    private static final Uri NOTIFICATION_NEW_INTERRUPTION_MODEL_URI =
            Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL);

    private static final String KEY_GENERATE_REPLIES = "generate_replies";
    private static final String KEY_GENERATE_ACTIONS = "generate_actions";
    /**
     * Flag determining whether the Notification Assistant should generate replies for
     * notifications.
     * <p>
     * This flag belongs to the namespace: {@link DeviceConfig#NAMESPACE_NOTIFICATION_ASSISTANT}.
     */
    @VisibleForTesting
    static final String KEY_GENERATE_REPLIES = "notification_assistant_generate_replies";

    /**
     * Flag determining whether the Notification Assistant should generate contextual actions in
     * notifications.
     * <p>
     * This flag belongs to the namespace: {@link DeviceConfig#NAMESPACE_NOTIFICATION_ASSISTANT}.
     */
    @VisibleForTesting
    static final String KEY_GENERATE_ACTIONS = "notification_assistant_generate_actions";

    private final KeyValueListParser mParser = new KeyValueListParser(',');
    private final ContentResolver mResolver;
    private final int mUserId;

    private final Handler mHandler;

    @VisibleForTesting
    protected final Runnable mOnUpdateRunnable;

@@ -65,6 +83,7 @@ final class AssistantSettings extends ContentObserver {
    private AssistantSettings(Handler handler, ContentResolver resolver, int userId,
            Runnable onUpdateRunnable) {
        super(handler);
        mHandler = handler;
        mResolver = resolver;
        mUserId = userId;
        mOnUpdateRunnable = onUpdateRunnable;
@@ -75,6 +94,7 @@ final class AssistantSettings extends ContentObserver {
        AssistantSettings assistantSettings =
                new AssistantSettings(handler, resolver, userId, onUpdateRunnable);
        assistantSettings.register();
        assistantSettings.registerDeviceConfigs();
        return assistantSettings;
    }

@@ -91,13 +111,62 @@ final class AssistantSettings extends ContentObserver {
        mResolver.registerContentObserver(
                DISMISS_TO_VIEW_RATIO_LIMIT_URI, false, this, mUserId);
        mResolver.registerContentObserver(STREAK_LIMIT_URI, false, this, mUserId);
        mResolver.registerContentObserver(
                SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS_URI, false, this, mUserId);

        // Update all uris on creation.
        update(null);
    }

    private void registerDeviceConfigs() {
        DeviceConfig.addOnPropertyChangedListener(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                this::postToHandler,
                this::onDeviceConfigPropertyChanged);

        // Update the fields in this class from the current state of the device config.
        updateFromDeviceConfigFlags();
    }

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

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

        updateFromDeviceConfigFlags();
    }

    private void updateFromDeviceConfigFlags() {
        String generateRepliesFlag = DeviceConfig.getProperty(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                KEY_GENERATE_REPLIES);
        if (TextUtils.isEmpty(generateRepliesFlag)) {
            mGenerateReplies = DEFAULT_GENERATE_REPLIES;
        } else {
            // parseBoolean returns false for everything that isn't 'true' so there's no need to
            // sanitise the flag string here.
            mGenerateReplies = Boolean.parseBoolean(generateRepliesFlag);
        }

        String generateActionsFlag = DeviceConfig.getProperty(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                KEY_GENERATE_ACTIONS);
        if (TextUtils.isEmpty(generateActionsFlag)) {
            mGenerateActions = DEFAULT_GENERATE_ACTIONS;
        } else {
            // parseBoolean returns false for everything that isn't 'true' so there's no need to
            // sanitise the flag string here.
            mGenerateActions = Boolean.parseBoolean(generateActionsFlag);
        }

        mOnUpdateRunnable.run();
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        update(uri);
@@ -114,15 +183,6 @@ final class AssistantSettings extends ContentObserver {
                    mResolver, Settings.Global.BLOCKING_HELPER_STREAK_LIMIT,
                    ChannelImpressions.DEFAULT_STREAK_LIMIT);
        }
        if (uri == null || SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS_URI.equals(uri)) {
            mParser.setString(
                    Settings.Global.getString(mResolver,
                            Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS));
            mGenerateReplies =
                    mParser.getBoolean(KEY_GENERATE_REPLIES, DEFAULT_GENERATE_REPLIES);
            mGenerateActions =
                    mParser.getBoolean(KEY_GENERATE_ACTIONS, DEFAULT_GENERATE_ACTIONS);
        }
        if (uri == null || NOTIFICATION_NEW_INTERRUPTION_MODEL_URI.equals(uri)) {
            int mNewInterruptionModelInt = Settings.Secure.getInt(
                    mResolver, Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL,
+53 −33
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.os.Handler;
import android.os.Looper;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -62,9 +63,6 @@ public class AssistantSettingsTest {
        Settings.Global.putFloat(mResolver,
                Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT, 0.8f);
        Settings.Global.putInt(mResolver, Settings.Global.BLOCKING_HELPER_STREAK_LIMIT, 2);
        Settings.Global.putString(mResolver,
                Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
                "generate_replies=true,generate_actions=true");
        Settings.Secure.putInt(mResolver, Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);

        mAssistantSettings = AssistantSettings.createForTesting(
@@ -73,56 +71,78 @@ public class AssistantSettingsTest {

    @Test
    public void testGenerateRepliesDisabled() {
        Settings.Global.putString(mResolver,
                Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
                "generate_replies=false");

        // Notify for the settings values we updated.
        mAssistantSettings.onChange(false,
                Settings.Global.getUriFor(
                        Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS));

        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_REPLIES,
                "false");

        assertFalse(mAssistantSettings.mGenerateReplies);
    }

    @Test
    public void testGenerateRepliesEnabled() {
        Settings.Global.putString(mResolver,
                Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS, "generate_replies=true");

        // Notify for the settings values we updated.
        mAssistantSettings.onChange(false,
                Settings.Global.getUriFor(
                        Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS));
        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_REPLIES,
                "true");

        assertTrue(mAssistantSettings.mGenerateReplies);
    }

    @Test
    public void testGenerateActionsDisabled() {
        Settings.Global.putString(mResolver,
                Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS, "generate_actions=false");
    public void testGenerateRepliesEmptyFlag() {
        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_REPLIES,
                "false");

        // Notify for the settings values we updated.
        mAssistantSettings.onChange(false,
                Settings.Global.getUriFor(
                        Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS));
        assertFalse(mAssistantSettings.mGenerateReplies);

        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_REPLIES,
                "");

        // Go back to the default value.
        assertTrue(mAssistantSettings.mGenerateReplies);
    }

    @Test
    public void testGenerateActionsDisabled() {
        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_ACTIONS,
                "false");

        assertFalse(mAssistantSettings.mGenerateActions);
    }

    @Test
    public void testGenerateActionsEnabled() {
        Settings.Global.putString(mResolver,
                Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS, "generate_actions=true");
        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_ACTIONS,
                "true");

        // Notify for the settings values we updated.
        mAssistantSettings.onChange(false,
                Settings.Global.getUriFor(
                        Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS));
        assertTrue(mAssistantSettings.mGenerateActions);
    }

        assertTrue(mAssistantSettings.mGenerateReplies);
    @Test
    public void testGenerateActionsEmptyFlag() {
        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_ACTIONS,
                "false");

        assertFalse(mAssistantSettings.mGenerateActions);

        mAssistantSettings.onDeviceConfigPropertyChanged(
                DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT,
                AssistantSettings.KEY_GENERATE_ACTIONS,
                "");

        // Go back to the default value.
        assertTrue(mAssistantSettings.mGenerateActions);
    }

    @Test