• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
17 package com.android.settings.development.tare;
18 
19 import static android.app.tare.EconomyManager.CAKE_IN_ARC;
20 import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES;
21 import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES;
22 import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES;
23 import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES;
24 import static android.app.tare.EconomyManager.parseCreditValue;
25 import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS;
26 import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS;
27 
28 import android.annotation.NonNull;
29 import android.app.tare.EconomyManager;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.content.res.Resources;
33 import android.database.ContentObserver;
34 import android.net.Uri;
35 import android.os.Handler;
36 import android.os.Looper;
37 import android.provider.Settings;
38 import android.util.ArrayMap;
39 import android.util.ArraySet;
40 import android.util.KeyValueListParser;
41 import android.util.Slog;
42 
43 import com.android.settings.R;
44 
45 /**
46  * Takes an AlarmManager or JobScheduler csv string and parses it to get key:value pairs.
47  * This allows us to populate a dialog with the correct information.
48  */
49 public class TareFactorController {
50     private static final String TAG = "TareFactorController";
51 
52     private static TareFactorController sInstance;
53 
54     private static final int POLICY_ALARM_MANAGER = 0;
55     private static final int POLICY_JOB_SCHEDULER = 1;
56 
57     private final ContentResolver mContentResolver;
58     private final KeyValueListParser mParser = new KeyValueListParser(',');
59     private final Resources mResources;
60     private final ArrayMap<String, TareFactorData> mAlarmManagerMap = new ArrayMap<>();
61     private final ArrayMap<String, TareFactorData> mJobSchedulerMap = new ArrayMap<>();
62     private String mAlarmManagerConstants;
63     private String mJobSchedulerConstants;
64 
65     private final ArraySet<DataChangeListener> mDataChangeListeners = new ArraySet<>();
66 
TareFactorController(Context context)67     private TareFactorController(Context context) {
68         mContentResolver = context.getContentResolver();
69         mResources = context.getResources();
70 
71         ConfigObserver configObserver = new ConfigObserver(new Handler(Looper.getMainLooper()));
72         configObserver.start();
73 
74         mAlarmManagerConstants =
75                 Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS);
76         mJobSchedulerConstants =
77                 Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS);
78 
79         initAlarmManagerMap();
80         parseAlarmManagerGlobalSettings();
81 
82         initJobSchedulerMap();
83         parseJobSchedulerGlobalSettings();
84     }
85 
getInstance(Context context)86     static TareFactorController getInstance(Context context) {
87         synchronized (TareFactorController.class) {
88             if (sInstance == null) {
89                 sInstance = new TareFactorController(context.getApplicationContext());
90             }
91         }
92         return sInstance;
93     }
94 
95     /**
96      * Initialization for AlarmManager Map that sets a AM factor key to a title, default value, and
97      * policy type in a data object.
98      */
initAlarmManagerMap()99     private void initAlarmManagerMap() {
100         mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED,
101                 new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted),
102                         EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
103                         POLICY_ALARM_MANAGER));
104         mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
105                 new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app),
106                         EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES,
107                         POLICY_ALARM_MANAGER));
108         mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP,
109                 new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app),
110                         EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES,
111                         POLICY_ALARM_MANAGER));
112         mAlarmManagerMap.put(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE,
113                 new TareFactorData(mResources.getString(R.string.tare_max_satiated_balance),
114                         EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES,
115                         POLICY_ALARM_MANAGER));
116         mAlarmManagerMap.put(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT,
117                 new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit),
118                         EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES,
119                         POLICY_ALARM_MANAGER));
120         mAlarmManagerMap.put(EconomyManager.KEY_AM_HARD_CONSUMPTION_LIMIT,
121                 new TareFactorData(mResources.getString(R.string.tare_hard_consumption_limit),
122                         EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES,
123                         POLICY_ALARM_MANAGER));
124         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_INSTANT,
125                 new TareFactorData(mResources.getString(R.string.tare_top_activity),
126                         EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES,
127                         POLICY_ALARM_MANAGER));
128         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_ONGOING,
129                 new TareFactorData(mResources.getString(R.string.tare_top_activity),
130                         EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES,
131                         POLICY_ALARM_MANAGER));
132         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_MAX,
133                 new TareFactorData(mResources.getString(R.string.tare_top_activity),
134                         EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES,
135                         POLICY_ALARM_MANAGER));
136         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT,
137                 new TareFactorData(mResources.getString(R.string.tare_notification_seen),
138                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES,
139                         POLICY_ALARM_MANAGER));
140         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING,
141                 new TareFactorData(mResources.getString(R.string.tare_notification_seen),
142                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES,
143                         POLICY_ALARM_MANAGER));
144         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_MAX,
145                 new TareFactorData(mResources.getString(R.string.tare_notification_seen),
146                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES,
147                         POLICY_ALARM_MANAGER));
148         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT,
149                 new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min),
150                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT_CAKES,
151                         POLICY_ALARM_MANAGER));
152         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING,
153                 new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min),
154                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING_CAKES,
155                         POLICY_ALARM_MANAGER));
156         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX,
157                 new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min),
158                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX_CAKES,
159                         POLICY_ALARM_MANAGER));
160         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT,
161                 new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
162                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES,
163                         POLICY_ALARM_MANAGER));
164         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING,
165                 new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
166                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES,
167                         POLICY_ALARM_MANAGER));
168         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX,
169                 new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
170                         EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES,
171                         POLICY_ALARM_MANAGER));
172         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT,
173                 new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
174                         EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES,
175                         POLICY_ALARM_MANAGER));
176         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING,
177                 new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
178                         EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES,
179                         POLICY_ALARM_MANAGER));
180         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_MAX,
181                 new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
182                         EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES,
183                         POLICY_ALARM_MANAGER));
184         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT,
185                 new TareFactorData(mResources.getString(R.string.tare_other_interaction),
186                         EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES,
187                         POLICY_ALARM_MANAGER));
188         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_ONGOING,
189                 new TareFactorData(mResources.getString(R.string.tare_other_interaction),
190                         EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES,
191                         POLICY_ALARM_MANAGER));
192         mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX,
193                 new TareFactorData(mResources.getString(R.string.tare_other_interaction),
194                         EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES,
195                         POLICY_ALARM_MANAGER));
196         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP,
197                 new TareFactorData(mResources.getString(R.string.tare_wakeup_exact_idle),
198                         EconomyManager
199                                 .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES,
200                         POLICY_ALARM_MANAGER));
201         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP,
202                 new TareFactorData(mResources.getString(R.string.tare_wakeup_inexact_idle),
203                         EconomyManager
204                                 .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES,
205                         POLICY_ALARM_MANAGER));
206         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP,
207                 new TareFactorData(mResources.getString(R.string.tare_wakeup_exact),
208                         EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES,
209                         POLICY_ALARM_MANAGER));
210         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP,
211                 new TareFactorData(mResources.getString(R.string.tare_wakeup_inexact),
212                         EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES,
213                         POLICY_ALARM_MANAGER));
214         mAlarmManagerMap.put(
215                 EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP,
216                 new TareFactorData(mResources.getString(R.string.tare_nonwakeup_exact_idle),
217                         EconomyManager
218                                 .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES,
219                         POLICY_ALARM_MANAGER));
220         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP,
221                 new TareFactorData(mResources.getString(R.string.tare_nonwakeup_exact),
222                         EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES,
223                         POLICY_ALARM_MANAGER));
224         mAlarmManagerMap.put(
225                 EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP,
226                 new TareFactorData(mResources.getString(R.string.tare_nonwakeup_inexact_idle),
227                         DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES,
228                         POLICY_ALARM_MANAGER));
229         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP,
230                 new TareFactorData(mResources.getString(R.string.tare_nonwakeup_inexact),
231                         EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES,
232                         POLICY_ALARM_MANAGER));
233         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP,
234                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
235                         EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES,
236                         POLICY_ALARM_MANAGER));
237         mAlarmManagerMap.put(
238                 EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE,
239                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
240                         DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES,
241                         POLICY_ALARM_MANAGER));
242         mAlarmManagerMap.put(
243                 EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE,
244                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
245                         DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES,
246                         POLICY_ALARM_MANAGER));
247         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE,
248                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
249                         EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
250                         POLICY_ALARM_MANAGER));
251         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE,
252                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
253                         EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
254                         POLICY_ALARM_MANAGER));
255         mAlarmManagerMap.put(
256                 EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE,
257                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
258                         EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
259                         POLICY_ALARM_MANAGER));
260         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE,
261                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
262                         EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES,
263                         POLICY_ALARM_MANAGER));
264         mAlarmManagerMap.put(
265                 EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE,
266                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
267                         DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES,
268                         POLICY_ALARM_MANAGER));
269         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE,
270                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
271                         EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES,
272                         POLICY_ALARM_MANAGER));
273         mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE,
274                 new TareFactorData(mResources.getString(R.string.tare_alarm_clock),
275                         EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES,
276                         POLICY_ALARM_MANAGER));
277     }
278 
279     /**
280      * Initialization for JobScheduler Map that sets a JS factor key to a title, default value, and
281      * policy type in a data object.
282      */
initJobSchedulerMap()283     private void initJobSchedulerMap() {
284         mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
285                 new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted),
286                         EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
287                         POLICY_JOB_SCHEDULER));
288         mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
289                 new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app),
290                         EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES,
291                         POLICY_JOB_SCHEDULER));
292         mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP,
293                 new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app),
294                         EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES,
295                         POLICY_JOB_SCHEDULER));
296         mJobSchedulerMap.put(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE,
297                 new TareFactorData(mResources.getString(R.string.tare_max_satiated_balance),
298                         EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES,
299                         POLICY_JOB_SCHEDULER));
300         mJobSchedulerMap.put(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT,
301                 new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit),
302                         EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES,
303                         POLICY_JOB_SCHEDULER));
304         mJobSchedulerMap.put(EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT,
305                 new TareFactorData(mResources.getString(R.string.tare_hard_consumption_limit),
306                         EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES,
307                         POLICY_JOB_SCHEDULER));
308         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_INSTANT,
309                 new TareFactorData(mResources.getString(R.string.tare_top_activity),
310                         EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES,
311                         POLICY_JOB_SCHEDULER));
312         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_ONGOING,
313                 new TareFactorData(mResources.getString(R.string.tare_top_activity),
314                         EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES,
315                         POLICY_JOB_SCHEDULER));
316         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_MAX,
317                 new TareFactorData(mResources.getString(R.string.tare_top_activity),
318                         EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES,
319                         POLICY_JOB_SCHEDULER));
320         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT,
321                 new TareFactorData(mResources.getString(R.string.tare_notification_seen),
322                         EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES,
323                         POLICY_JOB_SCHEDULER));
324         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING,
325                 new TareFactorData(mResources.getString(R.string.tare_notification_seen),
326                         EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES,
327                         POLICY_JOB_SCHEDULER));
328         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_MAX,
329                 new TareFactorData(mResources.getString(R.string.tare_notification_seen),
330                         EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES,
331                         POLICY_JOB_SCHEDULER));
332         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT,
333                 new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
334                         EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES,
335                         POLICY_JOB_SCHEDULER));
336         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING,
337                 new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
338                         EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES,
339                         POLICY_JOB_SCHEDULER));
340         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX,
341                 new TareFactorData(mResources.getString(R.string.tare_notification_interaction),
342                         EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES,
343                         POLICY_JOB_SCHEDULER));
344         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT,
345                 new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
346                         EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES,
347                         POLICY_JOB_SCHEDULER));
348         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING,
349                 new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
350                         EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES,
351                         POLICY_JOB_SCHEDULER));
352         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_MAX,
353                 new TareFactorData(mResources.getString(R.string.tare_widget_interaction),
354                         EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES,
355                         POLICY_JOB_SCHEDULER));
356         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT,
357                 new TareFactorData(mResources.getString(R.string.tare_other_interaction),
358                         EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES,
359                         POLICY_JOB_SCHEDULER));
360         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_ONGOING,
361                 new TareFactorData(mResources.getString(R.string.tare_other_interaction),
362                         EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES,
363                         POLICY_JOB_SCHEDULER));
364         mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX,
365                 new TareFactorData(mResources.getString(R.string.tare_other_interaction),
366                         EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES,
367                         POLICY_JOB_SCHEDULER));
368         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_START_CTP,
369                 new TareFactorData(mResources.getString(R.string.tare_job_max_start),
370                         EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES,
371                         POLICY_JOB_SCHEDULER));
372         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_CTP,
373                 new TareFactorData(mResources.getString(R.string.tare_job_max_running),
374                         EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES,
375                         POLICY_JOB_SCHEDULER));
376         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_CTP,
377                 new TareFactorData(mResources.getString(R.string.tare_job_high_start),
378                         EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES,
379                         POLICY_JOB_SCHEDULER));
380         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP,
381                 new TareFactorData(mResources.getString(R.string.tare_job_high_running),
382                         EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES,
383                         POLICY_JOB_SCHEDULER));
384         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_CTP,
385                 new TareFactorData(mResources.getString(R.string.tare_job_default_start),
386                         EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES,
387                         POLICY_JOB_SCHEDULER));
388         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP,
389                 new TareFactorData(mResources.getString(R.string.tare_job_default_running),
390                         EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES,
391                         POLICY_JOB_SCHEDULER));
392         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_LOW_START_CTP,
393                 new TareFactorData(mResources.getString(R.string.tare_job_low_start),
394                         EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES,
395                         POLICY_JOB_SCHEDULER));
396         mJobSchedulerMap.put(
397                 EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_CTP,
398                 new TareFactorData(mResources.getString(R.string.tare_job_low_running),
399                         EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES,
400                         POLICY_JOB_SCHEDULER));
401         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_CTP,
402                 new TareFactorData(mResources.getString(R.string.tare_job_min_start),
403                         EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES,
404                         POLICY_JOB_SCHEDULER));
405         mJobSchedulerMap.put(
406                 EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_CTP,
407                 new TareFactorData(mResources.getString(R.string.tare_job_min_running),
408                         EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES,
409                         POLICY_JOB_SCHEDULER));
410         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP,
411                 new TareFactorData(mResources.getString(R.string.tare_job_timeout_penalty),
412                         EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES,
413                         POLICY_JOB_SCHEDULER));
414         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE,
415                 new TareFactorData(mResources.getString(R.string.tare_job_max_start),
416                         EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES,
417                         POLICY_JOB_SCHEDULER));
418         mJobSchedulerMap.put(
419                 EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE,
420                 new TareFactorData(mResources.getString(R.string.tare_job_max_running),
421                         EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES,
422                         POLICY_JOB_SCHEDULER));
423         mJobSchedulerMap.put(
424                 EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE,
425                 new TareFactorData(mResources.getString(R.string.tare_job_high_start),
426                         EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES,
427                         POLICY_JOB_SCHEDULER));
428         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE,
429                 new TareFactorData(mResources.getString(R.string.tare_job_high_running),
430                         EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES,
431                         POLICY_JOB_SCHEDULER));
432         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE,
433                 new TareFactorData(mResources.getString(R.string.tare_job_default_start),
434                         EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES,
435                         POLICY_JOB_SCHEDULER));
436         mJobSchedulerMap.put(
437                 EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE,
438                 new TareFactorData(mResources.getString(R.string.tare_job_default_running),
439                         EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES,
440                         POLICY_JOB_SCHEDULER));
441         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE,
442                 new TareFactorData(mResources.getString(R.string.tare_job_low_start),
443                         EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES,
444                         POLICY_JOB_SCHEDULER));
445         mJobSchedulerMap.put(
446                 EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE,
447                 new TareFactorData(mResources.getString(R.string.tare_job_low_running),
448                         EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES,
449                         POLICY_JOB_SCHEDULER));
450         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE,
451                 new TareFactorData(mResources.getString(R.string.tare_job_min_start),
452                         EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES,
453                         POLICY_JOB_SCHEDULER));
454         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE,
455                 new TareFactorData(mResources.getString(R.string.tare_job_min_running),
456                         EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES,
457                         POLICY_JOB_SCHEDULER));
458         mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE,
459                 new TareFactorData(mResources.getString(R.string.tare_job_timeout_penalty),
460                         EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES,
461                         POLICY_JOB_SCHEDULER));
462     }
463 
464     /**
465      * Parses the AM constant from Settings.Global to get to the current value.
466      */
parseAlarmManagerGlobalSettings()467     private void parseAlarmManagerGlobalSettings() {
468         parseSettingsIntoMap(mAlarmManagerConstants, mAlarmManagerMap);
469     }
470 
471     /**
472      * Parses the JS constant from Settings.Global to get to the current value.
473      */
parseJobSchedulerGlobalSettings()474     private void parseJobSchedulerGlobalSettings() {
475         parseSettingsIntoMap(mJobSchedulerConstants, mJobSchedulerMap);
476     }
477 
parseSettingsIntoMap(String constants, ArrayMap<String, TareFactorData> map)478     private void parseSettingsIntoMap(String constants, ArrayMap<String, TareFactorData> map) {
479         try {
480             mParser.setString(constants);
481         } catch (Exception e) {
482             Slog.e(TAG, "Bad string constants value", e);
483         }
484 
485         for (int i = map.size() - 1; i >= 0; --i) {
486             final String key = map.keyAt(i);
487             final TareFactorData data = map.valueAt(i);
488             data.currentValue = parseCreditValue(mParser.getString(key, null), data.defaultValue);
489         }
490     }
491 
492     @NonNull
getMap(int factorPolicy)493     private ArrayMap<String, TareFactorData> getMap(int factorPolicy) {
494         switch (factorPolicy) {
495             case POLICY_ALARM_MANAGER:
496                 return mAlarmManagerMap;
497             case POLICY_JOB_SCHEDULER:
498                 return mJobSchedulerMap;
499             default:
500                 throw new IllegalArgumentException("Invalid factor policy given");
501         }
502     }
503 
504     /**
505      * Takes a key and factor policy as input and grabs the title linked to it.
506      *
507      * @param key          the key of the factor you want to get the title of
508      * @param factorPolicy the policy you want the title of
509      */
getTitle(String key, int factorPolicy)510     private String getTitle(String key, int factorPolicy) {
511         final ArrayMap<String, TareFactorData> currentMap = getMap(factorPolicy);
512         return currentMap.get(key).title;
513     }
514 
515     /**
516      * Takes a key and factor policy as input and grabs the current value linked to it.
517      *
518      * @param key          the key of the factor you want to get the default value of
519      * @param factorPolicy the policy you want the current value of
520      */
getCurrentValue(String key, int factorPolicy)521     private long getCurrentValue(String key, int factorPolicy) {
522         final ArrayMap<String, TareFactorData> currentMap = getMap(factorPolicy);
523         return currentMap.get(key).currentValue;
524     }
525 
526     /**
527      * Takes a key as input and grabs the factor type linked to it.
528      *
529      * @param key the key of the factor you want to get the factor type of
530      */
getFactorType(String key)531     private int getFactorType(String key) {
532         ArrayMap<String, TareFactorData> currentMap;
533         if (mAlarmManagerMap.containsKey(key)) {
534             currentMap = mAlarmManagerMap;
535         } else if (mJobSchedulerMap.containsKey(key)) {
536             currentMap = mJobSchedulerMap;
537         } else {
538             throw new IllegalArgumentException("Couldn't link key '" + key + "' to a policy");
539         }
540         return currentMap.get(key).factorPolicy;
541     }
542 
getValue(String key)543     long getValue(String key) {
544         final int policy = getFactorType(key);
545         return getCurrentValue(key, policy);
546     }
547 
548     /**
549      * Takes a key,edited value, and factor policy as input and assigns the new edited value to
550      * be the new current value for that factors key.
551      *
552      * @param key          the key of the factor you want to get the default value of
553      * @param editedValue  the value entered by the user in the dialog
554      * @param factorPolicy policy being updated
555      */
updateValue(String key, long editedValue, int factorPolicy)556     public void updateValue(String key, long editedValue, int factorPolicy) {
557         final ArrayMap<String, TareFactorData> map = getMap(factorPolicy);
558 
559         final TareFactorData data = map.get(key);
560         if (data.currentValue == editedValue) {
561             return;
562         }
563         data.currentValue = editedValue;
564         rebuildPolicyConstants(factorPolicy);
565     }
566 
567     /**
568      * Iterates through the factor policy map for keys and current values to
569      * rebuild a current string that is then assigned to be the new global settings string.
570      *
571      * @param factorPolicy policy being updated
572      */
rebuildPolicyConstants(int factorPolicy)573     private void rebuildPolicyConstants(int factorPolicy) {
574         switch (factorPolicy) {
575             case POLICY_ALARM_MANAGER:
576                 writeConstantsToSettings(mAlarmManagerMap, TARE_ALARM_MANAGER_CONSTANTS);
577                 break;
578             case POLICY_JOB_SCHEDULER:
579                 writeConstantsToSettings(mJobSchedulerMap, TARE_JOB_SCHEDULER_CONSTANTS);
580                 break;
581         }
582     }
583 
writeConstantsToSettings(ArrayMap<String, TareFactorData> factorMap, String settingsKey)584     private void writeConstantsToSettings(ArrayMap<String, TareFactorData> factorMap,
585             String settingsKey) {
586         final StringBuilder constantsStringBuilder = new StringBuilder();
587 
588         for (int i = 0, size = factorMap.size(); i < size; ++i) {
589             final TareFactorData factor = factorMap.valueAt(i);
590             if (factor.currentValue == factor.defaultValue) {
591                 continue;
592             }
593 
594             if (constantsStringBuilder.length() > 0) {
595                 constantsStringBuilder.append(",");
596             }
597 
598             constantsStringBuilder
599                     .append(factorMap.keyAt(i))
600                     .append("=");
601             if (factor.currentValue % CAKE_IN_ARC == 0) {
602                 constantsStringBuilder
603                         .append(factor.currentValue / CAKE_IN_ARC)
604                         .append("A");
605             } else {
606                 constantsStringBuilder
607                         .append(factor.currentValue)
608                         .append("ck");
609             }
610         }
611 
612         Settings.Global.putString(mContentResolver, settingsKey, constantsStringBuilder.toString());
613     }
614 
615     /**
616      * Creates a dialog with the values linked to the key.
617      *
618      * @param key the key of the factor you want to get the default value of
619      */
createDialog(String key)620     public TareFactorDialogFragment createDialog(String key) {
621         int policy = getFactorType(key);
622         return new TareFactorDialogFragment(getTitle(key, policy), key,
623                 getCurrentValue(key, policy), policy, this);
624     }
625 
626     /**
627      * Data object that holds a title,default value,and current value for a key.
628      */
629     private static class TareFactorData {
630         public final String title;
631         public final long defaultValue;
632         public final int factorPolicy;
633         public long currentValue;
634 
TareFactorData(String title, long defaultValue, int factorPolicy)635         TareFactorData(String title, long defaultValue, int factorPolicy) {
636             this.title = title;
637             this.defaultValue = defaultValue;
638             this.factorPolicy = factorPolicy;
639             this.currentValue = defaultValue;
640         }
641     }
642 
643     interface DataChangeListener {
onDataChanged()644         void onDataChanged();
645     }
646 
registerListener(DataChangeListener listener)647     void registerListener(DataChangeListener listener) {
648         mDataChangeListeners.add(listener);
649     }
650 
unregisterListener(DataChangeListener listener)651     void unregisterListener(DataChangeListener listener) {
652         mDataChangeListeners.remove(listener);
653     }
654 
notifyListeners()655     void notifyListeners() {
656         for (int i = mDataChangeListeners.size() - 1; i >= 0; --i) {
657             mDataChangeListeners.valueAt(i).onDataChanged();
658         }
659     }
660 
661     private class ConfigObserver extends ContentObserver {
662 
ConfigObserver(Handler handler)663         ConfigObserver(Handler handler) {
664             super(handler);
665         }
666 
start()667         public void start() {
668             mContentResolver.registerContentObserver(
669                     Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS), false, this);
670             mContentResolver.registerContentObserver(
671                     Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS), false, this);
672         }
673 
674         @Override
onChange(boolean selfChange, Uri uri)675         public void onChange(boolean selfChange, Uri uri) {
676             if (uri.equals(Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS))) {
677                 mAlarmManagerConstants =
678                         Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS);
679                 parseAlarmManagerGlobalSettings();
680                 notifyListeners();
681             } else if (uri.equals(Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS))) {
682                 mJobSchedulerConstants =
683                         Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS);
684                 parseJobSchedulerGlobalSettings();
685                 notifyListeners();
686             }
687         }
688     }
689 }
690