diff --git a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java index 39a1676b4ec73..406b44d64da2b 100644 --- a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java +++ b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java @@ -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. + *
+ * 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. + *
+ * 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, diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java index fd23f2b78b42d..51b723d0950c1 100644 --- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java +++ b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java @@ -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"); + mAssistantSettings.onDeviceConfigPropertyChanged( + DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT, + AssistantSettings.KEY_GENERATE_REPLIES, + "true"); - // Notify for the settings values we updated. - mAssistantSettings.onChange(false, - Settings.Global.getUriFor( - Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS)); + assertTrue(mAssistantSettings.mGenerateReplies); + } + @Test + public void testGenerateRepliesEmptyFlag() { + mAssistantSettings.onDeviceConfigPropertyChanged( + DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT, + AssistantSettings.KEY_GENERATE_REPLIES, + "false"); + + 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() { - Settings.Global.putString(mResolver, - Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS, "generate_actions=false"); + mAssistantSettings.onDeviceConfigPropertyChanged( + DeviceConfig.NAMESPACE_NOTIFICATION_ASSISTANT, + AssistantSettings.KEY_GENERATE_ACTIONS, + "false"); - // Notify for the settings values we updated. - mAssistantSettings.onChange(false, - Settings.Global.getUriFor( - Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS)); - - assertTrue(mAssistantSettings.mGenerateReplies); + 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