Merge "Use FakeFeatureFactory in SafetySourceBroadcastReceiverTest" into tm-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9d868cb..917c666 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13731,18 +13731,26 @@
translate "maximum balance when device is fully charged" instead. Balance is the same meaning as
having money in a bank account. Balance in our feature is the amount of Android Resource Credits
an app can have. Android Resource Credits are a form of payment used by apps to be able to
- perform tasks. [CHAR LIMIT=40]-->
+ perform tasks. [CHAR LIMIT=80]-->
<string name="tare_max_satiated_balance">Maximum Satiated Balance</string>
- <!-- Title for the TARE policy factor that determines the maximum credits in circulation between
- all the apps [CHAR LIMIT=40]-->
- <string name="tare_max_circulation">Maximum Circulation</string>
- <!-- Title for the TARE policy factor that determines the minimum credits an app can have in one
- battery life cycle. Satiated means battery is fully charged; If this is not easily translatable,
- translate "minimum balance when device is fully charged" instead. Balance is the same meaning as
- having money in a bank account. Balance in our feature is the amount of Android Resource Credits
- an app can have. Android Resource Credits are a form of payment used by apps to be able to
- perform tasks. [CHAR LIMIT=40]-->
- <string name="tare_min_satiated_balance">Minimum Satiated Balance</string>
+ <!-- Title for the TARE policy factors that affect how many credits an app may have. Balance
+ in this context is the same as "bank balance" or "account balance" (ie. how much "money" may be
+ in a bank account). [CHAR LIMIT=55]-->
+ <string name="tare_balances">Balances</string>
+ <!-- Title for the TARE section to modify consumption limits. "Consumption" refers to the idea
+ using resources that are not replenished. [CHAR LIMIT=55]-->
+ <string name="tare_consumption_limits">Consumption Limits</string>
+ <!-- Title for the TARE policy factor that determines the initial maximum amount of credits that
+ can be consumed by all the apps [CHAR LIMIT=80]-->
+ <string name="tare_initial_consumption_limit">Initial Consumption Limit</string>
+ <!-- Title for the TARE policy factor that determines the maximum consumption limit the system
+ can have [CHAR LIMIT=80]-->
+ <string name="tare_hard_consumption_limit">Maximum Consumption Limit</string>
+ <!-- Titles for the consumption limits factors. [CHAR LIMIT=40]-->
+ <string-array name="tare_consumption_limit_subfactors" translatable="false">
+ <item>@string/tare_initial_consumption_limit</item>
+ <item>@string/tare_hard_consumption_limit</item>
+ </string-array>
<!-- Title for the various modifiers that alter the cost of TARE tasks based on battery status
(charging, power save mode, etc.) [CHAR LIMIT=40]-->
<string name="tare_modifiers">Modifiers</string>
@@ -13778,14 +13786,6 @@
<string name="tare_nonwakeup_inexact" translatable="false">Inexact NonWakeup Alarm</string>
<!-- Title for the AlarmClock alarm set via AlarmManager.setAlarmClock() [CHAR LIMIT=50]-->
<string name="tare_alarm_clock" translatable="false">AlarmClock</string>
- <!-- Exempted apps are those apps exempted from most power saving features. [CHAR LIMIT=50]-->
- <string name="tare_exempted">Exempted</string>
- <!-- A headless system app is a preinstalled app that does not have any activities/UI that the
- user can interact with. [CHAR LIMIT=50]-->
- <string name="tare_headless_app">Headless System App</string>
- <!-- Other apps are those apps interacted with by users that are not exempted or headless
- system apps. [CHAR LIMIT=50]-->
- <string name="tare_other_app">Other App</string>
<!-- Top activity means an app is in the TOP android process state and is thus visible to the
user[CHAR LIMIT=50]-->
<string name="tare_top_activity">Top Activity</string>
@@ -13842,12 +13842,29 @@
<!-- Title for the penalty an app receives for letting a job use the maximum execution time and
time out [CHAR LIMIT=50]-->
<string name="tare_job_timeout_penalty">Job Timeout Penalty</string>
+ <!-- Title for the TARE factor that determines the minimum credits an app should have when the
+ device is fully charged. "Satiated" in this context means that the battery is fully charged.
+ Balance is the same meaning as having money in a bank account.
+ Exempted apps are those apps exempted from most power saving features. [CHAR LIMIT=80]-->
+ <string name="tare_min_balance_exempted">Minimum Satiated Balance (Exempted)</string>
+ <!-- Title for the TARE factor that determines the minimum credits an app should have when the
+ device is fully charged. "Satiated" in this context means that the battery is fully charged.
+ Balance is the same meaning as having money in a bank account.
+ A headless system app is a preinstalled app that does not have any activities/UI that the
+ user can interact with. [CHAR LIMIT=80]-->
+ <string name="tare_min_balance_headless_app">Minimum Satiated Balance (Headless System App)</string>
+ <!-- Title for the TARE factor that determines the minimum credits an app should have when the
+ device is fully charged. "Satiated" in this context means that the battery is fully charged.
+ Balance is the same meaning as having money in a bank account.
+ Remaining apps are those apps that don't fit into predefined categories. [CHAR LIMIT=80]-->
+ <string name="tare_min_balance_other_app">Minimum Satiated Balance (Remaining Apps)</string>
<!-- Titles for the minimum satiated credit balances for different types of apps
(per battery cycle). Satiated means battery is fully charged. [CHAR LIMIT=40]-->
- <string-array name="tare_min_satiated_balance_subfactors" translatable="false">
- <item>@string/tare_exempted</item>
- <item>@string/tare_headless_app</item>
- <item>@string/tare_other_app</item>
+ <string-array name="tare_app_balance_subfactors" translatable="false">
+ <item>@string/tare_max_satiated_balance</item>
+ <item>@string/tare_min_balance_exempted</item>
+ <item>@string/tare_min_balance_headless_app</item>
+ <item>@string/tare_min_balance_other_app</item>
</string-array>
<!-- Various modifier subfactors that alter the cost of TARE tasks depending on what battery
state the device is in [CHAR LIMIT=50]-->
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index e485d1e..ae24168 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -34,6 +34,9 @@
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.net.EthernetManager;
+import android.net.EthernetManager.InterfaceState;
+import android.net.EthernetManager.Role;
+import android.net.IpConfiguration;
import android.net.TetheringManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -42,10 +45,10 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
-import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
@@ -62,6 +65,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -97,7 +101,6 @@
private BroadcastReceiver mTetherChangeReceiver;
private String[] mBluetoothRegexs;
- private String mEthernetRegex;
private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
private Handler mHandler = new Handler();
@@ -106,6 +109,7 @@
private EthernetManager mEm;
private TetheringEventCallback mTetheringEventCallback;
private EthernetListener mEthernetListener;
+ private final HashSet<String> mAvailableInterfaces = new HashSet<>();
private WifiTetherPreferenceController mWifiTetherPreferenceController;
@@ -172,17 +176,17 @@
mDataSaverBackend.addListener(this);
mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- mEm = (EthernetManager) getSystemService(Context.ETHERNET_SERVICE);
mTm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
+ // Some devices do not have available EthernetManager. In that case getSystemService will
+ // return null.
+ mEm = mContext.getSystemService(EthernetManager.class);
mUsbRegexs = mTm.getTetherableUsbRegexs();
mBluetoothRegexs = mTm.getTetherableBluetoothRegexs();
- mEthernetRegex = mContext.getResources().getString(
- com.android.internal.R.string.config_ethernet_iface_regex);
final boolean usbAvailable = mUsbRegexs.length != 0;
final boolean bluetoothAvailable = adapter != null && mBluetoothRegexs.length != 0;
- final boolean ethernetAvailable = !TextUtils.isEmpty(mEthernetRegex);
+ final boolean ethernetAvailable = (mEm != null);
if (!usbAvailable || Utils.isMonkeyRunning()) {
getPreferenceScreen().removePreference(mUsbTether);
@@ -330,7 +334,7 @@
mEthernetListener = new EthernetListener();
if (mEm != null)
- mEm.addListener(mEthernetListener, r -> mHandler.post(r));
+ mEm.addInterfaceStateListener(r -> mHandler.post(r), mEthernetListener);
updateUsbState();
updateBluetoothAndEthernetState();
@@ -346,11 +350,10 @@
getActivity().unregisterReceiver(mTetherChangeReceiver);
mTm.unregisterTetheringEventCallback(mTetheringEventCallback);
if (mEm != null)
- mEm.removeListener(mEthernetListener);
+ mEm.removeInterfaceStateListener(mEthernetListener);
mTetherChangeReceiver = null;
mStartTetheringCallback = null;
mTetheringEventCallback = null;
- mEthernetListener = null;
}
@VisibleForTesting
@@ -483,11 +486,11 @@
boolean isTethered = false;
for (String s : available) {
- if (s.matches(mEthernetRegex)) isAvailable = true;
+ if (mAvailableInterfaces.contains(s)) isAvailable = true;
}
for (String s : tethered) {
- if (s.matches(mEthernetRegex)) isTethered = true;
+ if (mAvailableInterfaces.contains(s)) isTethered = true;
}
if (DEBUG) {
@@ -498,7 +501,7 @@
if (isTethered) {
mEthernetTether.setEnabled(!mDataSaverEnabled);
mEthernetTether.setChecked(true);
- } else if (isAvailable || (mEm != null && mEm.isAvailable())) {
+ } else if (mAvailableInterfaces.size() > 0) {
mEthernetTether.setEnabled(!mDataSaverEnabled);
mEthernetTether.setChecked(false);
} else {
@@ -600,9 +603,9 @@
keys.add(KEY_ENABLE_BLUETOOTH_TETHERING);
}
- final boolean ethernetAvailable = !TextUtils.isEmpty(
- context.getResources().getString(
- com.android.internal.R.string.config_ethernet_iface_regex));
+ final EthernetManager em =
+ context.getSystemService(EthernetManager.class);
+ final boolean ethernetAvailable = (em != null);
if (!ethernetAvailable) {
keys.add(KEY_ENABLE_ETHERNET_TETHERING);
}
@@ -646,9 +649,15 @@
}
}
- private final class EthernetListener implements EthernetManager.Listener {
- public void onAvailabilityChanged(String iface, boolean isAvailable) {
- mHandler.post(() -> updateBluetoothAndEthernetState());
+ private final class EthernetListener implements EthernetManager.InterfaceStateListener {
+ public void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
+ @Role int role, @NonNull IpConfiguration configuration) {
+ if (state == EthernetManager.STATE_LINK_UP) {
+ mAvailableInterfaces.add(iface);
+ } else {
+ mAvailableInterfaces.remove(iface);
+ }
+ updateBluetoothAndEthernetState();
}
}
}
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceController.java
index c56f630..8e2d3d4 100644
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceController.java
@@ -25,6 +25,7 @@
import com.android.settings.applications.AppStateBaseBridge;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.notification.NotificationBackend;
+import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
@@ -128,7 +129,7 @@
CheckBoxPreference preference = mScreen.findPreference(prefKey);
if (preference == null) {
preference = new CheckBoxPreference(mScreen.getContext());
- preference.setIcon(entry.icon);
+ preference.setIcon(AppUtils.getIcon(mContext, entry));
preference.setTitle(entry.label);
preference.setKey(prefKey);
mScreen.addPreference(preference);
diff --git a/src/com/android/settings/development/tare/AlarmManagerFragment.java b/src/com/android/settings/development/tare/AlarmManagerFragment.java
index dbc4e58..fe76b12 100644
--- a/src/com/android/settings/development/tare/AlarmManagerFragment.java
+++ b/src/com/android/settings/development/tare/AlarmManagerFragment.java
@@ -15,17 +15,16 @@
*/
package com.android.settings.development.tare;
+import android.annotation.Nullable;
import android.app.Fragment;
+import android.app.tare.EconomyManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
-import android.widget.TextView;
-import android.widget.Toast;
import com.android.settings.R;
@@ -33,130 +32,96 @@
* Creates the AlarmManager fragment to display all the AlarmManager factors
* when the AlarmManager policy is chosen in the dropdown TARE menu.
*/
-public class AlarmManagerFragment extends Fragment {
+public class AlarmManagerFragment extends Fragment implements
+ TareFactorController.DataChangeListener {
+
+ private TareFactorController mFactorController;
+
+ private TareFactorExpandableListAdapter mExpandableListAdapter;
+
+ private String[] mGroups;
+ private String[][] mChildren;
+ private String[][] mKeys;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mFactorController = TareFactorController.getInstance(getContext());
+ populateArrays();
+ }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tare_policy_fragment, null);
ExpandableListView elv = (ExpandableListView) v.findViewById(R.id.factor_list);
- final SavedTabsListAdapter expListAdapter = new SavedTabsListAdapter();
+ mExpandableListAdapter = new TareFactorExpandableListAdapter(
+ mFactorController, LayoutInflater.from(getActivity()), mGroups, mChildren, mKeys);
elv.setGroupIndicator(null);
- elv.setAdapter(expListAdapter);
+ elv.setAdapter(mExpandableListAdapter);
elv.setOnChildClickListener(new OnChildClickListener() {
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
- final String selected =
- (String) expListAdapter.getChild(groupPosition, childPosition);
- Toast.makeText(getActivity(), selected, Toast.LENGTH_SHORT).show();
+ final String key = mExpandableListAdapter.getKey(groupPosition, childPosition);
+ mFactorController.createDialog(key).show(getFragmentManager(), key);
return true;
}
});
return v;
}
- /**
- * Creates the expandable list containing all AlarmManager factors within the
- * AlarmManager fragment.
- */
- public class SavedTabsListAdapter extends BaseExpandableListAdapter {
+ @Override
+ public void onStart() {
+ super.onStart();
+ mFactorController.registerListener(this);
+ }
- private final LayoutInflater mInflater;
- private Resources mResources = getActivity().getResources();
+ @Override
+ public void onStop() {
+ mFactorController.unregisterListener(this);
+ super.onStop();
+ }
- private String[] mGroups = {
- mResources.getString(R.string.tare_max_circulation),
- mResources.getString(R.string.tare_max_satiated_balance),
- mResources.getString(R.string.tare_min_satiated_balance),
- mResources.getString(R.string.tare_modifiers),
- mResources.getString(R.string.tare_actions),
- mResources.getString(R.string.tare_rewards)
+ @Override
+ public void onDataChanged() {
+ mExpandableListAdapter.notifyDataSetChanged();
+ }
+
+ private void populateArrays() {
+ final Resources resources = getResources();
+
+ mGroups = new String[]{
+ resources.getString(R.string.tare_consumption_limits),
+ resources.getString(R.string.tare_balances),
+ // resources.getString(R.string.tare_modifiers),
+ // resources.getString(R.string.tare_actions),
+ // resources.getString(R.string.tare_rewards)
};
- /*
- * First two are empty arrays because the first two factors have no subfactors (no
- * children).
- */
- private String[][] mChildren = {
- {},
- {},
- mResources.getStringArray(R.array.tare_min_satiated_balance_subfactors),
- mResources.getStringArray(R.array.tare_modifiers_subfactors),
- mResources.getStringArray(R.array.tare_alarm_manager_actions),
- mResources.getStringArray(R.array.tare_rewards_subfactors)
+ mChildren = new String[][]{
+ resources.getStringArray(R.array.tare_consumption_limit_subfactors),
+ resources.getStringArray(R.array.tare_app_balance_subfactors),
+ // TODO: support
+ // resources.getStringArray(R.array.tare_modifiers_subfactors),
+ // resources.getStringArray(R.array.tare_alarm_manager_actions),
+ // resources.getStringArray(R.array.tare_rewards_subfactors)
};
- public SavedTabsListAdapter() {
- mInflater = LayoutInflater.from(getActivity());
- }
-
- @Override
- public int getGroupCount() {
- return mGroups.length;
- }
-
- @Override
- public int getChildrenCount(int groupPosition) {
- return mChildren[groupPosition].length;
- }
-
- @Override
- public Object getGroup(int groupPosition) {
- return mGroups[groupPosition];
- }
-
- @Override
- public Object getChild(int groupPosition, int childPosition) {
- return mChildren[groupPosition][childPosition];
- }
-
- @Override
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- @Override
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
- }
- TextView factor = (TextView) convertView.findViewById(android.R.id.text1);
- factor.setText(getGroup(groupPosition).toString());
- return convertView;
- }
-
- @Override
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- // Here a custom child item is used instead of android.R.simple_list_item_2 because it
- // is more customizable for this specific UI
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.tare_child_item, null);
- }
- TextView factor = (TextView) convertView.findViewById(R.id.factor);
- TextView value = (TextView) convertView.findViewById(R.id.factor_number);
-
- // TODO: Replace these hardcoded values with either default or user inputted TARE values
- factor.setText(getChild(groupPosition, childPosition).toString());
- value.setText("500");
-
- return convertView;
- }
-
- @Override
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
+ mKeys = new String[][]{
+ {
+ EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT,
+ EconomyManager.KEY_AM_HARD_CONSUMPTION_LIMIT
+ },
+ {
+ EconomyManager.KEY_AM_MAX_SATIATED_BALANCE,
+ EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED,
+ EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
+ EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP
+ },
+ // {},
+ // {},
+ // {},
+ };
}
}
diff --git a/src/com/android/settings/development/tare/DropdownActivity.java b/src/com/android/settings/development/tare/DropdownActivity.java
index 55f1fec..66b57dd 100644
--- a/src/com/android/settings/development/tare/DropdownActivity.java
+++ b/src/com/android/settings/development/tare/DropdownActivity.java
@@ -43,7 +43,6 @@
static final int POLICY_JOB_SCHEDULER = 1;
private static final int DEFAULT_POLICY = POLICY_ALARM_MANAGER;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/src/com/android/settings/development/tare/JobSchedulerFragment.java b/src/com/android/settings/development/tare/JobSchedulerFragment.java
index 5a7f4a9..1c6598c 100644
--- a/src/com/android/settings/development/tare/JobSchedulerFragment.java
+++ b/src/com/android/settings/development/tare/JobSchedulerFragment.java
@@ -15,17 +15,16 @@
*/
package com.android.settings.development.tare;
+import android.annotation.Nullable;
import android.app.Fragment;
+import android.app.tare.EconomyManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
-import android.widget.TextView;
-import android.widget.Toast;
import com.android.settings.R;
@@ -33,131 +32,97 @@
* Creates the JobScheduler fragment to display all the JobScheduler factors
* when the JobScheduler policy is chosen in the dropdown TARE menu.
*/
-public class JobSchedulerFragment extends Fragment {
+public class JobSchedulerFragment extends Fragment implements
+ TareFactorController.DataChangeListener {
+
+ private TareFactorController mFactorController;
+
+ private TareFactorExpandableListAdapter mExpandableListAdapter;
+
+ private String[] mGroups;
+ private String[][] mChildren;
+ private String[][] mKeys;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mFactorController = TareFactorController.getInstance(getContext());
+ populateArrays();
+ }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.tare_policy_fragment, null);
ExpandableListView elv = (ExpandableListView) v.findViewById(R.id.factor_list);
- final SavedTabsListAdapter expListAdapter = new SavedTabsListAdapter();
+ mExpandableListAdapter = new TareFactorExpandableListAdapter(
+ mFactorController, LayoutInflater.from(getActivity()), mGroups, mChildren, mKeys);
elv.setGroupIndicator(null);
- elv.setAdapter(expListAdapter);
+ elv.setAdapter(mExpandableListAdapter);
elv.setOnChildClickListener(new OnChildClickListener() {
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
- final String selected =
- (String) expListAdapter.getChild(groupPosition, childPosition);
- Toast.makeText(getActivity(), selected, Toast.LENGTH_SHORT)
- .show();
+ final String key = mExpandableListAdapter.getKey(groupPosition, childPosition);
+ mFactorController.createDialog(key).show(getFragmentManager(), key);
return true;
}
});
+
return v;
}
- /**
- * Creates the expandable list containing all JobScheduler factors within the
- * JobScheduler fragment.
- */
- public class SavedTabsListAdapter extends BaseExpandableListAdapter {
+ @Override
+ public void onStart() {
+ super.onStart();
+ mFactorController.registerListener(this);
+ }
- private final LayoutInflater mInflater;
- private Resources mResources = getActivity().getResources();
+ @Override
+ public void onStop() {
+ mFactorController.unregisterListener(this);
+ super.onStop();
+ }
- private String[] mGroups = {
- mResources.getString(R.string.tare_max_circulation),
- mResources.getString(R.string.tare_max_satiated_balance),
- mResources.getString(R.string.tare_min_satiated_balance),
- mResources.getString(R.string.tare_modifiers),
- mResources.getString(R.string.tare_actions),
- mResources.getString(R.string.tare_rewards)
+ @Override
+ public void onDataChanged() {
+ mExpandableListAdapter.notifyDataSetChanged();
+ }
+
+ private void populateArrays() {
+ final Resources resources = getResources();
+
+ mGroups = new String[]{
+ resources.getString(R.string.tare_consumption_limits),
+ resources.getString(R.string.tare_balances),
+ // mResources.getString(R.string.tare_modifiers),
+ // mResources.getString(R.string.tare_actions),
+ // mResources.getString(R.string.tare_rewards)
};
- /*
- * First two are empty arrays because the first two factors have no subfactors (no
- * children).
- */
- private String[][] mChildren = {
- {},
- {},
- mResources.getStringArray(R.array.tare_min_satiated_balance_subfactors),
- mResources.getStringArray(R.array.tare_modifiers_subfactors),
- mResources.getStringArray(R.array.tare_job_scheduler_actions),
- mResources.getStringArray(R.array.tare_rewards_subfactors)
+ mChildren = new String[][]{
+ resources.getStringArray(R.array.tare_consumption_limit_subfactors),
+ resources.getStringArray(R.array.tare_app_balance_subfactors),
+ // TODO: support
+ // mResources.getStringArray(R.array.tare_modifiers_subfactors),
+ // mResources.getStringArray(R.array.tare_job_scheduler_actions),
+ // mResources.getStringArray(R.array.tare_rewards_subfactors)
};
- public SavedTabsListAdapter() {
- mInflater = LayoutInflater.from(getActivity());
- }
-
- @Override
- public int getGroupCount() {
- return mGroups.length;
- }
-
- @Override
- public int getChildrenCount(int groupPosition) {
- return mChildren[groupPosition].length;
- }
-
- @Override
- public Object getGroup(int groupPosition) {
- return mGroups[groupPosition];
- }
-
- @Override
- public Object getChild(int groupPosition, int childPosition) {
- return mChildren[groupPosition][childPosition];
- }
-
- @Override
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- @Override
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- if (convertView == null) {
- convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
- }
- TextView factor = (TextView) convertView.findViewById(android.R.id.text1);
- factor.setText(getGroup(groupPosition).toString());
- return convertView;
- }
-
- @Override
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- // Here a custom child item is used instead of android.R.simple_list_item_2 because it
- // is more customizable for this specific UI
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.tare_child_item, null);
- }
- TextView factor = (TextView) convertView.findViewById(R.id.factor);
- TextView value = (TextView) convertView.findViewById(R.id.factor_number);
-
- // TODO: Replace these hardcoded values with either default or user inputted TARE values
- factor.setText(getChild(groupPosition, childPosition).toString());
- value.setText("500");
-
- return convertView;
- }
-
- @Override
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
+ mKeys = new String[][]{
+ {
+ EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT,
+ EconomyManager.KEY_JS_HARD_CONSUMPTION_LIMIT
+ },
+ {
+ EconomyManager.KEY_JS_MAX_SATIATED_BALANCE,
+ EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
+ EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
+ EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP
+ },
+ // {},
+ // {},
+ // {},
+ };
}
}
diff --git a/src/com/android/settings/development/tare/TareFactorController.java b/src/com/android/settings/development/tare/TareFactorController.java
index 7e9f314..b9f813d 100644
--- a/src/com/android/settings/development/tare/TareFactorController.java
+++ b/src/com/android/settings/development/tare/TareFactorController.java
@@ -16,12 +16,21 @@
package com.android.settings.development.tare;
+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;
@@ -34,6 +43,8 @@
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;
@@ -45,15 +56,19 @@
private String mAlarmManagerConstants;
private String mJobSchedulerConstants;
- public TareFactorController(Context context) {
+ private final ArraySet<DataChangeListener> mDataChangeListeners = new ArraySet<>();
+
+ private TareFactorController(Context context) {
mContentResolver = context.getContentResolver();
mResources = context.getResources();
- mAlarmManagerConstants = Settings.Global
- .getString(mContentResolver, Settings.Global.TARE_ALARM_MANAGER_CONSTANTS);
+ ConfigObserver configObserver = new ConfigObserver(new Handler(Looper.getMainLooper()));
+ configObserver.start();
- mJobSchedulerConstants = Settings.Global
- .getString(mContentResolver, Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS);
+ mAlarmManagerConstants =
+ Settings.Global.getString(mContentResolver, TARE_ALARM_MANAGER_CONSTANTS);
+ mJobSchedulerConstants =
+ Settings.Global.getString(mContentResolver, TARE_JOB_SCHEDULER_CONSTANTS);
initAlarmManagerMap();
parseAlarmManagerGlobalSettings();
@@ -62,21 +77,30 @@
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_satiated_balance),
+ new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted),
EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED,
POLICY_ALARM_MANAGER));
mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
- new TareFactorData(mResources.getString(R.string.tare_headless_app),
+ new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app),
EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
POLICY_ALARM_MANAGER));
mAlarmManagerMap.put(EconomyManager.KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP,
- new TareFactorData(mResources.getString(R.string.tare_other_app),
+ new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app),
EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP,
POLICY_ALARM_MANAGER));
mAlarmManagerMap.put(EconomyManager.KEY_AM_MAX_SATIATED_BALANCE,
@@ -84,9 +108,13 @@
EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE,
POLICY_ALARM_MANAGER));
mAlarmManagerMap.put(EconomyManager.KEY_AM_INITIAL_CONSUMPTION_LIMIT,
- new TareFactorData(mResources.getString(R.string.tare_max_circulation),
+ new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit),
EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT,
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,
+ 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,
@@ -250,15 +278,15 @@
*/
private void initJobSchedulerMap() {
mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
- new TareFactorData(mResources.getString(R.string.tare_min_satiated_balance),
+ new TareFactorData(mResources.getString(R.string.tare_min_balance_exempted),
EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED,
POLICY_JOB_SCHEDULER));
mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
- new TareFactorData(mResources.getString(R.string.tare_headless_app),
+ new TareFactorData(mResources.getString(R.string.tare_min_balance_headless_app),
EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP,
POLICY_JOB_SCHEDULER));
mJobSchedulerMap.put(EconomyManager.KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP,
- new TareFactorData(mResources.getString(R.string.tare_other_app),
+ new TareFactorData(mResources.getString(R.string.tare_min_balance_other_app),
EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP,
POLICY_JOB_SCHEDULER));
mJobSchedulerMap.put(EconomyManager.KEY_JS_MAX_SATIATED_BALANCE,
@@ -266,9 +294,13 @@
EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE,
POLICY_JOB_SCHEDULER));
mJobSchedulerMap.put(EconomyManager.KEY_JS_INITIAL_CONSUMPTION_LIMIT,
- new TareFactorData(mResources.getString(R.string.tare_max_circulation),
+ new TareFactorData(mResources.getString(R.string.tare_initial_consumption_limit),
EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT,
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,
+ 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,
@@ -408,8 +440,7 @@
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,
+ EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE,
POLICY_JOB_SCHEDULER));
mJobSchedulerMap.put(EconomyManager.KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE,
new TareFactorData(mResources.getString(R.string.tare_job_min_start),
@@ -425,103 +456,65 @@
POLICY_JOB_SCHEDULER));
}
-
- /**
- * Takes a key and factor policy as input and grabs the default 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 default value of
- */
- private int getDefaultValue(String key, int factorPolicy) {
- ArrayMap<String, TareFactorData> currentMap;
- switch (factorPolicy) {
- case POLICY_ALARM_MANAGER:
- currentMap = mAlarmManagerMap;
- break;
- case POLICY_JOB_SCHEDULER:
- currentMap = mJobSchedulerMap;
- break;
- default:
- throw new IllegalArgumentException("Invalid factor policy given");
- }
- return currentMap.get(key).defaultValue;
- }
-
/**
* Parses the AM constant from Settings.Global to get to the current value.
*/
private void parseAlarmManagerGlobalSettings() {
- try {
- mParser.setString(mAlarmManagerConstants);
- } catch (Exception e) {
- Slog.e(TAG, "Bad value string constants", e);
- }
- int size = mParser.size();
-
- for (int i = 0; i < size - 1; i++) {
- String key = mParser.keyAt(i);
- TareFactorData data = mAlarmManagerMap.get(key);
- data.currentValue = mParser.getInt(key, getDefaultValue(key, getFactorType(key)));
- }
+ parseSettingsIntoMap(mAlarmManagerConstants, mAlarmManagerMap);
}
/**
* Parses the JS constant from Settings.Global to get to the current value.
*/
private void parseJobSchedulerGlobalSettings() {
- try {
- mParser.setString(mJobSchedulerConstants);
- } catch (Exception e) {
- Slog.e(TAG, "Bad value string constants", e);
- }
- int size = mParser.size();
+ parseSettingsIntoMap(mJobSchedulerConstants, mJobSchedulerMap);
+ }
- for (int i = 0; i < size - 1; i++) {
- String key = mParser.keyAt(i);
- TareFactorData data = mJobSchedulerMap.get(key);
- data.currentValue = mParser.getInt(key, getDefaultValue(key, getFactorType(key)));
+ private void parseSettingsIntoMap(String constants, ArrayMap<String, TareFactorData> 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 = mParser.getInt(key, data.defaultValue);
+ }
+ }
+
+ @NonNull
+ private ArrayMap<String, TareFactorData> 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 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) {
- ArrayMap<String, TareFactorData> currentMap;
- switch (factorPolicy) {
- case POLICY_ALARM_MANAGER:
- currentMap = mAlarmManagerMap;
- break;
- case POLICY_JOB_SCHEDULER:
- currentMap = mJobSchedulerMap;
- break;
- default:
- throw new IllegalArgumentException("Invalid factor policy given");
- }
+ final ArrayMap<String, TareFactorData> 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 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 int getCurrentValue(String key, int factorPolicy) {
- ArrayMap<String, TareFactorData> currentMap;
- switch (factorPolicy) {
- case POLICY_ALARM_MANAGER:
- currentMap = mAlarmManagerMap;
- break;
- case POLICY_JOB_SCHEDULER:
- currentMap = mJobSchedulerMap;
- break;
- default:
- throw new IllegalArgumentException("Invalid factor policy given");
- }
+ final ArrayMap<String, TareFactorData> currentMap = getMap(factorPolicy);
return currentMap.get(key).currentValue;
}
@@ -542,6 +535,11 @@
return currentMap.get(key).factorPolicy;
}
+ int 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.
@@ -551,18 +549,14 @@
* @param factorPolicy policy being updated
*/
public void updateValue(String key, int editedValue, int factorPolicy) {
- switch (factorPolicy) {
- case POLICY_ALARM_MANAGER:
- mAlarmManagerMap.get(key).currentValue = editedValue;
- rebuildPolicyConstants(factorPolicy);
- break;
- case POLICY_JOB_SCHEDULER:
- mJobSchedulerMap.get(key).currentValue = editedValue;
- rebuildPolicyConstants(factorPolicy);
- break;
- default:
- throw new IllegalArgumentException("Invalid factor policy given");
+ final ArrayMap<String, TareFactorData> map = getMap(factorPolicy);
+
+ final TareFactorData data = map.get(key);
+ if (data.currentValue == editedValue) {
+ return;
}
+ data.currentValue = editedValue;
+ rebuildPolicyConstants(factorPolicy);
}
/**
@@ -574,20 +568,10 @@
private void rebuildPolicyConstants(int factorPolicy) {
switch (factorPolicy) {
case POLICY_ALARM_MANAGER:
- writeConstantsToSettings(mAlarmManagerMap,
- Settings.Global.TARE_ALARM_MANAGER_CONSTANTS);
-
- mAlarmManagerConstants = Settings.Global
- .getString(mContentResolver, Settings.Global
- .TARE_ALARM_MANAGER_CONSTANTS);
+ writeConstantsToSettings(mAlarmManagerMap, TARE_ALARM_MANAGER_CONSTANTS);
break;
case POLICY_JOB_SCHEDULER:
- writeConstantsToSettings(mJobSchedulerMap,
- Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS);
-
- mJobSchedulerConstants = Settings.Global
- .getString(mContentResolver, Settings.Global
- .TARE_JOB_SCHEDULER_CONSTANTS);
+ writeConstantsToSettings(mJobSchedulerMap, TARE_JOB_SCHEDULER_CONSTANTS);
break;
}
}
@@ -623,7 +607,7 @@
public TareFactorDialogFragment createDialog(String key) {
int policy = getFactorType(key);
return new TareFactorDialogFragment(getTitle(key, policy), key,
- getCurrentValue(key, policy), policy , this);
+ getCurrentValue(key, policy), policy, this);
}
/**
@@ -642,4 +626,51 @@
this.currentValue = defaultValue;
}
}
-}
\ No newline at end of file
+
+ 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();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/development/tare/TareFactorDialogFragment.java b/src/com/android/settings/development/tare/TareFactorDialogFragment.java
index ff7f5f9..8d2f341 100644
--- a/src/com/android/settings/development/tare/TareFactorDialogFragment.java
+++ b/src/com/android/settings/development/tare/TareFactorDialogFragment.java
@@ -16,7 +16,10 @@
package com.android.settings.development.tare;
+import android.annotation.NonNull;
+import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.DialogFragment;
import android.content.Context;
import android.os.Bundle;
import android.text.InputType;
@@ -25,10 +28,6 @@
import android.view.View;
import android.widget.EditText;
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.DialogFragment;
-
import com.android.settings.R;
import com.android.settings.Utils;
diff --git a/src/com/android/settings/development/tare/TareFactorExpandableListAdapter.java b/src/com/android/settings/development/tare/TareFactorExpandableListAdapter.java
new file mode 100644
index 0000000..8fe4c05
--- /dev/null
+++ b/src/com/android/settings/development/tare/TareFactorExpandableListAdapter.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2022 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 android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * Creates the expandable list that will allow modifying individual factors.
+ */
+public class TareFactorExpandableListAdapter extends BaseExpandableListAdapter {
+
+ private final LayoutInflater mLayoutInflater;
+ private final TareFactorController mFactorController;
+
+ private final String[] mGroups;
+ private final String[][] mChildren;
+ private final String[][] mKeys;
+
+ TareFactorExpandableListAdapter(TareFactorController factorController,
+ LayoutInflater layoutInflater, String[] groups, String[][] children, String[][] keys) {
+ mLayoutInflater = layoutInflater;
+ mFactorController = factorController;
+
+ mGroups = groups;
+ mChildren = children;
+ mKeys = keys;
+
+ validateMappings();
+ }
+
+ private void validateMappings() {
+ if (mGroups.length != mChildren.length) {
+ throw new IllegalStateException("groups and children don't have the same length");
+ }
+ if (mChildren.length != mKeys.length) {
+ throw new IllegalStateException("children and keys don't have the same length");
+ }
+ for (int i = 0; i < mChildren.length; ++i) {
+ if (mChildren[i].length != mKeys[i].length) {
+ throw new IllegalStateException(
+ "children and keys don't have the same length in row " + i);
+ }
+ }
+ }
+
+ @Override
+ public int getGroupCount() {
+ return mGroups.length;
+ }
+
+ @Override
+ public int getChildrenCount(int groupPosition) {
+ return mChildren[groupPosition].length;
+ }
+
+ @Override
+ public Object getGroup(int groupPosition) {
+ return mGroups[groupPosition];
+ }
+
+ @Override
+ public Object getChild(int groupPosition, int childPosition) {
+ return mChildren[groupPosition][childPosition];
+ }
+
+ @Override
+ public long getGroupId(int groupPosition) {
+ return groupPosition;
+ }
+
+ @Override
+ public long getChildId(int groupPosition, int childPosition) {
+ return childPosition;
+ }
+
+ @NonNull
+ String getKey(int groupPosition, int childPosition) {
+ return mKeys[groupPosition][childPosition];
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+ ViewGroup parent) {
+ if (convertView == null) {
+ convertView = mLayoutInflater.inflate(android.R.layout.simple_list_item_1, parent,
+ false);
+ }
+ TextView factor = convertView.findViewById(android.R.id.text1);
+ factor.setText(getGroup(groupPosition).toString());
+ return convertView;
+ }
+
+ @Override
+ @SuppressLint("InflateParams") // AdapterView doesn't support addView
+ public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+ View convertView, ViewGroup parent) {
+ // Here a custom child item is used instead of android.R.simple_list_item_2 because it
+ // is more customizable for this specific UI
+ if (convertView == null) {
+ convertView = mLayoutInflater.inflate(R.layout.tare_child_item, null);
+ }
+ TextView factor = convertView.findViewById(R.id.factor);
+ TextView value = convertView.findViewById(R.id.factor_number);
+
+ factor.setText(getChild(groupPosition, childPosition).toString());
+ value.setText(String.valueOf(
+ mFactorController.getValue(getKey(groupPosition, childPosition))));
+
+ return convertView;
+ }
+
+ @Override
+ public boolean isChildSelectable(int groupPosition, int childPosition) {
+ return true;
+ }
+}
diff --git a/src/com/android/settings/development/tare/TareHomePage.java b/src/com/android/settings/development/tare/TareHomePage.java
index 38e7ed8..cea0954 100644
--- a/src/com/android/settings/development/tare/TareHomePage.java
+++ b/src/com/android/settings/development/tare/TareHomePage.java
@@ -69,11 +69,14 @@
}
/** Reverts the TARE settings to the original default settings */
- // TODO: Establish default TARE values and make this method revert all settings back to default.
public void revertSettings(View v) {
Toast.makeText(this, R.string.tare_settings_reverted_toast, Toast.LENGTH_LONG).show();
Settings.Global.putString(getApplicationContext().getContentResolver(),
Settings.Global.ENABLE_TARE, null);
+ Settings.Global.putString(getApplicationContext().getContentResolver(),
+ Settings.Global.TARE_ALARM_MANAGER_CONSTANTS, null);
+ Settings.Global.putString(getApplicationContext().getContentResolver(),
+ Settings.Global.TARE_JOB_SCHEDULER_CONSTANTS, null);
setEnabled(Settings.Global.DEFAULT_ENABLE_TARE == SETTING_VALUE_ON);
}
diff --git a/src/com/android/settings/network/EthernetTetherPreferenceController.java b/src/com/android/settings/network/EthernetTetherPreferenceController.java
index 5b2cab7..58c1fd2 100644
--- a/src/com/android/settings/network/EthernetTetherPreferenceController.java
+++ b/src/com/android/settings/network/EthernetTetherPreferenceController.java
@@ -21,52 +21,63 @@
import android.net.TetheringManager;
import android.os.Handler;
import android.os.Looper;
-import android.text.TextUtils;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.OnLifecycleEvent;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.HashSet;
+
/**
* This controller helps to manage the switch state and visibility of ethernet tether switch
* preference.
*/
public final class EthernetTetherPreferenceController extends TetherBasePreferenceController {
- private final String mEthernetRegex;
+ private final HashSet<String> mAvailableInterfaces = new HashSet<>();
private final EthernetManager mEthernetManager;
+
@VisibleForTesting
- EthernetManager.Listener mEthernetListener;
+ EthernetManager.InterfaceStateListener mEthernetListener;
public EthernetTetherPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
- mEthernetRegex = context.getString(
- com.android.internal.R.string.config_ethernet_iface_regex);
- mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);
+ mEthernetManager = context.getSystemService(EthernetManager.class);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
- mEthernetListener = (iface, isAvailable) -> updateState(mPreference);
+ mEthernetListener = (iface, state, role, configuration) -> {
+ if (state == EthernetManager.STATE_LINK_UP) {
+ mAvailableInterfaces.add(iface);
+ } else {
+ mAvailableInterfaces.remove(iface);
+ }
+ updateState(mPreference);
+ };
final Handler handler = new Handler(Looper.getMainLooper());
// Executor will execute to post the updateState event to a new handler which is created
// from the main looper when the {@link EthernetManager.Listener.onAvailabilityChanged}
// is triggerd.
- mEthernetManager.addListener(mEthernetListener, r -> handler.post(r));
+ if (mEthernetManager != null) {
+ mEthernetManager.addInterfaceStateListener(r -> handler.post(r), mEthernetListener);
+ }
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
- mEthernetManager.removeListener(mEthernetListener);
- mEthernetListener = null;
+ if (mEthernetManager != null) {
+ mEthernetManager.removeInterfaceStateListener(mEthernetListener);
+ }
}
@Override
public boolean shouldEnable() {
+ ensureRunningOnMainLoopThread();
String[] available = mTm.getTetherableIfaces();
for (String s : available) {
- if (s.matches(mEthernetRegex)) {
+ if (mAvailableInterfaces.contains(s)) {
return true;
}
}
@@ -75,11 +86,19 @@
@Override
public boolean shouldShow() {
- return !TextUtils.isEmpty(mEthernetRegex);
+ return mEthernetManager != null;
}
@Override
public int getTetherType() {
return TetheringManager.TETHERING_ETHERNET;
}
+
+ private void ensureRunningOnMainLoopThread() {
+ if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
+ throw new IllegalStateException(
+ "Not running on main loop thread: "
+ + Thread.currentThread().getName());
+ }
+ }
}
diff --git a/src/com/android/settings/safetycenter/LockScreenSafetySource.java b/src/com/android/settings/safetycenter/LockScreenSafetySource.java
index 5ebe12a..f059920 100644
--- a/src/com/android/settings/safetycenter/LockScreenSafetySource.java
+++ b/src/com/android/settings/safetycenter/LockScreenSafetySource.java
@@ -57,7 +57,7 @@
screenLockPreferenceDetailsUtils);
final SafetySourceStatus status = new SafetySourceStatus.Builder(
- context.getString(R.string.unlock_set_unlock_launch_picker_title_profile),
+ context.getString(R.string.unlock_set_unlock_launch_picker_title),
screenLockPreferenceDetailsUtils.getSummary(UserHandle.myUserId()),
screenLockPreferenceDetailsUtils.isLockPatternSecure()
? SafetySourceStatus.STATUS_LEVEL_OK
diff --git a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
index aec31fc..01ec42e 100644
--- a/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/AllInOneTetherSettingsTest.java
@@ -33,6 +33,7 @@
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.EthernetManager;
import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
@@ -84,6 +85,8 @@
private PreferenceScreen mPreferenceScreen;
@Mock
private PreferenceGroup mWifiTetherGroup;
+ @Mock
+ private EthernetManager mEthernetManager;
@Before
public void setUp() {
@@ -95,6 +98,7 @@
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
doReturn(mTetheringManager)
.when(mContext).getSystemService(Context.TETHERING_SERVICE);
+ doReturn(mEthernetManager).when(mContext).getSystemService(EthernetManager.class);
doReturn(WIFI_REGEXS).when(mTetheringManager).getTetherableWifiRegexs();
doReturn(USB_REGEXS).when(mTetheringManager).getTetherableUsbRegexs();
doReturn(BT_REGEXS).when(mTetheringManager).getTetherableBluetoothRegexs();
diff --git a/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
index bf4811b..68d80d4 100644
--- a/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/EthernetTetherPreferenceControllerTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -65,10 +66,9 @@
mPreference = spy(SwitchPreference.class);
when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
when(mTetheringManager.getTetherableIfaces()).thenReturn(new String[]{ETHERNET_REGEX});
- when(mContext.getSystemService(Context.ETHERNET_SERVICE)).thenReturn(mEthernetManager);
+ when(mContext.getSystemService(EthernetManager.class)).thenReturn(mEthernetManager);
mController = new EthernetTetherPreferenceController(mContext, "ethernet");
mController.setTetherEnabler(mTetherEnabler);
- ReflectionHelpers.setField(mController, "mEthernetRegex", ETHERNET_REGEX);
ReflectionHelpers.setField(mController, "mPreference", mPreference);
}
@@ -77,7 +77,8 @@
public void lifecycle_shouldRegisterReceiverOnStart() {
mController.onStart();
- verify(mEthernetManager).addListener(eq(mController.mEthernetListener));
+ verify(mEthernetManager).addInterfaceStateListener(any(),
+ eq(mController.mEthernetListener));
}
@Test
@@ -95,11 +96,10 @@
@Test
public void lifecycle_shouldUnregisterReceiverOnStop() {
mController.onStart();
- EthernetManager.Listener listener = mController.mEthernetListener;
+ EthernetManager.InterfaceStateListener listener = mController.mEthernetListener;
mController.onStop();
- verify(mEthernetManager).removeListener(eq(listener));
- assertThat(mController.mEthernetListener).isNull();
+ verify(mEthernetManager).removeInterfaceStateListener(eq(listener));
}
@Test
@@ -110,8 +110,11 @@
@Test
public void shouldShow_noEthernetInterface() {
- ReflectionHelpers.setField(mController, "mEthernetRegex", "");
- assertThat(mController.shouldShow()).isFalse();
+ when(mContext.getSystemService(EthernetManager.class)).thenReturn(null);
+
+ final EthernetTetherPreferenceController controller =
+ new EthernetTetherPreferenceController(mContext, "ethernet");
+ assertThat(controller.shouldShow()).isFalse();
}
@Test
diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java
index 90b8927..38c605c 100644
--- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/BridgedAppsPreferenceControllerTest.java
@@ -30,7 +30,6 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.VersionedPackage;
-import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.service.notification.NotificationListenerFilter;
import android.util.ArraySet;
@@ -65,6 +64,7 @@
PreferenceScreen mScreen;
@Mock
ApplicationsState mAppState;
+
private ApplicationsState.AppEntry mAppEntry;
private ApplicationsState.AppEntry mAppEntry2;
@@ -92,8 +92,6 @@
mAppEntry.info = ai;
mAppEntry.label = "hi";
- Drawable icon = mock(Drawable.class);
- mAppEntry.icon = icon;
mController = new BridgedAppsPreferenceController(mContext, "key");
mController.setCn(mCn);
@@ -167,7 +165,7 @@
assertThat(actual.isChecked()).isTrue();
assertThat(actual.getTitle()).isEqualTo("hi");
- assertThat(actual.getIcon()).isEqualTo(mAppEntry.icon);
+ assertThat(actual.getIcon()).isNotNull();
}
@Test
diff --git a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
index 4b21408..64b9692 100644
--- a/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
+++ b/tests/unit/src/com/android/settings/safetycenter/LockScreenSafetySourceTest.java
@@ -108,7 +108,7 @@
assertThat(safetySourceStatus.getTitle().toString())
.isEqualTo(ResourcesUtils.getResourcesString(
mApplicationContext,
- "unlock_set_unlock_launch_picker_title_profile"));
+ "unlock_set_unlock_launch_picker_title"));
assertThat(safetySourceStatus.getSummary().toString())
.isEqualTo(SUMMARY);
assertThat(safetySourceStatus.getPendingIntent().getIntent()).isNotNull();