Snap for 12190349 from b1f8213735 to 24Q4-release

Change-Id: I5eb31f535e81bdbacdb1a3a6915bafbb7a48d0bb
This commit is contained in:
Android Build Coastguard Worker
2024-08-06 23:21:49 +00:00
17 changed files with 272 additions and 81 deletions

View File

@@ -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 { flag {
name: "remove_qs_tooltip_in_suw" name: "remove_qs_tooltip_in_suw"
namespace: "accessibility" namespace: "accessibility"

View File

@@ -40,4 +40,6 @@
<!-- PointerIcon Settings --> <!-- PointerIcon Settings -->
<integer name="pointer_scale_seek_bar_start">0</integer> <integer name="pointer_scale_seek_bar_start">0</integer>
<integer name="pointer_scale_seek_bar_end">3</integer> <integer name="pointer_scale_seek_bar_end">3</integer>
<integer name="max_integer">2147483647</integer>
</resources> </resources>

View File

@@ -33,6 +33,7 @@
android:persistent="false" android:persistent="false"
android:summary="@string/daltonizer_mode_deuteranomaly_summary" android:summary="@string/daltonizer_mode_deuteranomaly_summary"
android:title="@string/daltonizer_mode_deuteranomaly_title" android:title="@string/daltonizer_mode_deuteranomaly_title"
settings:titleMaxLines="@integer/max_integer"
settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" /> settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" />
<com.android.settingslib.widget.SelectorWithWidgetPreference <com.android.settingslib.widget.SelectorWithWidgetPreference
@@ -40,6 +41,7 @@
android:persistent="false" android:persistent="false"
android:summary="@string/daltonizer_mode_protanomaly_summary" android:summary="@string/daltonizer_mode_protanomaly_summary"
android:title="@string/daltonizer_mode_protanomaly_title" android:title="@string/daltonizer_mode_protanomaly_title"
settings:titleMaxLines="@integer/max_integer"
settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" /> settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" />
<com.android.settingslib.widget.SelectorWithWidgetPreference <com.android.settingslib.widget.SelectorWithWidgetPreference
@@ -47,12 +49,14 @@
android:persistent="false" android:persistent="false"
android:summary="@string/daltonizer_mode_tritanomaly_summary" android:summary="@string/daltonizer_mode_tritanomaly_summary"
android:title="@string/daltonizer_mode_tritanomaly_title" android:title="@string/daltonizer_mode_tritanomaly_title"
settings:titleMaxLines="@integer/max_integer"
settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" /> settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" />
<com.android.settingslib.widget.SelectorWithWidgetPreference <com.android.settingslib.widget.SelectorWithWidgetPreference
android:key="daltonizer_mode_grayscale" android:key="daltonizer_mode_grayscale"
android:persistent="false" android:persistent="false"
android:title="@string/daltonizer_mode_grayscale_title" android:title="@string/daltonizer_mode_grayscale_title"
settings:titleMaxLines="@integer/max_integer"
settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" /> settings:controller="com.android.settings.accessibility.DaltonizerRadioButtonPreferenceController" />
<com.android.settings.widget.SeekBarPreference <com.android.settings.widget.SeekBarPreference

View File

@@ -202,10 +202,12 @@
android:title="@string/call_category" android:title="@string/call_category"
settings:controller="com.android.settings.network.telephony.CallingPreferenceCategoryController"> settings:controller="com.android.settings.network.telephony.CallingPreferenceCategoryController">
<!-- Settings search is handled by WifiCallingSearchItem. -->
<Preference <Preference
android:key="wifi_calling" android:key="wifi_calling"
android:title="@string/wifi_calling_settings_title" android:title="@string/wifi_calling_settings_title"
android:summary="@string/wifi_calling_summary" android:summary="@string/wifi_calling_summary"
settings:searchable="false"
settings:controller="com.android.settings.network.telephony.WifiCallingPreferenceController"> settings:controller="com.android.settings.network.telephony.WifiCallingPreferenceController">
<intent android:action="android.intent.action.MAIN" <intent android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings" android:targetPackage="com.android.settings"

View File

@@ -29,7 +29,6 @@ import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.VibrationAttributes; import android.os.VibrationAttributes;
import android.os.Vibrator; import android.os.Vibrator;
import android.os.vibrator.Flags;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log; import android.util.Log;
@@ -110,8 +109,7 @@ public class KeyboardVibrationTogglePreferenceController extends TogglePreferenc
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
if (Flags.keyboardCategoryEnabled() if (mContext.getResources().getBoolean(
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) { com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) {
return AVAILABLE; return AVAILABLE;
} }

View File

@@ -128,7 +128,13 @@ public class RestrictedPreferenceHelper {
AccessibilityActivityPreference preference = new AccessibilityActivityPreference( AccessibilityActivityPreference preference = new AccessibilityActivityPreference(
mContext, componentName.getPackageName(), activityInfo.applicationInfo.uid, mContext, componentName.getPackageName(), activityInfo.applicationInfo.uid,
info); info);
if (Flags.neverRestrictAccessibilityActivity()) {
// Accessibility Activities do not have elevated privileges so restricting
// them based on ECM or device admin does not give any value.
preference.setEnabled(true);
} else {
setRestrictedPreferenceEnabled(preference, permittedServices, serviceEnabled); setRestrictedPreferenceEnabled(preference, permittedServices, serviceEnabled);
}
preferenceList.add(preference); preferenceList.add(preference);
} }
return preferenceList; return preferenceList;

View File

@@ -308,7 +308,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
* Helper to get the list of connectable and special profiles. * Helper to get the list of connectable and special profiles.
*/ */
private List<LocalBluetoothProfile> getProfiles() { private List<LocalBluetoothProfile> getProfiles() {
List<LocalBluetoothProfile> result = new ArrayList<LocalBluetoothProfile>(); List<LocalBluetoothProfile> result = new ArrayList<>();
mProfileDeviceMap.clear(); mProfileDeviceMap.clear();
if (mAllOfCachedDevices == null || mAllOfCachedDevices.isEmpty()) { if (mAllOfCachedDevices == null || mAllOfCachedDevices.isEmpty()) {
return result; return result;
@@ -319,8 +319,7 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
if (mProfileDeviceMap.containsKey(profile.toString())) { if (mProfileDeviceMap.containsKey(profile.toString())) {
mProfileDeviceMap.get(profile.toString()).add(cachedItem); mProfileDeviceMap.get(profile.toString()).add(cachedItem);
} else { } else {
List<CachedBluetoothDevice> tmpCachedDeviceList = List<CachedBluetoothDevice> tmpCachedDeviceList = new ArrayList<>();
new ArrayList<CachedBluetoothDevice>();
tmpCachedDeviceList.add(cachedItem); tmpCachedDeviceList.add(cachedItem);
mProfileDeviceMap.put(profile.toString(), tmpCachedDeviceList); mProfileDeviceMap.put(profile.toString(), tmpCachedDeviceList);
result.add(profile); result.add(profile);
@@ -356,6 +355,10 @@ public class BluetoothDetailsProfilesController extends BluetoothDetailsControll
} }
boolean hearingAidSupported = result.contains( boolean hearingAidSupported = result.contains(
mManager.getProfileManager().getHearingAidProfile()); 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) { if (leAudioSupported && !classicAudioSupported && !hearingAidSupported) {
mIsLeAudioOnlyDevice = true; mIsLeAudioOnlyDevice = true;
} }

View File

@@ -263,6 +263,16 @@ public abstract class BasePreferenceController extends AbstractPreferenceControl
|| availabilityStatus == DISABLED_DEPENDENT_SETTING); || 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 * @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 * 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 * Called by SearchIndexProvider#getNonIndexableKeys
*/ */
public void updateNonIndexableKeys(List<String> keys) { public void updateNonIndexableKeys(List<String> keys) {
final boolean shouldSuppressFromSearch = !isAvailable()
|| getAvailabilityStatus() == AVAILABLE_UNSEARCHABLE;
if (shouldSuppressFromSearch) {
final String key = getPreferenceKey(); final String key = getPreferenceKey();
if (TextUtils.isEmpty(key)) { if (TextUtils.isEmpty(key)) {
Log.w(TAG, "Skipping updateNonIndexableKeys due to empty key " + toString()); Log.w(TAG, "Skipping updateNonIndexableKeys due to empty key " + this);
return;
}
if (keys.contains(key)) {
Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list. " + toString());
return; return;
} }
if (!keys.contains(key) && !isAvailableForSearch()) {
keys.add(key); keys.add(key);
} }
} }

View File

@@ -29,6 +29,7 @@ import android.database.ContentObserver;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
@@ -79,19 +80,24 @@ public class MobileDataSlice implements CustomSliceable {
@Override @Override
public Slice getSlice() { public Slice getSlice() {
ListBuilder listBuilder = createListBuilder();
if (!isConfigMobileNetworksAllowed()) {
return listBuilder.build();
}
final IconCompat icon = IconCompat.createWithResource(mContext, final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_network_cell); R.drawable.ic_network_cell);
final String title = mContext.getText(R.string.mobile_data_settings_title).toString(); final String title = mContext.getText(R.string.mobile_data_settings_title).toString();
@ColorInt final int color = Utils.getColorAccentDefaultColor(mContext); @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()) { 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()) { if (!isMobileDataAvailable()) {
return null; return listBuilder.build();
} }
final CharSequence summary = getSummary(); final CharSequence summary = getSummary();
@@ -109,11 +115,15 @@ public class MobileDataSlice implements CustomSliceable {
rowBuilder.setSubtitle(summary); rowBuilder.setSubtitle(summary);
} }
final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), return listBuilder
ListBuilder.INFINITY)
.setAccentColor(color) .setAccentColor(color)
.addRow(rowBuilder); .addRow(rowBuilder)
return listBuilder.build(); .build();
}
@VisibleForTesting
ListBuilder createListBuilder() {
return new ListBuilder(mContext, getUri(), ListBuilder.INFINITY);
} }
@Override @Override
@@ -211,6 +221,19 @@ public class MobileDataSlice implements CustomSliceable {
return mTelephonyManager.isDataEnabled(); 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. * Listener for mobile data state changes.
* *

View File

@@ -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.MmsMessagePreferenceController.Companion.MmsMessageSearchItem
import com.android.settings.network.telephony.NrAdvancedCallingPreferenceController.Companion.NrAdvancedCallingSearchItem import com.android.settings.network.telephony.NrAdvancedCallingPreferenceController.Companion.NrAdvancedCallingSearchItem
import com.android.settings.network.telephony.RoamingPreferenceController.Companion.RoamingSearchItem 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.BundleValue
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingFragment
import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey import com.android.settings.spa.SpaSearchLanding.SpaSearchLandingKey
@@ -112,9 +113,10 @@ class MobileNetworkSettingsSearchIndex(
fun createSearchItems(context: Context): List<MobileNetworkSettingsSearchItem> = fun createSearchItems(context: Context): List<MobileNetworkSettingsSearchItem> =
listOf( listOf(
RoamingSearchItem(context),
MmsMessageSearchItem(context), MmsMessageSearchItem(context),
NrAdvancedCallingSearchItem(context), NrAdvancedCallingSearchItem(context),
RoamingSearchItem(context),
WifiCallingSearchItem(context),
) )
} }
} }

