getSliders() {
return mSideToSliderMap;
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java
index 8af08792180..01f8bb4cc8e 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceController.java
@@ -42,6 +42,7 @@ public class BluetoothDetailsHearingDeviceController extends BluetoothDetailsCon
public static final int ORDER_HEARING_DEVICE_SETTINGS = 1;
public static final int ORDER_HEARING_AIDS_PRESETS = 2;
+ public static final int ORDER_HEARING_DEVICE_INPUT_ROUTING = 3;
public static final int ORDER_AMBIENT_VOLUME = 4;
static final String KEY_HEARING_DEVICE_GROUP = "hearing_device_group";
@@ -62,10 +63,12 @@ public class BluetoothDetailsHearingDeviceController extends BluetoothDetailsCon
@VisibleForTesting
void setSubControllers(
BluetoothDetailsHearingDeviceSettingsController hearingDeviceSettingsController,
- BluetoothDetailsHearingAidsPresetsController presetsController) {
+ BluetoothDetailsHearingAidsPresetsController presetsController,
+ BluetoothDetailsHearingDeviceInputRoutingController inputRoutingController) {
mControllers.clear();
mControllers.add(hearingDeviceSettingsController);
mControllers.add(presetsController);
+ mControllers.add(inputRoutingController);
}
@Override
@@ -112,6 +115,11 @@ public class BluetoothDetailsHearingDeviceController extends BluetoothDetailsCon
mControllers.add(new BluetoothDetailsAmbientVolumePreferenceController(mContext,
mManager, mFragment, mCachedDevice, mLifecycle));
}
+ if (com.android.settingslib.flags.Flags.hearingDevicesInputRoutingControl()) {
+ mControllers.add(
+ new BluetoothDetailsHearingDeviceInputRoutingController(mContext, mFragment,
+ mCachedDevice, mLifecycle));
+ }
}
@NonNull
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceInputRoutingController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceInputRoutingController.java
new file mode 100644
index 00000000000..6c9a075672a
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceInputRoutingController.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2024 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.bluetooth;
+
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.KEY_HEARING_DEVICE_GROUP;
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.ORDER_HEARING_DEVICE_INPUT_ROUTING;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.bluetooth.HearingDeviceInputRoutingPreference.InputRoutingValue;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HapClientProfile;
+import com.android.settingslib.bluetooth.HearingAidAudioRoutingConstants;
+import com.android.settingslib.bluetooth.HearingAidAudioRoutingHelper;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.Arrays;
+
+/**
+ * The controller of the hearing device input routing
+ *
+ * It manages the input routing preference and update the routing according to the value.
+ */
+public class BluetoothDetailsHearingDeviceInputRoutingController extends
+ BluetoothDetailsController implements
+ HearingDeviceInputRoutingPreference.InputRoutingCallback {
+
+ private static final String TAG = "BluetoothDetailsHearingDeviceInputRoutingController";
+ static final String KEY_HEARING_DEVICE_INPUT_ROUTING = "hearing_device_input_routing";
+
+ private final HearingAidAudioRoutingHelper mAudioRoutingHelper;
+ private final AudioManager mAudioManager;
+
+ public BluetoothDetailsHearingDeviceInputRoutingController(
+ @NonNull Context context,
+ @NonNull PreferenceFragmentCompat fragment,
+ @NonNull CachedBluetoothDevice device,
+ @NonNull Lifecycle lifecycle) {
+ super(context, fragment, device, lifecycle);
+ mAudioRoutingHelper = new HearingAidAudioRoutingHelper(context);
+ mAudioManager = mContext.getSystemService(AudioManager.class);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ boolean isSupportedProfile = mCachedDevice.getProfiles().stream().anyMatch(
+ profile -> profile instanceof HapClientProfile);
+ boolean isSupportedInputDevice = Arrays.stream(
+ mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).anyMatch(
+ info -> mCachedDevice.getAddress().equals(info.getAddress()));
+ if (isSupportedProfile && !isSupportedInputDevice) {
+ Log.d(TAG, "Not supported input type hearing device.");
+ }
+ return isSupportedProfile && isSupportedInputDevice;
+ }
+
+ @Override
+ protected void init(PreferenceScreen screen) {
+ PreferenceCategory hearingCategory = screen.findPreference(KEY_HEARING_DEVICE_GROUP);
+ if (hearingCategory != null) {
+ hearingCategory.addPreference(
+ createInputRoutingPreference(hearingCategory.getContext()));
+ }
+ }
+
+ @Override
+ protected void refresh() {}
+
+ @Nullable
+ @Override
+ public String getPreferenceKey() {
+ return KEY_HEARING_DEVICE_INPUT_ROUTING;
+ }
+
+ private HearingDeviceInputRoutingPreference createInputRoutingPreference(Context context) {
+ HearingDeviceInputRoutingPreference pref = new HearingDeviceInputRoutingPreference(context);
+ pref.setKey(KEY_HEARING_DEVICE_INPUT_ROUTING);
+ pref.setOrder(ORDER_HEARING_DEVICE_INPUT_ROUTING);
+ pref.setTitle(context.getString(R.string.bluetooth_hearing_device_input_routing_title));
+ pref.setChecked(getUserPreferredInputRoutingValue());
+ pref.setInputRoutingCallback(this);
+ return pref;
+ }
+
+ @InputRoutingValue
+ private int getUserPreferredInputRoutingValue() {
+ return mCachedDevice.getDevice().isMicrophonePreferredForCalls()
+ ? InputRoutingValue.HEARING_DEVICE : InputRoutingValue.BUILTIN_MIC;
+ }
+
+ @Override
+ public void onInputRoutingUpdated(int selectedInputRoutingUiValue) {
+ boolean useBuiltinMic =
+ (selectedInputRoutingUiValue == InputRoutingValue.BUILTIN_MIC);
+ boolean status = mAudioRoutingHelper.setPreferredInputDeviceForCalls(mCachedDevice,
+ useBuiltinMic ? HearingAidAudioRoutingConstants.RoutingValue.BUILTIN_DEVICE
+ : HearingAidAudioRoutingConstants.RoutingValue.AUTO);
+ if (!status) {
+ Log.d(TAG, "Fail to configure setPreferredInputDeviceForCalls");
+ }
+ mCachedDevice.getDevice().setMicrophonePreferredForCalls(!useBuiltinMic);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 403a82429cc..f7829b1eb43 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -373,6 +373,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
}
mFormatter.updateLayout(FragmentTypeModel.DeviceDetailsMainFragment.INSTANCE);
}
+ setDivider(null);
}
@Override
diff --git a/src/com/android/settings/bluetooth/HearingDeviceInputRoutingPreference.java b/src/com/android/settings/bluetooth/HearingDeviceInputRoutingPreference.java
new file mode 100644
index 00000000000..2d09f6103f1
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingDeviceInputRoutingPreference.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2024 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.bluetooth;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RadioGroup;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settings.R;
+import com.android.settingslib.CustomDialogPreferenceCompat;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Preference for controlling the input routing for hearing device.
+ *
+ *
This preference displays a dialog that allows users to choose which input device that want to
+ * use when using this hearing device.
+ */
+public class HearingDeviceInputRoutingPreference extends CustomDialogPreferenceCompat {
+
+ /**
+ * Annotations for possible input routing UI for this hearing device input routing preference.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ InputRoutingValue.HEARING_DEVICE,
+ InputRoutingValue.BUILTIN_MIC
+ })
+ public @interface InputRoutingValue {
+ int HEARING_DEVICE = 0;
+ int BUILTIN_MIC = 1;
+ }
+
+ private static final int INVALID_ID = -1;
+ private final Context mContext;
+ private final int mFromHearingDeviceButtonId = R.id.input_from_hearing_device;
+ private final int mFromBuiltinMicButtonId = R.id.input_from_builtin_mic;
+
+ @Nullable
+ private RadioGroup mInputRoutingGroup;
+ @Nullable
+ private InputRoutingCallback mCallback;
+ // Default value is hearing device as input
+ @InputRoutingValue
+ private int mSelectedInputRoutingValue = InputRoutingValue.HEARING_DEVICE;
+
+
+ public HearingDeviceInputRoutingPreference(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public HearingDeviceInputRoutingPreference(@NonNull Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+
+ mContext = context;
+ setDialogTitle(R.string.bluetooth_hearing_device_input_routing_dialog_title);
+ setDialogLayoutResource(R.layout.hearing_device_input_routing_dialog);
+ setNegativeButtonText(R.string.cancel);
+ setPositiveButtonText(R.string.done_button);
+ }
+
+ /**
+ * Sets the callback to receive input routing updates.
+ */
+ public void setInputRoutingCallback(@NonNull InputRoutingCallback callback) {
+ mCallback = callback;
+ }
+
+ /**
+ * Sets the {@link InputRoutingValue} value to determine which radio button should be checked,
+ * and also update summary accordingly.
+ *
+ * @param inputRoutingValue The input routing value.
+ */
+ public void setChecked(@InputRoutingValue int inputRoutingValue) {
+ mSelectedInputRoutingValue = inputRoutingValue;
+ setSummary(getSummary());
+ }
+
+ @Override
+ protected void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ int prevBtnId = getRadioButtonId(mSelectedInputRoutingValue);
+ int curBtnId = Objects.requireNonNull(mInputRoutingGroup).getCheckedRadioButtonId();
+ if (prevBtnId == curBtnId) {
+ return;
+ }
+
+ setChecked(getSelectedInputRoutingValue());
+ if (mCallback != null) {
+ mCallback.onInputRoutingUpdated(mSelectedInputRoutingValue);
+ }
+ }
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mInputRoutingGroup = view.requireViewById(R.id.input_routing_group);
+ mInputRoutingGroup.check(getRadioButtonId(mSelectedInputRoutingValue));
+ }
+
+ @Nullable
+ @Override
+ public CharSequence getSummary() {
+ return switch (mSelectedInputRoutingValue) {
+ case InputRoutingValue.HEARING_DEVICE -> mContext.getResources().getString(
+ R.string.bluetooth_hearing_device_input_routing_hearing_device_option);
+ case InputRoutingValue.BUILTIN_MIC -> mContext.getResources().getString(
+ R.string.bluetooth_hearing_device_input_routing_builtin_option);
+ default -> null;
+ };
+ }
+
+ private int getRadioButtonId(@InputRoutingValue int inputRoutingValue) {
+ return switch (inputRoutingValue) {
+ case InputRoutingValue.HEARING_DEVICE -> mFromHearingDeviceButtonId;
+ case InputRoutingValue.BUILTIN_MIC -> mFromBuiltinMicButtonId;
+ default -> INVALID_ID;
+ };
+ }
+
+ @InputRoutingValue
+ private int getSelectedInputRoutingValue() {
+ int checkedId = Objects.requireNonNull(mInputRoutingGroup).getCheckedRadioButtonId();
+ if (checkedId == mFromBuiltinMicButtonId) {
+ return InputRoutingValue.BUILTIN_MIC;
+ } else {
+ // Should always return default value hearing device as input if something error
+ // happens.
+ return InputRoutingValue.HEARING_DEVICE;
+ }
+ }
+
+ /**
+ * Callback to be invoked when input routing changes.
+ */
+ public interface InputRoutingCallback {
+
+ /**
+ * Called when the positive button is clicked and input routing is changed.
+ *
+ * @param selectedInputRoutingValue The selected input routing value.
+ */
+ void onInputRoutingUpdated(@InputRoutingValue int selectedInputRoutingValue);
+ }
+}
diff --git a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
index e7ee9e1c37e..1ffbb50e548 100644
--- a/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
+++ b/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverController.java
@@ -92,7 +92,17 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
// This can be enabled by calling:
// `adb shell setprop debug.graphics.angle.developeroption.enable true`
private boolean isAngleDeveloperOptionEnabled() {
- return mSystemProperties.getBoolean(PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION, false);
+ boolean intendedUsingAngleDeveloperOption =
+ mSystemProperties.getBoolean(PROPERTY_DEBUG_ANGLE_DEVELOPER_OPTION, false);
+ if (intendedUsingAngleDeveloperOption) {
+ Log.v(TAG,
+ "ANGLE developer option is enabled in system properties, "
+ + "but temporarily overridden.");
+ }
+
+ // Temporarily disabling for broader rollout.
+ // The feature requires further maturation before general availability.
+ return false;
}
@VisibleForTesting
diff --git a/src/com/android/settings/display/AdaptiveSleepPreference.kt b/src/com/android/settings/display/AdaptiveSleepPreference.kt
index 7cc320d228a..0fe2a098734 100644
--- a/src/com/android/settings/display/AdaptiveSleepPreference.kt
+++ b/src/com/android/settings/display/AdaptiveSleepPreference.kt
@@ -77,6 +77,10 @@ class AdaptiveSleepPreference :
override fun storage(context: Context): KeyValueStore = Storage(context)
+ override fun getReadPermissions(context: Context) = SettingsSecureStore.getReadPermissions()
+
+ override fun getWritePermissions(context: Context) = SettingsSecureStore.getWritePermissions()
+
override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
diff --git a/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt b/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt
index 32d29101847..81592cabd31 100644
--- a/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt
+++ b/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt
@@ -50,6 +50,10 @@ class PeakRefreshRateSwitchPreference :
override fun storage(context: Context): KeyValueStore =
PeakRefreshRateStore(context, SettingsSystemStore.get(context))
+ override fun getReadPermissions(context: Context) = SettingsSystemStore.getReadPermissions()
+
+ override fun getWritePermissions(context: Context) = SettingsSystemStore.getWritePermissions()
+
override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
diff --git a/src/com/android/settings/display/darkmode/DarkModeScreen.kt b/src/com/android/settings/display/darkmode/DarkModeScreen.kt
index 807b0aeb633..87f9f23bf70 100644
--- a/src/com/android/settings/display/darkmode/DarkModeScreen.kt
+++ b/src/com/android/settings/display/darkmode/DarkModeScreen.kt
@@ -16,6 +16,7 @@
package com.android.settings.display.darkmode
+import android.Manifest
import android.app.UiModeManager
import android.content.BroadcastReceiver
import android.content.Context
@@ -29,6 +30,7 @@ import com.android.settings.flags.Flags
import com.android.settingslib.PrimarySwitchPreference
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.datastore.NoOpKeyedObservable
+import com.android.settingslib.datastore.Permissions
import com.android.settingslib.metadata.BooleanValue
import com.android.settingslib.metadata.PersistentPreference
import com.android.settingslib.metadata.PreferenceLifecycleContext
@@ -71,6 +73,11 @@ class DarkModeScreen :
override val keywords: Int
get() = R.string.keywords_dark_ui_mode
+ override fun getReadPermissions(context: Context) = Permissions.EMPTY
+
+ override fun getWritePermissions(context: Context) =
+ Permissions.allOf(Manifest.permission.MODIFY_DAY_NIGHT_MODE)
+
override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
diff --git a/src/com/android/settings/localepicker/NewTermsOfAddressController.java b/src/com/android/settings/localepicker/NewTermsOfAddressController.java
new file mode 100644
index 00000000000..fe92405f1a1
--- /dev/null
+++ b/src/com/android/settings/localepicker/NewTermsOfAddressController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 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.localepicker;
+
+import android.content.Context;
+import android.os.LocaleList;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.app.LocaleStore;
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class NewTermsOfAddressController extends BasePreferenceController {
+
+ public NewTermsOfAddressController(@NonNull Context context, @NonNull String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (Flags.regionalPreferencesApiEnabled()) {
+ if (Flags.termsOfAddressEnabled()) {
+ return checkAvailabilityStatus();
+ }
+ }
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+
+ private int checkAvailabilityStatus() {
+ // If language is not available for system language, or if ToA does not apply to
+ // system language, we will hide it.
+ final Locale defaultLocale = Locale.getDefault();
+ LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(defaultLocale);
+ final List supportedLanguageList = Arrays.asList(
+ mContext.getResources().getStringArray(
+ R.array.terms_of_address_supported_languages));
+ final List notSupportedLocaleList = Arrays.asList(
+ mContext.getResources().getStringArray(
+ R.array.terms_of_address_unsupported_locales));
+
+ final Locale locale = localeInfo.getLocale().stripExtensions();
+ final String language = locale.getLanguage();
+ final String localeTag = locale.toLanguageTag();
+
+ // Supported locales:
+ // 1. All French is supported except fr-CA.
+ // 2. QA language en-XA (LTR pseudo locale), ar_XB (RTL pseudo locale).
+ if ((supportedLanguageList.contains(language)
+ && !notSupportedLocaleList.contains(localeTag))
+ || LocaleList.isPseudoLocale(locale)) {
+ return AVAILABLE;
+ }
+
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressCategoryController.java b/src/com/android/settings/localepicker/TermsOfAddressCategoryController.java
index 01168c7ff7b..1e2fbef7e83 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressCategoryController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressCategoryController.java
@@ -20,7 +20,6 @@ import static com.android.settings.flags.Flags.termsOfAddressEnabled;
import android.content.Context;
import android.os.LocaleList;
-import android.text.TextUtils;
import android.util.Log;
import androidx.preference.PreferenceCategory;
@@ -28,6 +27,7 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.app.LocaleStore;
import com.android.settings.R;
+import com.android.settings.flags.Flags;
import com.android.settings.widget.PreferenceCategoryController;
import java.util.Arrays;
@@ -64,6 +64,9 @@ public class TermsOfAddressCategoryController extends PreferenceCategoryControll
@Override
public int getAvailabilityStatus() {
+ if (Flags.regionalPreferencesApiEnabled()) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
if (!termsOfAddressEnabled()) {
return CONDITIONALLY_UNAVAILABLE;
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index d934c99634b..f201b1ab037 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -468,7 +468,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
final MenuItem item = menu.add(Menu.NONE, R.id.edit_sim_name, Menu.NONE,
- R.string.mobile_network_sim_name);
+ R.string.mobile_network_sim_label_color_title);
item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
diff --git a/src/com/android/settings/wifi/repository/WifiRepository.kt b/src/com/android/settings/wifi/repository/WifiRepository.kt
index 77f0b1b47cf..39bf1aaec07 100644
--- a/src/com/android/settings/wifi/repository/WifiRepository.kt
+++ b/src/com/android/settings/wifi/repository/WifiRepository.kt
@@ -25,6 +25,7 @@ import com.android.settingslib.spaprivileged.framework.common.broadcastReceiverF
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.onStart
class WifiRepository(
private val context: Context,
@@ -32,11 +33,13 @@ class WifiRepository(
context.broadcastReceiverFlow(IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)),
) {
- fun wifiStateFlow() = wifiStateChangedActionFlow
- .map { intent ->
- intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)
- }
- .onEach { Log.d(TAG, "wifiStateFlow: $it") }
+ fun wifiStateFlow(): Flow =
+ wifiStateChangedActionFlow
+ .map { intent ->
+ intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)
+ }
+ .onStart { emit(WifiManager.WIFI_STATE_UNKNOWN) }
+ .onEach { Log.d(TAG, "wifiStateFlow: $it") }
private companion object {
private const val TAG = "WifiRepository"
diff --git a/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionFragmentTest.java
index d3f5457560c..2d2827e038b 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionFragmentTest.java
@@ -16,14 +16,10 @@
package com.android.settings.accessibility;
-import static android.view.accessibility.Flags.FLAG_FORCE_INVERT_COLOR;
-
import static com.google.common.truth.Truth.assertThat;
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.platform.test.annotations.RequiresFlagsDisabled;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -73,20 +69,6 @@ public class ColorAndMotionFragmentTest {
}
@Test
- @RequiresFlagsEnabled(FLAG_FORCE_INVERT_COLOR)
- public void forceInvertEnabled_getNonIndexableKeys_existInXmlLayout() {
- final List niks = ColorAndMotionFragment.SEARCH_INDEX_DATA_PROVIDER
- .getNonIndexableKeys(mContext);
- final List keys =
- XmlTestUtils.getKeysFromPreferenceXml(mContext,
- R.xml.accessibility_color_and_motion);
-
- assertThat(niks).doesNotContain(ColorAndMotionFragment.TOGGLE_FORCE_INVERT);
- assertThat(keys).containsAtLeastElementsIn(niks);
- }
-
- @Test
- @RequiresFlagsDisabled(FLAG_FORCE_INVERT_COLOR)
public void getNonIndexableKeys_existInXmlLayout() {
final List niks = ColorAndMotionFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
@@ -94,7 +76,6 @@ public class ColorAndMotionFragmentTest {
XmlTestUtils.getKeysFromPreferenceXml(mContext,
R.xml.accessibility_color_and_motion);
- assertThat(niks).contains(ColorAndMotionFragment.TOGGLE_FORCE_INVERT);
assertThat(keys).containsAtLeastElementsIn(niks);
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/HearingDeviceAudioRoutingBasePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HearingDeviceAudioRoutingBasePreferenceControllerTest.java
index 4decf68d68c..bf27bf8a721 100644
--- a/tests/robotests/src/com/android/settings/accessibility/HearingDeviceAudioRoutingBasePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/HearingDeviceAudioRoutingBasePreferenceControllerTest.java
@@ -108,7 +108,7 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
when(mBluetoothDevice.getAnonymizedAddress()).thenReturn(TEST_DEVICE_ADDRESS);
when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
doReturn(hearingDeviceAttribute).when(
- mAudioRoutingHelper).getMatchedHearingDeviceAttributes(any());
+ mAudioRoutingHelper).getMatchedHearingDeviceAttributesForOutput(any());
when(mAudioProductStrategyMedia.getAudioAttributesForLegacyStreamType(
AudioManager.STREAM_MUSIC)).thenReturn((new AudioAttributes.Builder()).build());
when(mAudioRoutingHelper.getAudioProductStrategies()).thenReturn(
@@ -143,7 +143,8 @@ public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
@Test
public void onPreferenceChange_noMatchedDeviceAttributes_notCallSetStrategies() {
- when(mAudioRoutingHelper.getMatchedHearingDeviceAttributes(any())).thenReturn(null);
+ when(mAudioRoutingHelper.getMatchedHearingDeviceAttributesForOutput(any())).thenReturn(
+ null);
verify(mAudioRoutingHelper, never()).setPreferredDeviceRoutingStrategies(any(), isNull(),
anyInt());
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleForceInvertPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleForceInvertPreferenceControllerTest.java
index d8197ef9a52..a2b259f60e2 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleForceInvertPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleForceInvertPreferenceControllerTest.java
@@ -23,13 +23,18 @@ import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
+import android.content.res.Configuration;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
+import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
@@ -52,10 +57,7 @@ public class ToggleForceInvertPreferenceControllerTest {
@Before
public void setUp() {
- mController = new ToggleForceInvertPreferenceController(
- mContext,
- ColorAndMotionFragment.TOGGLE_FORCE_INVERT
- );
+ mController = new ToggleForceInvertPreferenceController(mContext, "toggle_force_invert");
}
@Test
@@ -72,6 +74,30 @@ public class ToggleForceInvertPreferenceControllerTest {
.isEqualTo(BasePreferenceController.AVAILABLE);
}
+ @Test
+ public void updateState_darkModeOn_preferenceEnabled() {
+ Configuration config = mContext.getResources().getConfiguration();
+ config.uiMode = Configuration.UI_MODE_NIGHT_YES;
+ mContext.getResources().updateConfiguration(config, null);
+
+ Preference preference = mock(Preference.class);
+ mController.updateState(preference);
+
+ verify(preference).setEnabled(true);
+ }
+
+ @Test
+ public void updateState_darkModeOff_preferenceDisabled() {
+ Configuration config = mContext.getResources().getConfiguration();
+ config.uiMode = Configuration.UI_MODE_NIGHT_NO;
+ mContext.getResources().updateConfiguration(config, null);
+
+ Preference preference = mock(Preference.class);
+ mController.updateState(preference);
+
+ verify(preference).setEnabled(false);
+ }
+
@Test
public void settingOff_reflectsCorrectValue() {
setEnabled(false);
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
index 3bfe8197b1f..81a72694592 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
@@ -64,7 +64,6 @@ import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
-import com.android.settings.flags.Flags;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.SettingsShadowResources;
@@ -403,9 +402,7 @@ public class FaceEnrollIntroductionTest {
assertThat(getGlifLayout(mActivity).getDescriptionText().toString()).isEqualTo(
mContext.getString(
- Flags.biometricsOnboardingEducation()
- ? R.string.security_settings_face_enroll_introduction_message_class3_2
- : R.string.security_settings_face_enroll_introduction_message_class3));
+ R.string.security_settings_face_enroll_introduction_message_class3));
assertThat(mActivity.findViewById(R.id.info_row_less_secure).getVisibility()).isEqualTo(
View.GONE);
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AmbientVolumePreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/AmbientVolumePreferenceTest.java
index 115f642d19b..d8c09786a5d 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AmbientVolumePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AmbientVolumePreferenceTest.java
@@ -41,8 +41,8 @@ import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
-import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.bluetooth.AmbientVolumeUi;
+import com.android.settingslib.widget.SliderPreference;
import org.junit.Before;
import org.junit.Rule;
@@ -99,13 +99,13 @@ public class AmbientVolumePreferenceTest {
slider.setMax(4);
if (side == SIDE_LEFT) {
slider.setKey(KEY_LEFT_SLIDER);
- slider.setProgress(TEST_LEFT_VOLUME_LEVEL);
+ slider.setValue(TEST_LEFT_VOLUME_LEVEL);
} else if (side == SIDE_RIGHT) {
slider.setKey(KEY_RIGHT_SLIDER);
- slider.setProgress(TEST_RIGHT_VOLUME_LEVEL);
+ slider.setValue(TEST_RIGHT_VOLUME_LEVEL);
} else {
slider.setKey(KEY_UNIFIED_SLIDER);
- slider.setProgress(TEST_UNIFIED_VOLUME_LEVEL);
+ slider.setValue(TEST_UNIFIED_VOLUME_LEVEL);
}
});
@@ -223,7 +223,7 @@ public class AmbientVolumePreferenceTest {
private void assertControlUiCorrect() {
final boolean expanded = mPreference.isExpanded();
- Map sliders = mPreference.getSliders();
+ Map sliders = mPreference.getSliders();
assertThat(sliders.get(SIDE_UNIFIED).isVisible()).isEqualTo(!expanded);
assertThat(sliders.get(SIDE_LEFT).isVisible()).isEqualTo(expanded);
assertThat(sliders.get(SIDE_RIGHT).isVisible()).isEqualTo(expanded);
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java
index 4e3c742e284..d0177a8c2a7 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControllerTest.java
@@ -56,6 +56,8 @@ public class BluetoothDetailsHearingDeviceControllerTest extends
private BluetoothDetailsHearingAidsPresetsController mPresetsController;
@Mock
private BluetoothDetailsHearingDeviceSettingsController mHearingDeviceSettingsController;
+ @Mock
+ private BluetoothDetailsHearingDeviceInputRoutingController mInputRoutingController;
private BluetoothDetailsHearingDeviceController mHearingDeviceController;
@@ -67,7 +69,7 @@ public class BluetoothDetailsHearingDeviceControllerTest extends
mHearingDeviceController = new BluetoothDetailsHearingDeviceController(mContext,
mFragment, mLocalManager, mCachedDevice, mLifecycle);
mHearingDeviceController.setSubControllers(mHearingDeviceSettingsController,
- mPresetsController);
+ mPresetsController, mInputRoutingController);
}
@Test
@@ -84,6 +86,13 @@ public class BluetoothDetailsHearingDeviceControllerTest extends
assertThat(mHearingDeviceController.isAvailable()).isTrue();
}
+ @Test
+ public void isAvailable_inputRoutingControllersAvailable_returnFalse() {
+ when(mInputRoutingController.isAvailable()).thenReturn(true);
+
+ assertThat(mHearingDeviceController.isAvailable()).isTrue();
+ }
+
@Test
public void isAvailable_noControllersAvailable_returnFalse() {
when(mHearingDeviceSettingsController.isAvailable()).thenReturn(false);
@@ -146,4 +155,24 @@ public class BluetoothDetailsHearingDeviceControllerTest extends
assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
c -> c instanceof BluetoothDetailsAmbientVolumePreferenceController)).isFalse();
}
+
+ @Test
+ @RequiresFlagsEnabled(
+ com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICES_INPUT_ROUTING_CONTROL)
+ public void initSubControllers_flagEnabled_inputRoutingControllerExist() {
+ mHearingDeviceController.initSubControllers(false);
+
+ assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
+ c -> c instanceof BluetoothDetailsHearingDeviceInputRoutingController)).isTrue();
+ }
+
+ @Test
+ @RequiresFlagsDisabled(
+ com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICES_INPUT_ROUTING_CONTROL)
+ public void initSubControllers_flagDisabled_inputRoutingControllerNotExist() {
+ mHearingDeviceController.initSubControllers(false);
+
+ assertThat(mHearingDeviceController.getSubControllers().stream().anyMatch(
+ c -> c instanceof BluetoothDetailsHearingDeviceInputRoutingController)).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceInputRoutingControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceInputRoutingControllerTest.java
new file mode 100644
index 00000000000..dc4924da6d7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceInputRoutingControllerTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 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.bluetooth;
+
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceController.KEY_HEARING_DEVICE_GROUP;
+import static com.android.settings.bluetooth.BluetoothDetailsHearingDeviceInputRoutingController.KEY_HEARING_DEVICE_INPUT_ROUTING;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothDevice;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.bluetooth.HearingDeviceInputRoutingPreference.InputRoutingValue;
+import com.android.settingslib.bluetooth.HapClientProfile;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Collections;
+import java.util.List;
+
+/** Tests for {@link BluetoothDetailsHearingDeviceInputRoutingController}. */
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsHearingDeviceInputRoutingControllerTest extends
+ BluetoothDetailsControllerTestBase {
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private static final String TEST_ADDRESS = "55:66:77:88:99:AA";
+
+ @Mock
+ private BluetoothDevice mBluetoothDevice;
+ @Mock
+ private HapClientProfile mHapClientProfile;
+ @Spy
+ private AudioManager mAudioManager;
+
+ private BluetoothDetailsHearingDeviceInputRoutingController mController;
+
+ @Override
+ public void setUp() {
+ super.setUp();
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mAudioManager = spy(mContext.getSystemService(AudioManager.class));
+ when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager);
+ setupDevice(makeDefaultDeviceConfig());
+ when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice);
+ PreferenceCategory deviceControls = new PreferenceCategory(mContext);
+ deviceControls.setKey(KEY_HEARING_DEVICE_GROUP);
+ mScreen.addPreference(deviceControls);
+ mController = new BluetoothDetailsHearingDeviceInputRoutingController(mContext,
+ mFragment, mCachedDevice, mLifecycle);
+ }
+
+ @Test
+ public void init_getExpectedPreference() {
+ mController.init(mScreen);
+
+ Preference pref = mScreen.findPreference(KEY_HEARING_DEVICE_INPUT_ROUTING);
+ assertThat(pref.getKey()).isEqualTo(KEY_HEARING_DEVICE_INPUT_ROUTING);
+ }
+
+ @Test
+ public void init_setPreferredMicrophoneTrue_expectedSummary() {
+ when(mBluetoothDevice.isMicrophonePreferredForCalls()).thenReturn(true);
+
+ mController.init(mScreen);
+
+ Preference pref = mScreen.findPreference(KEY_HEARING_DEVICE_INPUT_ROUTING);
+ assertThat(pref.getSummary().toString()).isEqualTo(mContext.getString(
+ R.string.bluetooth_hearing_device_input_routing_hearing_device_option));
+ }
+
+ @Test
+ public void init_setPreferredMicrophoneFalse_expectedSummary() {
+ when(mBluetoothDevice.isMicrophonePreferredForCalls()).thenReturn(false);
+ mController.init(mScreen);
+
+ Preference pref = mScreen.findPreference(KEY_HEARING_DEVICE_INPUT_ROUTING);
+ assertThat(pref.getSummary().toString()).isEqualTo(mContext.getString(
+ R.string.bluetooth_hearing_device_input_routing_builtin_option));
+ }
+
+ @Test
+ public void onInputRoutingUpdated_hearingDevice_setMicrophonePreferredForCallsTrue() {
+ mController.init(mScreen);
+
+ mController.onInputRoutingUpdated(InputRoutingValue.HEARING_DEVICE);
+
+ verify(mBluetoothDevice).setMicrophonePreferredForCalls(true);
+ }
+
+ @Test
+ public void onInputRoutingUpdated_builtin_setMicrophonePreferredForCallsFalse() {
+ mController.init(mScreen);
+
+ mController.onInputRoutingUpdated(InputRoutingValue.BUILTIN_MIC);
+
+ verify(mBluetoothDevice).setMicrophonePreferredForCalls(false);
+ }
+
+ @Test
+ public void isAvailable_validInput_supportHapProfile_returnTrue() {
+ when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
+ AudioDeviceInfo[] mockInfo = new AudioDeviceInfo[] {mockTestAddressInfo(TEST_ADDRESS)};
+ when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(mockInfo);
+ when(mCachedDevice.getProfiles()).thenReturn(List.of(mHapClientProfile));
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_notSupportHapProfile_returnFalse() {
+ when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
+ AudioDeviceInfo[] mockInfo = new AudioDeviceInfo[] {mockTestAddressInfo(TEST_ADDRESS)};
+ when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(mockInfo);
+ when(mCachedDevice.getProfiles()).thenReturn(Collections.emptyList());
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_notValidInputDevice_returnFalse() {
+ when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
+ when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)).thenReturn(
+ new AudioDeviceInfo[] {});
+ when(mCachedDevice.getProfiles()).thenReturn(List.of(mHapClientProfile));
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ private AudioDeviceInfo mockTestAddressInfo(String address) {
+ final AudioDeviceInfo info = mock(AudioDeviceInfo.class);
+ when(info.getType()).thenReturn(AudioDeviceInfo.TYPE_BLE_HEADSET);
+ when(info.getAddress()).thenReturn(address);
+ return info;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/HearingDeviceInputRoutingPreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/HearingDeviceInputRoutingPreferenceTest.java
new file mode 100644
index 00000000000..e5778245ef4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/HearingDeviceInputRoutingPreferenceTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.RadioGroup;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.bluetooth.HearingDeviceInputRoutingPreference.InputRoutingValue;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link HearingDeviceInputRoutingPreference}. */
+@RunWith(RobolectricTestRunner.class)
+public class HearingDeviceInputRoutingPreferenceTest {
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ private HearingDeviceInputRoutingPreference mPreference;
+ private TestInputRoutingCallback mTestInputRoutingCallback;
+ private View mDialogView;
+
+ @Before
+ public void setup() {
+ mDialogView = LayoutInflater.from(mContext).inflate(
+ R.layout.hearing_device_input_routing_dialog, null);
+ mTestInputRoutingCallback = spy(new TestInputRoutingCallback());
+ mPreference = new HearingDeviceInputRoutingPreference(mContext);
+ }
+
+ @Test
+ public void onClick_checkToBuiltinMic_callbackWithBuiltinSpeaker() {
+ mPreference.setChecked(InputRoutingValue.HEARING_DEVICE);
+ mPreference.setInputRoutingCallback(mTestInputRoutingCallback);
+ mPreference.onBindDialogView(mDialogView);
+ RadioGroup radioGroup = mDialogView.requireViewById(R.id.input_routing_group);
+ Dialog dialog = mPreference.getDialog();
+
+ radioGroup.check(R.id.input_from_builtin_mic);
+ mPreference.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
+
+ verify(mTestInputRoutingCallback).onInputRoutingUpdated(InputRoutingValue.BUILTIN_MIC);
+ }
+
+ @Test
+ public void setChecked_checkNoChange_noCallback() {
+ mPreference.setChecked(InputRoutingValue.HEARING_DEVICE);
+ mPreference.setInputRoutingCallback(mTestInputRoutingCallback);
+ mPreference.onBindDialogView(mDialogView);
+ Dialog dialog = mPreference.getDialog();
+
+ mPreference.setChecked(InputRoutingValue.HEARING_DEVICE);
+ mPreference.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
+
+ verify(mTestInputRoutingCallback, never()).onInputRoutingUpdated(anyInt());
+ }
+
+ @Test
+ public void setChecked_builtinMic_expectedSummary() {
+ mPreference.setChecked(InputRoutingValue.BUILTIN_MIC);
+
+ assertThat(mPreference.getSummary().toString()).isEqualTo(
+ mContext.getString(R.string.bluetooth_hearing_device_input_routing_builtin_option));
+ }
+
+ @Test
+ public void setChecked_hearingDevice_expectedSummary() {
+ mPreference.setChecked(InputRoutingValue.HEARING_DEVICE);
+
+ assertThat(mPreference.getSummary().toString()).isEqualTo(mContext.getString(
+ R.string.bluetooth_hearing_device_input_routing_hearing_device_option));
+ }
+
+ private static class TestInputRoutingCallback implements
+ HearingDeviceInputRoutingPreference.InputRoutingCallback {
+
+ @Override
+ public void onInputRoutingUpdated(int selectedInputRoutingUiValue) {}
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/display/darkmode/DarkModeSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeSettingsFragmentTest.java
new file mode 100644
index 00000000000..4bd1daa5bdf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/display/darkmode/DarkModeSettingsFragmentTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 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.display.darkmode;
+
+import static android.view.accessibility.Flags.FLAG_FORCE_INVERT_COLOR;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.testutils.XmlTestUtils;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+/** Tests for {@link DarkModeSettingsFragment}. */
+@RunWith(RobolectricTestRunner.class)
+public class DarkModeSettingsFragmentTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ private DarkModeSettingsFragment mFragment;
+
+ @Before
+ public void setUp() {
+ mFragment = new DarkModeSettingsFragment();
+ }
+
+ @Test
+ public void getMetricsCategory_returnsCorrectCategory() {
+ assertThat(mFragment.getMetricsCategory()).isEqualTo(
+ SettingsEnums.DARK_UI_SETTINGS);
+ }
+
+ @Test
+ public void getPreferenceScreenResId_returnsCorrectXml() {
+ assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(
+ R.xml.dark_mode_settings);
+ }
+
+ @Test
+ public void getLogTag_returnsCorrectTag() {
+ assertThat(mFragment.getLogTag()).isEqualTo("DarkModeSettingsFrag");
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_FORCE_INVERT_COLOR)
+ public void getNonIndexableKeys_forceInvertEnabled_existInXmlLayout() {
+ final List niks = DarkModeSettingsFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getNonIndexableKeys(mContext);
+ final List keys =
+ XmlTestUtils.getKeysFromPreferenceXml(mContext,
+ R.xml.dark_mode_settings);
+
+ assertThat(niks).doesNotContain("toggle_force_invert");
+ assertThat(keys).containsAtLeastElementsIn(niks);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(FLAG_FORCE_INVERT_COLOR)
+ public void getNonIndexableKeys_existInXmlLayout() {
+ final List niks = DarkModeSettingsFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getNonIndexableKeys(mContext);
+ final List keys =
+ XmlTestUtils.getKeysFromPreferenceXml(mContext,
+ R.xml.dark_mode_settings);
+
+ assertThat(niks).contains("toggle_force_invert");
+ assertThat(keys).containsAtLeastElementsIn(niks);
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/wifi/repository/WifiRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/wifi/repository/WifiRepositoryTest.kt
index dae3617c37e..f39e70d9322 100644
--- a/tests/spa_unit/src/com/android/settings/wifi/repository/WifiRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/wifi/repository/WifiRepositoryTest.kt
@@ -21,8 +21,9 @@ import android.content.Intent
import android.net.wifi.WifiManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spa.testutils.lastWithTimeoutOrNull
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
import org.junit.Test
@@ -33,16 +34,25 @@ class WifiRepositoryTest {
private val context: Context = ApplicationProvider.getApplicationContext()
- private val mockWifiStateChangedActionFlow = flowOf(Intent().apply {
- putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED)
- })
-
- private val repository = WifiRepository(context, mockWifiStateChangedActionFlow)
-
@Test
- fun wifiStateFlow() = runBlocking {
- val wifiState = repository.wifiStateFlow().firstWithTimeoutOrNull()
+ fun wifiStateFlow_enabled() = runBlocking {
+ val wifiStateChangedIntent =
+ Intent().apply {
+ putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED)
+ }
+ val repository = WifiRepository(context, flowOf(wifiStateChangedIntent))
+
+ val wifiState = repository.wifiStateFlow().lastWithTimeoutOrNull()
assertThat(wifiState).isEqualTo(WifiManager.WIFI_STATE_ENABLED)
}
+
+ @Test
+ fun wifiStateFlow_unknown() = runBlocking {
+ val repository = WifiRepository(context, emptyFlow())
+
+ val wifiState = repository.wifiStateFlow().lastWithTimeoutOrNull()
+
+ assertThat(wifiState).isEqualTo(WifiManager.WIFI_STATE_UNKNOWN)
+ }
}
diff --git a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
index 8304e5d6083..e65a2491a7d 100644
--- a/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
+++ b/tests/unit/src/com/android/settings/development/graphicsdriver/GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest.java
@@ -182,7 +182,7 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
@Test
public void updateState_PreferenceShouldEnabled() {
mController.updateState(mPreference);
- assertThat(mPreference.isEnabled()).isTrue();
+ assertThat(mPreference.isEnabled()).isFalse();
}
@Test
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressCategoryControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressCategoryControllerTest.java
index b025abdf06a..4728c4541ef 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressCategoryControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressCategoryControllerTest.java
@@ -24,12 +24,17 @@ import static org.mockito.Mockito.spy;
import android.content.Context;
import android.os.Looper;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.settings.flags.Flags;
+
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
@@ -45,6 +50,8 @@ public class TermsOfAddressCategoryControllerTest {
private TermsOfAddressCategoryController mTermsOfAddressCategoryController;
private Locale mCacheLocale;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -65,6 +72,7 @@ public class TermsOfAddressCategoryControllerTest {
}
@Test
+ @DisableFlags(Flags.FLAG_REGIONAL_PREFERENCES_API_ENABLED)
public void getAvailabilityStatus_returnAvailable() {
Locale.setDefault(Locale.forLanguageTag("fr-FR"));