diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 469f20198e6..867fecb2e90 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1626,4 +1626,24 @@ 300000 + + + @string/ingress_rate_limit_no_limit_entry + 128kbps + 256kbps + 1Mbps + 5Mbps + 15Mbps + + + + + -1 + 16000 + 32000 + 125000 + 625000 + 1875000 + + diff --git a/res/values/strings.xml b/res/values/strings.xml index bd9cbbd2527..2c0780fb176 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -329,14 +329,16 @@ Disable Bluetooth A2DP hardware offload - - Restart Device? - - You need to restart your device to change this setting. - - Restart - - Cancel + + Disable Bluetooth LE AUDIO hardware offload + + Restart Device? + + You need to restart your device to change this setting. + + Restart + + Cancel Media devices @@ -14035,4 +14037,13 @@ Make audio more realistic Shift positioning of audio so it sounds more natural. + + + Network download rate limit + + Configure the network bandwidth ingress rate limit which is applied to all networks that provide internet connectivity. + + Configure network download rate limit + + No limit diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml index b21d5c931e5..ef5a9909cf9 100644 --- a/res/xml/bluetooth_device_details_fragment.xml +++ b/res/xml/bluetooth_device_details_fragment.xml @@ -38,11 +38,6 @@ android:key="action_buttons" settings:allowDividerBelow="true"/> - - - + + - - + + batteryDiffEntries = - BatteryChartPreferenceController.getBatteryLast24HrUsageData(mContext); - if (batteryDiffEntries == null) { - return null; - } - // Filter entry with consumer type to avoid system app, - // then use user id to divide normal app and work profile app, - // return target application from filter list by package name. - return batteryDiffEntries.stream() - .filter(entry -> entry.mBatteryHistEntry.mConsumerType - == ConvertUtils.CONSUMER_TYPE_UID_BATTERY) - .filter(entry -> entry.mBatteryHistEntry.mUserId == mUserId) - .filter(entry -> { - if (mPackageName.equals(entry.getPackageName())) { - Log.i(TAG, "Return target application: " - + entry.mBatteryHistEntry.mPackageName - + " | uid: " + entry.mBatteryHistEntry.mUid - + " | userId: " + entry.mBatteryHistEntry.mUserId); - return true; - } - return false; - }) - .findFirst() - .orElse(/* other */null); + final BatteryDiffEntry entry = + BatteryChartPreferenceController.getBatteryLast24HrUsageData( + mContext, mPackageName, mUserId); + Log.d(TAG, "loadBatteryDiffEntries():\n" + entry); + return entry; } @Override diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java index 95e663bf50f..2ffa11b6c99 100644 --- a/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java +++ b/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceController.java @@ -16,9 +16,12 @@ package com.android.settings.development; +import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController.LE_AUDIO_OFFLOAD_DISABLED_PROPERTY; + import android.content.Context; import android.os.SystemProperties; +import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.SwitchPreference; @@ -34,6 +37,9 @@ public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptions static final String A2DP_OFFLOAD_DISABLED_PROPERTY = "persist.bluetooth.a2dp_offload.disabled"; static final String A2DP_OFFLOAD_SUPPORTED_PROPERTY = "ro.bluetooth.a2dp_offload.supported"; + @VisibleForTesting + boolean mChanged = false; + public BluetoothA2dpHwOffloadPreferenceController(Context context, DevelopmentSettingsDashboardFragment fragment) { super(context); @@ -47,7 +53,8 @@ public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptions @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - BluetoothA2dpHwOffloadRebootDialog.show(mFragment, this); + BluetoothHwOffloadRebootDialog.show(mFragment); + mChanged = true; return false; } @@ -85,10 +92,26 @@ public class BluetoothA2dpHwOffloadPreferenceController extends DeveloperOptions return offloadSupported ? !offloadDisabled : true; } - public void onA2dpHwDialogConfirmed() { + /** + * Called when the HwOffloadDialog confirm is clicked. + */ + public void onHwOffloadDialogConfirmed() { + if (!mChanged) { + return; + } final boolean offloadDisabled = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(!offloadDisabled)); + if (offloadDisabled) { + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, + Boolean.toString(!offloadDisabled)); + } } + /** + * Called when the HwOffloadDialog cancel is clicked. + */ + public void onHwOffloadDialogCanceled() { + mChanged = false; + } } diff --git a/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java b/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java deleted file mode 100644 index f5c30f5811c..00000000000 --- a/src/com/android/settings/development/BluetoothGabeldorschePreferenceController.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2017 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; - -import android.content.Context; -import android.provider.DeviceConfig; - -import androidx.annotation.VisibleForTesting; -import androidx.preference.Preference; -import androidx.preference.SwitchPreference; - -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settingslib.development.DeveloperOptionsPreferenceController; - -/** - * Preference controller for Bluetooth Gabeldorche feature - */ -public class BluetoothGabeldorschePreferenceController extends - DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener, - PreferenceControllerMixin { - - private static final String BLUETOOTH_GABELDORSCHE_KEY = - "bluetooth_gabeldorsche_enable"; - - @VisibleForTesting - static final String CURRENT_GD_FLAG = "INIT_gd_scanning"; - - public BluetoothGabeldorschePreferenceController(Context context) { - super(context); - } - - @Override - public String getPreferenceKey() { - return BLUETOOTH_GABELDORSCHE_KEY; - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean isEnabled = (Boolean) newValue; - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG, isEnabled ? "true" : "false", false /* makeDefault */); - return true; - } - - @Override - public void updateState(Preference preference) { - final boolean isEnabled = DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_BLUETOOTH, CURRENT_GD_FLAG, false /* default */); - ((SwitchPreference) mPreference).setChecked(isEnabled); - } - - @Override - protected void onDeveloperOptionsSwitchDisabled() { - super.onDeveloperOptionsSwitchDisabled(); - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG, null, false /* makeDefault */); - ((SwitchPreference) mPreference).setChecked(false); - } -} diff --git a/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java b/src/com/android/settings/development/BluetoothHwOffloadRebootDialog.java similarity index 60% rename from src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java rename to src/com/android/settings/development/BluetoothHwOffloadRebootDialog.java index 95ef0197a40..389103e816d 100644 --- a/src/com/android/settings/development/BluetoothA2dpHwOffloadRebootDialog.java +++ b/src/com/android/settings/development/BluetoothHwOffloadRebootDialog.java @@ -28,17 +28,23 @@ import androidx.fragment.app.FragmentManager; import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; -public class BluetoothA2dpHwOffloadRebootDialog extends InstrumentedDialogFragment +/** + * The a2dp and LE audio offload switch should reboot the device to take effect, the dialog is + * to ask the user to reboot the device after a2dp or LE audio offload user preference changed + */ +public class BluetoothHwOffloadRebootDialog extends InstrumentedDialogFragment implements DialogInterface.OnClickListener { - public static final String TAG = "BluetoothA2dpHwOffloadReboot"; + public static final String TAG = "BluetoothHwOffloadReboot"; - public static void show(DevelopmentSettingsDashboardFragment host, - BluetoothA2dpHwOffloadPreferenceController controller) { + /** + * The function to show the HwOffloadReboot Dialog. + */ + public static void show(DevelopmentSettingsDashboardFragment host) { final FragmentManager manager = host.getActivity().getSupportFragmentManager(); if (manager.findFragmentByTag(TAG) == null) { - final BluetoothA2dpHwOffloadRebootDialog dialog = - new BluetoothA2dpHwOffloadRebootDialog(); + final BluetoothHwOffloadRebootDialog dialog = + new BluetoothHwOffloadRebootDialog(); dialog.setTargetFragment(host, 0 /* requestCode */); dialog.show(manager, TAG); } @@ -52,33 +58,44 @@ public class BluetoothA2dpHwOffloadRebootDialog extends InstrumentedDialogFragme @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return new AlertDialog.Builder(getActivity()) - .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message) - .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title) + .setMessage(R.string.bluetooth_disable_hw_offload_dialog_message) + .setTitle(R.string.bluetooth_disable_hw_offload_dialog_title) .setPositiveButton( - R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this) + R.string.bluetooth_disable_hw_offload_dialog_confirm, this) .setNegativeButton( - R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this) + R.string.bluetooth_disable_hw_offload_dialog_cancel, this) .create(); } @Override public void onClick(DialogInterface dialog, int which) { - final OnA2dpHwDialogConfirmedListener host = - (OnA2dpHwDialogConfirmedListener) getTargetFragment(); + final OnHwOffloadDialogListener host = + (OnHwOffloadDialogListener) getTargetFragment(); if (host == null) { return; } if (which == DialogInterface.BUTTON_POSITIVE) { - host.onA2dpHwDialogConfirmed(); + host.onHwOffloadDialogConfirmed(); PowerManager pm = getContext().getSystemService(PowerManager.class); pm.reboot(null); + } else { + host.onHwOffloadDialogCanceled(); } } - public interface OnA2dpHwDialogConfirmedListener { + /** + * The interface for the HsOffloadDialogListener to provide the action as the + * confirmed or canceled clicked. + */ + public interface OnHwOffloadDialogListener { /** * Called when the user presses reboot on the warning dialog. */ - void onA2dpHwDialogConfirmed(); + void onHwOffloadDialogConfirmed(); + + /** + * Called when the user presses cancel on the warning dialog. + */ + void onHwOffloadDialogCanceled(); } } diff --git a/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceController.java b/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceController.java new file mode 100644 index 00000000000..911b62d6cc4 --- /dev/null +++ b/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceController.java @@ -0,0 +1,127 @@ +/* + * Copyright 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; + +import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_SUPPORTED_PROPERTY; + +import android.content.Context; +import android.os.SystemProperties; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.SwitchPreference; + +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.development.DeveloperOptionsPreferenceController; + +/** + * Preference controller to control Bluetooth LE audio offload + */ +public class BluetoothLeAudioHwOffloadPreferenceController + extends DeveloperOptionsPreferenceController + implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { + + private static final String PREFERENCE_KEY = "bluetooth_disable_le_audio_hw_offload"; + private final DevelopmentSettingsDashboardFragment mFragment; + + static final String LE_AUDIO_OFFLOAD_DISABLED_PROPERTY = + "persist.bluetooth.leaudio_offload.disabled"; + static final String LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY = + "ro.bluetooth.leaudio_offload.supported"; + + @VisibleForTesting + boolean mChanged = false; + + public BluetoothLeAudioHwOffloadPreferenceController(Context context, + DevelopmentSettingsDashboardFragment fragment) { + super(context); + mFragment = fragment; + } + + @Override + public String getPreferenceKey() { + return PREFERENCE_KEY; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + BluetoothHwOffloadRebootDialog.show(mFragment); + mChanged = true; + return false; + } + + @Override + public void updateState(Preference preference) { + final boolean offloadSupported = + SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false) + && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false); + if (offloadSupported) { + final boolean offloadDisabled = + SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true); + ((SwitchPreference) mPreference).setChecked(offloadDisabled); + } else { + mPreference.setEnabled(false); + ((SwitchPreference) mPreference).setChecked(true); + } + } + + @Override + protected void onDeveloperOptionsSwitchDisabled() { + super.onDeveloperOptionsSwitchDisabled(); + final boolean offloadSupported = + SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false) + && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false); + if (offloadSupported) { + ((SwitchPreference) mPreference).setChecked(true); + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, "true"); + } + } + + /** + * Check if the le audio offload setting is default value. + */ + public boolean isDefaultValue() { + final boolean offloadSupported = + SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false) + && SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false); + final boolean offloadDisabled = + SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false); + return offloadSupported ? offloadDisabled : true; + } + + /** + * Called when the HwOffloadDialog confirm is clicked. + */ + public void onHwOffloadDialogConfirmed() { + if (!mChanged) { + return; + } + + final boolean offloadDisabled = + SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, + false); + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, + Boolean.toString(!offloadDisabled)); + } + + /** + * Called when the HwOffloadDialog cancel is clicked. + */ + public void onHwOffloadDialogCanceled() { + mChanged = false; + } +} diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 57114e2fc79..636404eb89c 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -80,7 +80,7 @@ import java.util.List; public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment implements OnMainSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost, AdbClearKeysDialogHost, LogPersistDialogHost, - BluetoothA2dpHwOffloadRebootDialog.OnA2dpHwDialogConfirmedListener, + BluetoothHwOffloadRebootDialog.OnHwOffloadDialogListener, AbstractBluetoothPreferenceController.Callback { private static final String TAG = "DevSettingsDashboard"; @@ -293,12 +293,16 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra if (isChecked) { EnableDevelopmentSettingWarningDialog.show(this /* host */); } else { - final BluetoothA2dpHwOffloadPreferenceController controller = + final BluetoothA2dpHwOffloadPreferenceController a2dpController = getDevelopmentOptionsController( BluetoothA2dpHwOffloadPreferenceController.class); - // If A2DP hardware offload isn't default value, we must reboot after disable + final BluetoothLeAudioHwOffloadPreferenceController leAudioController = + getDevelopmentOptionsController( + BluetoothLeAudioHwOffloadPreferenceController.class); + // If hardware offload isn't default value, we must reboot after disable // developer options. Show a dialog for the user to confirm. - if (controller == null || controller.isDefaultValue()) { + if ((a2dpController == null || a2dpController.isDefaultValue()) + && (leAudioController == null || leAudioController.isDefaultValue())) { disableDeveloperOptions(); } else { DisableDevSettingsDialogFragment.show(this /* host */); @@ -358,10 +362,27 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra } @Override - public void onA2dpHwDialogConfirmed() { - final BluetoothA2dpHwOffloadPreferenceController controller = + public void onHwOffloadDialogConfirmed() { + final BluetoothA2dpHwOffloadPreferenceController a2dpController = getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class); - controller.onA2dpHwDialogConfirmed(); + a2dpController.onHwOffloadDialogConfirmed(); + + final BluetoothLeAudioHwOffloadPreferenceController leAudioController = + getDevelopmentOptionsController( + BluetoothLeAudioHwOffloadPreferenceController.class); + leAudioController.onHwOffloadDialogConfirmed(); + } + + @Override + public void onHwOffloadDialogCanceled() { + final BluetoothA2dpHwOffloadPreferenceController a2dpController = + getDevelopmentOptionsController(BluetoothA2dpHwOffloadPreferenceController.class); + a2dpController.onHwOffloadDialogCanceled(); + + final BluetoothLeAudioHwOffloadPreferenceController leAudioController = + getDevelopmentOptionsController( + BluetoothLeAudioHwOffloadPreferenceController.class); + leAudioController.onHwOffloadDialogCanceled(); } @Override @@ -517,10 +538,10 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new TetheringHardwareAccelPreferenceController(context)); controllers.add(new BluetoothDeviceNoNamePreferenceController(context)); controllers.add(new BluetoothAbsoluteVolumePreferenceController(context)); - controllers.add(new BluetoothGabeldorschePreferenceController(context)); controllers.add(new BluetoothAvrcpVersionPreferenceController(context)); controllers.add(new BluetoothMapVersionPreferenceController(context)); controllers.add(new BluetoothA2dpHwOffloadPreferenceController(context, fragment)); + controllers.add(new BluetoothLeAudioHwOffloadPreferenceController(context, fragment)); controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context)); controllers.add(new NfcStackDebugLogPreferenceController(context)); controllers.add(new ShowTapsPreferenceController(context)); @@ -585,6 +606,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new SharedDataPreferenceController(context)); controllers.add(new OverlaySettingsPreferenceController(context)); controllers.add(new StylusHandwritingPreferenceController(context)); + controllers.add(new IngressRateLimitPreferenceController((context))); return controllers; } diff --git a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java index 803030eb83d..5db2ed4281b 100644 --- a/src/com/android/settings/development/DisableDevSettingsDialogFragment.java +++ b/src/com/android/settings/development/DisableDevSettingsDialogFragment.java @@ -56,15 +56,15 @@ public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - // Reuse the same text of disable_a2dp_hw_offload_dialog. + // Reuse the same text of disable_hw_offload_dialog. // The text is generic enough to be used for turning off Dev options. return new AlertDialog.Builder(getActivity()) - .setMessage(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message) - .setTitle(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title) + .setMessage(R.string.bluetooth_disable_hw_offload_dialog_message) + .setTitle(R.string.bluetooth_disable_hw_offload_dialog_title) .setPositiveButton( - R.string.bluetooth_disable_a2dp_hw_offload_dialog_confirm, this) + R.string.bluetooth_disable_hw_offload_dialog_confirm, this) .setNegativeButton( - R.string.bluetooth_disable_a2dp_hw_offload_dialog_cancel, this) + R.string.bluetooth_disable_hw_offload_dialog_cancel, this) .create(); } diff --git a/src/com/android/settings/development/IngressRateLimitPreferenceController.java b/src/com/android/settings/development/IngressRateLimitPreferenceController.java new file mode 100644 index 00000000000..2e84aba9835 --- /dev/null +++ b/src/com/android/settings/development/IngressRateLimitPreferenceController.java @@ -0,0 +1,82 @@ +/* + * 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; + +import android.content.Context; +import android.net.ConnectivitySettingsManager; +import android.util.Log; + +import androidx.preference.ListPreference; +import androidx.preference.Preference; + +import com.android.settings.core.PreferenceControllerMixin; +import com.android.settingslib.development.DeveloperOptionsPreferenceController; + +/** + * Controller for ingress rate limit developer setting. + */ +public class IngressRateLimitPreferenceController extends DeveloperOptionsPreferenceController + implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { + private static final String TAG = "IngressRateLimitPreferenceController"; + private static final String INGRESS_RATE_LIMIT_KEY = "ingress_rate_limit"; + private static final int RATE_LIMIT_DISABLED = -1; + + public IngressRateLimitPreferenceController(Context context) { + super(context); + } + + @Override + public String getPreferenceKey() { + return INGRESS_RATE_LIMIT_KEY; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final long value = Long.parseLong(newValue.toString()); + try { + ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, value); + return true; + } catch (IllegalArgumentException e) { + Log.e(TAG, "invalid rate limit", e); + return false; + } + } + + @Override + public void updateState(Preference preference) { + final String ingressRateLimit = String.valueOf( + ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(mContext)); + + // verify ingressRateLimit is valid / present in ListPreference; else do nothing. + final CharSequence[] entryValues = ((ListPreference) preference).getEntryValues(); + for (int i = 0; i < entryValues.length; i++) { + if (ingressRateLimit.contentEquals(entryValues[i])) { + ((ListPreference) preference).setValue(ingressRateLimit); + return; + } + } + } + + @Override + protected void onDeveloperOptionsSwitchDisabled() { + super.onDeveloperOptionsSwitchDisabled(); + // disable rate limiting when developer options are disabled + ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, + RATE_LIMIT_DISABLED); + ((ListPreference) mPreference).setValue(String.valueOf(RATE_LIMIT_DISABLED)); + } +} diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index 90a86f165c4..249ee492e67 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -617,6 +617,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll return true; } + /** Used for {@link AppBatteryPreferenceController}. */ public static List getBatteryLast24HrUsageData(Context context) { final long start = System.currentTimeMillis(); final Map> batteryHistoryMap = @@ -638,6 +639,28 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll return batteryIndexedMap.get(BatteryChartView.SELECTED_INDEX_ALL); } + /** Used for {@link AppBatteryPreferenceController}. */ + public static BatteryDiffEntry getBatteryLast24HrUsageData( + Context context, String packageName, int userId) { + if (packageName == null) { + return null; + } + final List entries = getBatteryLast24HrUsageData(context); + if (entries == null) { + return null; + } + for (BatteryDiffEntry entry : entries) { + final BatteryHistEntry batteryHistEntry = entry.mBatteryHistEntry; + if (batteryHistEntry != null + && batteryHistEntry.mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY + && batteryHistEntry.mUserId == userId + && packageName.equals(entry.getPackageName())) { + return entry; + } + } + return null; + } + private static long[] getBatteryHistoryKeys( final Map> batteryHistoryMap) { final List batteryHistoryKeyList = diff --git a/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java index a1d479ff3ac..fcb3ea929a4 100644 --- a/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/BluetoothA2dpHwOffloadPreferenceControllerTest.java @@ -18,6 +18,8 @@ package com.android.settings.development; import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController .A2DP_OFFLOAD_DISABLED_PROPERTY; +import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController + .LE_AUDIO_OFFLOAD_DISABLED_PROPERTY; import static com.google.common.truth.Truth.assertThat; @@ -62,15 +64,37 @@ public class BluetoothA2dpHwOffloadPreferenceControllerTest { } @Test - public void onA2dpHwDialogConfirmed_shouldChangeProperty() { + public void onA2dpHwDialogConfirmedAsA2dpOffloadDisabled_shouldChangeProperty() { SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false)); + mController.mChanged = true; - mController.onA2dpHwDialogConfirmed(); + mController.onHwOffloadDialogConfirmed(); final boolean mode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); assertThat(mode).isTrue(); + } - mController.onA2dpHwDialogConfirmed(); - final boolean mode2 = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); - assertThat(mode2).isFalse(); + @Test + public void onA2dpHwDialogConfirmedAsA2dpOffloadEnabled_shouldChangeProperty() { + SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true)); + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true)); + + mController.mChanged = true; + + mController.onHwOffloadDialogConfirmed(); + final boolean a2dpMode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, true); + final boolean leAudioMode = SystemProperties + .getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true); + assertThat(a2dpMode).isFalse(); + assertThat(leAudioMode).isFalse(); + } + + @Test + public void onA2dpHwDialogCanceled_shouldNotChangeProperty() { + SystemProperties.set(A2DP_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false)); + mController.mChanged = true; + + mController.onHwOffloadDialogCanceled(); + final boolean mode = SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false); + assertThat(mode).isFalse(); } } diff --git a/tests/robotests/src/com/android/settings/development/BluetoothGabeldorschePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothGabeldorschePreferenceControllerTest.java deleted file mode 100644 index 1916bf22af9..00000000000 --- a/tests/robotests/src/com/android/settings/development/BluetoothGabeldorschePreferenceControllerTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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; - -import static com.android.settings.development.BluetoothGabeldorschePreferenceController - .CURRENT_GD_FLAG; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.provider.DeviceConfig; - -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; - -@RunWith(RobolectricTestRunner.class) -public class BluetoothGabeldorschePreferenceControllerTest { - - @Mock - private SwitchPreference mPreference; - @Mock - private PreferenceScreen mPreferenceScreen; - - private BluetoothGabeldorschePreferenceController mController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - Context context = RuntimeEnvironment.application; - mController = new BluetoothGabeldorschePreferenceController(context); - when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) - .thenReturn(mPreference); - mController.displayPreference(mPreferenceScreen); - } - - @Test - @Ignore - public void onPreferenceChanged_settingEnabled_shouldTurnOnBluetoothGabeldorsche() { - mController.onPreferenceChange(mPreference, true /* new value */); - - boolean enabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG, false /* defaultValue */); - - assertThat(enabled).isTrue(); - } - - @Test - @Ignore - public void onPreferenceChanged_settingDisabled_shouldTurnOffBluetoothGabeldorsche() { - mController.onPreferenceChange(mPreference, false /* new value */); - - boolean enabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG, false /* defaultValue */); - - assertThat(enabled).isFalse(); - } - - @Test - @Ignore - public void updateState_settingEnabled_preferenceShouldBeChecked() { - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG, "true", false /* makeDefault */); - - mController.updateState(mPreference); - - verify(mPreference).setChecked(true); - } - - @Test - @Ignore - public void updateState_settingDisabled_preferenceShouldNotBeChecked() { - DeviceConfig.setProperty(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG, "false", false /* makeDefault */); - - mController.updateState(mPreference); - - verify(mPreference).setChecked(false); - } - - @Test - @Ignore - public void onDeveloperOptionsDisabled_shouldDisablePreference() { - mController.onDeveloperOptionsDisabled(); - - String configStr = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_BLUETOOTH, - CURRENT_GD_FLAG); - - assertThat(configStr).isNull(); - verify(mPreference).setEnabled(false); - verify(mPreference).setChecked(false); - } -} diff --git a/tests/robotests/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceControllerTest.java new file mode 100644 index 00000000000..c82df40e038 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/BluetoothLeAudioHwOffloadPreferenceControllerTest.java @@ -0,0 +1,94 @@ +/* + * 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; + +import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController + .LE_AUDIO_OFFLOAD_DISABLED_PROPERTY; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.SystemProperties; + +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class BluetoothLeAudioHwOffloadPreferenceControllerTest { + + @Mock + private PreferenceScreen mPreferenceScreen; + @Mock + private DevelopmentSettingsDashboardFragment mFragment; + + private Context mContext; + private SwitchPreference mPreference; + private BluetoothLeAudioHwOffloadPreferenceController mController; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mPreference = new SwitchPreference(mContext); + mController = spy(new BluetoothLeAudioHwOffloadPreferenceController(mContext, mFragment)); + when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) + .thenReturn(mPreference); + mController.displayPreference(mPreferenceScreen); + } + + @Test + public void onLeAudioHwDialogConfirmedAsLeAudioOffloadDisabled_shouldChangeProperty() { + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false)); + mController.mChanged = true; + + mController.onHwOffloadDialogConfirmed(); + final boolean mode = SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false); + assertThat(mode).isTrue(); + } + + @Test + public void onLeAudioHwDialogConfirmedAsLeAudioOffloadEnabled_shouldChangeProperty() { + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true)); + mController.mChanged = true; + + mController.onHwOffloadDialogConfirmed(); + final boolean mode2 = SystemProperties.getBoolean( + LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, true); + assertThat(mode2).isFalse(); + } + + @Test + public void onLeAudioHwDialogCanceled_shouldNotChangeProperty() { + SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(false)); + mController.mChanged = true; + + mController.onHwOffloadDialogCanceled(); + final boolean mode = SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false); + assertThat(mode).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java index 5e4be689906..7db7141809e 100644 --- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java @@ -208,9 +208,9 @@ public class DevelopmentSettingsDashboardFragmentTest { assertThat(dialog).isNotNull(); ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog); assertThat(shadowDialog.getTitle()).isEqualTo( - mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_title)); + mContext.getString(R.string.bluetooth_disable_hw_offload_dialog_title)); assertThat(shadowDialog.getMessage()).isEqualTo( - mContext.getString(R.string.bluetooth_disable_a2dp_hw_offload_dialog_message)); + mContext.getString(R.string.bluetooth_disable_hw_offload_dialog_message)); } @Test diff --git a/tests/robotests/src/com/android/settings/development/IngressRateLimitPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/IngressRateLimitPreferenceControllerTest.java new file mode 100644 index 00000000000..0f85a140fba --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/IngressRateLimitPreferenceControllerTest.java @@ -0,0 +1,107 @@ +/* + * 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; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.net.ConnectivitySettingsManager; + +import androidx.preference.ListPreference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class IngressRateLimitPreferenceControllerTest { + private Context mContext = RuntimeEnvironment.application; + private ListPreference mPreference; + private IngressRateLimitPreferenceController mController; + + @Mock + private PreferenceScreen mPreferenceScreen; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mPreference = new ListPreference(mContext); + mPreference.setEntries(R.array.ingress_rate_limit_entries); + mPreference.setEntryValues(R.array.ingress_rate_limit_values); + + mController = new IngressRateLimitPreferenceController(mContext); + when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn( + mPreference); + mController.displayPreference(mPreferenceScreen); + } + + @Test + public void onPreferenceChanged_select5Mbits_shouldEnableIngressRateLimit() { + final long newRateLimit = 625000; // 5mbit == 625000 B/s + assertThat(mController.onPreferenceChange(mPreference, newRateLimit)).isTrue(); + + final long configuredRateLimit = + ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(mContext); + assertThat(configuredRateLimit).isEqualTo(newRateLimit); + } + + @Test + public void onPreferenceChanged_selectDisabled_shouldDisableIngressRateLimit() { + final long disabledRateLimit = -1; // -1 == disabled + assertThat(mController.onPreferenceChange(mPreference, disabledRateLimit)).isTrue(); + + final long configuredRateLimit = + ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond(mContext); + assertThat(configuredRateLimit).isEqualTo(disabledRateLimit); + } + + @Test + public void onPreferenceChanged_invalidValue_returnsFalse() { + final long invalidRateLimit = -123; + assertThat(mController.onPreferenceChange(mPreference, invalidRateLimit)).isFalse(); + } + + @Test + public void updateState_preferenceShouldBeSelected() { + final long newRateLimit = 625000; // 5mbit == 625000 B/s + ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, newRateLimit); + mController.updateState(mPreference); + assertThat(Long.parseLong(mPreference.getValue())).isEqualTo(newRateLimit); + } + + @Test + public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() { + final long newRateLimit = 625000; // 5mbit == 625000 B/s + ConnectivitySettingsManager.setIngressRateLimitInBytesPerSecond(mContext, newRateLimit); + mController.updateState(mPreference); + + mController.onDeveloperOptionsSwitchDisabled(); + assertThat(Long.parseLong(mPreference.getValue())).isEqualTo(-1); + assertThat(ConnectivitySettingsManager.getIngressRateLimitInBytesPerSecond( + mContext)).isEqualTo(-1); + } +}