Loading packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java +76 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -75,6 +94,7 @@ final class AssistantSettings extends ContentObserver { AssistantSettings assistantSettings = new AssistantSettings(handler, resolver, userId, onUpdateRunnable); assistantSettings.register(); assistantSettings.registerDeviceConfigs(); return assistantSettings; } Loading @@ -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); Loading @@ -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, Loading packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java +53 −33 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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( Loading @@ -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 Loading Loading
packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java +76 −16 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -75,6 +94,7 @@ final class AssistantSettings extends ContentObserver { AssistantSettings assistantSettings = new AssistantSettings(handler, resolver, userId, onUpdateRunnable); assistantSettings.register(); assistantSettings.registerDeviceConfigs(); return assistantSettings; } Loading @@ -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); Loading @@ -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, Loading
packages/ExtServices/tests/src/android/ext/services/notification/AssistantSettingsTest.java +53 −33 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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( Loading @@ -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 Loading