From 4551e0693a3898087aefa1d032b5b5074ebe9d34 Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Fri, 3 May 2024 19:38:12 +0000 Subject: [PATCH 01/25] Add strict_mode: false As strict mode is in place, the default strict_mode is now set to true. We are encourage teams to write tests in strict_mode to make tests Bivalent (able to run on device and devicelessly) For more info on strict mode: go/roboStrictMode Test: atest SettingsRoboTests Bug: 334089788 Change-Id: I4381446dac381a34747043c564cf5288a2e16725 --- tests/robotests/Android.bp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp index 1c6794d027f..7830ab455f2 100644 --- a/tests/robotests/Android.bp +++ b/tests/robotests/Android.bp @@ -98,6 +98,8 @@ android_robolectric_test { ], upstream: true, + + strict_mode: false, } java_library { From 31938e13d8d71b83b7a8ea08a883ff96d7058521 Mon Sep 17 00:00:00 2001 From: Vlad Marica Date: Wed, 22 May 2024 22:50:06 +0000 Subject: [PATCH 02/25] Ignore OEM Unlocking when wiping PDB during factory reset on V+ On Android V and newer, the PDB will no longer wipe itself on start, even if OEM Unlocking is enabled, so trusted factory resets must wipe it. Bug: 336362291 Flag: EXEMPT bugfix Test: atest & manual testing Change-Id: I67cc0fc3e7470c5ddddd03d23942706345361f8f --- .../android/settings/MainClearConfirm.java | 13 ++++-- .../settings/MainClearConfirmTest.java | 41 +++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/MainClearConfirm.java b/src/com/android/settings/MainClearConfirm.java index b5ddd1aeb96..042c5c26c1a 100644 --- a/src/com/android/settings/MainClearConfirm.java +++ b/src/com/android/settings/MainClearConfirm.java @@ -151,15 +151,20 @@ public class MainClearConfirm extends InstrumentedFragment { if (pdbManager == null) { return false; } + // The persistent data block will persist if the device is still being provisioned. if (isDeviceStillBeingProvisioned()) { return false; } - // If OEM unlock is allowed, the persistent data block will be wiped during FR - // process. If disabled, it will be wiped here instead. - if (isOemUnlockedAllowed()) { + + // If OEM unlock is allowed, the persistent data block will be wiped during the FR + // process on devices without FRP Hardening. If disabled, it will be wiped here instead. + // On devices with FRP Hardening, the persistent data block should always be wiped, + // regardless of the OEM Unlocking state. + if (!android.security.Flags.frpEnforcement() && isOemUnlockedAllowed()) { return false; } + final DevicePolicyManager dpm = (DevicePolicyManager) getActivity() .getSystemService(Context.DEVICE_POLICY_SERVICE); // Do not erase the factory reset protection data (from Settings) if factory reset @@ -167,6 +172,7 @@ public class MainClearConfirm extends InstrumentedFragment { if (!dpm.isFactoryResetProtectionPolicySupported()) { return false; } + // Do not erase the factory reset protection data (from Settings) if the // device is an organization-owned managed profile device and a factory // reset protection policy has been set. @@ -175,6 +181,7 @@ public class MainClearConfirm extends InstrumentedFragment { && frpPolicy.isNotEmpty()) { return false; } + return true; } diff --git a/tests/robotests/src/com/android/settings/MainClearConfirmTest.java b/tests/robotests/src/com/android/settings/MainClearConfirmTest.java index b866c964f03..6d85368d0b8 100644 --- a/tests/robotests/src/com/android/settings/MainClearConfirmTest.java +++ b/tests/robotests/src/com/android/settings/MainClearConfirmTest.java @@ -25,6 +25,10 @@ import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; import android.app.admin.FactoryResetProtectionPolicy; import android.content.Context; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.security.Flags; import android.service.persistentdata.PersistentDataBlockManager; import android.view.LayoutInflater; import android.widget.TextView; @@ -32,6 +36,7 @@ import android.widget.TextView; import androidx.fragment.app.FragmentActivity; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -48,6 +53,9 @@ import java.util.ArrayList; }) public class MainClearConfirmTest { + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private FragmentActivity mActivity; @Mock @@ -66,6 +74,9 @@ public class MainClearConfirmTest { MockitoAnnotations.initMocks(this); mActivity = Robolectric.setupActivity(FragmentActivity.class); mMainClearConfirm = spy(new MainClearConfirm()); + + when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)) + .thenReturn(mDevicePolicyManager); } @Test @@ -110,12 +121,29 @@ public class MainClearConfirmTest { } @Test - public void shouldWipePersistentDataBlock_oemUnlockAllowed_shouldReturnFalse() { + @DisableFlags(Flags.FLAG_FRP_ENFORCEMENT) + public void shouldWipePersistentDataBlock_oemUnlockAllowedAndFlagDiscabled_shouldReturnFalse() { + when(mMainClearConfirm.getActivity()).thenReturn(mMockActivity); + + when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(true); doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned(); doReturn(true).when(mMainClearConfirm).isOemUnlockedAllowed(); - assertThat(mMainClearConfirm.shouldWipePersistentDataBlock( - mPersistentDataBlockManager)).isFalse(); + assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(mPersistentDataBlockManager)) + .isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_FRP_ENFORCEMENT) + public void shouldWipePersistentDataBlock_oemUnlockAllowedAndFlagEnabled_shouldReturnTrue() { + when(mMainClearConfirm.getActivity()).thenReturn(mMockActivity); + + when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(true); + doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned(); + doReturn(true).when(mMainClearConfirm).isOemUnlockedAllowed(); + + assertThat(mMainClearConfirm.shouldWipePersistentDataBlock(mPersistentDataBlockManager)) + .isTrue(); } @Test @@ -124,8 +152,7 @@ public class MainClearConfirmTest { doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned(); doReturn(false).when(mMainClearConfirm).isOemUnlockedAllowed(); - when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)) - .thenReturn(mDevicePolicyManager); + when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(false); assertThat(mMainClearConfirm.shouldWipePersistentDataBlock( @@ -144,8 +171,6 @@ public class MainClearConfirmTest { .setFactoryResetProtectionAccounts(accounts) .setFactoryResetProtectionEnabled(true) .build(); - when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)) - .thenReturn(mDevicePolicyManager); when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(true); when(mDevicePolicyManager.getFactoryResetProtectionPolicy(null)).thenReturn(frp); when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(true); @@ -161,8 +186,6 @@ public class MainClearConfirmTest { doReturn(false).when(mMainClearConfirm).isDeviceStillBeingProvisioned(); doReturn(false).when(mMainClearConfirm).isOemUnlockedAllowed(); - when(mMockActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)) - .thenReturn(mDevicePolicyManager); when(mDevicePolicyManager.isFactoryResetProtectionPolicySupported()).thenReturn(true); when(mDevicePolicyManager.getFactoryResetProtectionPolicy(null)).thenReturn(null); when(mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()).thenReturn(false); From 2a3815776c3e6d90cdbc512ede6e286a733d62b7 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Fri, 24 May 2024 18:25:03 +0800 Subject: [PATCH 03/25] Add Quick Settings shortcut option into Hearing Devices accessibility settings page * In Android V, we can add qs as one of the accessibility shortcut option to be more discoverable. Bug: 338327560 Flag: EXEMPT bugfix Test: check shortcut option in hearing devices settings page Change-Id: I60d4da2432605a5369eb87c1e594539d40c53ae8 --- .../accessibility/AccessibilityHearingAidsFragment.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java index cad21868e06..0f551b0fa1f 100644 --- a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java @@ -97,13 +97,12 @@ public class AccessibilityHearingAidsFragment extends AccessibilityShortcutPrefe @Override protected ComponentName getTileComponentName() { - // Don't have quick settings tile for now. - return null; + return AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_TILE_COMPONENT_NAME; } @Override protected CharSequence getTileTooltipContent(int type) { - // Don't have quick settings tile for now. + // No tooltip to be shown return null; } From 3b925a0cfeaa3cc1c6691243f299d96ea9020d2c Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Mon, 27 May 2024 18:24:52 +0800 Subject: [PATCH 04/25] Refactor SimStatusDialogRepository - Move data logic into repository for better testing - Check carrier config first, if not shows some items, we don't need to load data - Tests in SimStatusDialogControllerTest will be fixed in later cls Bug: 337417520 Test: manual - on SIM status Test: unit test Change-Id: Ia0c32882f0b35ec9154b3da58ac6a7b98c879efc --- .../simstatus/SimStatusDialogController.java | 46 +++++----------- .../simstatus/SimStatusDialogFragment.java | 7 +++ ...roller.kt => SimStatusDialogRepository.kt} | 53 ++++++++++++++++--- ...st.kt => SimStatusDialogRepositoryTest.kt} | 48 ++++++++++++++--- .../SimStatusDialogControllerTest.java | 23 +++----- 5 files changed, 113 insertions(+), 64 deletions(-) rename src/com/android/settings/deviceinfo/simstatus/{ImsRegistrationStateController.kt => SimStatusDialogRepository.kt} (57%) rename tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/{ImsRegistrationStateControllerTest.kt => SimStatusDialogRepositoryTest.kt} (53%) diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java index e5882dd9759..b39cce47582 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java @@ -227,7 +227,6 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { updateNetworkType(); updateRoamingStatus(serviceState); updateIccidNumber(); - updateImsRegistrationState(); } /** @@ -257,7 +256,7 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { .registerTelephonyCallback(mContext.getMainExecutor(), mTelephonyCallback); mSubscriptionManager.addOnSubscriptionsChangedListener( mContext.getMainExecutor(), mOnSubscriptionsChangedListener); - collectImsRegistered(owner); + collectSimStatusDialogInfo(owner); if (mShowLatestAreaInfo) { updateAreaInfoText(); @@ -581,39 +580,20 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { } } - private boolean isImsRegistrationStateShowUp() { - if (mSubscriptionInfo == null) { - return false; - } - final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); - final PersistableBundle carrierConfig = - mCarrierConfigManager.getConfigForSubId(subscriptionId); - return carrierConfig == null ? false : - carrierConfig.getBoolean( - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL); + private void updateImsRegistrationState(@Nullable Boolean imsRegistered) { + boolean isVisible = imsRegistered != null; + mDialog.setSettingVisibility(IMS_REGISTRATION_STATE_LABEL_ID, isVisible); + mDialog.setSettingVisibility(IMS_REGISTRATION_STATE_VALUE_ID, isVisible); + int stringId = Boolean.TRUE.equals(imsRegistered) + ? com.android.settingslib.R.string.ims_reg_status_registered + : com.android.settingslib.R.string.ims_reg_status_not_registered; + mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(stringId)); } - private void updateImsRegistrationState() { - if (isImsRegistrationStateShowUp()) { - return; - } - mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID); - mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID); - } - - private void collectImsRegistered(@NonNull LifecycleOwner owner) { - if (!isImsRegistrationStateShowUp()) { - return; - } - new ImsRegistrationStateController(mContext).collectImsRegistered( - owner, mSlotIndex, (Boolean imsRegistered) -> { - if (imsRegistered) { - mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( - com.android.settingslib.R.string.ims_reg_status_registered)); - } else { - mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( - com.android.settingslib.R.string.ims_reg_status_not_registered)); - } + private void collectSimStatusDialogInfo(@NonNull LifecycleOwner owner) { + new SimStatusDialogRepository(mContext).collectSimStatusDialogInfo( + owner, mSlotIndex, (simStatusDialogInfo) -> { + updateImsRegistrationState(simStatusDialogInfo.getImsRegistered()); return Unit.INSTANCE; } ); diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java index f212eea0d2e..3a0997a5b31 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java @@ -91,6 +91,13 @@ public class SimStatusDialogFragment extends InstrumentedDialogFragment { super.onDestroy(); } + public void setSettingVisibility(int viewId, boolean isVisible) { + final View view = mRootView.findViewById(viewId); + if (view != null) { + view.setVisibility(isVisible ? View.VISIBLE : View.GONE); + } + } + public void removeSettingFromScreen(int viewId) { final View view = mRootView.findViewById(viewId); if (view != null) { diff --git a/src/com/android/settings/deviceinfo/simstatus/ImsRegistrationStateController.kt b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt similarity index 57% rename from src/com/android/settings/deviceinfo/simstatus/ImsRegistrationStateController.kt rename to src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt index 3d17ec0d9ce..ab212be85d2 100644 --- a/src/com/android/settings/deviceinfo/simstatus/ImsRegistrationStateController.kt +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt @@ -17,6 +17,7 @@ package com.android.settings.deviceinfo.simstatus import android.content.Context +import android.telephony.CarrierConfigManager import android.telephony.SubscriptionManager import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner @@ -25,44 +26,82 @@ import androidx.lifecycle.repeatOnLifecycle import com.android.settings.network.telephony.SimSlotRepository import com.android.settings.network.telephony.ims.ImsMmTelRepository import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl +import com.android.settings.network.telephony.safeGetConfig import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) -class ImsRegistrationStateController @JvmOverloads constructor( +class SimStatusDialogRepository @JvmOverloads constructor( private val context: Context, private val simSlotRepository: SimSlotRepository = SimSlotRepository(context), private val imsMmTelRepositoryFactory: (subId: Int) -> ImsMmTelRepository = { subId -> ImsMmTelRepositoryImpl(context, subId) }, ) { - fun collectImsRegistered( + private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)!! + + data class SimStatusDialogInfo( + val imsRegistered: Boolean? = null, + ) + + private data class SimStatusDialogVisibility( + val imsRegisteredShowUp: Boolean, + ) + + fun collectSimStatusDialogInfo( lifecycleOwner: LifecycleOwner, simSlotIndex: Int, - action: (imsRegistered: Boolean) -> Unit, + action: (info: SimStatusDialogInfo) -> Unit, ) { lifecycleOwner.lifecycleScope.launch { lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { - imsRegisteredFlow(simSlotIndex).collect(action) + simStatusDialogInfoBySlotFlow(simSlotIndex).collect(action) } } } - private fun imsRegisteredFlow(simSlotIndex: Int): Flow = + private fun simStatusDialogInfoBySlotFlow(simSlotIndex: Int): Flow = simSlotRepository.subIdInSimSlotFlow(simSlotIndex) .flatMapLatest { subId -> if (SubscriptionManager.isValidSubscriptionId(subId)) { - imsMmTelRepositoryFactory(subId).imsRegisteredFlow() + simStatusDialogInfoFlow(subId) } else { - flowOf(false) + flowOf(SimStatusDialogInfo()) } } .conflate() .flowOn(Dispatchers.Default) + + private fun simStatusDialogInfoFlow(subId: Int): Flow = + showUpFlow(subId).flatMapLatest { visibility -> + combine( + if (visibility.imsRegisteredShowUp) { + imsMmTelRepositoryFactory(subId).imsRegisteredFlow() + } else flowOf(null), + ) { (imsRegistered) -> + SimStatusDialogInfo(imsRegistered = imsRegistered) + } + } + + private fun showUpFlow(subId: Int) = flow { + val config = carrierConfigManager.safeGetConfig( + keys = listOf(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL), + subId = subId, + ) + emit( + SimStatusDialogVisibility( + imsRegisteredShowUp = config.getBoolean( + CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL + ), + ) + ) + } } diff --git a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/ImsRegistrationStateControllerTest.kt b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt similarity index 53% rename from tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/ImsRegistrationStateControllerTest.kt rename to tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt index 5e486dd733e..3d13953ea10 100644 --- a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/ImsRegistrationStateControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt @@ -17,9 +17,12 @@ package com.android.settings.deviceinfo.simstatus import android.content.Context +import android.os.PersistableBundle +import android.telephony.CarrierConfigManager import androidx.lifecycle.testing.TestLifecycleOwner import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.deviceinfo.simstatus.SimStatusDialogRepository.SimStatusDialogInfo import com.android.settings.network.telephony.SimSlotRepository import com.android.settings.network.telephony.ims.ImsMmTelRepository import com.google.common.truth.Truth.assertThat @@ -30,11 +33,27 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock +import org.mockito.kotlin.spy @RunWith(AndroidJUnit4::class) -class ImsRegistrationStateControllerTest { +class SimStatusDialogRepositoryTest { - private val context: Context = ApplicationProvider.getApplicationContext() + private val carrierConfig = PersistableBundle().apply { + putBoolean(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, true) + } + + private val mockCarrierConfigManager = mock { + on { + getConfigForSubId( + SUB_ID, + CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, + ) + } doReturn carrierConfig + } + + private val context: Context = spy(ApplicationProvider.getApplicationContext()) { + on { getSystemService(CarrierConfigManager::class.java) } doReturn mockCarrierConfigManager + } private val mockSimSlotRepository = mock { on { subIdInSimSlotFlow(SIM_SLOT_INDEX) } doReturn flowOf(SUB_ID) @@ -44,7 +63,7 @@ class ImsRegistrationStateControllerTest { on { imsRegisteredFlow() } doReturn flowOf(true) } - private val controller = ImsRegistrationStateController( + private val controller = SimStatusDialogRepository( context = context, simSlotRepository = mockSimSlotRepository, imsMmTelRepositoryFactory = { subId -> @@ -54,15 +73,28 @@ class ImsRegistrationStateControllerTest { ) @Test - fun collectImsRegistered() = runBlocking { - var imsRegistered = false + fun collectSimStatusDialogInfo() = runBlocking { + var simStatusDialogInfo = SimStatusDialogInfo() - controller.collectImsRegistered(TestLifecycleOwner(), SIM_SLOT_INDEX) { - imsRegistered = it + controller.collectSimStatusDialogInfo(TestLifecycleOwner(), SIM_SLOT_INDEX) { + simStatusDialogInfo = it } delay(100) - assertThat(imsRegistered).isTrue() + assertThat(simStatusDialogInfo).isEqualTo(SimStatusDialogInfo(imsRegistered = true)) + } + + @Test + fun collectSimStatusDialogInfo_doNotShowImsRegistration() = runBlocking { + carrierConfig.putBoolean(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false) + var simStatusDialogInfo = SimStatusDialogInfo() + + controller.collectSimStatusDialogInfo(TestLifecycleOwner(), SIM_SLOT_INDEX) { + simStatusDialogInfo = it + } + delay(100) + + assertThat(simStatusDialogInfo.imsRegistered).isNull() } private companion object { diff --git a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java index f65480d3911..f4e6f187f36 100644 --- a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java +++ b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java @@ -36,7 +36,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; 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; @@ -394,8 +393,6 @@ public class SimStatusDialogControllerTest { @Test @Ignore public void initialize_imsRegistered_shouldSetImsRegistrationStateSummaryToRegisterd() { - mPersistableBundle.putBoolean( - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, true); when(mTelephonyManager.isImsRegistered(anyInt())).thenReturn(true); mController.initialize(); @@ -407,8 +404,6 @@ public class SimStatusDialogControllerTest { @Test @Ignore public void initialize_imsNotRegistered_shouldSetImsRegistrationStateSummaryToNotRegisterd() { - mPersistableBundle.putBoolean( - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, true); when(mTelephonyManager.isImsRegistered(anyInt())).thenReturn(false); mController.initialize(); @@ -418,24 +413,20 @@ public class SimStatusDialogControllerTest { } @Test - public void initialize_showImsRegistration_shouldNotRemoveImsRegistrationStateSetting() { - mPersistableBundle.putBoolean( - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, true); - + @Ignore("b/337417520") + public void initialize_showImsRegistration_shouldShowImsRegistrationStateSetting() { mController.initialize(); - verify(mDialog, never()).removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID); + verify(mDialog).setSettingVisibility(IMS_REGISTRATION_STATE_VALUE_ID, true); } @Test - public void initialize_doNotShowImsRegistration_shouldRemoveImsRegistrationStateSetting() { - mPersistableBundle.putBoolean( - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false); - + @Ignore("b/337417520") + public void initialize_doNotShowImsRegistration_shouldHideImsRegistrationStateSetting() { mController.initialize(); - verify(mDialog).removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID); - verify(mDialog).removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID); + verify(mDialog).setSettingVisibility(IMS_REGISTRATION_STATE_LABEL_ID, false); + verify(mDialog).setSettingVisibility(IMS_REGISTRATION_STATE_VALUE_ID, false); } @Test From 33d73862bfbcb5c438932dc8af7097cc9d943248 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Mon, 27 May 2024 20:30:17 +0800 Subject: [PATCH 05/25] Refactor signal strength in SIM status - Move data logic into repository for better testing - Check carrier config first, if not shows some items, we don't need to load data - Tests in SimStatusDialogControllerTest will be fixed in later cls Bug: 337417520 Test: manual - on SIM status Test: unit test Change-Id: Iccd209fd455d66d4f6438652ee7481d2a0e72a99 --- .../simstatus/SignalStrengthRepository.kt | 78 +++++++++ .../simstatus/SimStatusDialogController.java | 101 +----------- .../simstatus/SimStatusDialogFragment.java | 3 +- .../simstatus/SimStatusDialogRepository.kt | 31 ++-- .../simstatus/SignalStrengthRepositoryTest.kt | 148 ++++++++++++++++++ .../SimStatusDialogRepositoryTest.kt | 39 ++++- .../SimStatusDialogControllerTest.java | 136 +--------------- 7 files changed, 290 insertions(+), 246 deletions(-) create mode 100644 src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepository.kt create mode 100644 tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepositoryTest.kt diff --git a/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepository.kt b/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepository.kt new file mode 100644 index 00000000000..8b062e70e03 --- /dev/null +++ b/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepository.kt @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.deviceinfo.simstatus + +import android.content.Context +import android.telephony.ServiceState +import android.telephony.SignalStrength +import android.telephony.TelephonyCallback +import android.util.Log +import com.android.settings.R +import com.android.settings.network.telephony.serviceStateFlow +import com.android.settings.network.telephony.telephonyCallbackFlow +import com.android.settingslib.Utils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map + +@OptIn(ExperimentalCoroutinesApi::class) +class SignalStrengthRepository( + private val context: Context, + private val serviceStateFlowFactory: (subId: Int) -> Flow = { + context.serviceStateFlow(it) + }, +) { + fun signalStrengthDisplayFlow(subId: Int): Flow = + serviceStateFlowFactory(subId).flatMapLatest { serviceState -> + if (Utils.isInService(serviceState)) { + signalStrengthFlow(subId).map { it.displayString() } + } else { + flowOf("0") + } + }.conflate().flowOn(Dispatchers.Default) + + /** Creates an instance of a cold Flow for [SignalStrength] of given [subId]. */ + private fun signalStrengthFlow(subId: Int): Flow = + context.telephonyCallbackFlow(subId) { + object : TelephonyCallback(), TelephonyCallback.SignalStrengthsListener { + override fun onSignalStrengthsChanged(signalStrength: SignalStrength) { + trySend(signalStrength) + val cellSignalStrengths = signalStrength.cellSignalStrengths + Log.d(TAG, "[$subId] onSignalStrengthsChanged: $cellSignalStrengths") + } + } + } + + private fun SignalStrength.displayString() = + context.getString(R.string.sim_signal_strength, signalDbm(), signalAsu()) + + private companion object { + private const val TAG = "SignalStrengthRepo" + + + private fun SignalStrength.signalDbm(): Int = + cellSignalStrengths.firstOrNull { it.dbm != -1 }?.dbm ?: 0 + + private fun SignalStrength.signalAsu(): Int = + cellSignalStrengths.firstOrNull { it.asuLevel != -1 }?.asuLevel ?: 0 + } +} diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java index b39cce47582..b5ee1d88108 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java @@ -32,10 +32,8 @@ import android.telephony.Annotation; import android.telephony.CarrierConfigManager; import android.telephony.CellBroadcastIntents; import android.telephony.CellBroadcastService; -import android.telephony.CellSignalStrength; import android.telephony.ICellBroadcastService; import android.telephony.ServiceState; -import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; @@ -113,7 +111,6 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { private SubscriptionInfo mSubscriptionInfo; private TelephonyDisplayInfo mTelephonyDisplayInfo; - private ServiceState mPreviousServiceState; private final int mSlotIndex; private TelephonyManager mTelephonyManager; @@ -219,11 +216,9 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { // getServiceState() may return null when the subscription is inactive // or when there was an error communicating with the phone process. final ServiceState serviceState = getTelephonyManager().getServiceState(); - final SignalStrength signalStrength = getTelephonyManager().getSignalStrength(); updatePhoneNumber(); updateServiceState(serviceState); - updateSignalStrength(signalStrength); updateNetworkType(); updateRoamingStatus(serviceState); updateIccidNumber(); @@ -419,12 +414,6 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { private void updateServiceState(ServiceState serviceState) { final int state = Utils.getCombinedServiceState(serviceState); - if (!Utils.isInService(serviceState)) { - resetSignalStrength(); - } else if (!Utils.isInService(mPreviousServiceState)) { - // If ServiceState changed from out of service -> in service, update signal strength. - updateSignalStrength(getTelephonyManager().getSignalStrength()); - } String serviceStateValue; @@ -449,49 +438,11 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue); } - private void updateSignalStrength(SignalStrength signalStrength) { - if (signalStrength == null) { - return; - } - // by default we show the signal strength - boolean showSignalStrength = true; - if (mSubscriptionInfo != null) { - final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); - final PersistableBundle carrierConfig = - mCarrierConfigManager.getConfigForSubId(subscriptionId); - if (carrierConfig != null) { - showSignalStrength = carrierConfig.getBoolean( - CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL); - } - } - if (!showSignalStrength) { - mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_LABEL_ID); - mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_VALUE_ID); - return; - } - - ServiceState serviceState = getTelephonyManager().getServiceState(); - if (!Utils.isInService(serviceState)) { - return; - } - - int signalDbm = getDbm(signalStrength); - int signalAsu = getAsuLevel(signalStrength); - - if (signalDbm == -1) { - signalDbm = 0; - } - - if (signalAsu == -1) { - signalAsu = 0; - } - - mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, mRes.getString(R.string.sim_signal_strength, - signalDbm, signalAsu)); - } - - private void resetSignalStrength() { - mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, "0"); + private void updateSignalStrength(@Nullable String signalStrength) { + boolean isVisible = signalStrength != null; + mDialog.setSettingVisibility(SIGNAL_STRENGTH_LABEL_ID, isVisible); + mDialog.setSettingVisibility(SIGNAL_STRENGTH_VALUE_ID, isVisible); + mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, signalStrength); } private void updateNetworkType() { @@ -593,6 +544,7 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { private void collectSimStatusDialogInfo(@NonNull LifecycleOwner owner) { new SimStatusDialogRepository(mContext).collectSimStatusDialogInfo( owner, mSlotIndex, (simStatusDialogInfo) -> { + updateSignalStrength(simStatusDialogInfo.getSignalStrength()); updateImsRegistrationState(simStatusDialogInfo.getImsRegistered()); return Unit.INSTANCE; } @@ -603,44 +555,9 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { return SubscriptionManager.from(mContext).getActiveSubscriptionInfoForSimSlotIndex(slotId); } - private int getDbm(SignalStrength signalStrength) { - List cellSignalStrengthList = signalStrength.getCellSignalStrengths(); - int dbm = -1; - if (cellSignalStrengthList == null) { - return dbm; - } - - for (CellSignalStrength cell : cellSignalStrengthList) { - if (cell.getDbm() != -1) { - dbm = cell.getDbm(); - break; - } - } - - return dbm; - } - - private int getAsuLevel(SignalStrength signalStrength) { - List cellSignalStrengthList = signalStrength.getCellSignalStrengths(); - int asu = -1; - if (cellSignalStrengthList == null) { - return asu; - } - - for (CellSignalStrength cell : cellSignalStrengthList) { - if (cell.getAsuLevel() != -1) { - asu = cell.getAsuLevel(); - break; - } - } - - return asu; - } - @VisibleForTesting class SimStatusDialogTelephonyCallback extends TelephonyCallback implements TelephonyCallback.DataConnectionStateListener, - TelephonyCallback.SignalStrengthsListener, TelephonyCallback.ServiceStateListener, TelephonyCallback.DisplayInfoListener { @Override @@ -649,17 +566,11 @@ public class SimStatusDialogController implements DefaultLifecycleObserver { updateNetworkType(); } - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - updateSignalStrength(signalStrength); - } - @Override public void onServiceStateChanged(ServiceState serviceState) { updateNetworkProvider(); updateServiceState(serviceState); updateRoamingStatus(serviceState); - mPreviousServiceState = serviceState; } @Override diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java index 3a0997a5b31..c51417cfcb6 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java @@ -26,6 +26,7 @@ import android.view.View; import android.view.WindowManager; import android.widget.TextView; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -113,7 +114,7 @@ public class SimStatusDialogFragment extends InstrumentedDialogFragment { SimStatusDialogController.PHONE_NUMBER_VALUE_ID) .sorted().toArray(); - public void setText(int viewId, CharSequence text) { + public void setText(int viewId, @Nullable CharSequence text) { if (!isAdded()) { Log.d(TAG, "Fragment not attached yet."); return; diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt index ab212be85d2..5ed6993cc98 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepository.kt @@ -42,6 +42,8 @@ import kotlinx.coroutines.launch class SimStatusDialogRepository @JvmOverloads constructor( private val context: Context, private val simSlotRepository: SimSlotRepository = SimSlotRepository(context), + private val signalStrengthRepository: SignalStrengthRepository = + SignalStrengthRepository(context), private val imsMmTelRepositoryFactory: (subId: Int) -> ImsMmTelRepository = { subId -> ImsMmTelRepositoryImpl(context, subId) }, @@ -49,10 +51,12 @@ class SimStatusDialogRepository @JvmOverloads constructor( private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)!! data class SimStatusDialogInfo( + val signalStrength: String? = null, val imsRegistered: Boolean? = null, ) private data class SimStatusDialogVisibility( + val signalStrengthShowUp: Boolean, val imsRegisteredShowUp: Boolean, ) @@ -83,25 +87,34 @@ class SimStatusDialogRepository @JvmOverloads constructor( private fun simStatusDialogInfoFlow(subId: Int): Flow = showUpFlow(subId).flatMapLatest { visibility -> combine( + if (visibility.signalStrengthShowUp) { + signalStrengthRepository.signalStrengthDisplayFlow(subId) + } else flowOf(null), if (visibility.imsRegisteredShowUp) { imsMmTelRepositoryFactory(subId).imsRegisteredFlow() } else flowOf(null), - ) { (imsRegistered) -> - SimStatusDialogInfo(imsRegistered = imsRegistered) + ) { signalStrength, imsRegistered -> + SimStatusDialogInfo(signalStrength = signalStrength, imsRegistered = imsRegistered) } } private fun showUpFlow(subId: Int) = flow { val config = carrierConfigManager.safeGetConfig( - keys = listOf(CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL), + keys = listOf( + CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, + CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, + ), subId = subId, ) - emit( - SimStatusDialogVisibility( - imsRegisteredShowUp = config.getBoolean( - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL - ), - ) + val visibility = SimStatusDialogVisibility( + signalStrengthShowUp = config.getBoolean( + CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, + true, // by default we show the signal strength in sim status + ), + imsRegisteredShowUp = config.getBoolean( + CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL + ), ) + emit(visibility) } } diff --git a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepositoryTest.kt new file mode 100644 index 00000000000..d7486604f10 --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SignalStrengthRepositoryTest.kt @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.deviceinfo.simstatus + +import android.content.Context +import android.telephony.CellSignalStrengthCdma +import android.telephony.CellSignalStrengthGsm +import android.telephony.CellSignalStrengthLte +import android.telephony.CellSignalStrengthNr +import android.telephony.CellSignalStrengthTdscdma +import android.telephony.CellSignalStrengthWcdma +import android.telephony.ServiceState +import android.telephony.SignalStrength +import android.telephony.TelephonyCallback +import android.telephony.TelephonyManager +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy + +@RunWith(AndroidJUnit4::class) +class SignalStrengthRepositoryTest { + + private var signalStrength = SignalStrength() + + private val mockTelephonyManager = mock { + on { createForSubscriptionId(SUB_ID) } doReturn mock + on { registerTelephonyCallback(any(), any()) } doAnswer { + val listener = it.getArgument(1) + listener.onSignalStrengthsChanged(signalStrength) + } + } + + private val context: Context = spy(ApplicationProvider.getApplicationContext()) { + on { getSystemService(TelephonyManager::class.java) } doAnswer { mockTelephonyManager } + } + + private val serviceState = ServiceState() + + private val repository = SignalStrengthRepository(context) { flowOf(serviceState) } + + @Test + fun signalStrengthDisplayFlow_serviceStatePowerOff() = runBlocking { + serviceState.state = ServiceState.STATE_POWER_OFF + + val signalStrength = repository.signalStrengthDisplayFlow(SUB_ID).firstWithTimeoutOrNull() + + assertThat(signalStrength).isEqualTo("0") + } + + @Test + fun signalStrengthDisplayFlow_lteWcdma() = runBlocking { + serviceState.state = ServiceState.STATE_IN_SERVICE + signalStrength = SignalStrength( + CellSignalStrengthCdma(), + CellSignalStrengthGsm(), + mock { + on { isValid } doReturn true + on { dbm } doReturn 40 + on { asuLevel } doReturn 41 + }, + CellSignalStrengthTdscdma(), + mock { + on { isValid } doReturn true + on { dbm } doReturn 50 + on { asuLevel } doReturn 51 + }, + CellSignalStrengthNr(), + ) + + val signalStrength = repository.signalStrengthDisplayFlow(SUB_ID).firstWithTimeoutOrNull() + + assertThat(signalStrength).isEqualTo("50 dBm 51 asu") + } + + @Test + fun signalStrengthDisplayFlow_lteCdma() = runBlocking { + serviceState.state = ServiceState.STATE_IN_SERVICE + signalStrength = SignalStrength( + mock { + on { isValid } doReturn true + on { dbm } doReturn 30 + on { asuLevel } doReturn 31 + }, + CellSignalStrengthGsm(), + CellSignalStrengthWcdma(), + CellSignalStrengthTdscdma(), + mock { + on { isValid } doReturn true + on { dbm } doReturn 50 + on { asuLevel } doReturn 51 + }, + CellSignalStrengthNr(), + ) + + val signalStrength = repository.signalStrengthDisplayFlow(SUB_ID).firstWithTimeoutOrNull() + + assertThat(signalStrength).isEqualTo("50 dBm 51 asu") + } + + @Test + fun signalStrengthDisplayFlow_lteOnly() = runBlocking { + serviceState.state = ServiceState.STATE_IN_SERVICE + signalStrength = SignalStrength( + CellSignalStrengthCdma(), + CellSignalStrengthGsm(), + CellSignalStrengthWcdma(), + CellSignalStrengthTdscdma(), + mock { + on { isValid } doReturn true + on { dbm } doReturn 50 + on { asuLevel } doReturn 51 + }, + CellSignalStrengthNr(), + ) + + val signalStrength = repository.signalStrengthDisplayFlow(SUB_ID).firstWithTimeoutOrNull() + + assertThat(signalStrength).isEqualTo("50 dBm 51 asu") + } + + private companion object { + const val SUB_ID = 1 + } +} diff --git a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt index 3d13953ea10..01f32bfccf0 100644 --- a/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogRepositoryTest.kt @@ -31,7 +31,9 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.anyVararg import org.mockito.kotlin.doReturn +import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.spy @@ -43,12 +45,7 @@ class SimStatusDialogRepositoryTest { } private val mockCarrierConfigManager = mock { - on { - getConfigForSubId( - SUB_ID, - CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, - ) - } doReturn carrierConfig + on { getConfigForSubId(eq(SUB_ID), anyVararg()) } doReturn carrierConfig } private val context: Context = spy(ApplicationProvider.getApplicationContext()) { @@ -59,6 +56,10 @@ class SimStatusDialogRepositoryTest { on { subIdInSimSlotFlow(SIM_SLOT_INDEX) } doReturn flowOf(SUB_ID) } + private val mockSignalStrengthRepository = mock { + on { signalStrengthDisplayFlow(SUB_ID) } doReturn flowOf(SIGNAL_STRENGTH) + } + private val mockImsMmTelRepository = mock { on { imsRegisteredFlow() } doReturn flowOf(true) } @@ -66,6 +67,7 @@ class SimStatusDialogRepositoryTest { private val controller = SimStatusDialogRepository( context = context, simSlotRepository = mockSimSlotRepository, + signalStrengthRepository = mockSignalStrengthRepository, imsMmTelRepositoryFactory = { subId -> assertThat(subId).isEqualTo(SUB_ID) mockImsMmTelRepository @@ -81,7 +83,28 @@ class SimStatusDialogRepositoryTest { } delay(100) - assertThat(simStatusDialogInfo).isEqualTo(SimStatusDialogInfo(imsRegistered = true)) + assertThat(simStatusDialogInfo).isEqualTo( + SimStatusDialogInfo( + signalStrength = SIGNAL_STRENGTH, + imsRegistered = true, + ) + ) + } + + @Test + fun collectSimStatusDialogInfo_doNotShowSignalStrength() = runBlocking { + carrierConfig.putBoolean( + CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, + false + ) + var simStatusDialogInfo = SimStatusDialogInfo() + + controller.collectSimStatusDialogInfo(TestLifecycleOwner(), SIM_SLOT_INDEX) { + simStatusDialogInfo = it + } + delay(100) + + assertThat(simStatusDialogInfo.signalStrength).isNull() } @Test @@ -100,5 +123,7 @@ class SimStatusDialogRepositoryTest { private companion object { const val SIM_SLOT_INDEX = 0 const val SUB_ID = 1 + + const val SIGNAL_STRENGTH = "-82 dBm 58 asu" } } diff --git a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java index f4e6f187f36..3fa380828b9 100644 --- a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java +++ b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java @@ -28,25 +28,18 @@ import static com.android.settings.deviceinfo.simstatus.SimStatusDialogControlle import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.OPERATOR_INFO_VALUE_ID; import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.ROAMING_INFO_VALUE_ID; import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.SERVICE_STATE_VALUE_ID; -import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.SIGNAL_STRENGTH_LABEL_ID; -import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController.SIGNAL_STRENGTH_VALUE_ID; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; -import android.telephony.CellSignalStrength; import android.telephony.ServiceState; -import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -70,7 +63,6 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -86,14 +78,6 @@ public class SimStatusDialogControllerTest { @Mock private ServiceState mServiceState; @Mock - private SignalStrength mSignalStrength; - @Mock - private CellSignalStrength mCellSignalStrengthCdma; - @Mock - private CellSignalStrength mCellSignalStrengthLte; - @Mock - private CellSignalStrength mCellSignalStrengthWcdma; - @Mock private CarrierConfigManager mCarrierConfigManager; private PersistableBundle mPersistableBundle; @Mock @@ -148,15 +132,6 @@ public class SimStatusDialogControllerTest { mUpdatePhoneNumberCount.incrementAndGet(); } }; - // CellSignalStrength setup - doReturn(0).when(mCellSignalStrengthCdma).getDbm(); - doReturn(0).when(mCellSignalStrengthCdma).getAsuLevel(); - doReturn(0).when(mCellSignalStrengthLte).getDbm(); - doReturn(0).when(mCellSignalStrengthLte).getAsuLevel(); - doReturn(0).when(mCellSignalStrengthWcdma).getDbm(); - doReturn(0).when(mCellSignalStrengthWcdma).getAsuLevel(); - - doReturn(null).when(mSignalStrength).getCellSignalStrengths(); doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); when(mTelephonyManager.getActiveModemCount()).thenReturn(MAX_PHONE_COUNT_SINGLE_SIM); @@ -171,10 +146,7 @@ public class SimStatusDialogControllerTest { mPersistableBundle = new PersistableBundle(); when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mPersistableBundle); - mPersistableBundle.putBoolean( - CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, true); doReturn(mServiceState).when(mTelephonyManager).getServiceState(); - doReturn(mSignalStrength).when(mTelephonyManager).getSignalStrength(); } @Test @@ -217,7 +189,7 @@ public class SimStatusDialogControllerTest { @Test @Ignore("b/337417520") - public void initialize_updateServiceStateWithPowerOff_shouldUpdateTextAndResetSignalStrength() { + public void initialize_updateServiceStateWithPowerOff_shouldUpdateText() { when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF); mController.initialize(); @@ -225,12 +197,11 @@ public class SimStatusDialogControllerTest { final String offServiceText = ResourcesUtils.getResourcesString( mContext, "radioInfo_service_off"); verify(mDialog).setText(SERVICE_STATE_VALUE_ID, offServiceText); - verify(mDialog).setText(SIGNAL_STRENGTH_VALUE_ID, "0"); } @Test @Ignore("b/337417520") - public void initialize_updateVoiceDataOutOfService_shouldUpdateSettingAndResetSignalStrength() { + public void initialize_updateVoiceDataOutOfService_shouldUpdateSetting() { when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE); when(mServiceState.getDataRegistrationState()).thenReturn( ServiceState.STATE_OUT_OF_SERVICE); @@ -240,7 +211,6 @@ public class SimStatusDialogControllerTest { final String offServiceText = ResourcesUtils.getResourcesString( mContext, "radioInfo_service_out"); verify(mDialog).setText(SERVICE_STATE_VALUE_ID, offServiceText); - verify(mDialog).setText(SIGNAL_STRENGTH_VALUE_ID, "0"); } @Test @@ -255,52 +225,6 @@ public class SimStatusDialogControllerTest { verify(mDialog).setText(SERVICE_STATE_VALUE_ID, inServiceText); } - @Test - public void initialize_updateSignalStrengthWithLte50Wcdma40_shouldUpdateSignalStrengthTo50() { - final int lteDbm = 50; - final int lteAsu = 50; - final int wcdmaDbm = 40; - final int wcdmaAsu = 40; - setupCellSignalStrength_lteWcdma(lteDbm, lteAsu, wcdmaDbm, wcdmaAsu); - - mController.initialize(); - - final String signalStrengthString = ResourcesUtils.getResourcesString( - mContext, "sim_signal_strength", lteDbm, lteAsu); - verify(mDialog, times(2)).setText(SIGNAL_STRENGTH_VALUE_ID, signalStrengthString); - } - - @Test - public void initialize_updateSignalStrengthWithLte50Cdma30_shouldUpdateSignalStrengthTo50() { - final int lteDbm = 50; - final int lteAsu = 50; - final int cdmaDbm = 30; - final int cdmaAsu = 30; - setupCellSignalStrength_lteCdma(lteDbm, lteAsu, cdmaDbm, cdmaAsu); - - mController.initialize(); - - final String signalStrengthString = ResourcesUtils.getResourcesString( - mContext, "sim_signal_strength", lteDbm, lteAsu); - verify(mDialog, times(2)).setText(SIGNAL_STRENGTH_VALUE_ID, signalStrengthString); - } - - @Test - public void initialize_updateVoiceOutOfServiceDataInService_shouldUpdateSignalStrengthTo50() { - when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE); - when(mServiceState.getDataRegistrationState()).thenReturn(ServiceState.STATE_IN_SERVICE); - - final int lteDbm = 50; - final int lteAsu = 50; - setupCellSignalStrength_lteOnly(lteDbm, lteAsu); - - mController.initialize(); - - final String signalStrengthString = ResourcesUtils.getResourcesString( - mContext, "sim_signal_strength", lteDbm, lteAsu); - verify(mDialog, times(2)).setText(SIGNAL_STRENGTH_VALUE_ID, signalStrengthString); - } - @Test public void initialize_updateVoiceNetworkTypeWithEdge_shouldUpdateSettingToEdge() { when(mTelephonyManager.getVoiceNetworkType()).thenReturn( @@ -356,17 +280,6 @@ public class SimStatusDialogControllerTest { verify(mDialog).removeSettingFromScreen(ICCID_INFO_VALUE_ID); } - @Test - public void initialize_doNotShowSignalStrength_shouldRemoveSignalStrengthSetting() { - mPersistableBundle.putBoolean( - CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL, false); - - mController.initialize(); - - verify(mDialog, times(2)).removeSettingFromScreen(SIGNAL_STRENGTH_LABEL_ID); - verify(mDialog, times(2)).removeSettingFromScreen(SIGNAL_STRENGTH_VALUE_ID); - } - @Test public void initialize_showSignalStrengthAndIccId_shouldShowSignalStrengthAndIccIdSetting() { // getConfigForSubId is nullable, so make sure the default behavior is correct @@ -374,7 +287,6 @@ public class SimStatusDialogControllerTest { mController.initialize(); - verify(mDialog, times(2)).setText(eq(SIGNAL_STRENGTH_VALUE_ID), any()); verify(mDialog).removeSettingFromScreen(ICCID_INFO_LABEL_ID); verify(mDialog).removeSettingFromScreen(ICCID_INFO_VALUE_ID); } @@ -428,48 +340,4 @@ public class SimStatusDialogControllerTest { verify(mDialog).setSettingVisibility(IMS_REGISTRATION_STATE_LABEL_ID, false); verify(mDialog).setSettingVisibility(IMS_REGISTRATION_STATE_VALUE_ID, false); } - - @Test - public void initialize_nullSignalStrength_noCrash() { - doReturn(null).when(mTelephonyManager).getSignalStrength(); - // we should not crash when running the following line - mController.initialize(); - } - - private void setupCellSignalStrength_lteWcdma(int lteDbm, int lteAsu, int wcdmaDbm, - int wcdmaAsu) { - doReturn(lteDbm).when(mCellSignalStrengthLte).getDbm(); - doReturn(lteAsu).when(mCellSignalStrengthLte).getAsuLevel(); - doReturn(wcdmaDbm).when(mCellSignalStrengthWcdma).getDbm(); - doReturn(wcdmaAsu).when(mCellSignalStrengthWcdma).getAsuLevel(); - - List cellSignalStrengthList = new ArrayList<>(2); - cellSignalStrengthList.add(mCellSignalStrengthLte); - cellSignalStrengthList.add(mCellSignalStrengthWcdma); - - doReturn(cellSignalStrengthList).when(mSignalStrength).getCellSignalStrengths(); - } - - private void setupCellSignalStrength_lteCdma(int lteDbm, int lteAsu, int cdmaDbm, int cdmaAsu) { - doReturn(lteDbm).when(mCellSignalStrengthLte).getDbm(); - doReturn(lteAsu).when(mCellSignalStrengthLte).getAsuLevel(); - doReturn(cdmaDbm).when(mCellSignalStrengthCdma).getDbm(); - doReturn(cdmaAsu).when(mCellSignalStrengthCdma).getAsuLevel(); - - List cellSignalStrengthList = new ArrayList<>(2); - cellSignalStrengthList.add(mCellSignalStrengthLte); - cellSignalStrengthList.add(mCellSignalStrengthCdma); - - doReturn(cellSignalStrengthList).when(mSignalStrength).getCellSignalStrengths(); - } - - private void setupCellSignalStrength_lteOnly(int lteDbm, int lteAsu) { - doReturn(lteDbm).when(mCellSignalStrengthLte).getDbm(); - doReturn(lteAsu).when(mCellSignalStrengthLte).getAsuLevel(); - - List cellSignalStrengthList = new ArrayList<>(2); - cellSignalStrengthList.add(mCellSignalStrengthLte); - - doReturn(cellSignalStrengthList).when(mSignalStrength).getCellSignalStrengths(); - } } From 98efa5168104fd19c82128d1413176f9a48ef7af Mon Sep 17 00:00:00 2001 From: songferngwang Date: Tue, 28 May 2024 06:31:46 +0000 Subject: [PATCH 06/25] The pages of sim onboarding flow is wrong. Switch from SS mode to DSDS mode, the esim status will use the last status. It causes the condition of page selection is wrong. Bug: 342972402 Test: atest SimOnboardingPageProviderTest Change-Id: I8bb0b5f2802ec24f10467bac179ce54d13a9755e --- .../settings/network/SimOnboardingActivity.kt | 5 ++ .../settings/network/SimOnboardingService.kt | 53 ++++++++++++------- .../spa/network/SimOnboardingPageProvider.kt | 3 +- .../network/SimOnboardingPageProviderTest.kt | 1 + 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/com/android/settings/network/SimOnboardingActivity.kt b/src/com/android/settings/network/SimOnboardingActivity.kt index 481dc205f70..3a210493785 100644 --- a/src/com/android/settings/network/SimOnboardingActivity.kt +++ b/src/com/android/settings/network/SimOnboardingActivity.kt @@ -401,6 +401,11 @@ class SimOnboardingActivity : SpaBaseDialogActivity() { Log.d(TAG, "startSimSwitching:") var targetSubInfo = onboardingService.targetSubInfo + if(onboardingService.doesTargetSimActive) { + Log.d(TAG, "target subInfo is already active") + callbackListener(CallbackType.CALLBACK_SETUP_NAME) + return + } targetSubInfo?.let { var removedSubInfo = onboardingService.getRemovedSim() if (targetSubInfo.isEmbedded) { diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt index b7df7548f69..f6c6065e40d 100644 --- a/src/com/android/settings/network/SimOnboardingService.kt +++ b/src/com/android/settings/network/SimOnboardingService.kt @@ -16,6 +16,9 @@ package com.android.settings.network +import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID +import android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX + import android.content.Context import android.telephony.SubscriptionInfo import android.telephony.SubscriptionManager @@ -40,26 +43,26 @@ class SimOnboardingService { var subscriptionManager:SubscriptionManager? = null var telephonyManager:TelephonyManager? = null - var targetSubId: Int = INVALID + var targetSubId: Int = INVALID_SUBSCRIPTION_ID var targetSubInfo: SubscriptionInfo? = null var availableSubInfoList: List = listOf() var activeSubInfoList: List = listOf() var slotInfoList: List = listOf() var uiccCardInfoList: List = listOf() - var targetPrimarySimCalls: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID - var targetPrimarySimTexts: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID - var targetPrimarySimMobileData: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID + var targetPrimarySimCalls: Int = INVALID_SUBSCRIPTION_ID + var targetPrimarySimTexts: Int = INVALID_SUBSCRIPTION_ID + var targetPrimarySimMobileData: Int = INVALID_SUBSCRIPTION_ID val targetPrimarySimAutoDataSwitch = MutableStateFlow(false) - var targetNonDds: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID + var targetNonDds: Int = INVALID_SUBSCRIPTION_ID get() { - if(targetPrimarySimMobileData == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + if(targetPrimarySimMobileData == INVALID_SUBSCRIPTION_ID) { Log.w(TAG, "No DDS") - return SubscriptionManager.INVALID_SUBSCRIPTION_ID + return INVALID_SUBSCRIPTION_ID } return userSelectedSubInfoList .filter { info -> info.subscriptionId != targetPrimarySimMobileData } .map { it.subscriptionId } - .firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID + .firstOrNull() ?: INVALID_SUBSCRIPTION_ID } var callback: (CallbackType) -> Unit = {} @@ -84,6 +87,11 @@ class SimOnboardingService { activeSubInfoList.stream().anyMatch { it.isEmbedded } return false } + var doesTargetSimActive = false + get() { + return targetSubInfo?.getSimSlotIndex() ?: INVALID_SIM_SLOT_INDEX >= 0 + } + var doesTargetSimHaveEsimOperation = false get() { return targetSubInfo?.isEmbedded ?: false @@ -95,7 +103,7 @@ class SimOnboardingService { } var getActiveModemCount = 0 get() { - return telephonyManager?.getActiveModemCount() ?: 0 + return (telephonyManager?.getActiveModemCount() ?: 0) } var renameMutableMap : MutableMap = mutableMapOf() @@ -103,16 +111,18 @@ class SimOnboardingService { var isSimSelectionFinished = false get() { - return getActiveModemCount != 0 && userSelectedSubInfoList.size == getActiveModemCount + val activeModem = getActiveModemCount + return activeModem != 0 && userSelectedSubInfoList.size == activeModem } var isAllOfSlotAssigned = false get() { - if(getActiveModemCount == 0){ + val activeModem = getActiveModemCount + if(activeModem == 0){ Log.e(TAG, "isAllOfSlotAssigned: getActiveModemCount is 0") return true } - return getActiveModemCount != 0 && activeSubInfoList.size == getActiveModemCount + return getActiveModemCount != 0 && activeSubInfoList.size == activeModem } var isMultiSimEnabled = false get() { @@ -129,7 +139,7 @@ class SimOnboardingService { } fun isValid(): Boolean { - return targetSubId != INVALID + return targetSubId != INVALID_SUBSCRIPTION_ID && targetSubInfo != null && activeSubInfoList.isNotEmpty() && slotInfoList.isNotEmpty() @@ -156,14 +166,15 @@ class SimOnboardingService { fun initData(inputTargetSubId: Int, context: Context, callback: (CallbackType) -> Unit) { + clear() this.callback = callback targetSubId = inputTargetSubId subscriptionManager = context.getSystemService(SubscriptionManager::class.java) telephonyManager = context.getSystemService(TelephonyManager::class.java) + activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager) Log.d( TAG, "startInit: targetSubId:$targetSubId, activeSubInfoList: $activeSubInfoList" ) - activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager) ThreadUtils.postOnBackgroundThread { availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context) @@ -242,14 +253,19 @@ class SimOnboardingService { fun addCurrentItemForSelectedSim() { if (userSelectedSubInfoList.size < getActiveModemCount) { - userSelectedSubInfoList.addAll(activeSubInfoList) - Log.d(TAG, "addCurrentItemForSelectedSim: userSelectedSubInfoList:" + - ", $userSelectedSubInfoList") + userSelectedSubInfoList.addAll( + activeSubInfoList.filter { !userSelectedSubInfoList.contains(it) } + ) + Log.d(TAG, + "addCurrentItemForSelectedSim: userSelectedSubInfoList: $userSelectedSubInfoList" + ) } } fun addItemForSelectedSim(selectedSubInfo: SubscriptionInfo) { - userSelectedSubInfoList.add(selectedSubInfo) + if (!userSelectedSubInfoList.contains(selectedSubInfo)) { + userSelectedSubInfoList.add(selectedSubInfo) + } } fun removeItemForSelectedSim(selectedSubInfo: SubscriptionInfo) { @@ -370,7 +386,6 @@ class SimOnboardingService { companion object{ private const val TAG = "SimOnboardingService" - private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID const val NUM_OF_SIMS_FOR_DSDS = 2 } } \ No newline at end of file diff --git a/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt b/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt index fab9c12e8ac..028b50ddce2 100644 --- a/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt +++ b/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt @@ -107,7 +107,8 @@ fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostCo composable(route = SimOnboardingScreen.LabelSim.name) { val nextPage = if (onboardingService.isMultipleEnabledProfilesSupported - && onboardingService.isAllOfSlotAssigned) { + && onboardingService.isAllOfSlotAssigned + && !onboardingService.doesTargetSimActive) { SimOnboardingScreen.SelectSim.name } else { LaunchedEffect(Unit) { diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt index d1847c8d48f..1395ed4b373 100644 --- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt @@ -91,6 +91,7 @@ class SimOnboardingPageProviderTest { mockSimOnboardingService.stub { on { isMultipleEnabledProfilesSupported }.thenReturn(true) on { isAllOfSlotAssigned }.thenReturn(true) + on { doesTargetSimActive }.thenReturn(false) } composeTestRule.setContent { From d1b0ad25faab762dfeef8adad68c3aacfb1d6412 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Tue, 28 May 2024 17:26:18 +0800 Subject: [PATCH 07/25] Suppress rawData settings from indexing when page is disabled for search Test: robotest, manual Fix: 324424783 Change-Id: Ie8423d16df387f13cf35c03005640cfd08a5b492 --- .../settings/search/BaseSearchIndexProvider.java | 12 ++++++++++-- .../settings/search/BaseSearchIndexProviderTest.java | 11 +++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/search/BaseSearchIndexProvider.java b/src/com/android/settings/search/BaseSearchIndexProvider.java index 7fa83554988..cc05270cc0e 100644 --- a/src/com/android/settings/search/BaseSearchIndexProvider.java +++ b/src/com/android/settings/search/BaseSearchIndexProvider.java @@ -45,6 +45,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * A basic SearchIndexProvider that returns no data to index. @@ -117,11 +118,18 @@ public class BaseSearchIndexProvider implements Indexable.SearchIndexProvider { @Override @CallSuper public List getNonIndexableKeys(Context context) { + final List nonIndexableKeys = new ArrayList<>(); if (!isPageSearchEnabled(context)) { // Entire page should be suppressed, mark all keys from this page as non-indexable. - return getNonIndexableKeysFromXml(context, true /* suppressAllPage */); + nonIndexableKeys.addAll( + getNonIndexableKeysFromXml(context, true /* suppressAllPage */)); + nonIndexableKeys.addAll( + getRawDataToIndex(context, true /* enabled */) + .stream() + .map(data -> data.key) + .collect(Collectors.toList())); + return nonIndexableKeys; } - final List nonIndexableKeys = new ArrayList<>(); nonIndexableKeys.addAll(getNonIndexableKeysFromXml(context, false /* suppressAllPage */)); final List controllers = getPreferenceControllers(context); if (controllers != null && !controllers.isEmpty()) { diff --git a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java index 09b1ea944a5..18dc00480b0 100644 --- a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java +++ b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java @@ -166,6 +166,16 @@ public class BaseSearchIndexProviderTest { return Collections.singletonList(sir); } + @Override + public List getRawDataToIndex(Context context, boolean enabled) { + List rawData = super.getRawDataToIndex(context, enabled); + SearchIndexableRaw raw = new SearchIndexableRaw(context); + raw.key = TEST_PREF_KEY; + raw.title = "title"; + rawData.add(raw); + return rawData; + } + @Override protected boolean isPageSearchEnabled(Context context) { return false; @@ -176,6 +186,7 @@ public class BaseSearchIndexProviderTest { provider.getNonIndexableKeys(RuntimeEnvironment.application); assertThat(nonIndexableKeys).contains("status_header"); + assertThat(nonIndexableKeys).contains(TEST_PREF_KEY); } @Test From 20c78149f0db76d299c206d7add359a89060461a Mon Sep 17 00:00:00 2001 From: Liahav Eitan Date: Tue, 28 May 2024 10:56:55 +0000 Subject: [PATCH 08/25] Increase char limit for add_device_admin_msg Flag: DOCS_ONLY Bug: 333040579 Test: None Change-Id: I46c757f8700ee0ab168a1f68e4213f24f44aacd0 --- res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 7a1ce115274..6df77c5b3de 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6456,7 +6456,7 @@ No available trust agents - + Activate device admin app? Activate this device admin app From 7ef9c46afadc2d2992ae97fc6bdb593de146f829 Mon Sep 17 00:00:00 2001 From: josephpv Date: Tue, 28 May 2024 13:26:41 +0000 Subject: [PATCH 09/25] Private space auto lock on device restart during setup After creation of private space value of auto-lock setting is explicitly set to lock on device restarts. Just before the end of the setup flow the auto-lock setting is changed to auto-lock on device lock before the last screen of private space setup. Bug: 342398315 Test: atest PrivateSpaceMaintainerTest Change-Id: I8eeb0058c7ecb31d6e30b4cc78ec5877ed316f75 --- .../settings/privatespace/PrivateSpaceMaintainer.java | 7 ++++++- .../privatespace/SetupPreFinishDelayFragment.java | 11 +++++++++-- .../privatespace/PrivateSpaceMaintainerTest.java | 6 +++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java index debec45a159..bdbe993f8fc 100644 --- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java +++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java @@ -19,6 +19,7 @@ package com.android.settings.privatespace; import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE; import static android.provider.Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT; import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK; +import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_DEVICE_RESTART; import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK; import static android.provider.Settings.Secure.SKIP_FIRST_USE_HINTS; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; @@ -70,6 +71,10 @@ public class PrivateSpaceMaintainer { @Settings.Secure.PrivateSpaceAutoLockOption public static final int PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL = PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK; + /** Value for private space auto lock settings after private space creation. */ + @Settings.Secure.PrivateSpaceAutoLockOption + public static final int PRIVATE_SPACE_CREATE_AUTO_LOCK_VAL = + PRIVATE_SPACE_AUTO_LOCK_AFTER_DEVICE_RESTART; /** Default value for the hide private space sensitive notifications on lockscreen. */ public static final int HIDE_PRIVATE_SPACE_SENSITIVE_NOTIFICATIONS_DISABLED_VAL = 0; @@ -327,7 +332,7 @@ public class PrivateSpaceMaintainer { @GuardedBy("this") private void resetPrivateSpaceSettings() { setHidePrivateSpaceEntryPointSetting(HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL); - setPrivateSpaceAutoLockSetting(PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL); + setPrivateSpaceAutoLockSetting(PRIVATE_SPACE_CREATE_AUTO_LOCK_VAL); setPrivateSpaceSensitiveNotificationsDefaultValue(); } diff --git a/src/com/android/settings/privatespace/SetupPreFinishDelayFragment.java b/src/com/android/settings/privatespace/SetupPreFinishDelayFragment.java index 9d04e7900aa..4f2634eb775 100644 --- a/src/com/android/settings/privatespace/SetupPreFinishDelayFragment.java +++ b/src/com/android/settings/privatespace/SetupPreFinishDelayFragment.java @@ -19,6 +19,8 @@ package com.android.settings.privatespace; import static android.content.Intent.ACTION_PROFILE_INACCESSIBLE; import static android.content.Intent.ACTION_PROFILE_UNAVAILABLE; +import static com.android.settings.privatespace.PrivateSpaceMaintainer.PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL; + import android.app.settings.SettingsEnums; import android.content.BroadcastReceiver; import android.content.Context; @@ -101,8 +103,13 @@ public class SetupPreFinishDelayFragment extends InstrumentedFragment { }; requireActivity().getOnBackPressedDispatcher().addCallback(this, callback); if (savedInstanceState == null) { - // TODO(b/307729746): Add a test to verify PS is locked after setup completion. - PrivateSpaceMaintainer.getInstance(getActivity()).lockPrivateSpace(); + // TODO(b/307729746): Add test to verify PS is locked and auto-lock value is set to + // auto-lock on device lock after setup completion. + PrivateSpaceMaintainer privateSpaceMaintainer = + PrivateSpaceMaintainer.getInstance(getActivity()); + privateSpaceMaintainer.setPrivateSpaceAutoLockSetting( + PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL); + privateSpaceMaintainer.lockPrivateSpace(); } return rootView; } diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java index 522dcd5e242..36edfa0e9e1 100644 --- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java +++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java @@ -22,7 +22,7 @@ import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK; import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_ENTRY_POINT_DISABLED_VAL; import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_ENTRY_POINT_ENABLED_VAL; import static com.android.settings.privatespace.PrivateSpaceMaintainer.HIDE_PRIVATE_SPACE_SENSITIVE_NOTIFICATIONS_DISABLED_VAL; -import static com.android.settings.privatespace.PrivateSpaceMaintainer.PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL; +import static com.android.settings.privatespace.PrivateSpaceMaintainer.PRIVATE_SPACE_CREATE_AUTO_LOCK_VAL; import static com.google.common.truth.Truth.assertThat; @@ -336,9 +336,9 @@ public class PrivateSpaceMaintainerTest { privateSpaceMaintainer.deletePrivateSpace(); privateSpaceMaintainer.createPrivateSpace(); assertThat(privateSpaceMaintainer.getPrivateSpaceAutoLockSetting()) - .isEqualTo(PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL); + .isEqualTo(PRIVATE_SPACE_CREATE_AUTO_LOCK_VAL); assertThat(Settings.Secure.getInt(mContentResolver, PRIVATE_SPACE_AUTO_LOCK, -1)) - .isEqualTo(PRIVATE_SPACE_AUTO_LOCK_DEFAULT_VAL); + .isEqualTo(PRIVATE_SPACE_CREATE_AUTO_LOCK_VAL); } /** From 97b462dbf0cff3750e2a9c1e1af62e84e9c335d8 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Fri, 24 May 2024 16:59:02 -0400 Subject: [PATCH 10/25] Add button for activating modes manually Fixes: 308819907 Flag: android.app.modes_ui Test: ZenModeButtonPreferenceControllerTest Test: atest com.android.settings.notification.modes Change-Id: Id018d360c648dd948d2f950ca67cfbea71cc5c68 --- res/layout/modes_activation_button.xml | 30 +++ res/xml/modes_rule_settings.xml | 5 + .../AbstractZenModePreferenceController.java | 19 +- .../ZenModeButtonPreferenceController.java | 59 ++++++ .../notification/modes/ZenModeFragment.java | 1 + .../modes/ZenModeFragmentBase.java | 15 ++ .../modes/ZenModeHeaderController.java | 1 + .../modes/ZenModesFragmentBase.java | 8 +- ...ZenModeButtonPreferenceControllerTest.java | 187 ++++++++++++++++++ 9 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 res/layout/modes_activation_button.xml create mode 100644 src/com/android/settings/notification/modes/ZenModeButtonPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/notification/modes/ZenModeButtonPreferenceControllerTest.java diff --git a/res/layout/modes_activation_button.xml b/res/layout/modes_activation_button.xml new file mode 100644 index 00000000000..e8ed824dfb4 --- /dev/null +++ b/res/layout/modes_activation_button.xml @@ -0,0 +1,30 @@ + + + + + +