diff --git a/aconfig/accessibility/accessibility_flags.aconfig b/aconfig/accessibility/accessibility_flags.aconfig index 0338ed8c09c..5c81cc9a671 100644 --- a/aconfig/accessibility/accessibility_flags.aconfig +++ b/aconfig/accessibility/accessibility_flags.aconfig @@ -71,6 +71,16 @@ flag { } } +flag { + name: "never_restrict_accessibility_activity" + namespace: "accessibility" + description: "Stops possibly restricting AccessibilityActivityPreferences" + bug: "331990900" + metadata { + purpose: PURPOSE_BUGFIX + } +} + flag { name: "remove_qs_tooltip_in_suw" namespace: "accessibility" diff --git a/res/values/integers.xml b/res/values/integers.xml index 5427cdd0d35..5631e401ba1 100644 --- a/res/values/integers.xml +++ b/res/values/integers.xml @@ -40,4 +40,6 @@ 0 3 + + 2147483647 diff --git a/res/xml/accessibility_daltonizer_settings.xml b/res/xml/accessibility_daltonizer_settings.xml index 8dc5f3b5ab4..db961675c29 100644 --- a/res/xml/accessibility_daltonizer_settings.xml +++ b/res/xml/accessibility_daltonizer_settings.xml @@ -33,6 +33,7 @@ android:persistent="false" android:summary="@string/daltonizer_mode_deuteranomaly_summary" android:title="@string/daltonizer_mode_deuteranomaly_title" + settings:titleMaxLines="@integer/max_integer" settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" /> + getProfiles() { - List result = new ArrayList(); + List result = new ArrayList<>(); mProfileDeviceMap.clear(); if (mAllOfCachedDevices == null || mAllOfCachedDevices.isEmpty()) { return result; @@ -319,8 +319,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll if (mProfileDeviceMap.containsKey(profile.toString())) { mProfileDeviceMap.get(profile.toString()).add(cachedItem); } else { - List tmpCachedDeviceList = - new ArrayList(); + List tmpCachedDeviceList = new ArrayList<>(); tmpCachedDeviceList.add(cachedItem); mProfileDeviceMap.put(profile.toString(), tmpCachedDeviceList); result.add(profile); @@ -356,6 +355,10 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll } boolean hearingAidSupported = result.contains( mManager.getProfileManager().getHearingAidProfile()); + // Remove hearing aids toggle anyway since showing the toggle will confuse users + if (hearingAidSupported) { + result.remove(mManager.getProfileManager().getHearingAidProfile()); + } if (leAudioSupported && !classicAudioSupported && !hearingAidSupported) { mIsLeAudioOnlyDevice = true; } diff --git a/src/com/android/settings/core/BasePreferenceController.java b/src/com/android/settings/core/BasePreferenceController.java index 5763d3b93ef..3f91fb70ab4 100644 --- a/src/com/android/settings/core/BasePreferenceController.java +++ b/src/com/android/settings/core/BasePreferenceController.java @@ -263,6 +263,16 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl || availabilityStatus == DISABLED_DEPENDENT_SETTING); } + private boolean isAvailableForSearch() { + if (mIsForWork && mWorkProfileUser == null) { + return false; + } + + final int availabilityStatus = getAvailabilityStatus(); + return (availabilityStatus == AVAILABLE + || availabilityStatus == DISABLED_DEPENDENT_SETTING); + } + /** * @return {@code false} if the setting is not applicable to the device. This covers both * settings which were only introduced in future versions of android, or settings that have @@ -303,18 +313,12 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl * Called by SearchIndexProvider#getNonIndexableKeys */ public void updateNonIndexableKeys(List keys) { - final boolean shouldSuppressFromSearch = !isAvailable() - || getAvailabilityStatus() == AVAILABLE_UNSEARCHABLE; - if (shouldSuppressFromSearch) { - final String key = getPreferenceKey(); - if (TextUtils.isEmpty(key)) { - Log.w(TAG, "Skipping updateNonIndexableKeys due to empty key " + toString()); - return; - } - if (keys.contains(key)) { - Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list. " + toString()); - return; - } + final String key = getPreferenceKey(); + if (TextUtils.isEmpty(key)) { + Log.w(TAG, "Skipping updateNonIndexableKeys due to empty key " + this); + return; + } + if (!keys.contains(key) && !isAvailableForSearch()) { keys.add(key); } } diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java index fd65e8562a2..f5e734d7e09 100644 --- a/src/com/android/settings/network/telephony/MobileDataSlice.java +++ b/src/com/android/settings/network/telephony/MobileDataSlice.java @@ -29,6 +29,7 @@ import android.database.ContentObserver; import android.net.Uri; import android.os.Handler; import android.os.Looper; +import android.os.UserManager; import android.provider.Settings; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -79,19 +80,24 @@ public class MobileDataSlice implements CustomSliceable { @Override public Slice getSlice() { + ListBuilder listBuilder = createListBuilder(); + if (!isConfigMobileNetworksAllowed()) { + return listBuilder.build(); + } + final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.ic_network_cell); final String title = mContext.getText(R.string.mobile_data_settings_title).toString(); @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext); - // Return null until we can show a disabled-action Slice, blaming Airplane mode. + // Return empty slice until we can show a disabled-action Slice, blaming Airplane mode. if (isAirplaneModeEnabled()) { - return null; + return listBuilder.build(); } - // Return null until we can show a disabled-action Slice. + // Return empty slice until we can show a disabled-action Slice. if (!isMobileDataAvailable()) { - return null; + return listBuilder.build(); } final CharSequence summary = getSummary(); @@ -109,11 +115,15 @@ public class MobileDataSlice implements CustomSliceable { rowBuilder.setSubtitle(summary); } - final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), - ListBuilder.INFINITY) + return listBuilder .setAccentColor(color) - .addRow(rowBuilder); - return listBuilder.build(); + .addRow(rowBuilder) + .build(); + } + + @VisibleForTesting + ListBuilder createListBuilder() { + return new ListBuilder(mContext, getUri(), ListBuilder.INFINITY); } @Override @@ -211,6 +221,19 @@ public class MobileDataSlice implements CustomSliceable { return mTelephonyManager.isDataEnabled(); } + @VisibleForTesting + boolean isConfigMobileNetworksAllowed() { + if (mContext == null) return true; + UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager == null) return true; + boolean isAllowed = userManager.isAdminUser() && !userManager.hasUserRestriction( + UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS); + if (!isAllowed) { + Log.w(TAG, "The user is not allowed to configure Mobile Networks."); + } + return isAllowed; + } + /** * Listener for mobile data state changes. * diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt index d1800715302..4e97d318033 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt +++ b/src/com/android/settings/network/telephony/MobileNetworkSettingsSearchIndex.kt @@ -24,6 +24,7 @@ import com.android.settings.network.SubscriptionUtil import com.android.settings.network.telephony.MmsMessagePreferenceController.Companion.MmsMessageSearchItem import com.android.settings.network.telephony.NrAdvancedCallingPreferenceController.Companion.NrAdvancedCallingSearchItem import com.android.settings.network.telephony.RoamingPreferenceController.Companion.RoamingSearchItem +import com.android.settings.network.telephony.WifiCallingPreferenceController.Companion.WifiCallingSearchItem import com.android.settings.spa.SpaSearchLanding.BundleValue import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey @@ -112,9 +113,10 @@ class MobileNetworkSettingsSearchIndex( fun createSearchItems(context: Context): List = listOf( - RoamingSearchItem(context), MmsMessageSearchItem(context), NrAdvancedCallingSearchItem(context), + RoamingSearchItem(context), + WifiCallingSearchItem(context), ) } } diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt index 3bb267940d2..7e8e58cceb5 100644 --- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt +++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt @@ -22,14 +22,17 @@ import android.telecom.TelecomManager import android.telephony.SubscriptionManager import android.telephony.TelephonyManager import android.telephony.ims.ImsMmTelManager -import android.util.Log import androidx.lifecycle.LifecycleOwner import androidx.preference.Preference import androidx.preference.PreferenceScreen import com.android.settings.R +import com.android.settings.core.BasePreferenceController +import com.android.settings.network.telephony.MobileNetworkSettingsSearchIndex.MobileNetworkSettingsSearchItem import com.android.settings.network.telephony.wificalling.WifiCallingRepository import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext /** @@ -44,20 +47,21 @@ open class WifiCallingPreferenceController @JvmOverloads constructor( private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId -> WifiCallingRepository(context, subId) }, -) : TelephonyBasePreferenceController(context, key) { +) : BasePreferenceController(context, key) { + private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID private lateinit var preference: Preference private lateinit var callingPreferenceCategoryController: CallingPreferenceCategoryController private val resourcesForSub by lazy { - SubscriptionManager.getResourcesForSubId(mContext, mSubId) + SubscriptionManager.getResourcesForSubId(mContext, subId) } fun init( subId: Int, callingPreferenceCategoryController: CallingPreferenceCategoryController, ): WifiCallingPreferenceController { - mSubId = subId + this.subId = subId this.callingPreferenceCategoryController = callingPreferenceCategoryController return this } @@ -65,39 +69,32 @@ open class WifiCallingPreferenceController @JvmOverloads constructor( /** * Note: Visibility also controlled by [onViewCreated]. */ - override fun getAvailabilityStatus(subId: Int) = + override fun getAvailabilityStatus() = if (SubscriptionManager.isValidSubscriptionId(subId)) AVAILABLE else CONDITIONALLY_UNAVAILABLE override fun displayPreference(screen: PreferenceScreen) { // Not call super here, to avoid preference.isVisible changed unexpectedly preference = screen.findPreference(preferenceKey)!! - preference.intent?.putExtra(Settings.EXTRA_SUB_ID, mSubId) + preference.intent?.putExtra(Settings.EXTRA_SUB_ID, subId) } override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) { - if(mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID){ - Log.e( - this.javaClass.simpleName, - "mSubId is INVALID_SUBSCRIPTION_ID" - ) - return - } - wifiCallingRepositoryFactory(mSubId).wifiCallingReadyFlow() + wifiCallingRepositoryFactory(subId).wifiCallingReadyFlow() .collectLatestWithLifecycle(viewLifecycleOwner) { isReady -> preference.isVisible = isReady callingPreferenceCategoryController.updateChildVisible(preferenceKey, isReady) if (isReady) update() } - callStateRepository.callStateFlow(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { + callStateRepository.callStateFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) { preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) } } private suspend fun update() { val simCallManager = mContext.getSystemService(TelecomManager::class.java) - ?.getSimCallManagerForSubscription(mSubId) + ?.getSimCallManagerForSubscription(subId) if (simCallManager != null) { val intent = withContext(Dispatchers.Default) { MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, simCallManager) @@ -116,7 +113,7 @@ open class WifiCallingPreferenceController @JvmOverloads constructor( } private fun getSummaryForWfcMode(): String { - val resId = when (wifiCallingRepositoryFactory(mSubId).getWiFiCallingMode()) { + val resId = when (wifiCallingRepositoryFactory(subId).getWiFiCallingMode()) { ImsMmTelManager.WIFI_MODE_WIFI_ONLY -> com.android.internal.R.string.wfc_mode_wifi_only_summary @@ -130,4 +127,17 @@ open class WifiCallingPreferenceController @JvmOverloads constructor( } return resourcesForSub.getString(resId) } + + companion object { + class WifiCallingSearchItem( + private val context: Context, + ) : MobileNetworkSettingsSearchItem { + override val key: String = "wifi_calling" + override val title: String = context.getString(R.string.wifi_calling_settings_title) + + override fun isAvailable(subId: Int): Boolean = runBlocking { + WifiCallingRepository(context, subId).wifiCallingReadyFlow().first() + } + } + } } diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java index 588f01aaa79..66c278ed733 100644 --- a/src/com/android/settings/users/UserDetailsSettings.java +++ b/src/com/android/settings/users/UserDetailsSettings.java @@ -370,11 +370,18 @@ public class UserDetailsSettings extends SettingsPreferenceFragment } mSwitchUserPref.setOnPreferenceClickListener(this); } - if (mUserInfo.isMain() || mUserInfo.isGuest() || !UserManager.isMultipleAdminEnabled() - || mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_GRANT_ADMIN, - mUserInfo.getUserHandle()) || !mUserManager.isAdminUser()) { - removePreference(KEY_GRANT_ADMIN); + if (android.multiuser.Flags.unicornModeRefactoringForHsumReadOnly()) { + if (isChangingAdminStatusRestricted()) { + removePreference(KEY_GRANT_ADMIN); + } + } else { + if (mUserInfo.isMain() || mUserInfo.isGuest() || !UserManager.isMultipleAdminEnabled() + || mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_GRANT_ADMIN, + mUserInfo.getUserHandle()) || !mUserManager.isAdminUser()) { + removePreference(KEY_GRANT_ADMIN); + } } + if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls removePreference(KEY_ENABLE_TELEPHONY); removePreference(KEY_REMOVE_USER); @@ -552,4 +559,33 @@ public class UserDetailsSettings extends SettingsPreferenceFragment // return true so there will be no setup prompt dialog shown to the user anymore. return isSecondaryUser(mUserInfo) && !mUserInfo.isInitialized(); } + + /** + * Determines if changing admin status is restricted. + * + *

