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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user