View File

@@ -22,14 +22,17 @@ import android.telecom.TelecomManager
import android.telephony.SubscriptionManager import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager import android.telephony.TelephonyManager
import android.telephony.ims.ImsMmTelManager import android.telephony.ims.ImsMmTelManager
import android.util.Log
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import com.android.settings.R 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.settings.network.telephony.wificalling.WifiCallingRepository
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
/** /**
@@ -44,20 +47,21 @@ open class WifiCallingPreferenceController @JvmOverloads constructor(
private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId -> private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId ->
WifiCallingRepository(context, 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 preference: Preference
private lateinit var callingPreferenceCategoryController: CallingPreferenceCategoryController private lateinit var callingPreferenceCategoryController: CallingPreferenceCategoryController
private val resourcesForSub by lazy { private val resourcesForSub by lazy {
SubscriptionManager.getResourcesForSubId(mContext, mSubId) SubscriptionManager.getResourcesForSubId(mContext, subId)
} }
fun init( fun init(
subId: Int, subId: Int,
callingPreferenceCategoryController: CallingPreferenceCategoryController, callingPreferenceCategoryController: CallingPreferenceCategoryController,
): WifiCallingPreferenceController { ): WifiCallingPreferenceController {
mSubId = subId this.subId = subId
this.callingPreferenceCategoryController = callingPreferenceCategoryController this.callingPreferenceCategoryController = callingPreferenceCategoryController
return this return this
} }
@@ -65,39 +69,32 @@ open class WifiCallingPreferenceController @JvmOverloads constructor(
/** /**
* Note: Visibility also controlled by [onViewCreated]. * Note: Visibility also controlled by [onViewCreated].
*/ */
override fun getAvailabilityStatus(subId: Int) = override fun getAvailabilityStatus() =
if (SubscriptionManager.isValidSubscriptionId(subId)) AVAILABLE if (SubscriptionManager.isValidSubscriptionId(subId)) AVAILABLE
else CONDITIONALLY_UNAVAILABLE else CONDITIONALLY_UNAVAILABLE
override fun displayPreference(screen: PreferenceScreen) { override fun displayPreference(screen: PreferenceScreen) {
// Not call super here, to avoid preference.isVisible changed unexpectedly // Not call super here, to avoid preference.isVisible changed unexpectedly
preference = screen.findPreference(preferenceKey)!! 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) { override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
if(mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID){ wifiCallingRepositoryFactory(subId).wifiCallingReadyFlow()
Log.e(
this.javaClass.simpleName,
"mSubId is INVALID_SUBSCRIPTION_ID"
)
return
}
wifiCallingRepositoryFactory(mSubId).wifiCallingReadyFlow()
.collectLatestWithLifecycle(viewLifecycleOwner) { isReady -> .collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
preference.isVisible = isReady preference.isVisible = isReady
callingPreferenceCategoryController.updateChildVisible(preferenceKey, isReady) callingPreferenceCategoryController.updateChildVisible(preferenceKey, isReady)
if (isReady) update() if (isReady) update()
} }
callStateRepository.callStateFlow(mSubId).collectLatestWithLifecycle(viewLifecycleOwner) { callStateRepository.callStateFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE) preference.isEnabled = (it == TelephonyManager.CALL_STATE_IDLE)
} }
} }
private suspend fun update() { private suspend fun update() {
val simCallManager = mContext.getSystemService(TelecomManager::class.java) val simCallManager = mContext.getSystemService(TelecomManager::class.java)
?.getSimCallManagerForSubscription(mSubId) ?.getSimCallManagerForSubscription(subId)
if (simCallManager != null) { if (simCallManager != null) {
val intent = withContext(Dispatchers.Default) { val intent = withContext(Dispatchers.Default) {
MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, simCallManager) MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, simCallManager)
@@ -116,7 +113,7 @@ open class WifiCallingPreferenceController @JvmOverloads constructor(
} }
private fun getSummaryForWfcMode(): String { private fun getSummaryForWfcMode(): String {
val resId = when (wifiCallingRepositoryFactory(mSubId).getWiFiCallingMode()) { val resId = when (wifiCallingRepositoryFactory(subId).getWiFiCallingMode()) {
ImsMmTelManager.WIFI_MODE_WIFI_ONLY -> ImsMmTelManager.WIFI_MODE_WIFI_ONLY ->
com.android.internal.R.string.wfc_mode_wifi_only_summary com.android.internal.R.string.wfc_mode_wifi_only_summary
@@ -130,4 +127,17 @@ open class WifiCallingPreferenceController @JvmOverloads constructor(
} }
return resourcesForSub.getString(resId) 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()
}
}
}
} }

View File

@@ -370,11 +370,18 @@ public class UserDetailsSettings extends SettingsPreferenceFragment
} }
mSwitchUserPref.setOnPreferenceClickListener(this); mSwitchUserPref.setOnPreferenceClickListener(this);
} }
if (android.multiuser.Flags.unicornModeRefactoringForHsumReadOnly()) {
if (isChangingAdminStatusRestricted()) {
removePreference(KEY_GRANT_ADMIN);
}
} else {
if (mUserInfo.isMain() || mUserInfo.isGuest() || !UserManager.isMultipleAdminEnabled() if (mUserInfo.isMain() || mUserInfo.isGuest() || !UserManager.isMultipleAdminEnabled()
|| mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_GRANT_ADMIN, || mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_GRANT_ADMIN,
mUserInfo.getUserHandle()) || !mUserManager.isAdminUser()) { mUserInfo.getUserHandle()) || !mUserManager.isAdminUser()) {
removePreference(KEY_GRANT_ADMIN); removePreference(KEY_GRANT_ADMIN);
} }
}
if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls if (!mUserManager.isAdminUser()) { // non admin users can't remove users and allow calls
removePreference(KEY_ENABLE_TELEPHONY); removePreference(KEY_ENABLE_TELEPHONY);
removePreference(KEY_REMOVE_USER); 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 true so there will be no setup prompt dialog shown to the user anymore.
return isSecondaryUser(mUserInfo) && !mUserInfo.isInitialized(); return isSecondaryUser(mUserInfo) && !mUserInfo.isInitialized();
} }
/**
* Determines if changing admin status is restricted.
*
* <p>Admin status change is restricted under the following conditions of current & target user.
*
* <ul>
* <li>The <b>current</b> user is NOT an admin user.</li>
* <li>OR multiple admin support is NOT enabled.</li>
* <li>OR the <b>current</b> user has DISALLOW_GRANT_ADMIN restriction applied</li>
*
* <li>OR the <b>target</b> user ('mUserInfo') is a main user OR a guest user.</li>
* <li>OR the <b>target</b> user ('mUserInfo') has DISALLOW_GRANT_ADMIN restriction.</li>
* </ul>
*
* @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;
}
} }

View File

@@ -33,7 +33,6 @@ import android.app.settings.SettingsEnums;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.vibrator.Flags;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings; import android.provider.Settings;
@@ -41,7 +40,6 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before; import org.junit.Before;
@@ -87,7 +85,6 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
@Test @Test
public void getAvailabilityStatus_featureSupported_available() { public void getAvailabilityStatus_featureSupported_available() {
mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
when(mResources.getBoolean( when(mResources.getBoolean(
com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) com.android.internal.R.bool.config_keyboardVibrationSettingsSupported))
.thenReturn(true); .thenReturn(true);
@@ -97,7 +94,6 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
@Test @Test
public void getAvailabilityStatus_featureNotSupported_unavailable() { public void getAvailabilityStatus_featureNotSupported_unavailable() {
mSetFlagsRule.enableFlags(Flags.FLAG_KEYBOARD_CATEGORY_ENABLED);
when(mResources.getBoolean( when(mResources.getBoolean(
com.android.internal.R.bool.config_keyboardVibrationSettingsSupported)) com.android.internal.R.bool.config_keyboardVibrationSettingsSupported))
.thenReturn(false); .thenReturn(false);
@@ -105,15 +101,6 @@ public class KeyboardVibrationTogglePreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); 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 @Test
public void updateState_mainVibrateDisabled_shouldReturnFalseForCheckedAndEnabled() { public void updateState_mainVibrateDisabled_shouldReturnFalseForCheckedAndEnabled() {

View File

@@ -31,9 +31,8 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.annotations.DisableFlags;
import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -83,8 +82,6 @@ public class RestrictedPreferenceHelperTest {
@Rule @Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Test @Test
public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() { public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
@@ -100,7 +97,7 @@ public class RestrictedPreferenceHelperTest {
} }
@Test @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}) android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() { public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() {
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs( ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(
@@ -116,7 +113,7 @@ public class RestrictedPreferenceHelperTest {
} }
@Test @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}) android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() { public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() {
ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(); ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
@@ -144,6 +141,40 @@ public class RestrictedPreferenceHelperTest {
assertThat(preference.getKey()).isEqualTo(key); 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<AccessibilityActivityPreference> 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<AccessibilityActivityPreference> 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, private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName,
String className) { String className) {
final ApplicationInfo applicationInfo = new ApplicationInfo(); final ApplicationInfo applicationInfo = new ApplicationInfo();

View File

@@ -44,6 +44,7 @@ import com.android.settings.testutils.shadow.ShadowBluetoothDevice;
import com.android.settingslib.R; import com.android.settingslib.R;
import com.android.settingslib.bluetooth.A2dpProfile; import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.bluetooth.LeAudioProfile; import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.LocalBluetoothProfile;
@@ -90,8 +91,12 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
@Mock @Mock
private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager; private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
private @Mock A2dpProfile mA2dpProfile; @Mock
private @Mock LeAudioProfile mLeAudioProfile; private A2dpProfile mA2dpProfile;
@Mock
private LeAudioProfile mLeAudioProfile;
@Mock
private HearingAidProfile mHearingAidProfile;
@Override @Override
public void setUp() { public void setUp() {
@@ -399,18 +404,23 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
when(mProfileManager.getProfileByName(eq(mA2dpProfile.toString()))) when(mProfileManager.getProfileByName(eq(mA2dpProfile.toString())))
.thenReturn(mA2dpProfile); .thenReturn(mA2dpProfile);
when(mA2dpProfile.getNameResource(any())) when(mA2dpProfile.getNameResource(any()))
.thenReturn(com.android.settingslib.R.string.bluetooth_profile_a2dp); .thenReturn(R.string.bluetooth_profile_a2dp);
when(mA2dpProfile.getHighQualityAudioOptionLabel(any())).thenReturn( when(mA2dpProfile.getHighQualityAudioOptionLabel(any())).thenReturn(
mContext.getString(com.android.settingslib.R mContext.getString(R.string.bluetooth_profile_a2dp_high_quality_unknown_codec));
.string.bluetooth_profile_a2dp_high_quality_unknown_codec));
when(mA2dpProfile.isProfileReady()).thenReturn(true); when(mA2dpProfile.isProfileReady()).thenReturn(true);
when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile); when(mProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLeAudioProfile.toString()).thenReturn("LE_AUDIO"); when(mLeAudioProfile.toString()).thenReturn("LE_AUDIO");
when(mLeAudioProfile.getNameResource(any())) 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(mLeAudioProfile.isProfileReady()).thenReturn(true);
when(mProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile); 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, private void addA2dpProfileToDevice(boolean preferred, boolean supportsHighQualityAudio,
@@ -426,6 +436,11 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
mConnectableProfiles.add(mLeAudioProfile); mConnectableProfiles.add(mLeAudioProfile);
} }
private void addHearingAidProfileToDevice(boolean enabled) {
when(mHearingAidProfile.isEnabled(any())).thenReturn(enabled);
mConnectableProfiles.add(mHearingAidProfile);
}
private SwitchPreferenceCompat getHighQualityAudioPref() { private SwitchPreferenceCompat getHighQualityAudioPref() {
return (SwitchPreferenceCompat) mScreen.findPreference( return (SwitchPreferenceCompat) mScreen.findPreference(
BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG); BluetoothDetailsProfilesController.HIGH_QUALITY_AUDIO_PREF_TAG);
@@ -591,4 +606,27 @@ public class BluetoothDetailsProfilesControllerTest extends BluetoothDetailsCont
List<SwitchPreferenceCompat> switches = getProfileSwitches(false); List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
assertThat(switches.get(0).isVisible()).isFalse(); assertThat(switches.get(0).isVisible()).isFalse();
} }
@Test
public void ashaHearingAid_hideAshaToggle() {
setupDevice(makeDefaultDeviceConfig());
addHearingAidProfileToDevice(true);
showScreen(mController);
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
assertThat(switches.isEmpty()).isTrue();
}
@Test
public void ashaHearingAidWithLeAudio_showLeAudioToggle() {
setupDevice(makeDefaultDeviceConfig());
addHearingAidProfileToDevice(false);
addLeAudioProfileToDevice(true);
showScreen(mController);
List<SwitchPreferenceCompat> switches = getProfileSwitches(false);
assertThat(switches.getFirst().getTitle()).isEqualTo(
mContext.getString(mLeAudioProfile.getNameResource(mDevice)));
}
} }

View File

@@ -19,8 +19,10 @@ package com.android.settings.network.telephony;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -37,6 +39,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice; import androidx.slice.Slice;
import androidx.slice.SliceMetadata; import androidx.slice.SliceMetadata;
import androidx.slice.SliceProvider; import androidx.slice.SliceProvider;
import androidx.slice.builders.ListBuilder;
import androidx.slice.core.SliceAction; import androidx.slice.core.SliceAction;
import androidx.slice.widget.SliceLiveData; import androidx.slice.widget.SliceLiveData;
@@ -68,6 +71,7 @@ public class MobileDataSliceTest {
private Context mContext; private Context mContext;
private MobileDataSlice mMobileDataSlice; private MobileDataSlice mMobileDataSlice;
private ListBuilder mListBuilder;
@Before @Before
public void setUp() { public void setUp() {
@@ -86,6 +90,8 @@ public class MobileDataSliceTest {
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
mMobileDataSlice = spy(new MobileDataSlice(mContext)); mMobileDataSlice = spy(new MobileDataSlice(mContext));
mListBuilder = spy(mMobileDataSlice.createListBuilder());
doReturn(mListBuilder).when(mMobileDataSlice).createListBuilder();
} }
@Test @Test
@@ -175,25 +181,41 @@ public class MobileDataSliceTest {
@Test @Test
public void isMobileDataAvailable_noSubscriptions_slicePrimaryActionIsEmpty() { public void isMobileDataAvailable_noSubscriptions_slicePrimaryActionIsEmpty() {
when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(new ArrayList<>()); 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 @Test
public void isMobileDataAvailable_nullSubscriptions_slicePrimaryActionIsEmpty() { public void isMobileDataAvailable_nullSubscriptions_slicePrimaryActionIsEmpty() {
when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(null); 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 @Test
public void airplaneModeEnabled_slicePrimaryActionIsEmpty() { public void airplaneModeEnabled_slicePrimaryActionIsEmpty() {
doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled(); doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled();
doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); 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());
} }
} }

View File

@@ -729,12 +729,25 @@ public class UserDetailsSettingsTest {
public void initialize_restrictUserSelected_shouldNotShowGrantAdminPref_MultipleAdminEnabled() { public void initialize_restrictUserSelected_shouldNotShowGrantAdminPref_MultipleAdminEnabled() {
setupSelectedUser(); setupSelectedUser();
ShadowUserManager.setIsMultipleAdminEnabled(true); ShadowUserManager.setIsMultipleAdminEnabled(true);
// target user has DISALLOW_GRANT_ADMIN restriction
mUserManager.setUserRestriction(mUserInfo.getUserHandle(), mUserManager.setUserRestriction(mUserInfo.getUserHandle(),
UserManager.DISALLOW_GRANT_ADMIN, true); UserManager.DISALLOW_GRANT_ADMIN, true);
mFragment.initialize(mActivity, mArguments); mFragment.initialize(mActivity, mArguments);
verify(mFragment).removePreference(KEY_GRANT_ADMIN); 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 @Test
public void initialize_mainUserSelected_shouldShowGrantAdminPref_MultipleAdminEnabled() { public void initialize_mainUserSelected_shouldShowGrantAdminPref_MultipleAdminEnabled() {
setupSelectedMainUser(); setupSelectedMainUser();