/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.development.tare; import static android.app.tare.EconomyManager.CAKE_IN_ARC; import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES; import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES; import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES; import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES; import static android.app.tare.EconomyManager.parseCreditValue; import static android.provider.Settings.Global.TARE_ALARM_MANAGER_CONSTANTS; import static android.provider.Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS; import android.annotation.NonNull; import android.app.tare.EconomyManager; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.util.ArrayMap; import android.util.ArraySet; import android.util.KeyValueListParser; import android.util.Slog; import com.android.settings.R; /** * Takes an AlarmManager or JobScheduler csv string and parses it to get key:value pairs. * This allows us to populate a dialog with the correct information. */ public class TareFactorController { private static final String TAG = "TareFactorController"; private static TareFactorController sInstance; private static final int POLICY_ALARM_MANAGER = 0; private static final int POLICY_JOB_SCHEDULER = 1; private final ContentResolver mContentResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); private final Resources mResources; private final ArrayMap mAlarmManagerMap = new ArrayMap<>(); private final ArrayMap mJobSchedulerMap = new ArrayMap<>(); private String mAlarmManagerConstants; private String mJobSchedulerConstants; private final ArraySet mDataChangeListeners = new ArraySet<>(); private TareFactorController(Context context) { mContentResolver = context.getContentResolver(); mResources = context.getResources(); ConfigObserver configObserver = new ConfigObserver(new Handler(Looper.getMainLooper())); configObserver.start(); mAlarmManagerConstants = Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS); mJobSchedulerConstants = Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS); initAlarmManagerMap(); parseAlarmManagerGlobalSettings(); initJobSchedulerMap(); parseJobSchedulerGlobalSettings(); } static TareFactorController getInstance(Context context) { synchronized (TareFactorController.class) { if (sInstance == null) { sInstance = new TareFactorController(context.getApplicationContext()); } } return sInstance; } /** * Initialization for AlarmManager Map that sets a AM factor key to a title, default value, and * policy type in a data object. */ private void initAlarmManagerMap() { mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED, new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted), EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app), EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP, new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app), EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE, new TareFactorData(mResources.getString(R.string.tare_max_satiated_balance), EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT, new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit), EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_HARD_CONSUMPTION_LIMIT, new TareFactorData(mResources.getString(R.string.tare_hard_consumption_limit), EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_INSTANT, new TareFactorData(mResources.getString(R.string.tare_top_activity), EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_ONGOING, new TareFactorData(mResources.getString(R.string.tare_top_activity), EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_TOP_ACTIVITY_MAX, new TareFactorData(mResources.getString(R.string.tare_top_activity), EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT, new TareFactorData(mResources.getString(R.string.tare_notification_seen), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING, new TareFactorData(mResources.getString(R.string.tare_notification_seen), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_MAX, new TareFactorData(mResources.getString(R.string.tare_notification_seen), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT, new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING, new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX, new TareFactorData(mResources.getString(R.string.tare_notification_seen_15_min), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT, new TareFactorData(mResources.getString(R.string.tare_notification_interaction), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING, new TareFactorData(mResources.getString(R.string.tare_notification_interaction), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX, new TareFactorData(mResources.getString(R.string.tare_notification_interaction), EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT, new TareFactorData(mResources.getString(R.string.tare_widget_interaction), EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING, new TareFactorData(mResources.getString(R.string.tare_widget_interaction), EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_WIDGET_INTERACTION_MAX, new TareFactorData(mResources.getString(R.string.tare_widget_interaction), EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT, new TareFactorData(mResources.getString(R.string.tare_other_interaction), EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_ONGOING, new TareFactorData(mResources.getString(R.string.tare_other_interaction), EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX, new TareFactorData(mResources.getString(R.string.tare_other_interaction), EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_wakeup_exact_idle), EconomyManager .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_wakeup_inexact_idle), EconomyManager .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_wakeup_exact), EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_wakeup_inexact), EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put( EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_nonwakeup_exact_idle), EconomyManager .DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_nonwakeup_exact), EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put( EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_nonwakeup_inexact_idle), DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP, new TareFactorData(mResources.getString(R.string.tare_nonwakeup_inexact), EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put( EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put( EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put( EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put( EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); mAlarmManagerMap.put(EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_alarm_clock), EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES, POLICY_ALARM_MANAGER)); } /** * Initialization for JobScheduler Map that sets a JS factor key to a title, default value, and * policy type in a data object. */ private void initJobSchedulerMap() { mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED, new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted), EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP, new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app), EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP, new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app), EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE, new TareFactorData(mResources.getString(R.string.tare_max_satiated_balance), EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT, new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit), EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT, new TareFactorData(mResources.getString(R.string.tare_hard_consumption_limit), EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_INSTANT, new TareFactorData(mResources.getString(R.string.tare_top_activity), EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_ONGOING, new TareFactorData(mResources.getString(R.string.tare_top_activity), EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_TOP_ACTIVITY_MAX, new TareFactorData(mResources.getString(R.string.tare_top_activity), EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT, new TareFactorData(mResources.getString(R.string.tare_notification_seen), EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING, new TareFactorData(mResources.getString(R.string.tare_notification_seen), EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_SEEN_MAX, new TareFactorData(mResources.getString(R.string.tare_notification_seen), EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT, new TareFactorData(mResources.getString(R.string.tare_notification_interaction), EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING, new TareFactorData(mResources.getString(R.string.tare_notification_interaction), EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX, new TareFactorData(mResources.getString(R.string.tare_notification_interaction), EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT, new TareFactorData(mResources.getString(R.string.tare_widget_interaction), EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING, new TareFactorData(mResources.getString(R.string.tare_widget_interaction), EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_WIDGET_INTERACTION_MAX, new TareFactorData(mResources.getString(R.string.tare_widget_interaction), EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT, new TareFactorData(mResources.getString(R.string.tare_other_interaction), EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_ONGOING, new TareFactorData(mResources.getString(R.string.tare_other_interaction), EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX, new TareFactorData(mResources.getString(R.string.tare_other_interaction), EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_START_CTP, new TareFactorData(mResources.getString(R.string.tare_job_max_start), EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_CTP, new TareFactorData(mResources.getString(R.string.tare_job_max_running), EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_CTP, new TareFactorData(mResources.getString(R.string.tare_job_high_start), EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP, new TareFactorData(mResources.getString(R.string.tare_job_high_running), EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_CTP, new TareFactorData(mResources.getString(R.string.tare_job_default_start), EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP, new TareFactorData(mResources.getString(R.string.tare_job_default_running), EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_LOW_START_CTP, new TareFactorData(mResources.getString(R.string.tare_job_low_start), EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_CTP, new TareFactorData(mResources.getString(R.string.tare_job_low_running), EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_CTP, new TareFactorData(mResources.getString(R.string.tare_job_min_start), EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_CTP, new TareFactorData(mResources.getString(R.string.tare_job_min_running), EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP, new TareFactorData(mResources.getString(R.string.tare_job_timeout_penalty), EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_max_start), EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_max_running), EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_high_start), EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_high_running), EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_default_start), EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_default_running), EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_low_start), EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put( EconomyManager.KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_low_running), EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_min_start), EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_min_running), EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE, new TareFactorData(mResources.getString(R.string.tare_job_timeout_penalty), EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES, POLICY_JOB_SCHEDULER)); } /** * Parses the AM constant from Settings.Global to get to the current value. */ private void parseAlarmManagerGlobalSettings() { parseSettingsIntoMap(mAlarmManagerConstants, mAlarmManagerMap); } /** * Parses the JS constant from Settings.Global to get to the current value. */ private void parseJobSchedulerGlobalSettings() { parseSettingsIntoMap(mJobSchedulerConstants, mJobSchedulerMap); } private void parseSettingsIntoMap(String constants, ArrayMap map) { try { mParser.setString(constants); } catch (Exception e) { Slog.e(TAG, "Bad string constants value", e); } for (int i = map.size() - 1; i >= 0; --i) { final String key = map.keyAt(i); final TareFactorData data = map.valueAt(i); data.currentValue = parseCreditValue(mParser.getString(key, null), data.defaultValue); } } @NonNull private ArrayMap getMap(int factorPolicy) { switch (factorPolicy) { case POLICY_ALARM_MANAGER: return mAlarmManagerMap; case POLICY_JOB_SCHEDULER: return mJobSchedulerMap; default: throw new IllegalArgumentException("Invalid factor policy given"); } } /** * Takes a key and factor policy as input and grabs the title linked to it. * * @param key the key of the factor you want to get the title of * @param factorPolicy the policy you want the title of */ private String getTitle(String key, int factorPolicy) { final ArrayMap currentMap = getMap(factorPolicy); return currentMap.get(key).title; } /** * Takes a key and factor policy as input and grabs the current value linked to it. * * @param key the key of the factor you want to get the default value of * @param factorPolicy the policy you want the current value of */ private long getCurrentValue(String key, int factorPolicy) { final ArrayMap currentMap = getMap(factorPolicy); return currentMap.get(key).currentValue; } /** * Takes a key as input and grabs the factor type linked to it. * * @param key the key of the factor you want to get the factor type of */ private int getFactorType(String key) { ArrayMap currentMap; if (mAlarmManagerMap.containsKey(key)) { currentMap = mAlarmManagerMap; } else if (mJobSchedulerMap.containsKey(key)) { currentMap = mJobSchedulerMap; } else { throw new IllegalArgumentException("Couldn't link key '" + key + "' to a policy"); } return currentMap.get(key).factorPolicy; } long getValue(String key) { final int policy = getFactorType(key); return getCurrentValue(key, policy); } /** * Takes a key,edited value, and factor policy as input and assigns the new edited value to * be the new current value for that factors key. * * @param key the key of the factor you want to get the default value of * @param editedValue the value entered by the user in the dialog * @param factorPolicy policy being updated */ public void updateValue(String key, long editedValue, int factorPolicy) { final ArrayMap map = getMap(factorPolicy); final TareFactorData data = map.get(key); if (data.currentValue == editedValue) { return; } data.currentValue = editedValue; rebuildPolicyConstants(factorPolicy); } /** * Iterates through the factor policy map for keys and current values to * rebuild a current string that is then assigned to be the new global settings string. * * @param factorPolicy policy being updated */ private void rebuildPolicyConstants(int factorPolicy) { switch (factorPolicy) { case POLICY_ALARM_MANAGER: writeConstantsToSettings(mAlarmManagerMap, TARE_ALARM_MANAGER_CONSTANTS); break; case POLICY_JOB_SCHEDULER: writeConstantsToSettings(mJobSchedulerMap, TARE_JOB_SCHEDULER_CONSTANTS); break; } } private void writeConstantsToSettings(ArrayMap factorMap, String settingsKey) { final StringBuilder constantsStringBuilder = new StringBuilder(); for (int i = 0, size = factorMap.size(); i < size; ++i) { final TareFactorData factor = factorMap.valueAt(i); if (factor.currentValue == factor.defaultValue) { continue; } if (constantsStringBuilder.length() > 0) { constantsStringBuilder.append(","); } constantsStringBuilder .append(factorMap.keyAt(i)) .append("="); if (factor.currentValue % CAKE_IN_ARC == 0) { constantsStringBuilder .append(factor.currentValue / CAKE_IN_ARC) .append("A"); } else { constantsStringBuilder .append(factor.currentValue) .append("ck"); } } Settings.Global.putString(mContentResolver, settingsKey, constantsStringBuilder.toString()); } /** * Creates a dialog with the values linked to the key. * * @param key the key of the factor you want to get the default value of */ public TareFactorDialogFragment createDialog(String key) { int policy = getFactorType(key); return new TareFactorDialogFragment(getTitle(key, policy), key, getCurrentValue(key, policy), policy, this); } /** * Data object that holds a title,default value,and current value for a key. */ private static class TareFactorData { public final String title; public final long defaultValue; public final int factorPolicy; public long currentValue; TareFactorData(String title, long defaultValue, int factorPolicy) { this.title = title; this.defaultValue = defaultValue; this.factorPolicy = factorPolicy; this.currentValue = defaultValue; } } interface DataChangeListener { void onDataChanged(); } void registerListener(DataChangeListener listener) { mDataChangeListeners.add(listener); } void unregisterListener(DataChangeListener listener) { mDataChangeListeners.remove(listener); } void notifyListeners() { for (int i = mDataChangeListeners.size() - 1; i >= 0; --i) { mDataChangeListeners.valueAt(i).onDataChanged(); } } private class ConfigObserver extends ContentObserver { ConfigObserver(Handler handler) { super(handler); } public void start() { mContentResolver.registerContentObserver( Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS), false, this); mContentResolver.registerContentObserver( Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS), false, this); } @Override public void onChange(boolean selfChange, Uri uri) { if (uri.equals(Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS))) { mAlarmManagerConstants = Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS); parseAlarmManagerGlobalSettings(); notifyListeners(); } else if (uri.equals(Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS))) { mJobSchedulerConstants = Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS); parseJobSchedulerGlobalSettings(); notifyListeners(); } } } }