diff --git a/res/layout/accessibility_text_reading_preview.xml b/res/layout/accessibility_text_reading_preview.xml index 2532a7957eb..252736efa0b 100644 --- a/res/layout/accessibility_text_reading_preview.xml +++ b/res/layout/accessibility_text_reading_preview.xml @@ -46,7 +46,6 @@ android:id="@+id/preview_pager" android:layout_width="wrap_content" android:layout_height="217dp" - android:contentDescription="@string/preview_pager_content_description" android:nestedScrollingEnabled="true" /> - - + android:contentDescription="@string/preview_pager_home_content_description" > + + diff --git a/res/layout/accessibility_text_reading_preview_mail_content.xml b/res/layout/accessibility_text_reading_preview_mail_content.xml index e55d3891b38..db5ee7dc91b 100644 --- a/res/layout/accessibility_text_reading_preview_mail_content.xml +++ b/res/layout/accessibility_text_reading_preview_mail_content.xml @@ -14,18 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. --> - + android:contentDescription="@string/preview_pager_email_content_description"> + android:orientation="vertical" + android:importantForAccessibility="noHideDescendants"> + android:contentDescription="@string/preview_pager_message_content_description"> + android:layout_height="wrap_content" + android:importantForAccessibility="noHideDescendants"> @color/homepage_cyan_bg @color/homepage_cyan_fg @color/homepage_cyan_bg - @color/homepage_cyan_fg - @color/homepage_cyan_bg @color/homepage_cyan_fg @color/homepage_cyan_bg @color/homepage_red_fg diff --git a/res/values/config.xml b/res/values/config.xml index ea16af46e11..4b380446540 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -810,23 +810,13 @@ - + @layout/accessibility_text_reading_preview_app_grid @layout/screen_zoom_preview_1 @layout/accessibility_text_reading_preview_mail_content - - - @string/preview_pager_home_content_description - @string/preview_pager_message_content_description - @string/preview_pager_email_content_description - - com.android.vending diff --git a/res/values/strings.xml b/res/values/strings.xml index 28e3ba64bc6..ac99f2d5160 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3695,10 +3695,6 @@ While docked - - - Satellite messaging - APNs @@ -10914,7 +10910,7 @@ Data usage charges may apply. %1$d apps installed - %1$s used - %2$s free + %1$s used - %2$s free Dark theme, font size, brightness @@ -12687,8 +12683,10 @@ Data usage charges may apply. Invalid Network Mode %1$d. Ignore. - - Satellite messaging + + + + Satellite connectivity Send and receive text messages by satellite. Included with your account. @@ -12731,14 +12729,14 @@ Data usage charges may apply. A satellite connection may be slower and is available only in some areas. Weather and certain structures may affect the connection. Calling by satellite isn\u2019t available. Emergency calls may still connect.\n\nIt may take some time for account changes to show in Settings. Contact %1$s for details. A satellite connection may be slower and is available only in some areas. Weather and certain structures may affect the connection. Calling by satellite isn\u2019t available. Emergency calls may still connect. Texting with emergency services may not be available in all areas.\n\nIt may take some time for account changes to show in Settings. Contact %1$s for details. - - More about %1$s + + More about satellite connectivity Can’t turn on %1$s To turn on %1$s, first end the satellite connection - Satellite connectivity + Satellite Satellite connectivity diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml index a0da44051c6..12f3bebdb73 100644 --- a/res/xml/mobile_network_settings.xml +++ b/res/xml/mobile_network_settings.xml @@ -210,7 +210,7 @@ diff --git a/res/xml/satellite_setting.xml b/res/xml/satellite_setting.xml index 74bee71c31a..06509700cf7 100644 --- a/res/xml/satellite_setting.xml +++ b/res/xml/satellite_setting.xml @@ -32,7 +32,8 @@ + android:title="@string/category_title_your_satellite_plan" + settings:controller="com.android.settings.network.telephony.satellite.SatelliteSettingAccountInfoController"> { + if (mBluetoothAdapter.getScanMode() + != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { + mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); + } + }); } public void stop() { @@ -67,7 +71,8 @@ public class AlwaysDiscoverable extends BroadcastReceiver { } mContext.unregisterReceiver(this); mStarted = false; - mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE); + ThreadUtils.postOnBackgroundThread( + () -> mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE)); } @Override @@ -76,9 +81,11 @@ public class AlwaysDiscoverable extends BroadcastReceiver { if (action != BluetoothAdapter.ACTION_SCAN_MODE_CHANGED) { return; } - if (mBluetoothAdapter.getScanMode() - != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { - mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); - } + ThreadUtils.postOnBackgroundThread(() -> { + if (mBluetoothAdapter.getScanMode() + != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { + mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); + } + }); } } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java index 0c8b16bfab6..be861a66dd9 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceController.java @@ -207,7 +207,7 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP (AudioSharingDeviceItem item) -> { int currentCallAudioGroupId = BluetoothUtils.getPrimaryGroupIdForBroadcast( - mContext.getContentResolver()); + mContext.getContentResolver(), mBtManager); int clickedGroupId = item.getGroupId(); if (clickedGroupId == currentCallAudioGroupId) { Log.d(TAG, "Skip set call audio device: unchanged"); @@ -414,7 +414,8 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP private Pair getActiveItemWithIndex() { List deviceItems = new ArrayList<>(mDeviceItemsInSharingSession); int fallbackActiveGroupId = - BluetoothUtils.getPrimaryGroupIdForBroadcast(mContext.getContentResolver()); + BluetoothUtils.getPrimaryGroupIdForBroadcast(mContext.getContentResolver(), + mBtManager); if (fallbackActiveGroupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { for (AudioSharingDeviceItem item : deviceItems) { if (item.getGroupId() == fallbackActiveGroupId) { diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java index 7b670a80fba..1659d2da2da 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupController.java @@ -418,7 +418,8 @@ public class AudioSharingDeviceVolumeGroupController extends AudioSharingBasePre int groupId = BluetoothUtils.getGroupId(cachedDevice); // The fallback device rank first among the audio sharing device list. return (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID - && groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast(mContentResolver)) + && groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast(mContentResolver, + mBtManager)) ? 0 : 1; } diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java index 816ec6e2cd3..944ac25941b 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreference.java @@ -46,6 +46,7 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference { private final Context mContext; private final CachedBluetoothDevice mCachedDevice; + @Nullable private final LocalBluetoothManager mBtManager; @Nullable protected SeekBar mSeekBar; private Boolean mTrackingTouch = false; private MetricsFeatureProvider mMetricsFeatureProvider = @@ -57,6 +58,7 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference { setLayoutResource(R.layout.preference_volume_slider); mContext = context; mCachedDevice = device; + mBtManager = Utils.getLocalBtManager(mContext); } @NonNull @@ -110,7 +112,7 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference { if (groupId != BluetoothCsipSetCoordinator.GROUP_ID_INVALID && groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast( - mContext.getContentResolver())) { + mContext.getContentResolver(), mBtManager)) { // Set media stream volume for primary buds, audio manager will // update all buds volume in the audio sharing. setAudioManagerStreamVolume(progress); @@ -126,9 +128,8 @@ public class AudioSharingDeviceVolumePreference extends SeekBarPreference { Log.d(TAG, "Skip set device volume, device is null"); return; } - LocalBluetoothManager btManager = Utils.getLocalBtManager(mContext); - VolumeControlProfile vc = - btManager == null ? null : btManager.getProfileManager().getVolumeControlProfile(); + VolumeControlProfile vc = mBtManager == null ? null + : mBtManager.getProfileManager().getVolumeControlProfile(); if (vc != null) { vc.setDeviceVolume(device, progress, /* isGroupOp= */ true); mMetricsFeatureProvider.action( diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java index f61fbb6d13a..4fd8a211c35 100644 --- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java +++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java @@ -507,10 +507,6 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider { R.dimen.dashboard_tile_image_size); drawable.setLayerSize(0, size, size); return drawable; - } else if (TextUtils.equals(tile.getPackageName(), - mPackageManager.getWellbeingPackageName())) { - return getRoundedIcon(iconDrawable, - R.color.homepage_wellbeing_foreground, R.color.homepage_wellbeing_background); } Pair colors = getSchemedColors(tile); diff --git a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java index 1955f36059a..05e4f25ee78 100644 --- a/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java +++ b/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceController.java @@ -93,7 +93,7 @@ public class TopLevelStoragePreferenceController extends BasePreferenceControlle private String getSummary(long usedBytes, long totalBytes) { NumberFormat percentageFormat = NumberFormat.getPercentInstance(); - return mContext.getString(R.string.storage_summary, + return mContext.getString(R.string.storage_toplevel_summary, totalBytes == 0L ? "0" : percentageFormat.format(((double) usedBytes) / totalBytes), Formatter.formatFileSize(mContext, totalBytes - usedBytes)); } diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java index 22e34317702..2a731bf50b7 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java +++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java @@ -73,7 +73,7 @@ public class LowStorageSlice implements CustomSliceable { if (usedPercentage < LOW_STORAGE_THRESHOLD) { // For clients that ignore error checking, a generic storage slice will be given. final CharSequence titleStorage = mContext.getText(R.string.storage_settings); - final String summaryStorage = mContext.getString(R.string.storage_summary, + final String summaryStorage = mContext.getString(R.string.storage_toplevel_summary, percentageString, freeSizeString); return listBuilder diff --git a/src/com/android/settings/network/AdaptiveConnectivityScreen.kt b/src/com/android/settings/network/AdaptiveConnectivityScreen.kt index 829ec8dc534..8d3878db683 100644 --- a/src/com/android/settings/network/AdaptiveConnectivityScreen.kt +++ b/src/com/android/settings/network/AdaptiveConnectivityScreen.kt @@ -37,6 +37,10 @@ class AdaptiveConnectivityScreen : PreferenceScreenCreator { override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(context, this) { +AdaptiveConnectivityTogglePreference() + if (Flags.enableNestedToggleSwitches()) { + +WifiScorerTogglePreference() + +AdaptiveMobileNetworkTogglePreference() + } } override fun hasCompleteHierarchy() = false @@ -44,4 +48,4 @@ class AdaptiveConnectivityScreen : PreferenceScreenCreator { companion object { const val KEY = "adaptive_connectivity" } -} +} \ No newline at end of file diff --git a/src/com/android/settings/network/AdaptiveConnectivitySettings.java b/src/com/android/settings/network/AdaptiveConnectivitySettings.java index a099d79f007..20bb73a464e 100644 --- a/src/com/android/settings/network/AdaptiveConnectivitySettings.java +++ b/src/com/android/settings/network/AdaptiveConnectivitySettings.java @@ -15,9 +15,14 @@ */ package com.android.settings.network; +import static android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED; +import static android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED; + import android.app.settings.SettingsEnums; import android.content.Context; +import android.net.wifi.WifiManager; import android.os.Bundle; +import android.provider.Settings; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -31,12 +36,7 @@ import com.android.settingslib.search.SearchIndexable; /** Adaptive connectivity is a feature which automatically manages network connections. */ @SearchIndexable public class AdaptiveConnectivitySettings extends DashboardFragment { - private static final String TAG = "AdaptiveConnectivitySettings"; - protected static final String ADAPTIVE_CONNECTIVITY_WIFI_ENABLED = - "adaptive_connectivity_wifi_enabled"; - protected static final String ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED = - "adaptive_connectivity_mobile_network_enabled"; @Override public int getMetricsCategory() { @@ -65,16 +65,25 @@ public class AdaptiveConnectivitySettings extends DashboardFragment { public void onCreatePreferences(@NonNull Bundle savedInstanceState, @NonNull String rootKey) { Log.i("Settings", "onCreatePreferences"); super.onCreatePreferences(savedInstanceState, rootKey); - if (Flags.enableNestedToggleSwitches()) { - setSwitchVisibility(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, true); - setSwitchVisibility(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, true); + if (Flags.enableNestedToggleSwitches() && !isCatalystEnabled()) { + setupSwitchPreferenceCompat(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED); + setupSwitchPreferenceCompat(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED); } } - private void setSwitchVisibility(String key, boolean isVisible) { + private void setupSwitchPreferenceCompat(String key) { SwitchPreferenceCompat switchPreference = findPreference(key); if (switchPreference != null) { - switchPreference.setVisible(isVisible); + switchPreference.setOnPreferenceChangeListener( + (preference, newValue) -> { + boolean isChecked = (Boolean) newValue; + Settings.Secure.putInt(getContentResolver(), key, isChecked ? 1 : 0); + if (preference.getKey().equals(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)) { + getSystemService(WifiManager.class).setWifiScoringEnabled(isChecked); + } + return true; + }); + switchPreference.setVisible(true); } } } diff --git a/src/com/android/settings/network/AdaptiveMobileNetworkTogglePreference.kt b/src/com/android/settings/network/AdaptiveMobileNetworkTogglePreference.kt new file mode 100644 index 00000000000..2b6ec916dc3 --- /dev/null +++ b/src/com/android/settings/network/AdaptiveMobileNetworkTogglePreference.kt @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2025 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.network + +import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY +import android.content.Context +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED +import com.android.settings.R +import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY +import com.android.settings.metrics.PreferenceActionMetricsProvider +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.KeyValueStoreDelegate +import com.android.settingslib.datastore.SettingsSecureStore +import com.android.settingslib.datastore.SettingsStore +import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.metadata.SensitivityLevel +import com.android.settingslib.metadata.SwitchPreference + +class AdaptiveMobileNetworkTogglePreference() : + SwitchPreference( + KEY, + R.string.adaptive_connectivity_mobile_network_switch_title, + ), + PreferenceActionMetricsProvider { + + override val preferenceActionMetrics: Int + get() = ACTION_ADAPTIVE_CONNECTIVITY + + override val key: String + get() = KEY + + override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) + + override fun storage(context: Context): KeyValueStore = + AdaptiveMobileNetworkToggleStorage(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 + + override fun getWritePermit( + context: Context, + value: Boolean?, + callingPid: Int, + callingUid: Int, + ) = ReadWritePermit.ALLOW + + override val sensitivityLevel + get() = SensitivityLevel.NO_SENSITIVITY + + @Suppress("UNCHECKED_CAST") + private class AdaptiveMobileNetworkToggleStorage( + private val context: Context, + private val settingsStore: SettingsStore = SettingsSecureStore.get(context), + ) : KeyValueStoreDelegate { + + override val keyValueStoreDelegate + get() = settingsStore + + override fun getDefaultValue(key: String, valueType: Class) = + DEFAULT_VALUE as T + + override fun setValue(key: String, valueType: Class, value: T?) { + settingsStore.setValue(key, valueType, value) + } + } + + companion object { + const val KEY = ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED + const val DEFAULT_VALUE = true + } +} \ No newline at end of file diff --git a/src/com/android/settings/network/WifiScorerTogglePreference.kt b/src/com/android/settings/network/WifiScorerTogglePreference.kt new file mode 100644 index 00000000000..b94f6217dad --- /dev/null +++ b/src/com/android/settings/network/WifiScorerTogglePreference.kt @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2025 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.network + +import android.Manifest +import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY +import android.content.Context +import android.net.wifi.WifiManager +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED +import androidx.annotation.RequiresPermission +import com.android.settings.R +import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY +import com.android.settings.metrics.PreferenceActionMetricsProvider +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.KeyValueStoreDelegate +import com.android.settingslib.datastore.SettingsSecureStore +import com.android.settingslib.datastore.SettingsStore +import com.android.settingslib.datastore.and +import com.android.settingslib.metadata.ReadWritePermit +import com.android.settingslib.metadata.SensitivityLevel +import com.android.settingslib.metadata.SwitchPreference + +class WifiScorerTogglePreference() : + SwitchPreference( + KEY, + R.string.adaptive_connectivity_wifi_switch_title + ), + PreferenceActionMetricsProvider { + + override val preferenceActionMetrics: Int + get() = ACTION_ADAPTIVE_CONNECTIVITY + + override val key: String + get() = KEY + + override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY) + + override fun storage(context: Context): KeyValueStore = + WifiScorerToggleStorage(context) + + override fun getReadPermissions(context: Context) = SettingsSecureStore.getReadPermissions() + + override fun getWritePermissions(context: Context) = + SettingsSecureStore.getWritePermissions() and Manifest.permission.NETWORK_SETTINGS + + override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = + ReadWritePermit.ALLOW + + override fun getWritePermit( + context: Context, + value: Boolean?, + callingPid: Int, + callingUid: Int, + ) = ReadWritePermit.ALLOW + + override val sensitivityLevel + get() = SensitivityLevel.NO_SENSITIVITY + + @Suppress("UNCHECKED_CAST") + private class WifiScorerToggleStorage( + private val context: Context, + private val settingsStore: SettingsStore = SettingsSecureStore.get(context), + ) : KeyValueStoreDelegate { + + override val keyValueStoreDelegate + get() = settingsStore + + override fun getDefaultValue(key: String, valueType: Class) = + DEFAULT_VALUE as T + + @RequiresPermission(Manifest.permission.NETWORK_SETTINGS) + override fun setValue(key: String, valueType: Class, value: T?) { + settingsStore.setValue(key, valueType, value) + context + .getSystemService(WifiManager::class.java) + ?.setWifiScoringEnabled( + (value as Boolean?) + ?: DEFAULT_VALUE + ) + } + } + + companion object { + const val KEY = ADAPTIVE_CONNECTIVITY_WIFI_ENABLED + const val DEFAULT_VALUE = true + } +} \ No newline at end of file diff --git a/src/com/android/settings/network/telephony/satellite/SatelliteSetting.java b/src/com/android/settings/network/telephony/satellite/SatelliteSetting.java index 851038a7a45..5af26584613 100644 --- a/src/com/android/settings/network/telephony/satellite/SatelliteSetting.java +++ b/src/com/android/settings/network/telephony/satellite/SatelliteSetting.java @@ -28,9 +28,6 @@ import android.app.Activity; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.Bundle; import android.os.PersistableBundle; import android.os.UserManager; @@ -38,10 +35,6 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.satellite.SatelliteManager; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.style.StyleSpan; -import android.text.style.UnderlineSpan; import android.util.Log; import android.view.View; @@ -53,7 +46,6 @@ import androidx.preference.PreferenceCategory; import com.android.settings.R; import com.android.settings.dashboard.RestrictedDashboardFragment; import com.android.settingslib.HelpUtils; -import com.android.settingslib.Utils; import com.android.settingslib.widget.FooterPreference; import java.util.Set; @@ -61,12 +53,7 @@ import java.util.Set; /** Handle Satellite Setting Preference Layout. */ public class SatelliteSetting extends RestrictedDashboardFragment { private static final String TAG = "SatelliteSetting"; - private static final String PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN = - "key_category_your_satellite_plan"; - private static final String PREF_KEY_YOUR_SATELLITE_PLAN = "key_your_satellite_plan"; private static final String PREF_KEY_CATEGORY_HOW_IT_WORKS = "key_category_how_it_works"; - private static final String PREF_KEY_YOUR_SATELLITE_DATA_PLAN = "key_your_satellite_data_plan"; - private static final String PREF_KEY_CATEGORY_ABOUT_SATELLITE = "key_category_about_satellite"; private static final String KEY_FOOTER_PREFERENCE = "satellite_setting_extra_info_footer_pref"; private static final String KEY_SATELLITE_CONNECTION_GUIDE = "key_satellite_connection_guide"; private static final String KEY_SUPPORTED_SERVICE = "key_supported_service"; @@ -99,9 +86,15 @@ public class SatelliteSetting extends RestrictedDashboardFragment { mActivity = getActivity(); mSubId = mActivity.getIntent().getIntExtra(SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + mConfigBundle = fetchCarrierConfigData(mSubId); + mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false); + mIsSmsAvailableForManualType = getIntent().getBooleanExtra( + EXTRA_IS_SMS_AVAILABLE_FOR_MANUAL_TYPE, false); use(SatelliteAppListCategoryController.class).init(); use(SatelliteSettingAboutContentController.class).init(mSubId); + use(SatelliteSettingAccountInfoController.class).init(mSubId, mConfigBundle, + mIsSmsAvailableForManualType, mIsServiceDataType); } @Override @@ -114,8 +107,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment { return; } - mConfigBundle = fetchCarrierConfigData(mSubId); - if (!isSatelliteAttachSupported(mSubId)) { Log.d(TAG, "SatelliteSettings: KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is false, " + "do nothing."); @@ -123,9 +114,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment { return; } - mIsServiceDataType = getIntent().getBooleanExtra(EXTRA_IS_SERVICE_DATA_TYPE, false); - mIsSmsAvailableForManualType = getIntent().getBooleanExtra( - EXTRA_IS_SMS_AVAILABLE_FOR_MANUAL_TYPE, false); mSimOperatorName = getSystemService(TelephonyManager.class).getSimOperatorName(mSubId); } @@ -133,8 +121,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); boolean isSatelliteEligible = isSatelliteEligible(); - updateTitle(); - updateMobilePlan(isSatelliteEligible); updateHowItWorksContent(isSatelliteEligible); updateFooterContent(); } @@ -149,65 +135,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment { return R.xml.satellite_setting; } - private void updateTitle() { - findPreference("satellite_setting").setTitle(getSubjectString()); - } - - private void updateMobilePlan(boolean isSatelliteEligible) { - PreferenceCategory prefCategory = findPreference(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); - if (prefCategory == null || !mConfigBundle.getBoolean( - KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL)) { - prefCategory.setVisible(false); - return; - } - - // Your mobile plan - prefCategory.setTitle(getResources().getString(R.string.category_title_your_satellite_plan, - mSimOperatorName)); - Preference messagingPreference = findPreference(PREF_KEY_YOUR_SATELLITE_PLAN); - - Drawable icon = getContext().getDrawable(R.drawable.ic_check_circle_24px); - if (isSatelliteEligible) { - /* In case satellite is allowed by carrier's entitlement server, the page will show - the check icon with guidance that satellite is included in user's mobile plan */ - messagingPreference.setTitle(R.string.title_have_satellite_plan); - if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { - if (mIsServiceDataType) { - Preference connectivityPreference = findPreference( - PREF_KEY_YOUR_SATELLITE_DATA_PLAN); - connectivityPreference.setTitle(R.string.title_have_satellite_data_plan); - connectivityPreference.setIcon(icon); - connectivityPreference.setVisible(true); - } - } - } else { - /* Or, it will show the blocked icon with the guidance that satellite is not included - in user's mobile plan */ - messagingPreference.setTitle(R.string.title_no_satellite_plan); - /* And, the link url provides more information via web page will be shown */ - SpannableString spannable = new SpannableString( - getResources().getString(R.string.summary_add_satellite_setting)); - spannable.setSpan(new UnderlineSpan(), 0, spannable.length(), - Spanned.SPAN_INCLUSIVE_INCLUSIVE); - spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(), - Spanned.SPAN_INCLUSIVE_INCLUSIVE); - messagingPreference.setSummary(spannable); - /* The link will lead users to a guide page */ - messagingPreference.setOnPreferenceClickListener(pref -> { - String url = readSatelliteMoreInfoString(); - if (!url.isEmpty()) { - Uri uri = Uri.parse(url); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } - return true; - }); - icon = getResources().getDrawable(R.drawable.ic_block_24px, null); - } - icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)); - messagingPreference.setIcon(icon); - } - private void updateHowItWorksContent(boolean isSatelliteEligible) { /* Composes "How it works" section, which guides how users can use satellite messaging, when satellite messaging is included in user's mobile plan, or it'll will be grey out. */ @@ -250,7 +177,7 @@ public class SatelliteSetting extends RestrictedDashboardFragment { }); footerPreference.setLearnMoreText( - getString(R.string.more_about_satellite_messaging, getDescriptionString())); + getString(R.string.more_about_satellite_messaging)); } } } @@ -304,32 +231,6 @@ public class SatelliteSetting extends RestrictedDashboardFragment { return mConfigBundle.getBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false); } - // This is for a word which first letter is uppercase. e.g. Satellite messaging. - private String getSubjectString() { - int result; - if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { - result = mIsServiceDataType - ? R.string.title_satellite_setting_connectivity - : R.string.satellite_setting_title; - } else { - result = R.string.satellite_setting_title; - } - return getString(result); - } - - // This is for a word without uppercase letter. e.g. satellite messaging. - private String getDescriptionString() { - int result; - if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { - result = mIsServiceDataType - ? R.string.description_satellite_setting_connectivity - : R.string.description_satellite_setting_messaging; - } else { - result = R.string.satellite_setting_title; - } - return getString(result); - } - private static void loge(String message) { Log.e(TAG, message); } diff --git a/src/com/android/settings/network/telephony/satellite/SatelliteSettingAccountInfoController.java b/src/com/android/settings/network/telephony/satellite/SatelliteSettingAccountInfoController.java new file mode 100644 index 00000000000..f688a92305e --- /dev/null +++ b/src/com/android/settings/network/telephony/satellite/SatelliteSettingAccountInfoController.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2025 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.network.telephony.satellite; + +import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL; +import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT; +import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL; +import static android.telephony.CarrierConfigManager.KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.PersistableBundle; +import android.telephony.TelephonyManager; +import android.telephony.satellite.SatelliteManager; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.style.StyleSpan; +import android.text.style.UnderlineSpan; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.network.telephony.TelephonyBasePreferenceController; +import com.android.settingslib.Utils; + +import java.util.Set; + +/** A controller to control content of "Your mobile plan". */ +public class SatelliteSettingAccountInfoController extends TelephonyBasePreferenceController { + private static final String TAG = "SatelliteSettingAccountInfoController"; + @VisibleForTesting + static final String PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN = + "key_category_your_satellite_plan"; + @VisibleForTesting + static final String PREF_KEY_YOUR_SATELLITE_PLAN = "key_your_satellite_plan"; + @VisibleForTesting + static final String PREF_KEY_YOUR_SATELLITE_DATA_PLAN = "key_your_satellite_data_plan"; + + private PreferenceScreen mScreen; + private String mSimOperatorName; + private boolean mIsSmsAvailable; + private boolean mIsDataAvailable; + private boolean mIsSatelliteEligible; + private PersistableBundle mConfigBundle = new PersistableBundle(); + + public SatelliteSettingAccountInfoController(@NonNull Context context, + @NonNull String preferenceKey) { + super(context, preferenceKey); + } + + /** Initialize the UI settings. */ + public void init(int subId, @NonNull PersistableBundle configBundle, boolean isSmsAvailable, + boolean isDataAvailable) { + mSubId = subId; + mConfigBundle = configBundle; + mSimOperatorName = mContext.getSystemService(TelephonyManager.class).getSimOperatorName( + mSubId); + mIsSmsAvailable = isSmsAvailable; + mIsDataAvailable = isDataAvailable; + mIsSatelliteEligible = isSatelliteEligible(); + } + + @Override + public void displayPreference(@NonNull PreferenceScreen screen) { + mScreen = screen; + super.displayPreference(screen); + PreferenceCategory prefCategory = screen.findPreference( + PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); + // Your mobile plan + prefCategory.setTitle(mContext.getString(R.string.category_title_your_satellite_plan, + mSimOperatorName)); + + if (mIsSatelliteEligible) { + handleEligibleUI(); + return; + } + handleIneligibleUI(); + } + + @Override + public int getAvailabilityStatus(int subId) { + return mConfigBundle.getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + private void handleEligibleUI() { + Preference messagingPreference = mScreen.findPreference(PREF_KEY_YOUR_SATELLITE_PLAN); + Drawable icon = mContext.getDrawable(R.drawable.ic_check_circle_24px); + /* In case satellite is allowed by carrier's entitlement server, the page will show + the check icon with guidance that satellite is included in user's mobile plan */ + messagingPreference.setTitle(R.string.title_have_satellite_plan); + if (com.android.settings.flags.Flags.satelliteOemSettingsUxMigration()) { + if (mIsDataAvailable) { + Preference connectivityPreference = mScreen.findPreference( + PREF_KEY_YOUR_SATELLITE_DATA_PLAN); + connectivityPreference.setTitle(R.string.title_have_satellite_data_plan); + connectivityPreference.setIcon(icon); + connectivityPreference.setVisible(true); + } + } + icon.setTintList(Utils.getColorAttr(mContext, android.R.attr.textColorPrimary)); + messagingPreference.setIcon(icon); + } + + private void handleIneligibleUI() { + Preference messagingPreference = mScreen.findPreference(PREF_KEY_YOUR_SATELLITE_PLAN); + /* Or, it will show the blocked icon with the guidance that satellite is not included + in user's mobile plan */ + messagingPreference.setTitle(R.string.title_no_satellite_plan); + String url = mConfigBundle.getString(KEY_SATELLITE_INFORMATION_REDIRECT_URL_STRING, ""); + if (!url.isEmpty()) { + /* And, the link url provides more information via web page will be shown */ + SpannableString spannable = new SpannableString( + mContext.getString(R.string.summary_add_satellite_setting)); + spannable.setSpan(new UnderlineSpan(), 0, spannable.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(), + Spanned.SPAN_INCLUSIVE_INCLUSIVE); + messagingPreference.setSummary(spannable); + /* The link will lead users to a guide page */ + messagingPreference.setOnPreferenceClickListener(pref -> { + Uri uri = Uri.parse(url); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + mContext.startActivity(intent); + return true; + }); + } + + Drawable icon = mContext.getDrawable(R.drawable.ic_block_24px); + icon.setTintList(Utils.getColorAttr(mContext, android.R.attr.textColorPrimary)); + messagingPreference.setIcon(icon); + } + + @VisibleForTesting + protected boolean isSatelliteEligible() { + if (mConfigBundle.getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT) + == CARRIER_ROAMING_NTN_CONNECT_MANUAL) { + return mIsSmsAvailable; + } + SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class); + if (satelliteManager == null) { + Log.d(TAG, "SatelliteManager is null."); + return false; + } + try { + Set restrictionReason = + satelliteManager.getAttachRestrictionReasonsForCarrier(mSubId); + return !restrictionReason.contains( + SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT); + } catch (SecurityException | IllegalStateException | IllegalArgumentException ex) { + Log.d(TAG, "Error to getAttachRestrictionReasonsForCarrier : " + ex.toString()); + return false; + } + } +} diff --git a/src/com/android/settings/network/telephony/satellite/SatelliteSettingPreferenceController.java b/src/com/android/settings/network/telephony/satellite/SatelliteSettingPreferenceController.java index 18217fd5d62..04f2c5fe73f 100644 --- a/src/com/android/settings/network/telephony/satellite/SatelliteSettingPreferenceController.java +++ b/src/com/android/settings/network/telephony/satellite/SatelliteSettingPreferenceController.java @@ -145,7 +145,6 @@ public class SatelliteSettingPreferenceController extends public void updateState(@Nullable Preference preference) { super.updateState(preference); if (preference != null && preference.getKey().equals(getPreferenceKey())) { - updateTitle(preference); updateSummary(preference); } } @@ -170,12 +169,6 @@ public class SatelliteSettingPreferenceController extends return false; } - private void updateTitle(Preference preference) { - preference.setTitle(mCarrierRoamingNtnModeCallback.isSatelliteServiceDataType() - ? R.string.title_satellite_setting_connectivity - : R.string.satellite_setting_title); - } - private void updateSummary(Preference preference) { if (preference == null) { logd("updateSummary - no Preference"); @@ -186,17 +179,17 @@ public class SatelliteSettingPreferenceController extends return; } - if (!mCarrierConfigs.getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL)) { - preference.setSummary(R.string.satellite_setting_summary_without_entitlement); - return; - } - if (isCarrierRoamingNtnConnectedTypeManual()) { preference.setSummary( mCarrierRoamingNtnModeCallback.isSatelliteSmsAvailable() ? R.string.satellite_setting_enabled_summary : R.string.satellite_setting_disabled_summary); } else { + if (!mCarrierConfigs.getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL)) { + preference.setSummary(R.string.satellite_setting_summary_without_entitlement); + return; + } + try { Set restrictionReason = mSatelliteManager.getAttachRestrictionReasonsForCarrier(mSubId); diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewControllerTest.java index 81c869d5063..375952f725c 100644 --- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewControllerTest.java @@ -16,8 +16,6 @@ package com.android.settings.accessibility; -import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -78,15 +76,6 @@ public class TextReadingPreviewControllerTest { mDisplaySizePreference = new AccessibilitySeekBarPreference(mContext, /* attr= */ null); } - @Test - public void numberOfPreviewSamples_numberOfPreviewContentDescription_isEqual() { - int[] previewSamples = TextReadingPreviewController.getPreviewSampleLayouts(mContext); - int[] previewContentDescriptions = - TextReadingPreviewController.getPreviewSampleContentDescriptions(mContext); - - assertThat(previewSamples.length).isEqualTo(previewContentDescriptions.length); - } - @Test public void initPreviewerAdapter_verifyAction() { when(mPreferenceScreen.findPreference(PREVIEW_KEY)).thenReturn(mPreviewPreference); diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java index 9cd8fa232c5..ac503bd9ebc 100644 --- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java @@ -49,48 +49,28 @@ import org.robolectric.RobolectricTestRunner; */ @RunWith(RobolectricTestRunner.class) public class TextReadingPreviewPreferenceTest { - private Context mContext; private TextReadingPreviewPreference mTextReadingPreviewPreference; private PreferenceViewHolder mHolder; private ViewPager mViewPager; private PreviewPagerAdapter mPreviewPagerAdapter; private int mPreviewSampleCount; - private int[] mPreviewContentDescriptions; @Before public void setUp() { - mContext = ApplicationProvider.getApplicationContext(); - mPreviewContentDescriptions = - TextReadingPreviewController.getPreviewSampleContentDescriptions(mContext); - final int[] previewSamples = TextReadingPreviewController.getPreviewSampleLayouts(mContext); + final Context context = ApplicationProvider.getApplicationContext(); + final int[] previewSamples = TextReadingPreviewController.getPreviewSampleLayouts(context); mPreviewSampleCount = previewSamples.length; final Configuration[] configurations = createConfigurations(mPreviewSampleCount); - mTextReadingPreviewPreference = new TextReadingPreviewPreference(mContext); + mTextReadingPreviewPreference = new TextReadingPreviewPreference(context); mPreviewPagerAdapter = - spy(new PreviewPagerAdapter(mContext, /* isLayoutRtl= */ false, + spy(new PreviewPagerAdapter(context, /* isLayoutRtl= */ false, previewSamples, configurations)); - final LayoutInflater inflater = LayoutInflater.from(mContext); + final LayoutInflater inflater = LayoutInflater.from(context); final View view = inflater.inflate(mTextReadingPreviewPreference.getLayoutResource(), - new LinearLayout(mContext), false); + new LinearLayout(context), false); mHolder = PreferenceViewHolder.createInstanceForTests(view); mViewPager = view.findViewById(R.id.preview_pager); - mTextReadingPreviewPreference.setContentDescription(mPreviewContentDescriptions); - } - - @Test - public void changePreviewPage_getExpectedContentDescription() { - mTextReadingPreviewPreference.setPreviewAdapter(mPreviewPagerAdapter); - mTextReadingPreviewPreference.onBindViewHolder(mHolder); - - // Verify the initial content description - assertThat(mViewPager.getContentDescription().toString()) - .isEqualTo(mContext.getString(mPreviewContentDescriptions[0])); - - // Change the preview page - mViewPager.setCurrentItem(1); - assertThat(mViewPager.getContentDescription().toString()) - .isEqualTo(mContext.getString(mPreviewContentDescriptions[1])); } @Test diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java index 4f6fed7b732..7fece8bb2d3 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingCallAudioPreferenceControllerTest.java @@ -43,6 +43,8 @@ import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.os.Looper; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.view.View; @@ -78,6 +80,7 @@ import com.android.settingslib.flags.Flags; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import org.junit.After; import org.junit.Before; @@ -113,9 +116,6 @@ public class AudioSharingCallAudioPreferenceControllerTest { private static final int TEST_DEVICE_GROUP_ID1 = 1; private static final int TEST_DEVICE_GROUP_ID2 = 2; - private static final String TEST_SETTINGS_KEY = - "bluetooth_le_broadcast_fallback_active_group_id"; - @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -125,6 +125,7 @@ public class AudioSharingCallAudioPreferenceControllerTest { @Mock private BluetoothEventManager mBtEventManager; @Mock private LocalBluetoothProfileManager mBtProfileManager; @Mock private CachedBluetoothDeviceManager mCacheManager; + @Mock private LeAudioProfile mLeaProfile; @Mock private LocalBluetoothLeBroadcast mBroadcast; @Mock private LocalBluetoothLeBroadcastAssistant mAssistant; @Mock private VolumeControlProfile mVolumeControl; @@ -169,6 +170,7 @@ public class AudioSharingCallAudioPreferenceControllerTest { when(btManager.getEventManager()).thenReturn(mBtEventManager); when(btManager.getProfileManager()).thenReturn(mBtProfileManager); when(btManager.getCachedDeviceManager()).thenReturn(mCacheManager); + when(mBtProfileManager.getLeAudioProfile()).thenReturn(mLeaProfile); when(mBtProfileManager.getLeAudioBroadcastProfile()).thenReturn(mBroadcast); when(mBtProfileManager.getLeAudioBroadcastAssistantProfile()).thenReturn(mAssistant); when(mBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl); @@ -210,8 +212,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStart_flagOff_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.onStart(mLifecycleOwner); verify(mBtEventManager, never()).registerCallback(mController); verify(mContentResolver, never()) @@ -225,8 +227,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStart_flagOn_registerCallback() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.onStart(mLifecycleOwner); verify(mBtEventManager).registerCallback(mController); verify(mContentResolver) @@ -240,8 +242,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStop_flagOff_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mController.onStop(mLifecycleOwner); verify(mBtEventManager, never()).unregisterCallback(mController); @@ -251,8 +253,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStop_flagOn_notRegistered_doNothing() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(false); mController.onStop(mLifecycleOwner); verify(mBtEventManager, never()).unregisterCallback(mController); @@ -262,8 +264,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStop_flagOn_registered_unregisterCallback() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mController.onStop(mLifecycleOwner); verify(mBtEventManager).unregisterCallback(mController); @@ -273,20 +275,20 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void getAvailabilityStatus_flagOn() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void getAvailabilityStatus_flagOff() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_flagOff_invisible() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); when(mBroadcast.isEnabled(any())).thenReturn(true); mController.displayPreference(mScreen); mController.updateVisibility(); @@ -295,8 +297,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_broadcastOffBluetoothOff_invisible() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); when(mBroadcast.isEnabled(any())).thenReturn(false); mShadowBluetoothAdapter.setEnabled(false); mController.displayPreference(mScreen); @@ -306,8 +308,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_broadcastOnBluetoothOff_invisible() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); when(mBroadcast.isEnabled(any())).thenReturn(true); mShadowBluetoothAdapter.setEnabled(false); mController.displayPreference(mScreen); @@ -317,8 +319,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_broadcastOffBluetoothOn_invisible() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); when(mBroadcast.isEnabled(any())).thenReturn(false); mController.displayPreference(mScreen); mController.updateVisibility(); @@ -327,8 +329,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_broadcastOnBluetoothOn_visible() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); when(mBroadcast.isEnabled(any())).thenReturn(true); mController.displayPreference(mScreen); mController.updateVisibility(); @@ -337,8 +339,9 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void onProfileConnectionStateChanged_noDeviceInSharing_updateSummary() { - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onProfileConnectionStateChanged_adoptApi_noDeviceInSharing_updateSummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); mController.displayPreference(mScreen); @@ -354,8 +357,9 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void onFallbackDeviceChanged_updateSummary() { - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onFallbackDeviceChanged_adoptApi_updateSummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); @@ -372,8 +376,9 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void onActiveDeviceChanged_updateSummary() { - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onActiveDeviceChanged_adoptApi_updateSummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn( BluetoothCsipSetCoordinator.GROUP_ID_INVALID); when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); when(mBroadcast.isEnabled(any())).thenReturn(true); @@ -392,8 +397,9 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void displayPreference_fallbackDeviceInSharing_showCorrectSummary() { - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_adoptApi_fallbackDeviceInSharing_showCorrectSummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()) @@ -408,8 +414,9 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void displayPreference_activeDeviceInSharing_showCorrectSummary() { - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID2); + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_adoptApi_activeDeviceInSharing_showCorrectSummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID2); when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2)); @@ -422,8 +429,9 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void displayPreference_noFallbackDeviceOrActiveInSharing_showEmptySummary() { - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID2); + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_adoptApi_noFallbackDeviceOrActiveInSharing_showEmptySummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID2); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2)); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); @@ -433,9 +441,10 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test - public void displayPreference_noFallbackOrActiveDevice_showEmptySummary() { - Settings.Secure.putInt( - mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_adoptApi_noFallbackOrActiveDevice_showEmptySummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn( + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); mController.displayPreference(mScreen); @@ -444,13 +453,235 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_adoptApi_clickToShowCorrectDialog() { + AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog(); + if (latestAlertDialog != null) { + latestAlertDialog.dismiss(); + ShadowAlertDialogCompat.reset(); + } + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); + mShadowBluetoothAdapter.setMostRecentlyConnectedDevices( + List.of(mDevice1, mDevice2, mDevice3)); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn( + ImmutableList.of(mDevice1, mDevice2, mDevice3)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.init(mParentFragment); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + mPreference.performClick(); + shadowOf(Looper.getMainLooper()).idle(); + AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog(); + assertThat(dialog.isShowing()).isTrue(); + assertThat(dialog.getListView().getCount()).isEqualTo(2); + ArrayList outViews = new ArrayList<>(); + dialog.getListView() + .findViewsWithText(outViews, TEST_DEVICE_NAME1, View.FIND_VIEWS_WITH_TEXT); + assertThat(outViews.size()).isEqualTo(1); + View view = Iterables.getOnlyElement(outViews); + assertThat(view instanceof CheckedTextView).isTrue(); + assertThat(((CheckedTextView) view).isChecked()).isTrue(); + verify(mFeatureFactory.metricsFeatureProvider) + .visible( + /* context= */ eq(null), + /* source= */ anyInt(), + eq(SettingsEnums.DIALOG_AUDIO_SHARING_CALL_AUDIO), + /* latency= */ anyInt()); + } + + @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void testBluetoothLeBroadcastAssistantCallbacks_adoptApi_updateSummary() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn( + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + + // onSourceAdded will update summary + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */ + 1, /* reason= */ 1); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo( + mContext.getString( + R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1)); + } + + @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void testBluetoothLeBroadcastAssistantCallbacks_adoptApi_doNothing() { + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn( + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + + when(mLeaProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1); + mController.mBroadcastAssistantCallback.onSearchStartFailed(/* reason= */ 1); + mController.mBroadcastAssistantCallback.onSearchStopped(/* reason= */ 1); + mController.mBroadcastAssistantCallback.onSearchStopFailed(/* reason= */ 1); + mController.mBroadcastAssistantCallback.onSourceAddFailed( + mDevice1, mSource, /* reason= */ 1); + mController.mBroadcastAssistantCallback.onSourceRemoved( + mDevice1, /* sourceId= */ 1, /* reason= */ 1); + mController.mBroadcastAssistantCallback.onSourceRemoveFailed( + mDevice1, /* sourceId= */ 1, /* reason= */ 1); + mController.mBroadcastAssistantCallback.onSourceModified( + mDevice1, /* sourceId= */ 1, /* reason= */ 1); + mController.mBroadcastAssistantCallback.onSourceModifyFailed( + mDevice1, /* sourceId= */ 1, /* reason= */ 1); + mController.mBroadcastAssistantCallback.onSourceFound(mSource); + mController.mBroadcastAssistantCallback.onSourceLost(/* broadcastId= */ 1); + shadowOf(Looper.getMainLooper()).idle(); + mController.mBroadcastAssistantCallback.onReceiveStateChanged(mDevice1, /* sourceId= */ 1, + mState); + + // Above callbacks won't update summary. + assertThat(mPreference.getSummary().toString()).isEmpty(); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onProfileConnectionStateChanged_noDeviceInSharing_updateSummary() { + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID1); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + mPreference.setSummary("test"); + + mController.onProfileConnectionStateChanged( + mCachedDevice1, + BluetoothAdapter.STATE_DISCONNECTED, + BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onFallbackDeviceChanged_updateSummary() { + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID1); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + mPreference.setSummary("test"); + + mContentObserver.onChange(true); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo( + mContext.getString( + R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1)); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onActiveDeviceChanged_updateSummary() { + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + mPreference.setSummary("test"); + + mController.onActiveDeviceChanged(mCachedDevice1, BluetoothProfile.LE_AUDIO); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo( + mContext.getString( + R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1)); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_fallbackDeviceInSharing_showCorrectSummary() { + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID1); + when(mCachedDevice3.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()) + .thenReturn(ImmutableList.of(mDevice1, mDevice2, mDevice3)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo( + mContext.getString( + R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1)); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_activeDeviceInSharing_showCorrectSummary() { + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID2); + when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()) + .isEqualTo(mContext.getString( + R.string.audio_sharing_call_audio_description, TEST_DEVICE_NAME1)); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_noFallbackDeviceOrActiveInSharing_showEmptySummary() { + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID2); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2)); + when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void displayPreference_noFallbackOrActiveDevice_showEmptySummary() { + Settings.Secure.putInt( + mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + when(mBroadcast.isEnabled(any())).thenReturn(true); + when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); + mController.displayPreference(mScreen); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(mPreference.getSummary().toString()).isEmpty(); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void displayPreference_clickToShowCorrectDialog() { AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog(); if (latestAlertDialog != null) { latestAlertDialog.dismiss(); ShadowAlertDialogCompat.reset(); } - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID1); mShadowBluetoothAdapter.setMostRecentlyConnectedDevices( List.of(mDevice1, mDevice2, mDevice3)); when(mBroadcast.isEnabled(any())).thenReturn(true); @@ -497,7 +728,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { // Perform click to switch call audio device with API mSetFlagsRule.enableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API); - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID2); + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID2); index = listView.findIndexOfItemContainingText(TEST_DEVICE_NAME1); listView.performItemClick(index); shadowOf(Looper.getMainLooper()).idle(); @@ -548,9 +780,11 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void testBluetoothLeBroadcastAssistantCallbacks_updateSummary() { Settings.Secure.putInt( - mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); mController.displayPreference(mScreen); @@ -558,7 +792,8 @@ public class AudioSharingCallAudioPreferenceControllerTest { assertThat(mPreference.getSummary().toString()).isEmpty(); // onSourceAdded will update summary - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID1); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); mController.mBroadcastAssistantCallback.onSourceAdded(mDevice1, /* sourceId= */ @@ -571,16 +806,19 @@ public class AudioSharingCallAudioPreferenceControllerTest { } @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void testBluetoothLeBroadcastAssistantCallbacks_doNothing() { Settings.Secure.putInt( - mContentResolver, TEST_SETTINGS_KEY, BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); when(mBroadcast.isEnabled(any())).thenReturn(true); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of()); mController.displayPreference(mScreen); shadowOf(Looper.getMainLooper()).idle(); assertThat(mPreference.getSummary().toString()).isEmpty(); - Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1); + Settings.Secure.putInt(mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), + TEST_DEVICE_GROUP_ID1); when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1)); when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState)); mController.mBroadcastAssistantCallback.onSearchStarted(/* reason= */ 1); diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java index a739bb3b4fb..6ca03067a15 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumeGroupControllerTest.java @@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -42,6 +43,8 @@ import android.content.Context; import android.database.ContentObserver; import android.media.AudioManager; import android.os.Looper; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; @@ -60,6 +63,7 @@ import com.android.settings.testutils.shadow.ShadowThreadUtils; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.LeAudioProfile; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -196,8 +200,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStart_flagOff_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.onStart(mLifecycleOwner); verify(mAssistant, never()) .registerServiceCallBack( @@ -214,8 +218,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStart_flagOn_registerCallbacks() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.onStart(mLifecycleOwner); verify(mAssistant) .registerServiceCallBack( @@ -229,8 +233,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onAudioSharingProfilesConnected_flagOn_registerCallbacks() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.onAudioSharingProfilesConnected(); verify(mAssistant) .registerServiceCallBack( @@ -247,8 +251,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStop_flagOff_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.onStop(mLifecycleOwner); verify(mAssistant, never()) .unregisterServiceCallBack(any(BluetoothLeBroadcastAssistant.Callback.class)); @@ -259,8 +263,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStop_flagOn_callbacksNotRegistered_doNothing() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(false); mController.onStop(mLifecycleOwner); verify(mAssistant, never()) @@ -272,8 +276,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void onStop_flagOn_callbacksRegistered_unregisterCallbacks() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mController.onStop(mLifecycleOwner); verify(mAssistant) @@ -284,16 +288,16 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void displayPreference_flagOff_doNothing() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.displayPreference(mScreen); assertThat(mPreferenceGroup.isVisible()).isFalse(); verify(mDeviceUpdater, never()).forceUpdate(); } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void displayPreference_flagOn_updateDeviceList() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.displayPreference(mScreen); assertThat(mPreferenceGroup.isVisible()).isFalse(); verify(mDeviceUpdater).forceUpdate(); @@ -316,6 +320,24 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onDeviceAdded_adoptApi_rankFallbackDeviceOnTop() { + LeAudioProfile leAudioProfile = mock(LeAudioProfile.class); + when(leAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID2); + when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile); + when(mPreference1.getProgress()).thenReturn(TEST_VOLUME_VALUE); + when(mPreference2.getProgress()).thenReturn(TEST_VOLUME_VALUE); + mController.setPreferenceGroup(mPreferenceGroup); + mController.onDeviceAdded(mPreference1); + mController.onDeviceAdded(mPreference2); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mPreference1).setOrder(1); + verify(mPreference2).setOrder(0); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void onDeviceAdded_rankFallbackDeviceOnTop() { Settings.Secure.putInt( mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), @@ -374,8 +396,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_emptyPreferenceGroup_doNothing() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mController.updateVisibility(); shadowOf(Looper.getMainLooper()).idle(); @@ -384,8 +406,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @DisableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_flagOff_setVisibleToFalse() { - mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mPreferenceGroup.addPreference(mPreference1); when(mBroadcast.isEnabled(null)).thenReturn(true); @@ -399,8 +421,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_notEmptyPreferenceGroup_noSharing_setVisibleToFalse() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mPreferenceGroup.addPreference(mPreference1); when(mBroadcast.isEnabled(null)).thenReturn(false); @@ -414,8 +436,8 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING) public void updateVisibility_notEmptyPreferenceGroup_isSharing_setVisibleToTrue() { - mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING); mController.setCallbacksRegistered(true); mPreferenceGroup.addPreference(mPreference1); when(mBroadcast.isEnabled(null)).thenReturn(true); @@ -429,6 +451,29 @@ public class AudioSharingDeviceVolumeGroupControllerTest { } @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void settingsObserverOnChange_adoptApi_updatePreferenceOrder() { + LeAudioProfile leAudioProfile = mock(LeAudioProfile.class); + when(leAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID2); + when(mProfileManager.getLeAudioProfile()).thenReturn(leAudioProfile); + when(mPreference1.getProgress()).thenReturn(TEST_VOLUME_VALUE); + when(mPreference2.getProgress()).thenReturn(TEST_VOLUME_VALUE); + mController.setPreferenceGroup(mPreferenceGroup); + mController.onDeviceAdded(mPreference1); + mController.onDeviceAdded(mPreference2); + shadowOf(Looper.getMainLooper()).idle(); + + + when(leAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID1); + mContentObserver.onChange(true); + shadowOf(Looper.getMainLooper()).idle(); + + verify(mPreference1).setOrder(0); + verify(mPreference2).setOrder(1); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void settingsObserverOnChange_updatePreferenceOrder() { Settings.Secure.putInt( mContentResolver, BluetoothUtils.getPrimaryGroupIdUriForBroadcast(), diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java index 5ff143fa1dc..c84d7f8184d 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceVolumePreferenceTest.java @@ -31,6 +31,9 @@ import android.app.settings.SettingsEnums; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.media.AudioManager; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.widget.SeekBar; @@ -41,9 +44,11 @@ import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowBluetoothUtils; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import com.android.settingslib.bluetooth.LeAudioProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.bluetooth.VolumeControlProfile; +import com.android.settingslib.flags.Flags; import org.junit.Before; import org.junit.Rule; @@ -64,9 +69,11 @@ public class AudioSharingDeviceVolumePreferenceTest { private static final int TEST_MIN_STREAM_VALUE = 0; @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private LocalBluetoothManager mLocalBtManager; @Mock private LocalBluetoothProfileManager mLocalBtProfileManager; + @Mock private LeAudioProfile mLeAudioProfile; @Mock private VolumeControlProfile mVolumeControl; @Mock private CachedBluetoothDevice mCachedDevice; @Mock private BluetoothDevice mDevice; @@ -84,6 +91,7 @@ public class AudioSharingDeviceVolumePreferenceTest { mFeatureFactory = FakeFeatureFactory.setupForTest(); when(mLocalBtManager.getProfileManager()).thenReturn(mLocalBtProfileManager); when(mLocalBtProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControl); + when(mLocalBtProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .thenReturn(TEST_MAX_STREAM_VALUE); @@ -161,6 +169,70 @@ public class AudioSharingDeviceVolumePreferenceTest { } @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onStopTrackingTouch_adoptApi_fallbackDevice_setDeviceVolume() { + when(mLeAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID); + mPreference.onStopTrackingTouch(mSeekBar); + + verifyNoInteractions(mVolumeControl); + verify(mAudioManager) + .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ true); + } + + @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onProgressChanged_adoptApi_fallbackDevice_fromUserNotInTouch_setDeviceVolume() { + when(mLeAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true); + + verifyNoInteractions(mVolumeControl); + verify(mAudioManager) + .setStreamVolume(AudioManager.STREAM_MUSIC, TEST_MAX_STREAM_VALUE, /* flags= */ 0); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + mContext, + SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME, + /* isPrimary= */ true); + } + + @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onProgressChanged_adoptApi_fallbackDevice_fromUserInTouch_doNothing() { + when(mLeAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID); + mPreference.onStartTrackingTouch(mSeekBar); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ true); + + verifyNoInteractions(mVolumeControl); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider, never()) + .action( + any(Context.class), + eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME), + anyBoolean()); + } + + @Test + @EnableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) + public void onProgressChanged_adoptApi_fallbackDevice_notFromUserNotInTouch_doNothing() { + when(mLeAudioProfile.getBroadcastToUnicastFallbackGroup()).thenReturn(TEST_DEVICE_GROUP_ID); + mPreference.onProgressChanged(mSeekBar, TEST_VOLUME_VALUE, /* fromUser= */ false); + + verifyNoInteractions(mVolumeControl); + verifyNoInteractions(mAudioManager); + verify(mFeatureFactory.metricsFeatureProvider, never()) + .action( + any(Context.class), + eq(SettingsEnums.ACTION_AUDIO_SHARING_CHANGE_MEDIA_DEVICE_VOLUME), + anyBoolean()); + } + + @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void onStopTrackingTouch_fallbackDevice_setDeviceVolume() { Settings.Secure.putInt( mContext.getContentResolver(), @@ -179,6 +251,7 @@ public class AudioSharingDeviceVolumePreferenceTest { } @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void onProgressChanged_fallbackDevice_fromUserNotInTouch_setDeviceVolume() { Settings.Secure.putInt( mContext.getContentResolver(), @@ -197,6 +270,7 @@ public class AudioSharingDeviceVolumePreferenceTest { } @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void onProgressChanged_fallbackDevice_fromUserInTouch_doNothing() { Settings.Secure.putInt( mContext.getContentResolver(), @@ -215,6 +289,7 @@ public class AudioSharingDeviceVolumePreferenceTest { } @Test + @DisableFlags(Flags.FLAG_ADOPT_PRIMARY_GROUP_MANAGEMENT_API_V2) public void onProgressChanged_fallbackDevice_notFromUserNotInTouch_doNothing() { Settings.Secure.putInt( mContext.getContentResolver(), diff --git a/tests/robotests/src/com/android/settings/network/AdaptiveConnectivityScreenTest.kt b/tests/robotests/src/com/android/settings/network/AdaptiveConnectivityScreenTest.kt index 2b3173a051c..53f37c90164 100644 --- a/tests/robotests/src/com/android/settings/network/AdaptiveConnectivityScreenTest.kt +++ b/tests/robotests/src/com/android/settings/network/AdaptiveConnectivityScreenTest.kt @@ -16,11 +16,18 @@ package com.android.settings.network +import android.content.Context +import android.platform.test.annotations.EnableFlags +import android.provider.Settings +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED +import androidx.fragment.app.testing.launchFragmentInContainer import androidx.preference.SwitchPreferenceCompat +import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.flags.Flags -import com.android.settings.network.AdaptiveConnectivitySettings.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED -import com.android.settings.network.AdaptiveConnectivitySettings.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED +import com.android.settingslib.metadata.PreferenceHierarchy import com.android.settingslib.preference.CatalystScreenTestCase import com.google.common.truth.Truth.assertThat import org.junit.Test @@ -28,11 +35,12 @@ import org.junit.runner.RunWith @Suppress("DEPRECATION") @RunWith(AndroidJUnit4::class) -class AdaptiveConnectivityScreenTest : CatalystScreenTestCase() { +class AdaptiveConnectivityScreenTest() : CatalystScreenTestCase() { override val preferenceScreenCreator = AdaptiveConnectivityScreen() override val flagName get() = Flags.FLAG_CATALYST_ADAPTIVE_CONNECTIVITY - + private lateinit var fragment: AdaptiveConnectivitySettings + private val mContext: Context = ApplicationProvider.getApplicationContext() override fun migration() {} @Test @@ -41,21 +49,121 @@ class AdaptiveConnectivityScreenTest : CatalystScreenTestCase() { } @Test - fun flagDefaultDisabled_noSwitchPreferenceCompatExists() { - // create fragment - val fragment: AdaptiveConnectivitySettings = - preferenceScreenCreator.fragmentClass().newInstance() - // check if switch preference exists - assertSwitchPreferenceCompatIsNull(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment) - assertSwitchPreferenceCompatIsNull(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, fragment) + fun getPreferenceHierarchy_returnsHierarchy() { + val hierarchy: PreferenceHierarchy = + preferenceScreenCreator.getPreferenceHierarchy(mContext) + (appContext) + assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_ENABLED)).isNotNull() + assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isNull() + assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isNull() } - private fun assertSwitchPreferenceCompatIsNull( + @Test + @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) + fun getPreferenceHierarchy_flagEnabled_returnsHierarchyWithNestedToggle() { + val hierarchy: PreferenceHierarchy = + preferenceScreenCreator.getPreferenceHierarchy(mContext) + (appContext) + assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_ENABLED)).isNotNull() + assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isNotNull() + assertThat(hierarchy.find(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isNotNull() + + } + + @Test + fun flagDefaultDisabled_noSwitchPreferenceCompatExists() { + val scenario = launchFragmentInContainer() + scenario.onFragment { fragment -> + this.fragment = fragment + assertSwitchPreferenceCompatVisibility( + ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment, + false + ) + assertSwitchPreferenceCompatVisibility( + ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, + fragment, + false + ) + } + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) + fun flagEnabled_switchPreferenceCompatExists() { + val scenario = launchFragmentInContainer() + scenario.onFragment { fragment -> + this.fragment = fragment + assertSwitchPreferenceCompatVisibility( + ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, fragment, + true + ) + assertSwitchPreferenceCompatVisibility( + ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, + fragment, + true + ) + } + } + + + @Test + @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) + fun flagEnabled_onWifiScorerSwitchClick_shouldUpdateSetting() { + val scenario = launchFragmentInContainer() + scenario.onFragment { fragment: AdaptiveConnectivitySettings -> + this.fragment = fragment + val switchPreference = + fragment.findPreference(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED) + assertThat(switchPreference?.isChecked).isTrue() + switchPreference?.performClick() + assertThat(switchPreference?.isChecked).isFalse() + assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isFalse() + switchPreference?.performClick() + assertThat(switchPreference?.isChecked).isTrue() + assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED)).isTrue() + } + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_NESTED_TOGGLE_SWITCHES) + fun flagEnabled_onAdaptiveMobileNetworkSwitchClick_shouldUpdateSetting() { + val scenario = launchFragmentInContainer() + scenario.onFragment { fragment: AdaptiveConnectivitySettings -> + this.fragment = fragment + val switchPreference = + fragment.findPreference( + ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED + ) + assertThat(switchPreference?.isChecked).isTrue() + switchPreference?.performClick() + assertThat(switchPreference?.isChecked).isFalse() + assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isFalse() + switchPreference?.performClick() + assertThat(switchPreference?.isChecked).isTrue() + assertThat(updateSetting(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED)).isTrue() + } + } + + /** + * Helper function to get the setting value from Settings.Secure. + * + * @param key the key of the setting to get. + */ + private fun updateSetting(key: String): Boolean { + return (Settings.Secure.getInt( + mContext.contentResolver, + key, + 0 + ) == 1) + } + + private fun assertSwitchPreferenceCompatVisibility( key: String, - fragment: AdaptiveConnectivitySettings + fragment: AdaptiveConnectivitySettings, + isVisible: Boolean ) { val switchPreference = fragment.findPreference(key) - assertThat(switchPreference).isNull() + assertThat(switchPreference?.isVisible).isEqualTo(isVisible) } } diff --git a/tests/robotests/src/com/android/settings/network/AdaptiveMobileNetworkTogglePreferenceTest.kt b/tests/robotests/src/com/android/settings/network/AdaptiveMobileNetworkTogglePreferenceTest.kt new file mode 100644 index 00000000000..6b2b7dde2ae --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/AdaptiveMobileNetworkTogglePreferenceTest.kt @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2025 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.network + +import android.content.Context +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED +import androidx.preference.SwitchPreferenceCompat +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.preference.createAndBindWidget +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class AdaptiveMobileNetworkTogglePreferenceTest { + private val context: Context = ApplicationProvider.getApplicationContext() + + private val adaptiveMobileNetworkTogglePreference = AdaptiveMobileNetworkTogglePreference() + + @Test + fun switchClick_defaultDisabled_returnFalse() { + setAdaptiveMobileNetworkEnabled(false) + + assertThat(getSwitchPreference().isChecked).isFalse() + } + + @Test + fun switchClick_defaultEnabled_returnTrue() { + setAdaptiveMobileNetworkEnabled(true) + + assertThat(getSwitchPreference().isChecked).isTrue() + } + + @Test + fun setChecked_defaultEnabled_updatesCorrectly() { + val preference = getSwitchPreference() + assertThat(preference.isChecked).isTrue() + + preference.performClick() + + assertThat(preference.isChecked).isFalse() + + preference.performClick() + + assertThat(preference.isChecked).isTrue() + } + + @Test + fun storeSetTrue_setAdaptiveMobileNetworkEnabled() { + setAdaptiveMobileNetworkEnabled(true) + + assertThat( + getAdaptiveMobileNetworkEnabled() + ).isTrue() + } + + @Test + fun storeSetFalse_setAdaptiveMobileNetworkDisabled() { + setAdaptiveMobileNetworkEnabled(false) + + assertThat( + getAdaptiveMobileNetworkEnabled() + ).isFalse() + } + + private fun getSwitchPreference(): SwitchPreferenceCompat = + adaptiveMobileNetworkTogglePreference.createAndBindWidget(context) + + private fun setAdaptiveMobileNetworkEnabled(enabled: Boolean) = + adaptiveMobileNetworkTogglePreference + .storage(context) + .setBoolean(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED, enabled) + + private fun getAdaptiveMobileNetworkEnabled() = + adaptiveMobileNetworkTogglePreference + .storage(context) + .getBoolean(ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED) +} diff --git a/tests/robotests/src/com/android/settings/network/WifiScorerTogglePreferenceTest.kt b/tests/robotests/src/com/android/settings/network/WifiScorerTogglePreferenceTest.kt new file mode 100644 index 00000000000..794b5eb2401 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/WifiScorerTogglePreferenceTest.kt @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2025 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.network + +import android.content.Context +import android.content.ContextWrapper +import android.net.wifi.WifiManager +import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED +import androidx.preference.SwitchPreferenceCompat +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.preference.createAndBindWidget +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify + +@RunWith(AndroidJUnit4::class) +class WifiScorerTogglePreferenceTest { + private val mockWifiManager = mock() + + private val context: Context = + object : ContextWrapper(ApplicationProvider.getApplicationContext()) { + override fun getSystemService(name: String): Any? = + when { + name == getSystemServiceName(WifiManager::class.java) -> mockWifiManager + else -> super.getSystemService(name) + } + } + + private val wifiScorerTogglePreference = WifiScorerTogglePreference() + + @Test + fun switchClick_defaultDisabled_returnFalse() { + setWifiScorerEnabled(false) + + assertThat(getSwitchPreference().isChecked).isFalse() + } + + @Test + fun switchClick_defaultEnabled_returnTrue() { + setWifiScorerEnabled(true) + + assertThat(getSwitchPreference().isChecked).isTrue() + } + + @Test + fun setChecked_defaultEnabled_updatesCorrectly() { + val preference = getSwitchPreference() + assertThat(preference.isChecked).isTrue() + + preference.performClick() + + assertThat(preference.isChecked).isFalse() + + preference.performClick() + + assertThat(preference.isChecked).isTrue() + } + + @Test + fun storeSetTrue_wifiManagerSetWifiScoringEnabled() { + setWifiScorerEnabled(true) + + assertThat(getWifiScorerEnabled()).isTrue() + verify(mockWifiManager).setWifiScoringEnabled(true) + } + + @Test + fun storeSetFalse_wifiManagerSetWifiScoringDisabled() { + setWifiScorerEnabled(false) + + assertThat(getWifiScorerEnabled()).isFalse() + verify(mockWifiManager).setWifiScoringEnabled(false) + } + + private fun getSwitchPreference(): SwitchPreferenceCompat = + wifiScorerTogglePreference.createAndBindWidget(context) + + private fun setWifiScorerEnabled(enabled: Boolean) = + wifiScorerTogglePreference + .storage(context) + .setBoolean(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED, enabled) + + private fun getWifiScorerEnabled() = + wifiScorerTogglePreference + .storage(context) + .getBoolean(ADAPTIVE_CONNECTIVITY_WIFI_ENABLED) +} diff --git a/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java index 6318c9c6914..c5c69af998f 100644 --- a/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/deviceinfo/TopLevelStoragePreferenceControllerTest.java @@ -103,6 +103,6 @@ public class TopLevelStoragePreferenceControllerTest { // the background thread. TimeUnit.SECONDS.sleep(5); assertThat(preference.getSummary()).isEqualTo(ResourcesUtils.getResourcesString( - mContext, "storage_summary", percentage, freeSpace)); + mContext, "storage_toplevel_summary", percentage, freeSpace)); } } diff --git a/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAboutContentControllerTest.kt b/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAboutContentControllerTest.kt index d070811c3b9..036cc3ff68b 100644 --- a/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAboutContentControllerTest.kt +++ b/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAboutContentControllerTest.kt @@ -63,11 +63,9 @@ class SatelliteSettingAboutContentControllerTest { controller.displayPreference(screen) assertThat(preference.title).isEqualTo( - context.getString( - R.string.description_about_satellite_setting, - TEST_SIM_OPERATOR_NAME + "You can send and receive text messages and use some apps by satellite with an eligible Test Carrier account" ) - ) + } private companion object { diff --git a/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAccountInfoControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAccountInfoControllerTest.java new file mode 100644 index 00000000000..331a74c8b5c --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingAccountInfoControllerTest.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2025 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.network.telephony.satellite; + +import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; +import static com.android.settings.network.telephony.satellite.SatelliteSettingAccountInfoController.PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN; +import static com.android.settings.network.telephony.satellite.SatelliteSettingAccountInfoController.PREF_KEY_YOUR_SATELLITE_DATA_PLAN; +import static com.android.settings.network.telephony.satellite.SatelliteSettingAccountInfoController.PREF_KEY_YOUR_SATELLITE_PLAN; + +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.Looper; +import android.os.PersistableBundle; +import android.telephony.TelephonyManager; +import android.telephony.satellite.SatelliteManager; + +import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.testutils.ResourcesUtils; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(AndroidJUnit4.class) +public class SatelliteSettingAccountInfoControllerTest { + private static final int TEST_SUB_ID = 5; + private static final String TEST_OPERATOR_NAME = "test_operator_name"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock + private TelephonyManager mTelephonyManager; + + private Context mContext; + private SatelliteSettingAccountInfoController mController; + private final PersistableBundle mPersistableBundle = new PersistableBundle(); + + @Before + public void setUp() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + mContext = spy(ApplicationProvider.getApplicationContext()); + mController = new SatelliteSettingAccountInfoController(mContext, + PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); + when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mTelephonyManager.getSimOperatorName(TEST_SUB_ID)).thenReturn(TEST_OPERATOR_NAME); + } + + @Test + public void getAvailabilityStatus_entitlementNotSupport_returnConditionalUnavailable() { + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mController.init(TEST_SUB_ID, mPersistableBundle, false, false); + + int result = mController.getAvailabilityStatus(TEST_SUB_ID); + + assertThat(result).isEqualTo(CONDITIONALLY_UNAVAILABLE); + } + + @Test + public void getAvailabilityStatus_entitlementIsSupported_returnConditionalUnavailable() { + mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); + mController.init(TEST_SUB_ID, mPersistableBundle, false, false); + + int result = mController.getAvailabilityStatus(TEST_SUB_ID); + + assertThat(result).isEqualTo(AVAILABLE); + } + + @Test + public void displayPreference_showCategoryTitle_correctOperatorName() { + mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mController.init(TEST_SUB_ID, mPersistableBundle, false, false); + + PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); + PreferenceCategory preferenceCategory = new PreferenceCategory(mContext); + preferenceCategory.setKey(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); + Preference preference = new Preference(mContext); + preference.setKey(PREF_KEY_YOUR_SATELLITE_PLAN); + screen.addPreference(preferenceCategory); + screen.addPreference(preference); + + mController.displayPreference(screen); + + assertThat(preferenceCategory.getTitle().toString()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "category_title_your_satellite_plan", + TEST_OPERATOR_NAME)); + } + + @Test + public void displayPreference_showEligibleUiButDataUnavailable_showSmsEligibleAccountState() { + mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mController = new SatelliteSettingAccountInfoController(mContext, + PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN) { + @Override + protected boolean isSatelliteEligible() { + return true; + } + }; + mController.init(TEST_SUB_ID, mPersistableBundle, true, false); + PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); + PreferenceCategory preferenceCategory = new PreferenceCategory(mContext); + preferenceCategory.setKey(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); + Preference preference = new Preference(mContext); + preference.setKey(PREF_KEY_YOUR_SATELLITE_PLAN); + Preference preferenceData = new Preference(mContext); + preferenceData.setKey(PREF_KEY_YOUR_SATELLITE_DATA_PLAN); + screen.addPreference(preferenceCategory); + screen.addPreference(preference); + screen.addPreference(preferenceData); + + mController.displayPreference(screen); + + assertThat(preference.getTitle().toString()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "title_have_satellite_plan")); + assertThat(preferenceData.getTitle()).isEqualTo(null); + } + + @Test + public void + displayPreference_showEligibleUiAndDataAvailable_showSmsAndDataEligibleAccountState() { + mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mController = new SatelliteSettingAccountInfoController(mContext, + PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN) { + @Override + protected boolean isSatelliteEligible() { + return true; + } + }; + mController.init(TEST_SUB_ID, mPersistableBundle, true, true); + PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); + PreferenceCategory preferenceCategory = new PreferenceCategory(mContext); + preferenceCategory.setKey(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); + Preference preference = new Preference(mContext); + preference.setKey(PREF_KEY_YOUR_SATELLITE_PLAN); + Preference preferenceData = new Preference(mContext); + preferenceData.setKey(PREF_KEY_YOUR_SATELLITE_DATA_PLAN); + screen.addPreference(preferenceCategory); + screen.addPreference(preference); + screen.addPreference(preferenceData); + + mController.displayPreference(screen); + + assertThat(preference.getTitle().toString()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "title_have_satellite_plan")); + assertThat(preferenceData.getTitle().toString()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "title_have_satellite_data_plan")); + } + + @Test + public void displayPreference_showIneligibleUi_showSmsAccountState() { + mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); + when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null); + mController = new SatelliteSettingAccountInfoController(mContext, + PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN) { + @Override + protected boolean isSatelliteEligible() { + return false; + } + }; + mController.init(TEST_SUB_ID, mPersistableBundle, false, false); + PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); + PreferenceCategory preferenceCategory = new PreferenceCategory(mContext); + preferenceCategory.setKey(PREF_KEY_CATEGORY_YOUR_SATELLITE_PLAN); + Preference preference = new Preference(mContext); + preference.setKey(PREF_KEY_YOUR_SATELLITE_PLAN); + screen.addPreference(preferenceCategory); + screen.addPreference(preference); + + mController.displayPreference(screen); + + assertThat(preference.getTitle().toString()).isEqualTo( + ResourcesUtils.getResourcesString(mContext, "title_no_satellite_plan")); + } +} diff --git a/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceControllerTest.java index c67f0aca6a1..7cb85a580e4 100644 --- a/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/satellite/SatelliteSettingsPreferenceControllerTest.java @@ -19,7 +19,6 @@ package com.android.settings.network.telephony.satellite; import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC; import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL; -import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA; import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS; import static com.android.settings.core.BasePreferenceController.AVAILABLE; @@ -183,41 +182,10 @@ public class SatelliteSettingsPreferenceControllerTest { @Test @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) - public void title_hasServiceDataType_showDataUi() { - mController.initialize(TEST_SUB_ID); - PreferenceManager preferenceManager = new PreferenceManager(mContext); - PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext); - Preference preference = new Preference(mContext); - preference.setKey(KEY); - preference.setTitle("test title"); - preferenceScreen.addPreference(preference); - mController.displayPreference(preferenceScreen); - mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged( - new int[]{SERVICE_TYPE_SMS, SERVICE_TYPE_DATA}); - - assertThat(preference.getTitle()).isEqualTo("Satellite connectivity"); - } - - @Test - @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) - public void title_onlyHasServiceSmsType_showSmsUi() { - mController.initialize(TEST_SUB_ID); - PreferenceManager preferenceManager = new PreferenceManager(mContext); - PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext); - Preference preference = new Preference(mContext); - preference.setKey(KEY); - preference.setTitle("test title"); - preferenceScreen.addPreference(preference); - mController.displayPreference(preferenceScreen); - mController.mCarrierRoamingNtnModeCallback.onCarrierRoamingNtnAvailableServicesChanged( - new int[]{SERVICE_TYPE_SMS}); - - assertThat(preference.getTitle()).isEqualTo("Satellite messaging"); - } - - @Test - @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) - public void summary_noEntitlement_showSummaryWithoutEntitlement() { + public void summary_noEntitlementAndTypeIsAuto_showSummaryWithoutEntitlement() { + mCarrierConfig.putInt( + CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, + CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC); mCarrierConfig.putBoolean( KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false); @@ -237,9 +205,6 @@ public class SatelliteSettingsPreferenceControllerTest { @Test @EnableFlags(com.android.settings.flags.Flags.FLAG_SATELLITE_OEM_SETTINGS_UX_MIGRATION) public void summary_smsAvailableForManualType_showSummaryWithAccount() { - mCarrierConfig.putBoolean( - KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, - true); mCarrierConfig.putInt( CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, CARRIER_ROAMING_NTN_CONNECT_MANUAL);