Admin status change is restricted under the following conditions of current & target user. + * + *

    + *
  • The current user is NOT an admin user.
  • + *
  • OR multiple admin support is NOT enabled.
  • + *
  • OR the current user has DISALLOW_GRANT_ADMIN restriction applied
  • + * + *
  • OR the target user ('mUserInfo') is a main user OR a guest user.
  • + *
  • OR the target user ('mUserInfo') has DISALLOW_GRANT_ADMIN restriction.
  • + *
+ * + * @return true if changing admin status is restricted, false otherwise + */ + private boolean isChangingAdminStatusRestricted() { + boolean currentUserRestricted = !mUserManager.isAdminUser() + || !UserManager.isMultipleAdminEnabled() + || mUserManager.hasUserRestriction(UserManager.DISALLOW_GRANT_ADMIN); + + boolean targetUserRestricted = mUserInfo.isMain() + || mUserInfo.isGuest() + || mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_GRANT_ADMIN, + mUserInfo.getUserHandle()); + + return currentUserRestricted || targetUserRestricted; + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java index 569109c5cd4..78f49a66906 100644 --- a/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/KeyboardVibrationTogglePreferenceControllerTest.java @@ -33,7 +33,6 @@ import android.app.settings.SettingsEnums; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; -import android.os.vibrator.Flags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; @@ -41,7 +40,6 @@ import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; -import com.android.settings.R; import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; @@ -87,7 +85,6 @@ public class KeyboardVibrationTogglePreferenceControllerTest { @Test public void getAvailabilityStatus_featureSupported_available() { - mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); when(mResources.getBoolean( com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) .thenReturn(true); @@ -97,7 +94,6 @@ public class KeyboardVibrationTogglePreferenceControllerTest { @Test public void getAvailabilityStatus_featureNotSupported_unavailable() { - mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); when(mResources.getBoolean( com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) .thenReturn(false); @@ -105,15 +101,6 @@ public class KeyboardVibrationTogglePreferenceControllerTest { assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); } - @Test - public void getAvailabilityStatus_keyboardCategoryDisabled_unavailable() { - mSetFlagsRule.disableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED); - when(mResources.getBoolean( - com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) - .thenReturn(true); - - assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); - } @Test public void updateState_mainVibrateDisabled_shouldReturnFalseForCheckedAndEnabled() { diff --git a/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java b/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java index b4f4dc1127e..2a41e62e7ae 100644 --- a/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/RestrictedPreferenceHelperTest.java @@ -31,9 +31,8 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.core.app.ApplicationProvider; @@ -83,8 +82,6 @@ public class RestrictedPreferenceHelperTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Test public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() { @@ -100,7 +97,7 @@ public class RestrictedPreferenceHelperTest { } @Test - @RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS, + @EnableFlags(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS, android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED}) public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() { ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs( @@ -116,7 +113,7 @@ public class RestrictedPreferenceHelperTest { } @Test - @RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS, + @EnableFlags(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS, android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED}) public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() { ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(); @@ -144,6 +141,40 @@ public class RestrictedPreferenceHelperTest { assertThat(preference.getKey()).isEqualTo(key); } + @Test + @EnableFlags(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS, + android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED}) + @DisableFlags(Flags.FLAG_NEVER_RESTRICT_ACCESSIBILITY_ACTIVITY) + public void createAccessibilityActivityPreference_ecmRestricted_prefIsEcmRestricted() { + setMockAccessibilityShortcutInfo(mShortcutInfo); + ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(PACKAGE_NAME); + + final List preferenceList = + mHelper.createAccessibilityActivityPreferenceList(List.of(mShortcutInfo)); + assertThat(preferenceList).hasSize(1); + final RestrictedPreference preference = preferenceList.get(0); + + assertThat(preference.isDisabledByEcm()).isTrue(); + } + + @Test + @EnableFlags(value = { + android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS, + android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED, + Flags.FLAG_NEVER_RESTRICT_ACCESSIBILITY_ACTIVITY, + }) + public void createAccessibilityActivityPreference_ecmRestricted_prefIsNotEcmRestricted() { + setMockAccessibilityShortcutInfo(mShortcutInfo); + ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(PACKAGE_NAME); + + final List preferenceList = + mHelper.createAccessibilityActivityPreferenceList(List.of(mShortcutInfo)); + assertThat(preferenceList).hasSize(1); + final RestrictedPreference preference = preferenceList.get(0); + + assertThat(preference.isDisabledByEcm()).isFalse(); + } + private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName, String className) { final ApplicationInfo applicationInfo = new ApplicationInfo(); diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java index 2d1f4c0e907..219c37b6c08 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsProfilesControllerTest.java @@ -44,6 +44,7 @@ import com.android.settings.testutils.shadow.ShadowBluetoothDevice; import com.android.settingslib.R; import com.android.settingslib.bluetooth.A2dpProfile; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; +import com.android.settingslib.bluetooth.HearingAidProfile; import com.android.settingslib.bluetooth.LeAudioProfile; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; @@ -90,8 +91,12 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont @Mock private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager; - private @Mock A2dpProfile mA2dpProfile; - private @Mock LeAudioProfile mLeAudioProfile; + @Mock + private A2dpProfile mA2dpProfile; + @Mock + private LeAudioProfile mLeAudioProfile; + @Mock + private HearingAidProfile mHearingAidProfile; @Override public void setUp() { @@ -399,18 +404,23 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont when(mProfileManager.getProfileByName(eq(mA2dpProfile.toString()))) .thenReturn(mA2dpProfile); when(mA2dpProfile.getNameResource(any())) - .thenReturn(com.android.settingslib.R.string.bluetooth_profile_a2dp); + .thenReturn(R.string.bluetooth_profile_a2dp); when(mA2dpProfile.getHighQualityAudioOptionLabel(any())).thenReturn( - mContext.getString(com.android.settingslib.R - .string.bluetooth_profile_a2dp_high_quality_unknown_codec)); + mContext.getString(R.string.bluetooth_profile_a2dp_high_quality_unknown_codec)); when(mA2dpProfile.isProfileReady()).thenReturn(true); when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); when(mLeAudioProfile.toString()).thenReturn("LE_AUDIO"); when(mLeAudioProfile.getNameResource(any())) - .thenReturn(com.android.settingslib.R.string.bluetooth_profile_le_audio); + .thenReturn(R.string.bluetooth_profile_le_audio); when(mLeAudioProfile.isProfileReady()).thenReturn(true); when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); + + when(mHearingAidProfile.toString()).thenReturn("HearingAid"); + when(mHearingAidProfile.getNameResource(any())) + .thenReturn(R.string.bluetooth_profile_hearing_aid); + when(mHearingAidProfile.isProfileReady()).thenReturn(true); + when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); } private void addA2dpProfileToDevice(boolean preferred, boolean supportsHighQualityAudio, @@ -426,6 +436,11 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont mConnectableProfiles.add(mLeAudioProfile); } + private void addHearingAidProfileToDevice(boolean enabled) { + when(mHearingAidProfile.isEnabled(any())).thenReturn(enabled); + mConnectableProfiles.add(mHearingAidProfile); + } + private SwitchPreferenceCompat getHighQualityAudioPref() { return (SwitchPreferenceCompat) mScreen.findPreference( BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG); @@ -591,4 +606,27 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont List switches = getProfileSwitches(false); assertThat(switches.get(0).isVisible()).isFalse(); } + + @Test + public void ashaHearingAid_hideAshaToggle() { + setupDevice(makeDefaultDeviceConfig()); + addHearingAidProfileToDevice(true); + + showScreen(mController); + + List switches = getProfileSwitches(false); + assertThat(switches.isEmpty()).isTrue(); + } + @Test + public void ashaHearingAidWithLeAudio_showLeAudioToggle() { + setupDevice(makeDefaultDeviceConfig()); + addHearingAidProfileToDevice(false); + addLeAudioProfileToDevice(true); + + showScreen(mController); + + List switches = getProfileSwitches(false); + assertThat(switches.getFirst().getTitle()).isEqualTo( + mContext.getString(mLeAudioProfile.getNameResource(mDevice))); + } } diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java index 8445fe22c9f..9cd69b4e4b0 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java @@ -19,8 +19,10 @@ package com.android.settings.network.telephony; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -37,6 +39,7 @@ import androidx.core.graphics.drawable.IconCompat; import androidx.slice.Slice; import androidx.slice.SliceMetadata; import androidx.slice.SliceProvider; +import androidx.slice.builders.ListBuilder; import androidx.slice.core.SliceAction; import androidx.slice.widget.SliceLiveData; @@ -68,6 +71,7 @@ public class MobileDataSliceTest { private Context mContext; private MobileDataSlice mMobileDataSlice; + private ListBuilder mListBuilder; @Before public void setUp() { @@ -86,6 +90,8 @@ public class MobileDataSliceTest { SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); mMobileDataSlice = spy(new MobileDataSlice(mContext)); + mListBuilder = spy(mMobileDataSlice.createListBuilder()); + doReturn(mListBuilder).when(mMobileDataSlice).createListBuilder(); } @Test @@ -175,25 +181,41 @@ public class MobileDataSliceTest { @Test public void isMobileDataAvailable_noSubscriptions_slicePrimaryActionIsEmpty() { when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(new ArrayList<>()); - final Slice mobileData = mMobileDataSlice.getSlice(); - assertThat(mobileData).isNull(); + Slice mobileData = mMobileDataSlice.getSlice(); + + assertThat(mobileData).isNotNull(); + verify(mListBuilder, never()).addRow(any()); } @Test public void isMobileDataAvailable_nullSubscriptions_slicePrimaryActionIsEmpty() { when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(null); - final Slice mobileData = mMobileDataSlice.getSlice(); - assertThat(mobileData).isNull(); + Slice mobileData = mMobileDataSlice.getSlice(); + + assertThat(mobileData).isNotNull(); + verify(mListBuilder, never()).addRow(any()); } @Test public void airplaneModeEnabled_slicePrimaryActionIsEmpty() { doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled(); doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); - final Slice mobileData = mMobileDataSlice.getSlice(); - assertThat(mobileData).isNull(); + Slice mobileData = mMobileDataSlice.getSlice(); + + assertThat(mobileData).isNotNull(); + verify(mListBuilder, never()).addRow(any()); + } + + @Test + public void getSlice_disallowConfigMobileNetworks_slicePrimaryActionIsEmpty() { + doReturn(false).when(mMobileDataSlice).isConfigMobileNetworksAllowed(); + + Slice mobileData = mMobileDataSlice.getSlice(); + + assertThat(mobileData).isNotNull(); + verify(mListBuilder, never()).addRow(any()); } } diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java index e035274a5de..482aa5d5b93 100644 --- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java +++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java @@ -729,12 +729,25 @@ public class UserDetailsSettingsTest { public void initialize_restrictUserSelected_shouldNotShowGrantAdminPref_MultipleAdminEnabled() { setupSelectedUser(); ShadowUserManager.setIsMultipleAdminEnabled(true); + // target user has DISALLOW_GRANT_ADMIN restriction mUserManager.setUserRestriction(mUserInfo.getUserHandle(), UserManager.DISALLOW_GRANT_ADMIN, true); mFragment.initialize(mActivity, mArguments); verify(mFragment).removePreference(KEY_GRANT_ADMIN); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_UNICORN_MODE_REFACTORING_FOR_HSUM_READ_ONLY) + public void initialize_currentUserRestrict_shouldNotShowGrantAdminPref_MultipleAdminEnabled() { + setupSelectedUser(); + ShadowUserManager.setIsMultipleAdminEnabled(true); + // current user has DISALLOW_GRANT_ADMIN restriction + mUserManager.setUserRestriction(mContext.getUser(), + UserManager.DISALLOW_GRANT_ADMIN, true); + mFragment.initialize(mActivity, mArguments); + verify(mFragment).removePreference(KEY_GRANT_ADMIN); + } + @Test public void initialize_mainUserSelected_shouldShowGrantAdminPref_MultipleAdminEnabled() { setupSelectedMainUser();