blob: 8b81585836dc917e1a69053d81fed245f34ed413 [file] [log] [blame]
Petr Cermak10011fa2018-02-05 19:00:54 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.policy;
18
Jason Monk27d01a622018-12-10 15:57:09 -050019import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
20
Milo Sredkov41dc4ba2018-12-27 12:03:45 +000021import android.app.RemoteInput;
Petr Cermak10011fa2018-02-05 19:00:54 +000022import android.content.Context;
23import android.content.res.Resources;
24import android.database.ContentObserver;
25import android.net.Uri;
26import android.os.Handler;
27import android.provider.Settings;
28import android.util.KeyValueListParser;
29import android.util.Log;
30
31import com.android.systemui.R;
32
Jason Monk27d01a622018-12-10 15:57:09 -050033import javax.inject.Inject;
34import javax.inject.Named;
35import javax.inject.Singleton;
36
37@Singleton
Petr Cermak10011fa2018-02-05 19:00:54 +000038public final class SmartReplyConstants extends ContentObserver {
39
40 private static final String TAG = "SmartReplyConstants";
41
42 private static final String KEY_ENABLED = "enabled";
Richard Ledley28944cb2018-02-26 10:36:00 +000043 private static final String KEY_REQUIRES_TARGETING_P = "requires_targeting_p";
Petr Cermak10011fa2018-02-05 19:00:54 +000044 private static final String KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS =
45 "max_squeeze_remeasure_attempts";
Milo Sredkov41dc4ba2018-12-27 12:03:45 +000046 private static final String KEY_EDIT_CHOICES_BEFORE_SENDING =
47 "edit_choices_before_sending";
Gustav Sennton3f3eaff2019-01-08 09:39:51 +000048 private static final String KEY_SHOW_IN_HEADS_UP = "show_in_heads_up";
Gustav Senntona31f6ae2019-01-08 11:20:49 +000049 private static final String KEY_MIN_NUM_REPLIES = "min_num_system_generated_replies";
Gustav Sennton4bf5ff52019-01-16 14:27:25 +000050 private static final String KEY_MAX_NUM_ACTIONS = "max_num_actions";
Petr Cermak10011fa2018-02-05 19:00:54 +000051
52 private final boolean mDefaultEnabled;
Richard Ledley28944cb2018-02-26 10:36:00 +000053 private final boolean mDefaultRequiresP;
Petr Cermak10011fa2018-02-05 19:00:54 +000054 private final int mDefaultMaxSqueezeRemeasureAttempts;
Milo Sredkov41dc4ba2018-12-27 12:03:45 +000055 private final boolean mDefaultEditChoicesBeforeSending;
Gustav Sennton3f3eaff2019-01-08 09:39:51 +000056 private final boolean mDefaultShowInHeadsUp;
Gustav Senntona31f6ae2019-01-08 11:20:49 +000057 private final int mDefaultMinNumSystemGeneratedReplies;
Gustav Sennton4bf5ff52019-01-16 14:27:25 +000058 private final int mDefaultMaxNumActions;
Petr Cermak10011fa2018-02-05 19:00:54 +000059
Gustav Senntoneb93c402019-02-25 18:44:01 +000060 // These fields are updated on the UI thread but can be accessed on both the UI thread and
61 // background threads. We use the volatile keyword here instead of synchronization blocks since
62 // we only care about variable updates here being visible to other threads (and not for example
63 // whether the variables we are reading were updated in the same go).
64 private volatile boolean mEnabled;
65 private volatile boolean mRequiresTargetingP;
66 private volatile int mMaxSqueezeRemeasureAttempts;
67 private volatile boolean mEditChoicesBeforeSending;
68 private volatile boolean mShowInHeadsUp;
69 private volatile int mMinNumSystemGeneratedReplies;
70 private volatile int mMaxNumActions;
Petr Cermak10011fa2018-02-05 19:00:54 +000071
72 private final Context mContext;
73 private final KeyValueListParser mParser = new KeyValueListParser(',');
74
Jason Monk27d01a622018-12-10 15:57:09 -050075 @Inject
76 public SmartReplyConstants(@Named(MAIN_HANDLER_NAME) Handler handler, Context context) {
Petr Cermak10011fa2018-02-05 19:00:54 +000077 super(handler);
78
79 mContext = context;
80 final Resources resources = mContext.getResources();
81 mDefaultEnabled = resources.getBoolean(
82 R.bool.config_smart_replies_in_notifications_enabled);
Richard Ledley28944cb2018-02-26 10:36:00 +000083 mDefaultRequiresP = resources.getBoolean(
84 R.bool.config_smart_replies_in_notifications_requires_targeting_p);
Petr Cermak10011fa2018-02-05 19:00:54 +000085 mDefaultMaxSqueezeRemeasureAttempts = resources.getInteger(
86 R.integer.config_smart_replies_in_notifications_max_squeeze_remeasure_attempts);
Milo Sredkov41dc4ba2018-12-27 12:03:45 +000087 mDefaultEditChoicesBeforeSending = resources.getBoolean(
88 R.bool.config_smart_replies_in_notifications_edit_choices_before_sending);
Gustav Sennton3f3eaff2019-01-08 09:39:51 +000089 mDefaultShowInHeadsUp = resources.getBoolean(
90 R.bool.config_smart_replies_in_notifications_show_in_heads_up);
Gustav Senntona31f6ae2019-01-08 11:20:49 +000091 mDefaultMinNumSystemGeneratedReplies = resources.getInteger(
92 R.integer.config_smart_replies_in_notifications_min_num_system_generated_replies);
Gustav Sennton4bf5ff52019-01-16 14:27:25 +000093 mDefaultMaxNumActions = resources.getInteger(
94 R.integer.config_smart_replies_in_notifications_max_num_actions);
Petr Cermak10011fa2018-02-05 19:00:54 +000095
96 mContext.getContentResolver().registerContentObserver(
97 Settings.Global.getUriFor(Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS),
98 false, this);
99 updateConstants();
100 }
101
102 @Override
103 public void onChange(boolean selfChange, Uri uri) {
104 updateConstants();
105 }
106
107 private void updateConstants() {
108 synchronized (SmartReplyConstants.this) {
109 try {
110 mParser.setString(Settings.Global.getString(mContext.getContentResolver(),
111 Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS));
112 } catch (IllegalArgumentException e) {
113 Log.e(TAG, "Bad smart reply constants", e);
114 }
115 mEnabled = mParser.getBoolean(KEY_ENABLED, mDefaultEnabled);
Richard Ledley28944cb2018-02-26 10:36:00 +0000116 mRequiresTargetingP = mParser.getBoolean(KEY_REQUIRES_TARGETING_P, mDefaultRequiresP);
Petr Cermak10011fa2018-02-05 19:00:54 +0000117 mMaxSqueezeRemeasureAttempts = mParser.getInt(
118 KEY_MAX_SQUEEZE_REMEASURE_ATTEMPTS, mDefaultMaxSqueezeRemeasureAttempts);
Milo Sredkov41dc4ba2018-12-27 12:03:45 +0000119 mEditChoicesBeforeSending = mParser.getBoolean(
120 KEY_EDIT_CHOICES_BEFORE_SENDING, mDefaultEditChoicesBeforeSending);
Gustav Sennton3f3eaff2019-01-08 09:39:51 +0000121 mShowInHeadsUp = mParser.getBoolean(KEY_SHOW_IN_HEADS_UP, mDefaultShowInHeadsUp);
Gustav Senntona31f6ae2019-01-08 11:20:49 +0000122 mMinNumSystemGeneratedReplies =
123 mParser.getInt(KEY_MIN_NUM_REPLIES, mDefaultMinNumSystemGeneratedReplies);
Gustav Sennton4bf5ff52019-01-16 14:27:25 +0000124 mMaxNumActions = mParser.getInt(KEY_MAX_NUM_ACTIONS, mDefaultMaxNumActions);
Petr Cermak10011fa2018-02-05 19:00:54 +0000125 }
126 }
127
128 /** Returns whether smart replies in notifications are enabled. */
129 public boolean isEnabled() {
130 return mEnabled;
131 }
132
133 /**
Richard Ledley28944cb2018-02-26 10:36:00 +0000134 * Returns whether smart replies in notifications should be disabled when the app targets a
135 * version of Android older than P.
136 */
137 public boolean requiresTargetingP() {
138 return mRequiresTargetingP;
139 }
140
141 /**
Petr Cermak10011fa2018-02-05 19:00:54 +0000142 * Returns the maximum number of times {@link SmartReplyView#onMeasure(int, int)} will try to
143 * find a better (narrower) line-break for a double-line smart reply button.
144 */
145 public int getMaxSqueezeRemeasureAttempts() {
146 return mMaxSqueezeRemeasureAttempts;
147 }
Milo Sredkov41dc4ba2018-12-27 12:03:45 +0000148
149 /**
150 * Returns whether by tapping on a choice should let the user edit the input before it
151 * is sent to the app.
152 *
153 * @param remoteInputEditChoicesBeforeSending The value from
154 * {@link RemoteInput#getEditChoicesBeforeSending()}
155 */
156 public boolean getEffectiveEditChoicesBeforeSending(
157 @RemoteInput.EditChoicesBeforeSending int remoteInputEditChoicesBeforeSending) {
158 switch (remoteInputEditChoicesBeforeSending) {
159 case RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED:
160 return false;
161 case RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED:
162 return true;
163 case RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO:
164 default:
165 return mEditChoicesBeforeSending;
166 }
167 }
Gustav Sennton3f3eaff2019-01-08 09:39:51 +0000168
169 /**
170 * Returns whether smart suggestions should be enabled in heads-up notifications.
171 */
172 public boolean getShowInHeadsUp() {
173 return mShowInHeadsUp;
174 }
Gustav Senntona31f6ae2019-01-08 11:20:49 +0000175
176 /**
177 * Returns the minimum number of system generated replies to show in a notification.
178 * If we cannot show at least this many system generated replies we should show none.
179 */
180 public int getMinNumSystemGeneratedReplies() {
181 return mMinNumSystemGeneratedReplies;
182 }
Gustav Sennton4bf5ff52019-01-16 14:27:25 +0000183
184 /**
185 * Returns the maximum number smart actions to show in a notification, or -1 if there shouldn't
186 * be a limit.
187 */
188 public int getMaxNumActions() {
189 return mMaxNumActions;
190 }
Petr Cermak10011fa2018-02-05 19:00:54 +0000191}