From af56a3ea211c0697e27c4883cc80e16d33b7810e Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Tue, 25 Jun 2024 17:03:46 +0800 Subject: [PATCH 1/8] Not use SubscriptionInfoEntity in DataUsageList Carrier id will be get in DataUsageListAppsController async. Bug: 348118234 Flag: EXEMPT clean up Test: manual - on DataUsageList Change-Id: I06b361f38d04c5020431cd8c6e359aa3a69942e5 --- .../settings/datausage/DataUsageList.kt | 34 ++++++++----------- .../datausage/DataUsageListAppsController.kt | 7 +++- .../network/NetworkProviderSettings.java | 3 +- .../network/NetworkProviderSettingsTest.java | 4 ++- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/com/android/settings/datausage/DataUsageList.kt b/src/com/android/settings/datausage/DataUsageList.kt index af115d9d370..a2932776669 100644 --- a/src/com/android/settings/datausage/DataUsageList.kt +++ b/src/com/android/settings/datausage/DataUsageList.kt @@ -33,13 +33,10 @@ import com.android.settings.R import com.android.settings.dashboard.DashboardFragment import com.android.settings.datausage.lib.BillingCycleRepository import com.android.settings.datausage.lib.NetworkUsageData -import com.android.settings.network.MobileNetworkRepository import com.android.settings.network.SubscriptionUtil -import com.android.settings.network.telephony.requireSubscriptionManager -import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity +import com.android.settings.network.telephony.SubscriptionRepository import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle import com.android.settingslib.spaprivileged.framework.common.userManager -import com.android.settingslib.utils.ThreadUtils import kotlin.jvm.optionals.getOrNull /** @@ -59,7 +56,6 @@ open class DataUsageList : DashboardFragment() { private lateinit var billingCycleRepository: BillingCycleRepository private var usageAmount: Preference? = null - private var subscriptionInfoEntity: SubscriptionInfoEntity? = null private var dataUsageListAppsController: DataUsageListAppsController? = null private var chartDataUsagePreferenceController: ChartDataUsagePreferenceController? = null private var dataUsageListHeaderController: DataUsageListHeaderController? = null @@ -90,7 +86,6 @@ open class DataUsageList : DashboardFragment() { finish() return } - updateSubscriptionInfoEntity() dataUsageListAppsController = use(DataUsageListAppsController::class.java).apply { init(template) } @@ -132,6 +127,16 @@ open class DataUsageList : DashboardFragment() { viewModel.chartDataFlow.collectLatestWithLifecycle(viewLifecycleOwner) { chartData -> chartDataUsagePreferenceController?.update(chartData) } + finishIfSubscriptionDisabled() + } + + private fun finishIfSubscriptionDisabled() { + if (SubscriptionManager.isUsableSubscriptionId(subId)) { + SubscriptionRepository(requireContext()).isSubscriptionEnabledFlow(subId) + .collectLatestWithLifecycle(viewLifecycleOwner) { isSubscriptionEnabled -> + if (!isSubscriptionEnabled) finish() + } + } } override fun getPreferenceScreenResId() = R.xml.data_usage_list @@ -155,23 +160,12 @@ open class DataUsageList : DashboardFragment() { } } - private fun updateSubscriptionInfoEntity() { - ThreadUtils.postOnBackgroundThread { - subscriptionInfoEntity = - MobileNetworkRepository.getInstance(context).getSubInfoById(subId.toString()) - } - } - /** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */ private fun updatePolicy(isModifiable: Boolean) { - val isBillingCycleModifiable = isModifiable && isActiveSubscription() - dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable) - chartDataUsagePreferenceController?.setBillingCycleModifiable(isBillingCycleModifiable) + dataUsageListHeaderController?.setConfigButtonVisible(isModifiable) + chartDataUsagePreferenceController?.setBillingCycleModifiable(isModifiable) } - private fun isActiveSubscription(): Boolean = - requireContext().requireSubscriptionManager().getActiveSubscriptionInfo(subId) != null - /** * Updates the chart and detail data when initial loaded or selected cycle changed. */ @@ -187,7 +181,7 @@ open class DataUsageList : DashboardFragment() { /** Updates applications data usage. */ private fun updateApps(usageData: NetworkUsageData) { dataUsageListAppsController?.update( - carrierId = subscriptionInfoEntity?.carrierId, + subId = subId, startTime = usageData.startTime, endTime = usageData.endTime, ) diff --git a/src/com/android/settings/datausage/DataUsageListAppsController.kt b/src/com/android/settings/datausage/DataUsageListAppsController.kt index 93623f479e3..d8bddde4fe2 100644 --- a/src/com/android/settings/datausage/DataUsageListAppsController.kt +++ b/src/com/android/settings/datausage/DataUsageListAppsController.kt @@ -20,6 +20,7 @@ import android.app.ActivityManager import android.content.Context import android.net.NetworkTemplate import android.os.Bundle +import android.telephony.SubscriptionManager import androidx.annotation.OpenForTesting import androidx.annotation.VisibleForTesting import androidx.lifecycle.LifecycleCoroutineScope @@ -32,6 +33,7 @@ import com.android.settings.core.BasePreferenceController import com.android.settings.core.SubSettingLauncher import com.android.settings.datausage.lib.AppDataUsageRepository import com.android.settings.datausage.lib.NetworkUsageData +import com.android.settings.network.telephony.requireSubscriptionManager import com.android.settingslib.AppItem import com.android.settingslib.net.UidDetailProvider import kotlinx.coroutines.Dispatchers @@ -74,8 +76,11 @@ open class DataUsageListAppsController(context: Context, preferenceKey: String) this.cycleData = cycleData } - fun update(carrierId: Int?, startTime: Long, endTime: Long) = lifecycleScope.launch { + fun update(subId: Int, startTime: Long, endTime: Long) = lifecycleScope.launch { val apps = withContext(Dispatchers.Default) { + val carrierId = if (SubscriptionManager.isValidSubscriptionId(subId)) { + mContext.requireSubscriptionManager().getActiveSubscriptionInfo(subId)?.carrierId + } else null repository.getAppPercent(carrierId, startTime, endTime).map { (appItem, percent) -> AppDataUsagePreference(mContext, appItem, percent, uidDetailProvider).apply { setOnPreferenceClickListener { diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index a4193f8219c..0fcfcb515a1 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -36,6 +36,7 @@ import android.os.PowerManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.EventLog; @@ -370,7 +371,7 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment mDataUsagePreference = findPreference(PREF_KEY_DATA_USAGE); mDataUsagePreference.setVisible(DataUsageUtils.hasWifiRadio(getContext())); mDataUsagePreference.setTemplate(new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI) - .build(), 0 /*subId*/); + .build(), SubscriptionManager.INVALID_SUBSCRIPTION_ID); mResetInternetPreference = findPreference(PREF_KEY_RESET_INTERNET); if (mResetInternetPreference != null) { mResetInternetPreference.setVisible(false); diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java index fb29e059ed5..01611788e49 100644 --- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java +++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java @@ -51,6 +51,7 @@ import android.os.Bundle; import android.os.PowerManager; import android.os.UserManager; import android.provider.Settings; +import android.telephony.SubscriptionManager; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; @@ -319,7 +320,8 @@ public class NetworkProviderSettingsTest { mNetworkProviderSettings.onCreate(Bundle.EMPTY); verify(mDataUsagePreference).setVisible(true); - verify(mDataUsagePreference).setTemplate(any(), eq(0) /*subId*/); + verify(mDataUsagePreference) + .setTemplate(any(), eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID)); } @Test From 60d3a11662585c9bc0754ad043e2a72909adcd13 Mon Sep 17 00:00:00 2001 From: Lyn Date: Mon, 17 Jun 2024 23:04:01 +0000 Subject: [PATCH 2/8] Bind action to fragment: adaptive notif settings Bug: 330608738 Test: send high pri HUN => see edu HUN from sysui tap HUN/action => shows adaptive notif settings page, notif menu key highlighted in split screen Test: adb shell am start-activity -a android.settings.MANAGE_ADAPTIVE_NOTIFICATIONS Flag: com.android.systemui.notification_avalanche_throttle_hun Change-Id: I8bc36412b6ce6364887b04d737310e6b01478964 --- AndroidManifest.xml | 13 +++++++++++++ src/com/android/settings/Settings.java | 1 + .../settings/core/gateway/SettingsGateway.java | 2 ++ 3 files changed, 16 insertions(+) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8cfd9b597a9..b28da4f77ce 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1427,6 +1427,19 @@ android:value="true" /> + + + + + + + + + Date: Tue, 11 Jun 2024 18:45:11 +0000 Subject: [PATCH 3/8] Keep FakeFeatureFlagsImpl * Keep FakeFeatureFlagsImpl. * Use EnableFlags and DisableFlags annotation * Switch back from `assumeTrue` to `assert` when flag is enabled or disabled. * Remove flag rollback test. Bug: 342830919 Change-Id: Ic9b3438f3f0e31e64d5405ed81903b352195714a --- proguard.flags | 3 +++ tests/unit/Android.bp | 1 - ...ryptoFallbackPreferenceControllerTest.java | 25 ++++++------------- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/proguard.flags b/proguard.flags index 492404ce7be..d1c97f36da5 100644 --- a/proguard.flags +++ b/proguard.flags @@ -65,3 +65,6 @@ -keep class androidx.window.extensions.** { *; } -dontwarn androidx.window.extensions.** -keep class androidx.window.** { *; } + +# Keep the com.android.settings.media_drm.FakeFeatureFlagsImpl +-keep class com.android.settings.media_drm.FakeFeatureFlagsImpl { *; } diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp index 55df480e787..be43f8ef923 100644 --- a/tests/unit/Android.bp +++ b/tests/unit/Android.bp @@ -32,7 +32,6 @@ android_test { "truth", "kotlinx_coroutines_test", "Settings-testutils2", - "MediaDrmSettingsFlagsLib", "servicestests-utils", // Don't add SettingsLib libraries here - you can use them directly as they are in the // instrumented Settings app. diff --git a/tests/unit/src/com/android/settings/development/mediadrm/ForceSwSecureCryptoFallbackPreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/mediadrm/ForceSwSecureCryptoFallbackPreferenceControllerTest.java index 2a0cd05811e..5eb76f110d6 100644 --- a/tests/unit/src/com/android/settings/development/mediadrm/ForceSwSecureCryptoFallbackPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/development/mediadrm/ForceSwSecureCryptoFallbackPreferenceControllerTest.java @@ -29,6 +29,8 @@ import android.util.Log; import android.content.Context; import com.android.settings.media_drm.Flags; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import androidx.preference.SwitchPreference; @@ -65,10 +67,10 @@ public class ForceSwSecureCryptoFallbackPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_FORCE_L3_ENABLED) public void updateState_flagEnabled_checkPreference() { - mSetFlagsRule.enableFlags(Flags.FLAG_FORCE_L3_ENABLED); mController.updateState(mPreference); - assumeTrue(mPreference.isEnabled()); + assertThat(mPreference.isEnabled()).isTrue(); assertThat(mPreference.isChecked()).isFalse(); assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isFalse(); @@ -85,33 +87,22 @@ public class ForceSwSecureCryptoFallbackPreferenceControllerTest { assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isFalse(); assertThat(mPreference.isEnabled()).isTrue(); assertThat(mPreference.isChecked()).isFalse(); - - // Test flag rollback - mController.setChecked(true); - mController.updateState(mPreference); - assertThat(mPreference.isChecked()).isTrue(); - assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isTrue(); - mSetFlagsRule.disableFlags(Flags.FLAG_FORCE_L3_ENABLED); - mController.updateState(mPreference); - assertThat(mPreference.isEnabled()).isFalse(); - assertThat(mPreference.isChecked()).isFalse(); - assertThat(WidevineProperties.forcel3_enabled().orElse(false)).isFalse(); } @Test + @DisableFlags(Flags.FLAG_FORCE_L3_ENABLED) public void updateState_flagDisabled_checkPreference() { - mSetFlagsRule.disableFlags(Flags.FLAG_FORCE_L3_ENABLED); mController.updateState(mPreference); assertThat(mPreference.isEnabled()).isFalse(); } @Test + @EnableFlags(Flags.FLAG_FORCE_L3_ENABLED) public void updateState_checkWidevine() throws Exception { try (MediaDrm drm = new MediaDrm(WIDEVINE_UUID)) { assumeTrue(drm.getPropertyString("securityLevel").equals("L1")); - mSetFlagsRule.enableFlags(Flags.FLAG_FORCE_L3_ENABLED); mController.updateState(mPreference); - assumeTrue(mPreference.isEnabled()); + assertThat(mPreference.isEnabled()).isTrue(); } catch (UnsupportedSchemeException ex) { assumeNoException(ex); } @@ -139,11 +130,11 @@ public class ForceSwSecureCryptoFallbackPreferenceControllerTest { } @Test + @EnableFlags(Flags.FLAG_FORCE_L3_ENABLED) public void updateState_checkWhenWidevineReady() throws Exception { try (MediaDrm drm = new MediaDrm(WIDEVINE_UUID)) { if (drm.getPropertyString("securityLevel").equals("L1")) { String version = drm.getPropertyString(MediaDrm.PROPERTY_VERSION); - mSetFlagsRule.enableFlags(Flags.FLAG_FORCE_L3_ENABLED); mController.updateState(mPreference); if (Integer.parseInt(version.split("\\.", 2)[0]) >= 19) { assertThat(mPreference.isEnabled()).isTrue(); From b8ad25f8bd73c25aef4d35aa5917626f7353666b Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Thu, 27 Jun 2024 17:30:19 +0800 Subject: [PATCH 4/8] Clean up MobileNetworkInfoEntity unused fields It's safe since MobileNetworkDatabase is in memory only. Bug: 348118234 Flag: EXEMPT clean up Test: manual - check Mobile Settings Change-Id: I25141a87b9afb42b85d73cbcd7307b899b3f0a3b --- .../network/MobileNetworkRepository.java | 35 +++++-------------- .../MobileDataPreferenceControllerTest.java | 3 +- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java index ebb341e0fec..bd892c8bf32 100644 --- a/src/com/android/settings/network/MobileNetworkRepository.java +++ b/src/com/android/settings/network/MobileNetworkRepository.java @@ -41,7 +41,6 @@ import androidx.annotation.NonNull; import androidx.lifecycle.LifecycleOwner; import com.android.internal.telephony.flags.Flags; -import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.mobile.dataservice.MobileNetworkDatabase; @@ -435,7 +434,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_SUB_INFO, subId); insertUiccInfo(subId, telephonyManager); - insertMobileNetworkInfo(context, subId, telephonyManager); + insertMobileNetworkInfo(subId, telephonyManager); } } else if (DEBUG) { Log.d(TAG, "Can not insert subInfo, the entity is null"); @@ -517,20 +516,13 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } } - private void insertMobileNetworkInfo(Context context, int subId, - TelephonyManager telephonyManager) { - MobileNetworkInfoEntity mobileNetworkInfoEntity = convertToMobileNetworkInfoEntity(context, - subId, telephonyManager); - + private void insertMobileNetworkInfo(int subId, TelephonyManager telephonyManager) { + MobileNetworkInfoEntity mobileNetworkInfoEntity = + convertToMobileNetworkInfoEntity(subId, telephonyManager); Log.d(TAG, "insertMobileNetworkInfo, mobileNetworkInfoEntity = " + mobileNetworkInfoEntity); - - if (mobileNetworkInfoEntity == null) { - return; - } - if (!sCacheMobileNetworkInfoEntityMap.containsKey(subId) || !sCacheMobileNetworkInfoEntityMap.get(subId).equals(mobileNetworkInfoEntity)) { sCacheMobileNetworkInfoEntityMap.put(subId, mobileNetworkInfoEntity); @@ -540,7 +532,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } } - private MobileNetworkInfoEntity convertToMobileNetworkInfoEntity(Context context, int subId, + private MobileNetworkInfoEntity convertToMobileNetworkInfoEntity(int subId, TelephonyManager telephonyManager) { boolean isDataEnabled = false; if (telephonyManager != null) { @@ -549,18 +541,8 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions Log.d(TAG, "TelephonyManager is null, subId = " + subId); } - return new MobileNetworkInfoEntity(String.valueOf(subId), - MobileNetworkUtils.isContactDiscoveryEnabled(context, subId), - MobileNetworkUtils.isContactDiscoveryVisible(context, subId), - isDataEnabled, - MobileNetworkUtils.isCdmaOptions(context, subId), - MobileNetworkUtils.isGsmOptions(context, subId), - MobileNetworkUtils.isWorldMode(context, subId), - MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, subId), - MobileNetworkUtils.isTdscdmaSupported(context, subId), - MobileNetworkUtils.activeNetworkIsCellular(context), - SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager), - /* deprecated isDataRoamingEnabled = */ false + return new MobileNetworkInfoEntity(String.valueOf(subId), isDataEnabled, + SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager) ); } @@ -681,8 +663,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions public void onUserMobileDataStateChanged(boolean enabled) { Log.d(TAG, "onUserMobileDataStateChanged enabled " + enabled + " on SUB " + mSubId); sExecutor.execute(() -> { - insertMobileNetworkInfo(mContext, mSubId, - getTelephonyManagerBySubId(mContext, mSubId)); + insertMobileNetworkInfo(mSubId, getTelephonyManagerBySubId(mContext, mSubId)); }); } } diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java index 152091a0226..f31e274233f 100644 --- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java @@ -131,8 +131,7 @@ public class MobileDataPreferenceControllerTest { private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId, boolean isDatEnabled) { - return new MobileNetworkInfoEntity(subId, false, false, isDatEnabled, false, false, false, - false, false, false, false, false); + return new MobileNetworkInfoEntity(subId, isDatEnabled, false); } @Test From 75a382fc4640f2698ab94f16c02e634d5abd7ade Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Wed, 26 Jun 2024 15:09:59 +0800 Subject: [PATCH 5/8] Migrate SearchFeatureProviderImpl to Kotlin This is no-op. Bug: 346776183 Flag: EXEMPT refactor Test: manual - do settings search Change-Id: I5c113f6ed5db1401e1d237f0022ab6dccde8d060 --- .../search/SearchFeatureProviderImpl.java | 81 ------------------- .../search/SearchFeatureProviderImpl.kt | 64 +++++++++++++++ .../SearchIndexableResourcesFactory.java | 34 ++++++++ .../search/SearchFeatureProviderImplTest.java | 4 +- 4 files changed, 100 insertions(+), 83 deletions(-) delete mode 100644 src/com/android/settings/search/SearchFeatureProviderImpl.java create mode 100644 src/com/android/settings/search/SearchFeatureProviderImpl.kt create mode 100644 src/com/android/settings/search/SearchIndexableResourcesFactory.java diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java deleted file mode 100644 index 3a62ddfb67e..00000000000 --- a/src/com/android/settings/search/SearchFeatureProviderImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2017 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.search; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.provider.Settings; -import android.text.TextUtils; - -import androidx.annotation.NonNull; - -import com.android.settingslib.search.SearchIndexableResources; -import com.android.settingslib.search.SearchIndexableResourcesMobile; - -/** - * FeatureProvider for the refactored search code. - */ -public class SearchFeatureProviderImpl implements SearchFeatureProvider { - - private SearchIndexableResources mSearchIndexableResources; - - @Override - public void verifyLaunchSearchResultPageCaller(@NonNull Context context, - @NonNull String callerPackage) { - if (TextUtils.isEmpty(callerPackage)) { - throw new IllegalArgumentException("ExternalSettingsTrampoline intents " - + "must be called with startActivityForResult"); - } - final boolean isSettingsPackage = TextUtils.equals(callerPackage, context.getPackageName()) - || TextUtils.equals(getSettingsIntelligencePkgName(context), callerPackage); - final boolean isAllowlistedPackage = isSignatureAllowlisted(context, callerPackage); - if (isSettingsPackage || isAllowlistedPackage) { - return; - } - throw new SecurityException("Search result intents must be called with from an " - + "allowlisted package."); - } - - @Override - public SearchIndexableResources getSearchIndexableResources() { - if (mSearchIndexableResources == null) { - mSearchIndexableResources = new SearchIndexableResourcesMobile(); - } - return mSearchIndexableResources; - } - - @Override - public Intent buildSearchIntent(Context context, int pageId) { - return new Intent(Settings.ACTION_APP_SEARCH_SETTINGS) - .setPackage(getSettingsIntelligencePkgName(context)) - .putExtra(Intent.EXTRA_REFERRER, buildReferrer(context, pageId)); - } - - protected boolean isSignatureAllowlisted(Context context, String callerPackage) { - return false; - } - - private static Uri buildReferrer(Context context, int pageId) { - return new Uri.Builder() - .scheme("android-app") - .authority(context.getPackageName()) - .path(String.valueOf(pageId)) - .build(); - } -} diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.kt b/src/com/android/settings/search/SearchFeatureProviderImpl.kt new file mode 100644 index 00000000000..2ea9910935e --- /dev/null +++ b/src/com/android/settings/search/SearchFeatureProviderImpl.kt @@ -0,0 +1,64 @@ +/* + * 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.search + +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.provider.Settings +import com.android.settings.search.SearchIndexableResourcesFactory.createSearchIndexableResources +import com.android.settingslib.search.SearchIndexableResources + +/** FeatureProvider for the refactored search code. */ +open class SearchFeatureProviderImpl : SearchFeatureProvider { + private val lazySearchIndexableResources by lazy { createSearchIndexableResources() } + + override fun verifyLaunchSearchResultPageCaller(context: Context, callerPackage: String) { + require(callerPackage.isNotEmpty()) { + "ExternalSettingsTrampoline intents must be called with startActivityForResult" + } + val isSettingsPackage = callerPackage == context.packageName + if (isSettingsPackage || + callerPackage == getSettingsIntelligencePkgName(context) || + isSignatureAllowlisted(context, callerPackage)) { + return + } + throw SecurityException( + "Search result intents must be called with from an allowlisted package.") + } + + override fun getSearchIndexableResources(): SearchIndexableResources = + lazySearchIndexableResources + + override fun buildSearchIntent(context: Context, pageId: Int): Intent = + Intent(Settings.ACTION_APP_SEARCH_SETTINGS) + .setPackage(getSettingsIntelligencePkgName(context)) + .putExtra(Intent.EXTRA_REFERRER, buildReferrer(context, pageId)) + + protected open fun isSignatureAllowlisted(context: Context, callerPackage: String): Boolean = + false + + companion object { + private fun buildReferrer(context: Context, pageId: Int): Uri = + Uri.Builder() + .scheme("android-app") + .authority(context.packageName) + .path(pageId.toString()) + .build() + } +} diff --git a/src/com/android/settings/search/SearchIndexableResourcesFactory.java b/src/com/android/settings/search/SearchIndexableResourcesFactory.java new file mode 100644 index 00000000000..25f34edcaf5 --- /dev/null +++ b/src/com/android/settings/search/SearchIndexableResourcesFactory.java @@ -0,0 +1,34 @@ +/* + * 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.search; + +import androidx.annotation.NonNull; + +import com.android.settingslib.search.SearchIndexableResources; +import com.android.settingslib.search.SearchIndexableResourcesMobile; + +/** + * Creates the {@link SearchIndexableResourcesMobile}. + *

+ * Since this class is generated by annotation processor, so it can only be created in Java now. + */ +class SearchIndexableResourcesFactory { + @NonNull + static SearchIndexableResources createSearchIndexableResources() { + return new SearchIndexableResourcesMobile(); + } +} diff --git a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java index 8a7419bb1ba..599649b92c2 100644 --- a/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java @@ -124,8 +124,8 @@ public class SearchFeatureProviderImplTest { } @Test(expected = IllegalArgumentException.class) - public void verifyLaunchSearchResultPageCaller_nullCaller_shouldCrash() { - mProvider.verifyLaunchSearchResultPageCaller(mActivity, null /* caller */); + public void verifyLaunchSearchResultPageCaller_emptyCaller_shouldCrash() { + mProvider.verifyLaunchSearchResultPageCaller(mActivity, ""); } @Test(expected = SecurityException.class) From daeb06c3b0dd9bb80eb8e87254e96cfc5c5e9bfc Mon Sep 17 00:00:00 2001 From: pajacechen Date: Wed, 26 Jun 2024 14:56:58 +0800 Subject: [PATCH 6/8] [Bug Fix] "Dock defend string and tips in settings are incorrectly" issue Symptom: After the dock defend was triggered, the battery tips still show "Future-Bypass" dock defend mode. It should be the "Active" dock defend mode. Root Cause: The original `BatteryInfo.isBatteryDefender` was implemented by using `longlife`, due to the charging limit also reuse `longlife` issue, we replace the implementation of `BatteryInfo.isBatteryDefender` with HAL API call `isTempDefend` and `isDwellDefend`. However, the dock defend also needs `longlife`, the original `BatteryInfo.isBatteryDefender`. So the dock defend checking failed after replacing the implementation of `BatteryInfo.isBatteryDefender` Solution: - Add new property isLonglife in BatteryInfo - Replace all isBatteryDefender reference that needs isLonglife Bug: 348563863 Test: Manual Test and robotest Test: http://ab/I08300010291126076 (unit test) Test: http://ab/I67800010291096764 (robo test) Flag: EXEMPT bugfix Change-Id: I58424927522acc29dc49261a2c24829a5b34ef85 --- .../settings/fuelgauge/BatteryInfo.java | 7 +-- .../settings/fuelgauge/BatteryUtils.java | 4 +- .../PowerUsageFeatureProviderImpl.java | 2 +- .../detectors/BatteryDefenderDetector.java | 9 ++-- .../settings/fuelgauge/BatteryInfoTest.java | 43 +++++++++++++++++++ .../PowerUsageFeatureProviderImplTest.java | 8 ++-- .../BatteryDefenderDetectorTest.java | 12 +----- 7 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java index b54801a677a..7cf9e44bd66 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfo.java +++ b/src/com/android/settings/fuelgauge/BatteryInfo.java @@ -53,7 +53,8 @@ public class BatteryInfo { public int batteryStatus; public int pluggedStatus; public boolean discharging = true; - public boolean isBatteryDefender; + public boolean isBatteryDefender = false; + public boolean isLongLife = false; public boolean isFastCharging; public long remainingTimeUs = 0; public long averageTimeToDischarge = EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN; @@ -306,7 +307,7 @@ public class BatteryInfo { info.pluggedStatus = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); info.mCharging = info.pluggedStatus != 0; info.averageTimeToDischarge = estimate.getAverageDischargeTime(); - info.isBatteryDefender = + info.isLongLife = batteryBroadcast.getIntExtra( BatteryManager.EXTRA_CHARGING_STATUS, BatteryManager.CHARGING_POLICY_DEFAULT) @@ -319,7 +320,7 @@ public class BatteryInfo { info.isFastCharging = BatteryStatus.getChargingSpeed(context, batteryBroadcast) == BatteryStatus.CHARGING_FAST; - if (info.isBatteryDefender) { + if (info.isLongLife) { info.isBatteryDefender = FeatureFactory.getFeatureFactory() .getPowerUsageFeatureProvider() diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java index 9e08664c901..7cb5733a9b0 100644 --- a/src/com/android/settings/fuelgauge/BatteryUtils.java +++ b/src/com/android/settings/fuelgauge/BatteryUtils.java @@ -600,12 +600,12 @@ public class BatteryUtils { context.getContentResolver(), SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS, 0) == 1) { return DockDefenderMode.TEMPORARILY_BYPASSED; - } else if (batteryInfo.isBatteryDefender + } else if (batteryInfo.isLongLife && FeatureFactory.getFeatureFactory() .getPowerUsageFeatureProvider() .isExtraDefend()) { return DockDefenderMode.ACTIVE; - } else if (!batteryInfo.isBatteryDefender) { + } else if (!batteryInfo.isLongLife) { return DockDefenderMode.FUTURE_BYPASS; } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index dc5b2269cf8..8ba63749cbd 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -247,7 +247,7 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider @Override public boolean isBatteryDefend(BatteryInfo info) { - return info.isBatteryDefender && !isExtraDefend(); + return info.isLongLife && !isExtraDefend(); } @Override diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java index 639b3c7b20d..6ff266574c9 100644 --- a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java +++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java @@ -21,7 +21,6 @@ import android.content.Context; import com.android.settings.fuelgauge.BatteryInfo; import com.android.settings.fuelgauge.batterytip.tips.BatteryDefenderTip; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; -import com.android.settings.overlay.FeatureFactory; /** Detect whether the battery is overheated */ public class BatteryDefenderDetector implements BatteryTipDetector { @@ -35,12 +34,10 @@ public class BatteryDefenderDetector implements BatteryTipDetector { @Override public BatteryTip detect() { - final boolean isBasicBatteryDefend = - FeatureFactory.getFeatureFactory() - .getPowerUsageFeatureProvider() - .isBatteryDefend(mBatteryInfo); final int state = - isBasicBatteryDefend ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE; + mBatteryInfo.isBatteryDefender + ? BatteryTip.StateType.NEW + : BatteryTip.StateType.INVISIBLE; final boolean isPluggedIn = mBatteryInfo.pluggedStatus != 0; return new BatteryDefenderTip(state, isPluggedIn); } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java index 7bafc6d5198..b7e65906fab 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java @@ -789,6 +789,40 @@ public class BatteryInfoTest { expectedChargeLabel); } + @Test + public void getBatteryInfo_longlife_shouldSetLonglife() { + var batteryIntent = createIntentForLongLifeTest(/* hasLongLife= */ true); + + var batteryInfo = + BatteryInfo.getBatteryInfo( + mContext, + batteryIntent, + mBatteryUsageStats, + /* estimate= */ MOCK_ESTIMATE, + /* elapsedRealtimeUs= */ 0L, + /* shortString= */ false, + /* currentTimeMs= */ 0L); + + assertThat(batteryInfo.isLongLife).isTrue(); + } + + @Test + public void getBatteryInfo_noLonglife_shouldNotLonglife() { + var batteryIntent = createIntentForLongLifeTest(/* hasLongLife= */ false); + + var batteryInfo = + BatteryInfo.getBatteryInfo( + mContext, + batteryIntent, + mBatteryUsageStats, + /* estimate= */ MOCK_ESTIMATE, + /* elapsedRealtimeUs= */ 0L, + /* shortString= */ false, + /* currentTimeMs= */ 0L); + + assertThat(batteryInfo.isLongLife).isFalse(); + } + private enum ChargingSpeed { FAST, REGULAR, @@ -801,6 +835,15 @@ public class BatteryInfoTest { DOCKED } + private Intent createIntentForLongLifeTest(Boolean hasLongLife) { + return new Intent(Intent.ACTION_BATTERY_CHANGED) + .putExtra( + BatteryManager.EXTRA_CHARGING_STATUS, + hasLongLife + ? BatteryManager.CHARGING_POLICY_ADAPTIVE_LONGLIFE + : BatteryManager.CHARGING_POLICY_DEFAULT); + } + private Intent createIntentForGetBatteryInfoTest( ChargingType chargingType, ChargingSpeed chargingSpeed, int batteryLevel) { return createBatteryIntent( diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java index 6b32ff54c57..cecf8f0f6be 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java @@ -165,7 +165,7 @@ public class PowerUsageFeatureProviderImplTest { @Test public void isBatteryDefend_defenderModeAndExtraDefendAreFalse_returnFalse() { - mBatteryInfo.isBatteryDefender = false; + mBatteryInfo.isLongLife = false; doReturn(false).when(mPowerFeatureProvider).isExtraDefend(); assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isFalse(); @@ -173,7 +173,7 @@ public class PowerUsageFeatureProviderImplTest { @Test public void isBatteryDefend_defenderModeIsFalse_returnFalse() { - mBatteryInfo.isBatteryDefender = false; + mBatteryInfo.isLongLife = false; doReturn(true).when(mPowerFeatureProvider).isExtraDefend(); assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isFalse(); @@ -181,7 +181,7 @@ public class PowerUsageFeatureProviderImplTest { @Test public void isBatteryDefend_defenderModeAndExtraDefendAreTrue_returnFalse() { - mBatteryInfo.isBatteryDefender = true; + mBatteryInfo.isLongLife = true; doReturn(true).when(mPowerFeatureProvider).isExtraDefend(); assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isFalse(); @@ -189,7 +189,7 @@ public class PowerUsageFeatureProviderImplTest { @Test public void isBatteryDefend_extraDefendIsFalse_returnTrue() { - mBatteryInfo.isBatteryDefender = true; + mBatteryInfo.isLongLife = true; doReturn(false).when(mPowerFeatureProvider).isExtraDefend(); assertThat(mPowerFeatureProvider.isBatteryDefend(mBatteryInfo)).isTrue(); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java index ab1ceb582aa..7643c410d5a 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java @@ -18,15 +18,12 @@ package com.android.settings.fuelgauge.batterytip.detectors; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.when; - import android.content.Context; import androidx.test.core.app.ApplicationProvider; import com.android.settings.fuelgauge.BatteryInfo; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; -import com.android.settings.testutils.FakeFeatureFactory; import org.junit.Before; import org.junit.Test; @@ -41,28 +38,23 @@ public class BatteryDefenderDetectorTest { @Mock private BatteryInfo mBatteryInfo; private BatteryDefenderDetector mBatteryDefenderDetector; - private FakeFeatureFactory mFakeFeatureFactory; - @Before public void setUp() { MockitoAnnotations.initMocks(this); final Context context = ApplicationProvider.getApplicationContext(); mBatteryDefenderDetector = new BatteryDefenderDetector(mBatteryInfo, context); - mFakeFeatureFactory = FakeFeatureFactory.setupForTest(); } @Test public void detect_notBatteryDefend_tipInvisible() { - when(mFakeFeatureFactory.powerUsageFeatureProvider.isBatteryDefend(mBatteryInfo)) - .thenReturn(false); + mBatteryInfo.isBatteryDefender = false; assertThat(mBatteryDefenderDetector.detect().isVisible()).isFalse(); } @Test public void detect_isBatteryDefend_tipNew() { - when(mFakeFeatureFactory.powerUsageFeatureProvider.isBatteryDefend(mBatteryInfo)) - .thenReturn(true); + mBatteryInfo.isBatteryDefender = true; assertThat(mBatteryDefenderDetector.detect().getState()) .isEqualTo(BatteryTip.StateType.NEW); From dd0ae72eb932110a668d0e6286a8ad61be1e3887 Mon Sep 17 00:00:00 2001 From: Billy Huang Date: Thu, 27 Jun 2024 11:53:01 -0700 Subject: [PATCH 7/8] fix TrustAgentsPreferenceControllerTest Removed non-platform Robolectric shadow in favor of setting up fake package/services directly with ShadowApplicationPackageManager. Bug: 313612480 Test: atest "SettingsRoboTests:TrustAgentsPreferenceControllerTest" --host Flag: TEST_ONLY Change-Id: Iadcb5bcb977201e2f394b699621bfb34657a7820 --- .../TrustAgentsPreferenceControllerTest.java | 145 +++++------------- 1 file changed, 41 insertions(+), 104 deletions(-) diff --git a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java index 8339798e685..766855ca35e 100644 --- a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java @@ -21,14 +21,10 @@ import static com.google.common.truth.Truth.assertThat; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; +import android.content.IntentFilter; +import android.content.pm.PackageInfo; import android.service.trust.TrustAgentService; -import android.text.TextUtils; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -38,34 +34,30 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils; import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal; import com.android.settingslib.RestrictedSwitchPreference; -import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.Shadows; import org.robolectric.annotation.Config; -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; import org.robolectric.shadows.ShadowApplicationPackageManager; -import java.util.ArrayList; -import java.util.List; - @RunWith(RobolectricTestRunner.class) @Config(shadows = { ShadowLockPatternUtils.class, ShadowRestrictedLockUtilsInternal.class, - ShadowDevicePolicyManager.class, - ShadowApplicationPackageManager.class, - TrustAgentsPreferenceControllerTest.ShadowTrustAgentManager.class + ShadowDevicePolicyManager.class, ShadowApplicationPackageManager.class }) public class TrustAgentsPreferenceControllerTest { - - private static final Intent TEST_INTENT = - new Intent(TrustAgentService.SERVICE_INTERFACE); + private static final ComponentName TRUST_AGENT_A = new ComponentName( + "test.data.packageA", "clzAAA"); + private static final ComponentName TRUST_AGENT_B = new ComponentName( + "test.data.packageB", "clzBBB"); + private static final ComponentName TRUST_AGENT_C = new ComponentName( + "test.data.packageC", "clzCCC"); + private static final ComponentName TRUST_AGENT_D = new ComponentName( + "test.data.packageD", "clzDDD"); private Context mContext; private ShadowApplicationPackageManager mPackageManager; @@ -84,11 +76,6 @@ public class TrustAgentsPreferenceControllerTest { mPreferenceScreen.setKey("pref_key"); } - @After - public void tearDown() { - ShadowTrustAgentManager.clearPermissionGrantedList(); - } - @Test public void getAvailabilityStatus_byDefault_shouldBeShown() { assertThat(mController.getAvailabilityStatus()) @@ -97,8 +84,7 @@ public class TrustAgentsPreferenceControllerTest { @Test public void onStart_noTrustAgent_shouldNotAddPreference() { - final List availableAgents = createFakeAvailableAgents(); - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); + installFakeAvailableAgents(/* grantPermission= */ false); mController.displayPreference(mPreferenceScreen); mController.onStart(); @@ -106,57 +92,34 @@ public class TrustAgentsPreferenceControllerTest { assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(0); } - @Ignore("b/313612480") @Test - public void - onStart_hasAUninstalledTrustAgent_shouldRemoveOnePreferenceAndLeaveTwoPreferences() { - final List availableAgents = createFakeAvailableAgents(); - final ResolveInfo uninstalledTrustAgent = availableAgents.get(0); - - for (ResolveInfo rInfo : availableAgents) { - ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo); - } - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); + public void onStart_uninstalledTrustAgent_shouldRemoveOnePreferenceAndLeaveTwoPreferences() { + installFakeAvailableAgents(/* grantPermission= */ true); mController.displayPreference(mPreferenceScreen); mController.onStart(); - availableAgents.remove(uninstalledTrustAgent); + uninstallAgent(TRUST_AGENT_A); - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); mController.onStart(); assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(2); } - @Ignore("b/313612480") @Test public void onStart_hasANewTrustAgent_shouldAddOnePreferenceAndHaveFourPreferences() { - final List availableAgents = createFakeAvailableAgents(); - final ComponentName newComponentName = new ComponentName("test.data.packageD", "clzDDD"); - final ResolveInfo newTrustAgent = createFakeResolveInfo(newComponentName); - for (ResolveInfo rInfo : availableAgents) { - ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo); - } - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); + installFakeAvailableAgents(/* grantPermission= */ true); mController.displayPreference(mPreferenceScreen); mController.onStart(); - availableAgents.add(newTrustAgent); - ShadowTrustAgentManager.grantPermissionToResolveInfo(newTrustAgent); + installFakeAvailableAgent(TRUST_AGENT_D, /* grantPermission= */ true); - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); mController.onStart(); assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(4); } - @Ignore("b/313612480") @Test public void onStart_hasUnrestrictedTrustAgent_shouldAddThreeChangeablePreferences() { ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(0); - final List availableAgents = createFakeAvailableAgents(); - for (ResolveInfo rInfo : availableAgents) { - ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo); - } - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); + installFakeAvailableAgents(/* grantPermission= */ true); mController.displayPreference(mPreferenceScreen); mController.onStart(); @@ -169,14 +132,9 @@ public class TrustAgentsPreferenceControllerTest { } } - @Ignore("b/313612480") @Test - public void onStart_hasRestrictedTructAgent_shouldAddThreeUnchangeablePreferences() { - final List availableAgents = createFakeAvailableAgents(); - for (ResolveInfo rInfo : availableAgents) { - ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo); - } - mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents); + public void onStart_hasRestrictedTrustAgent_shouldAddThreeUnchangeablePreferences() { + installFakeAvailableAgents(/* grantPermission= */ true); ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures( DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS); @@ -191,51 +149,30 @@ public class TrustAgentsPreferenceControllerTest { } } - private List createFakeAvailableAgents() { - final List componentNames = new ArrayList<>(); - componentNames.add(new ComponentName("test.data.packageA", "clzAAA")); - componentNames.add(new ComponentName("test.data.packageB", "clzBBB")); - componentNames.add(new ComponentName("test.data.packageC", "clzCCC")); - final List result = new ArrayList<>(); - for (ComponentName cn : componentNames) { - final ResolveInfo ri = createFakeResolveInfo(cn); - result.add(ri); - } - return result; + private void installFakeAvailableAgents(boolean grantPermission) { + installFakeAvailableAgent(TRUST_AGENT_A, grantPermission); + installFakeAvailableAgent(TRUST_AGENT_B, grantPermission); + installFakeAvailableAgent(TRUST_AGENT_C, grantPermission); } - private ResolveInfo createFakeResolveInfo(ComponentName cn) { - final ResolveInfo ri = new ResolveInfo(); - ri.serviceInfo = new ServiceInfo(); - ri.serviceInfo.packageName = cn.getPackageName(); - ri.serviceInfo.name = cn.getClassName(); - ri.serviceInfo.applicationInfo = new ApplicationInfo(); - ri.serviceInfo.applicationInfo.packageName = cn.getPackageName(); - ri.serviceInfo.applicationInfo.name = cn.getClassName(); - return ri; + private void installFakeAvailableAgent(ComponentName name, + boolean grantPermission) { + mPackageManager.addServiceIfNotPresent(name); + mPackageManager.addIntentFilterForService(name, + new IntentFilter(TrustAgentService.SERVICE_INTERFACE)); + if (!grantPermission) { + return; + } + PackageInfo pkgInfo = mPackageManager.getInternalMutablePackageInfo( + name.getPackageName()); + pkgInfo.requestedPermissions = + new String[]{android.Manifest.permission.PROVIDE_TRUST_AGENT}; + pkgInfo.requestedPermissionsFlags = + new int[]{PackageInfo.REQUESTED_PERMISSION_GRANTED}; } - @Implements(TrustAgentManager.class) - public static class ShadowTrustAgentManager { - private final static List sPermissionGrantedList = new ArrayList<>(); - - @Implementation - protected boolean shouldProvideTrust(ResolveInfo resolveInfo, PackageManager pm) { - for (ResolveInfo info : sPermissionGrantedList) { - if (info.serviceInfo.equals(resolveInfo.serviceInfo)) { - return true; - } - } - - return false; - } - - private static void grantPermissionToResolveInfo(ResolveInfo rInfo) { - sPermissionGrantedList.add(rInfo); - } - - private static void clearPermissionGrantedList() { - sPermissionGrantedList.clear(); - } + private void uninstallAgent(ComponentName name) { + mPackageManager.removeService(name); + mPackageManager.removePackage(name.getPackageName()); } } From 234872e187349919c82cbd1fe0afaf731b2c27c7 Mon Sep 17 00:00:00 2001 From: Pawan Wagh Date: Thu, 27 Jun 2024 19:40:38 +0000 Subject: [PATCH 8/8] Fix UI issues in localization - Some of the locales don't display entire text and BigTextStyle doesn't display ellipsis for them. Removing bigText. - Fixing strings to display 4KB - Reduce string for bootloader unlock title Bug: 345291007 Bug: 343893991 Bug: 343815951 Test: m Settings && adb install -r $ANDROID_PRODUCT_OUT/system_ext/priv-app/Settings/Settings.apk Flag: EXEMPT bugfix Change-Id: I3e5bf9bf70be1240cfe7d3a381bb8fef62ce2efa --- res/values/strings.xml | 6 +++--- .../development/PageAgnosticNotificationService.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index dae8f5e1dae..1f6917e6bfa 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11650,7 +11650,7 @@ Failed to reformat and wipe the data partition to ext4. - Bootloader Unlock Required for 16KB Mode + Bootloader Unlock Required This device needs to have the bootloader unlocked before using the 16KB developer option. Software integrity cannot be guaranteed in this mode, and any data stored on the phone while the bootloader is unlocked may be at risk. All user data and settings will be wiped when activating 16KB mode. Once the bootloader is unlocked, activating the 16KB option will require two reboots. @@ -11679,10 +11679,10 @@ You are in the 16KB mode of the page-agnostic mode. Software integrity cannot be guaranteed in this mode, and any data stored on the phone while the bootloader is unlocked may be at risk. Some features will be disabled in these modes, so some applications may not work. - In order to re-enter the production mode, you must, switch back to 4K mode and then lock the bootloader of the device. Tap to read more. + In order to re-enter the production mode, you must, switch back to 4KB mode and then lock the bootloader of the device. Tap to read more. You are in the 16KB mode of the page-agnostic mode. Software integrity cannot be guaranteed in this mode, and any data stored on the phone while the bootloader is unlocked may be at risk. Some features will be disabled in these modes, so some applications may not work. - In order to re-enter the production mode, you must, switch back to 4K mode and then lock the bootloader of the device. This would factory reset the device again and + In order to re-enter the production mode, you must, switch back to 4KB mode and then lock the bootloader of the device. This would factory reset the device again and restore it to production settings. After the device successfully boots into Android, disable OEM unlocking in Developer options. If the device fails to boot into Android or is unstable, re-flash the device with the latest factory images from <a href=\"https://developers.google.com/android/images\">https://developers.google.com/android/images</a> diff --git a/src/com/android/settings/development/PageAgnosticNotificationService.java b/src/com/android/settings/development/PageAgnosticNotificationService.java index bce1dd9e106..40dff0c8dbf 100644 --- a/src/com/android/settings/development/PageAgnosticNotificationService.java +++ b/src/com/android/settings/development/PageAgnosticNotificationService.java @@ -96,13 +96,13 @@ public class PageAgnosticNotificationService extends Service { notifyPendingIntent) .build(); + // TODO:(b/349860833) Change text style to BigTextStyle once the ellipsis issue is fixed. Notification.Builder builder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) .setContentTitle(title) .setContentText(text) .setOngoing(true) .setSmallIcon(R.drawable.ic_settings_24dp) - .setStyle(new Notification.BigTextStyle().bigText(text)) .setContentIntent(notifyPendingIntent) .addAction(action);