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
diff --git a/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java b/packages/ExtServices/src/android/ext/services/notification/AssistantSettings.java
index 39a1676..406b44d 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.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 @@
* 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 @@
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 @@
private AssistantSettings(Handler handler, ContentResolver resolver, int userId,
Runnable onUpdateRunnable) {
super(handler);
+ mHandler = handler;
mResolver = resolver;
mUserId = userId;
mOnUpdateRunnable = onUpdateRunnable;
@@ -75,6 +94,7 @@
AssistantSettings assistantSettings =
new AssistantSettings(handler, resolver, userId, onUpdateRunnable);
assistantSettings.register();
+ assistantSettings.registerDeviceConfigs();
return assistantSettings;
}
@@ -91,13 +111,62 @@
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 @@
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,