From ae5f82d36bebe793ad1cd4d4439cedee7f847695 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Thu, 17 Oct 2024 15:02:58 +0800 Subject: [PATCH 01/11] Move the annotation right before String Fix: 374015480 Test: build Flag: EXEMPT N/A Change-Id: Id4eb78319b10f63a0a8959643b63ed9a598f24af --- src/com/android/settings/DisplaySettings.java | 3 +-- src/com/android/settings/LegalSettings.java | 3 +-- .../settings/fuelgauge/batterysaver/BatterySaverSettings.java | 3 +-- src/com/android/settings/network/NetworkDashboardFragment.java | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index a0950066770..10763d00102 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -97,9 +97,8 @@ public class DisplaySettings extends DashboardFragment { } }; - @Nullable @Override - public String getPreferenceScreenBindingKey(@NonNull Context context) { + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { return DisplayScreen.KEY; } } diff --git a/src/com/android/settings/LegalSettings.java b/src/com/android/settings/LegalSettings.java index e48da2663b9..533dde3bb29 100644 --- a/src/com/android/settings/LegalSettings.java +++ b/src/com/android/settings/LegalSettings.java @@ -50,9 +50,8 @@ public class LegalSettings extends DashboardFragment { public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.about_legal); - @Nullable @Override - public String getPreferenceScreenBindingKey(@NonNull Context context) { + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { return LegalSettingsScreen.KEY; } } diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java index 8373d03de17..df6c1d9729d 100644 --- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java +++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java @@ -97,9 +97,8 @@ public class BatterySaverSettings extends DashboardFragment { } } - @Nullable @Override - public String getPreferenceScreenBindingKey(@NonNull Context context) { + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { return BatterySaverScreen.KEY; } } diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java index 3ba3dc6853c..2585d04a3f0 100644 --- a/src/com/android/settings/network/NetworkDashboardFragment.java +++ b/src/com/android/settings/network/NetworkDashboardFragment.java @@ -117,9 +117,8 @@ public class NetworkDashboardFragment extends DashboardFragment implements } }; - @Nullable @Override - public String getPreferenceScreenBindingKey(@NonNull Context context) { + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { return NetworkDashboardScreen.KEY; } } From 033b7e5620eea5e57b0dfeed6586f291ac22ba7a Mon Sep 17 00:00:00 2001 From: MiltonWu Date: Thu, 17 Oct 2024 07:48:37 +0000 Subject: [PATCH 02/11] Refine biometrics accessibility interactor 1. support non-flow version isEnabled 2. support send announment Bug: 372385781 Test: Function works w/o build break Flag: EXEMPT feature flag protected on override project Change-Id: I2867edf9e9b9cc9190888e257a203acd7877ab3b --- .../fingerprint2/BiometricsEnvironment.kt | 9 ++--- .../interactor/AccessibilityInteractor.kt | 36 +++++++++++++------ .../interactor/UdfpsEnrollInteractor.kt | 3 +- .../udfps/ui/viewmodel/UdfpsViewModel.kt | 4 +-- .../FingerprintEnrollFindSensorViewModel.kt | 4 +-- .../biometrics/fingerprint/Injector.kt | 6 +++- ...gerprintEnrollFindSensorViewModelV2Test.kt | 6 +++- 7 files changed, 44 insertions(+), 24 deletions(-) diff --git a/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt b/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt index 761a9c3a871..50ac3cdcee5 100644 --- a/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt +++ b/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt @@ -133,11 +133,8 @@ class BiometricsEnvironment( fun createRenameFingerprintInteractor(): RenameFingerprintInteractor = RenameFingerprintsInteractorImpl(fingerprintManager, context.userId, backgroundDispatcher) - val accessibilityInteractor: AccessibilityInteractor by lazy { - AccessibilityInteractorImpl( - context.getSystemService(AccessibilityManager::class.java)!!, - applicationScope, - ) + fun createAccessibilityInteractor(): AccessibilityInteractor { + return AccessibilityInteractorImpl(context.getSystemService(AccessibilityManager::class.java)!!) } val foldStateInteractor: FoldStateInteractor by lazy { FoldStateInteractorImpl(context) } @@ -157,7 +154,7 @@ class BiometricsEnvironment( val enrollStageInteractor: EnrollStageInteractor by lazy { EnrollStageInteractorImpl() } val udfpsEnrollInteractor: UdfpsEnrollInteractor by lazy { - UdfpsEnrollInteractorImpl(context, accessibilityInteractor) + UdfpsEnrollInteractorImpl(context, createAccessibilityInteractor()) } val sensorInteractor: FingerprintSensorInteractor by lazy { diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt index e1a08e6cda2..9f62ed03572 100644 --- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt +++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt @@ -16,6 +16,8 @@ package com.android.settings.biometrics.fingerprint2.domain.interactor +import android.view.accessibility.AccessibilityEvent +import android.view.accessibility.AccessibilityEvent.TYPE_ANNOUNCEMENT import android.view.accessibility.AccessibilityManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose @@ -27,26 +29,38 @@ import kotlinx.coroutines.flow.stateIn /** Represents all of the information on accessibility state. */ interface AccessibilityInteractor { /** A flow that contains whether or not accessibility is enabled */ - val isAccessibilityEnabled: Flow + fun isEnabledFlow(scope: CoroutineScope): Flow + val isEnabled: Boolean + fun announce(clazz: Class<*>, announcement: CharSequence?) } class AccessibilityInteractorImpl( - accessibilityManager: AccessibilityManager, - applicationScope: CoroutineScope, + private val accessibilityManager: AccessibilityManager, ) : AccessibilityInteractor { /** A flow that contains whether or not accessibility is enabled */ - override val isAccessibilityEnabled: Flow = + override fun isEnabledFlow(scope: CoroutineScope): Flow = callbackFlow { - val listener = - AccessibilityManager.AccessibilityStateChangeListener { enabled -> trySend(enabled) } - accessibilityManager.addAccessibilityStateChangeListener(listener) + val listener = + AccessibilityManager.AccessibilityStateChangeListener { enabled -> trySend(enabled) } + accessibilityManager.addAccessibilityStateChangeListener(listener) - // This clause will be called when no one is listening to the flow - awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) } - } + // This clause will be called when no one is listening to the flow + awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) } + } .stateIn( - applicationScope, // This is going to tied to the activity scope + scope, SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener false, ) + + override val isEnabled: Boolean + get() = accessibilityManager.isEnabled + + override fun announce(clazz: Class<*>, announcement: CharSequence?) { + val event = AccessibilityEvent(TYPE_ANNOUNCEMENT) + event.className = clazz.javaClass.name + event.packageName = clazz.packageName + event.text.add(announcement) + accessibilityManager.sendAccessibilityEvent(event) + } } diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt index 006060a54b9..62c51aeb527 100644 --- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt +++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt @@ -19,6 +19,7 @@ package com.android.settings.biometrics.fingerprint2.domain.interactor import android.content.Context import android.graphics.PointF import android.util.TypedValue +import kotlinx.coroutines.MainScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine @@ -87,7 +88,7 @@ class UdfpsEnrollInteractorImpl( override val guidedEnrollmentOffset: Flow = combine( _guidedEnrollment, - accessibilityInteractor.isAccessibilityEnabled, + accessibilityInteractor.isEnabledFlow(MainScope()), isGuidedEnrollment, ) { point, accessibilityEnabled, guidedEnrollmentEnabled -> if (accessibilityEnabled || !guidedEnrollmentEnabled) { diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt index 658c6c747c2..df46aa4c8a5 100644 --- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt +++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt @@ -179,7 +179,7 @@ class UdfpsViewModel( /** Indicates if accessibility is enabled */ val accessibilityEnabled = - accessibilityInteractor.isAccessibilityEnabled.shareIn( + accessibilityInteractor.isEnabledFlow(viewModelScope).shareIn( this.viewModelScope, SharingStarted.Eagerly, replay = 1, @@ -425,7 +425,7 @@ class UdfpsViewModel( biometricEnvironment.enrollStageInteractor, biometricEnvironment.orientationInteractor, biometricEnvironment.udfpsEnrollInteractor, - biometricEnvironment.accessibilityInteractor, + biometricEnvironment.createAccessibilityInteractor(), biometricEnvironment.sensorInteractor, biometricEnvironment.touchEventInteractor, biometricEnvironment.createSensorPropertiesInteractor(), diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt index 9b2cdde7cef..b27cfdd2eea 100644 --- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt +++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt @@ -84,7 +84,7 @@ class FingerprintEnrollFindSensorViewModel( /** Represents the stream of showing udfps lottie and whether accessibility is enabled. */ val udfpsLottieInfo: Flow = - _showUdfpsLottie.combine(accessibilityInteractor.isAccessibilityEnabled) { + _showUdfpsLottie.combine(accessibilityInteractor.isEnabledFlow(viewModelScope)) { _, isAccessibilityEnabled -> isAccessibilityEnabled @@ -213,7 +213,7 @@ class FingerprintEnrollFindSensorViewModel( provider[FingerprintGatekeeperViewModel::class], provider[BackgroundViewModel::class], provider[FingerprintFlowViewModel::class], - biometricEnvironment.accessibilityInteractor, + biometricEnvironment.createAccessibilityInteractor(), biometricEnvironment.foldStateInteractor, biometricEnvironment.orientationInteractor, biometricEnvironment.createSensorPropertiesInteractor(), diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt index e7fc3ed3d66..a5d0461e4a3 100644 --- a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt +++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt @@ -44,6 +44,7 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel import com.android.settings.testutils2.FakeFingerprintManagerInteractor import com.android.systemui.biometrics.shared.model.toFingerprintSensor +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -73,7 +74,10 @@ class Injector(step: FingerprintNavigationStep.UiStep) { var accessibilityInteractor = object : AccessibilityInteractor { - override val isAccessibilityEnabled: Flow = flowOf(true) + override fun isEnabledFlow(scope: CoroutineScope): Flow = flowOf(true) + override val isEnabled: Boolean + get() = true + override fun announce(clazz: Class<*>, announcement: CharSequence?) {} } var foldStateInteractor = diff --git a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt index 04cece83cd0..a8c5e684d33 100644 --- a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt +++ b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt @@ -39,6 +39,7 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing import com.android.settings.testutils2.FakeFingerprintManagerInteractor import com.android.systemui.biometrics.shared.model.toFingerprintSensor import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -106,7 +107,10 @@ class FingerprintEnrollFindSensorViewModelV2Test { ) accessibilityInteractor = object : AccessibilityInteractor { - override val isAccessibilityEnabled: Flow = flowOf(false) + override fun isEnabledFlow(scope: CoroutineScope): Flow = flowOf(true) + override val isEnabled: Boolean + get() = true + override fun announce(clazz: Class<*>, announcement: CharSequence?) {} } foldStateInteractor = object : FoldStateInteractor { From 136244ab2a45959164eccf0dbedae59211117fdd Mon Sep 17 00:00:00 2001 From: Fan Wu Date: Mon, 14 Oct 2024 15:44:01 +0800 Subject: [PATCH 03/11] Add Battery skeleton page and corresponding TS flag Test: atest Bug: 372774754 Flag: com.android.settings.flags.catalyst_power_usage_summary_screen Change-Id: I2ce7581d0f7fdce3516fef415efdf562c63e38d4 --- aconfig/catalyst/battery.aconfig | 9 ++- .../batteryusage/PowerUsageSummary.java | 7 ++ .../batteryusage/PowerUsageSummaryScreen.kt | 62 +++++++++++++++ .../PowerUsageSummaryScreenTest.kt | 78 +++++++++++++++++++ 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt create mode 100644 tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt diff --git a/aconfig/catalyst/battery.aconfig b/aconfig/catalyst/battery.aconfig index ce5c5c5d8d9..cec40f3746b 100644 --- a/aconfig/catalyst/battery.aconfig +++ b/aconfig/catalyst/battery.aconfig @@ -1,9 +1,16 @@ package: "com.android.settings.flags" container: "system" +flag { + name: "catalyst_power_usage_summary_screen" + namespace: "android_settings" + description: "Flag for Battery screen" + bug: "323791114" +} + flag { name: "catalyst_battery_saver_screen" namespace: "android_settings" description: "Flag for Battery Saver" bug: "323791114" -} +} \ No newline at end of file diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java index 4c700d260b2..b5581d0c081 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java @@ -27,6 +27,8 @@ import android.os.Bundle; import android.os.Handler; import android.provider.Settings.Global; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; @@ -270,4 +272,9 @@ public class PowerUsageSummary extends PowerUsageBase public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.power_usage_summary); + + @Override + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { + return PowerUsageSummaryScreen.KEY; + } } diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt new file mode 100644 index 00000000000..229e3084081 --- /dev/null +++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreen.kt @@ -0,0 +1,62 @@ +/* + * 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.fuelgauge.batteryusage + +import android.content.Context +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.metadata.PreferenceAvailabilityProvider +import com.android.settingslib.metadata.PreferenceIconProvider +import com.android.settingslib.metadata.ProvidePreferenceScreen +import com.android.settingslib.metadata.preferenceHierarchy +import com.android.settingslib.preference.PreferenceScreenCreator + +@ProvidePreferenceScreen +class PowerUsageSummaryScreen : PreferenceScreenCreator, + PreferenceAvailabilityProvider, + PreferenceIconProvider { + override val key: String + get() = KEY + + override val title: Int + get() = R.string.power_usage_summary_title + + override val keywords: Int + get() = R.string.keywords_battery + + override fun isFlagEnabled(context: Context) = Flags.catalystPowerUsageSummaryScreen() + + override fun hasCompleteHierarchy() = false + + override fun fragmentClass() = PowerUsageSummary::class.java + + override fun isAvailable(context: Context) = + context.resources.getBoolean(R.bool.config_show_top_level_battery) + + override fun getIcon(context: Context): Int = + if (Flags.homepageRevamp()) { + R.drawable.ic_settings_battery_filled + } else { + R.drawable.ic_settings_battery_white + } + + + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} + + companion object { + const val KEY = "power_usage_summary_screen" + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt new file mode 100644 index 00000000000..ce045c66a96 --- /dev/null +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.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.fuelgauge.batteryusage + +import android.content.ContextWrapper +import android.content.res.Resources +import android.platform.test.annotations.DisableFlags +import android.platform.test.annotations.EnableFlags +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.preference.CatalystScreenTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.stub + +class PowerUsageSummaryScreenTest : CatalystScreenTestCase() { + + override val preferenceScreenCreator = PowerUsageSummaryScreen() + + override val flagName: String + get() = Flags.FLAG_CATALYST_POWER_USAGE_SUMMARY_SCREEN + + private val mockResources = mock() + + private val contextWrapper = + object : ContextWrapper(context) { + override fun getResources(): Resources = mockResources + } + + @Test + fun key() { + assertThat(preferenceScreenCreator.key).isEqualTo(PowerUsageSummaryScreen.KEY) + } + + @Test + fun isAvailable_configTrue_shouldReturnTrue() { + mockResources.stub { on { getBoolean(anyInt()) } doReturn true } + + assertThat(preferenceScreenCreator.isAvailable(contextWrapper)).isTrue() + } + + @Test + fun isAvailable_configFalse_shouldReturnFalse() { + mockResources.stub { on { getBoolean(anyInt()) } doReturn false } + + assertThat(preferenceScreenCreator.isAvailable(contextWrapper)).isFalse() + } + + @Test + @EnableFlags(Flags.FLAG_HOMEPAGE_REVAMP) + fun getIcon_whenHomePageRevampFlagOn() { + assertThat(preferenceScreenCreator.getIcon(contextWrapper)).isEqualTo(R.drawable.ic_settings_battery_filled) + } + + @Test + @DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP) + fun getIcon_whenHomePageRevampFlagOff() { + assertThat(preferenceScreenCreator.getIcon(contextWrapper)).isEqualTo(R.drawable.ic_settings_battery_white) + } + + override fun migration() {} +} From 940b2143eb13293ab62fed6182f17a090dbe1020 Mon Sep 17 00:00:00 2001 From: Yi Jiang Date: Wed, 16 Oct 2024 11:11:18 -0700 Subject: [PATCH 04/11] Create a config flag for the new Screen Timeout settings screen Test: compile Bug: 368359967 Flag: com.android.settings.flags.catalyst_screen_timeout Change-Id: I44f3898a0d003e1947d63985edf571c76b783f07 --- aconfig/catalyst/display.aconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aconfig/catalyst/display.aconfig b/aconfig/catalyst/display.aconfig index f722f743085..94a01e02f7b 100644 --- a/aconfig/catalyst/display.aconfig +++ b/aconfig/catalyst/display.aconfig @@ -7,3 +7,10 @@ flag { description: "Flag for Display" bug: "323791114" } + +flag { + name: "catalyst_screen_timeout" + namespace: "android_settings" + description: "Flag for Screen Timeout settings" + bug: "323791114" +} From 4c3473134c12c2c633bab9d7fc2e94c96a96af7a Mon Sep 17 00:00:00 2001 From: Daniel Norman Date: Fri, 18 Oct 2024 00:18:48 +0000 Subject: [PATCH 05/11] Hides the Edit Shortcut top preference when empty. This fixes an issue where this page was presenting an inaccurate preference list count to TalkBack because it was including this empty preference. (Uses the same flag as other fixes for this same bug, even though the flag name doesn't make sense here.) Test: atest EditShortcutsPreferenceFragmentTest Test: Confirm preference invisible when editing a single feature, opened from the Settings app Test: Confirm preference invisible when editing a single feature, opened from the FAB Drag-to-Edit Test: Confirm preference still visible when editing multiple features, opened from the FAB Drag-to-Edit Test: Confirm TalkBack announces correct item counts in both cases, including when editing Magnification which has an "advanced" preference that gets replaced with the triple-tap shortcut. Bug: 318607873 Flag: com.android.settings.accessibility.toggle_feature_fragment_collection_info Change-Id: I2e1eb7f66022c1a47d1f96a914294fd8da25549c --- .../EditShortcutsPreferenceFragment.java | 15 ++-- .../EditShortcutsPreferenceFragmentTest.java | 72 ++++++++++++++++--- .../shadow/ShadowAccessibilityManager.java | 12 ++++ 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java index d04b34a4c3f..f05b15710c8 100644 --- a/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java +++ b/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragment.java @@ -61,6 +61,7 @@ import com.android.internal.accessibility.dialog.AccessibilityTargetHelper; import com.android.settings.R; import com.android.settings.SetupWizardUtils; import com.android.settings.accessibility.AccessibilitySetupWizardUtils; +import com.android.settings.accessibility.Flags; import com.android.settings.accessibility.PreferredShortcuts; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; @@ -201,9 +202,14 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment { super.onCreatePreferences(savedInstanceState, rootKey); Activity activity = getActivity(); + final Preference descriptionPref = findPreference(getString( + R.string.accessibility_shortcut_description_pref)); if (!activity.getIntent().getAction().equals( Settings.ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS)) { + if (Flags.toggleFeatureFragmentCollectionInfo()) { + descriptionPref.setVisible(false); + } return; } @@ -219,10 +225,11 @@ public class EditShortcutsPreferenceFragment extends DashboardFragment { ); activity.setTitle(titles.first); - - String screenDescriptionPrefKey = getString( - R.string.accessibility_shortcut_description_pref); - findPreference(screenDescriptionPrefKey).setSummary(titles.second); + if (titles.second != null || !Flags.toggleFeatureFragmentCollectionInfo()) { + descriptionPref.setSummary(titles.second); + } else { + descriptionPref.setVisible(false); + } } @NonNull diff --git a/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java index 414fe6333f5..b3270e95c11 100644 --- a/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/shortcuts/EditShortcutsPreferenceFragmentTest.java @@ -16,6 +16,9 @@ package com.android.settings.accessibility.shortcuts; +import static android.provider.Settings.ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS; + +import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; @@ -45,6 +48,7 @@ import android.util.Pair; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.Flags; +import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.testing.FragmentScenario; import androidx.lifecycle.Lifecycle; @@ -160,7 +164,7 @@ public class EditShortcutsPreferenceFragmentTest { public void showEditShortcutScreen_inSuw_launchSubSettingWithSuw() { EditShortcutsPreferenceFragment.showEditShortcutScreen( mActivity, METRICS_CATEGORY, SCREEN_TITLE, - TARGET_FAKE_COMPONENT, createSuwIntent(new Intent(), /* isInSuw= */ true)); + TARGET_FAKE_COMPONENT, setIntentInSuw(new Intent(), /* isInSuw= */ true)); assertLaunchSubSettingWithCurrentTargetComponents( TARGET_FAKE_COMPONENT.flattenToString(), /* isInSuw= */ true); @@ -198,6 +202,53 @@ public class EditShortcutsPreferenceFragmentTest { }); } + @Test + @EnableFlags( + com.android.settings.accessibility.Flags.FLAG_TOGGLE_FEATURE_FRAGMENT_COLLECTION_INFO) + public void shortcutDescriptionPref_defaultLaunch_notVisible() { + mFragmentScenario = createFragScenario(/* isInSuw= */ false, TARGET); + mFragmentScenario.moveToState(Lifecycle.State.CREATED); + + mFragmentScenario.onFragment(fragment -> { + Preference preference = fragment.findPreference( + mContext.getString(R.string.accessibility_shortcut_description_pref)); + assertThat(preference.isVisible()).isFalse(); + }); + } + + @Test + @EnableFlags( + com.android.settings.accessibility.Flags.FLAG_TOGGLE_FEATURE_FRAGMENT_COLLECTION_INFO) + public void shortcutDescriptionPref_launchFromAction_singleTarget_notVisible() { + mFragmentScenario = createFragScenario(/* isInSuw= */ false, List.of(TARGET), + ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS); + mFragmentScenario.moveToState(Lifecycle.State.CREATED); + + mFragmentScenario.onFragment(fragment -> { + Preference preference = fragment.findPreference( + mContext.getString(R.string.accessibility_shortcut_description_pref)); + assertThat(preference.isVisible()).isFalse(); + }); + } + + @Test + @EnableFlags( + com.android.settings.accessibility.Flags.FLAG_TOGGLE_FEATURE_FRAGMENT_COLLECTION_INFO) + public void shortcutDescriptionPref_launchFromAction_multipleTargets_isVisible() { + mFragmentScenario = createFragScenario(/* isInSuw= */ false, + // Both of these components are system components with known labels, so we don't + // need to mock AccessibilityManager with fake labels. + List.of(TARGET, DALTONIZER_COMPONENT_NAME.flattenToString()), + ACTION_ACCESSIBILITY_SHORTCUT_SETTINGS); + mFragmentScenario.moveToState(Lifecycle.State.CREATED); + + mFragmentScenario.onFragment(fragment -> { + Preference preference = fragment.findPreference( + mContext.getString(R.string.accessibility_shortcut_description_pref)); + assertThat(preference.isVisible()).isTrue(); + }); + } + @Test public void fragmentCreated_settingsObserversAreRegistered() { ShadowContentResolver contentResolver = shadowOf(mContext.getContentResolver()); @@ -654,9 +705,14 @@ public class EditShortcutsPreferenceFragmentTest { private FragmentScenario createFragScenario( boolean isInSuw, String target) { + return createFragScenario(isInSuw, List.of(target), null); + } + private FragmentScenario createFragScenario( + boolean isInSuw, List targets, @Nullable String intentAction) { Bundle args = new Bundle(); args.putStringArray( - EditShortcutsPreferenceFragment.ARG_KEY_SHORTCUT_TARGETS, new String[]{target}); + EditShortcutsPreferenceFragment.ARG_KEY_SHORTCUT_TARGETS, + targets.toArray(new String[0])); FragmentScenario scenario = FragmentScenario.launch( EditShortcutsPreferenceFragment.class, args, @@ -664,7 +720,11 @@ public class EditShortcutsPreferenceFragmentTest { scenario.onFragment(fragment -> { Intent intent = fragment.requireActivity().getIntent(); intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, SCREEN_TITLE); - fragment.requireActivity().setIntent(createSuwIntent(intent, isInSuw)); + setIntentInSuw(intent, isInSuw); + if (intentAction != null) { + intent.setAction(intentAction); + } + fragment.requireActivity().setIntent(intent); // Since the fragment is attached before we have a chance // to modify the activity's intent; initialize controllers again fragment.initializePreferenceControllerArguments(); @@ -672,11 +732,7 @@ public class EditShortcutsPreferenceFragmentTest { return scenario; } - private Intent createSuwIntent(Intent intent, boolean isInSuw) { - - if (intent == null) { - intent = new Intent(); - } + private Intent setIntentInSuw(Intent intent, boolean isInSuw) { intent.putExtra(EXTRA_IS_SETUP_FLOW, isInSuw); intent.putExtra(EXTRA_IS_FIRST_RUN, isInSuw); intent.putExtra(EXTRA_IS_PRE_DEFERRED_SETUP, isInSuw); diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java index fcd1e42c547..7de69a7ec55 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAccessibilityManager.java @@ -24,6 +24,8 @@ import android.content.Context; import android.util.ArrayMap; import android.view.accessibility.AccessibilityManager; +import com.android.internal.accessibility.common.ShortcutConstants; + import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; @@ -71,4 +73,14 @@ public class ShadowAccessibilityManager extends org.robolectric.shadows.ShadowAc @NonNull List installedAccessibilityShortcutList) { mInstalledAccessibilityShortcutList = installedAccessibilityShortcutList; } + + /** + * Implements the hidden method + * {@link AccessibilityManager#getAccessibilityShortcutTargets}. + */ + @Implementation + public List getAccessibilityShortcutTargets( + @ShortcutConstants.UserShortcutType int shortcutType) { + return List.of(); + } } From af1e8f7353f67ef9ab2c776cdeff673e7138f089 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Thu, 17 Oct 2024 14:03:05 +0800 Subject: [PATCH 06/11] [Catalyst] SIMs screen migration - Add a flag for the migration - Add the skeleton of the screen Test: atest MobileNetworkListScreenTest Bug: 368355368 Flag: com.android.settings.flags.catalyst_mobile_network_list Change-Id: I9d5d57b78d8f2c7d2bc6fd02e402fcdaf5b97bdf --- aconfig/catalyst/network_and_internet.aconfig | 7 +++ .../network/MobileNetworkListFragment.kt | 2 + .../network/MobileNetworkListScreen.kt | 50 +++++++++++++++++++ .../network/MobileNetworkListScreenTest.kt | 36 +++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 src/com/android/settings/network/MobileNetworkListScreen.kt create mode 100644 tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt diff --git a/aconfig/catalyst/network_and_internet.aconfig b/aconfig/catalyst/network_and_internet.aconfig index a3e1784035d..a5183f3738a 100644 --- a/aconfig/catalyst/network_and_internet.aconfig +++ b/aconfig/catalyst/network_and_internet.aconfig @@ -7,3 +7,10 @@ flag { description: "Flag for Network & Internet" bug: "323791114" } + +flag { + name: "catalyst_mobile_network_list" + namespace: "android_settings" + description: "Flag for SIMs" + bug: "323791114" +} diff --git a/src/com/android/settings/network/MobileNetworkListFragment.kt b/src/com/android/settings/network/MobileNetworkListFragment.kt index 3118088c6c3..a0da636379b 100644 --- a/src/com/android/settings/network/MobileNetworkListFragment.kt +++ b/src/com/android/settings/network/MobileNetworkListFragment.kt @@ -92,4 +92,6 @@ class MobileNetworkListFragment : DashboardFragment() { simRepositoryFactory(context).canEnterMobileNetworkPage() } } + + override fun getPreferenceScreenBindingKey(context: Context) = MobileNetworkListScreen.KEY } diff --git a/src/com/android/settings/network/MobileNetworkListScreen.kt b/src/com/android/settings/network/MobileNetworkListScreen.kt new file mode 100644 index 00000000000..93d8ee671d1 --- /dev/null +++ b/src/com/android/settings/network/MobileNetworkListScreen.kt @@ -0,0 +1,50 @@ +/* + * 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.network + +import android.content.Context +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.metadata.ProvidePreferenceScreen +import com.android.settingslib.metadata.preferenceHierarchy +import com.android.settingslib.preference.PreferenceScreenCreator + +@ProvidePreferenceScreen +class MobileNetworkListScreen : PreferenceScreenCreator { + override val key: String + get() = KEY + + override val title: Int + get() = R.string.provider_network_settings_title + + override val icon: Int + get() = R.drawable.ic_sim_card + + override val keywords: Int + get() = R.string.keywords_more_mobile_networks + + override fun isFlagEnabled(context: Context) = Flags.catalystMobileNetworkList() + + override fun hasCompleteHierarchy() = false + + override fun fragmentClass() = MobileNetworkListFragment::class.java + + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} + + companion object { + const val KEY = "mobile_network_list" + } +} diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt b/tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt new file mode 100644 index 00000000000..1d7a1d989e4 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/MobileNetworkListScreenTest.kt @@ -0,0 +1,36 @@ +/* + * 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.network + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.flags.Flags +import com.android.settingslib.preference.CatalystScreenTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class MobileNetworkListScreenTest : CatalystScreenTestCase() { + override val preferenceScreenCreator = MobileNetworkListScreen() + + override val flagName: String + get() = Flags.FLAG_CATALYST_MOBILE_NETWORK_LIST + + @Test + fun key() { + assertThat(preferenceScreenCreator.key).isEqualTo(MobileNetworkListScreen.KEY) + } +} From 97f2c3dfb4206b57dc1796246ce095cdb35c351b Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Wed, 16 Oct 2024 16:50:52 +0800 Subject: [PATCH 07/11] [Catalyst] Bluetooth screen migration - Add a flag for the migration - Add the skeleton of the screen Test: atest BluetoothDashboardScreenTest Bug: 372774767 Flag: com.android.settings.flags.catalyst_bluetooth_switchbar_screen Change-Id: I48e446532d3e839ae55880095a496e3ac4790c81 --- aconfig/catalyst/connected_devices.aconfig | 9 ++++ .../BluetoothDashboardFragment.java | 7 +++ .../BluetoothDashboardScreen.kt | 47 +++++++++++++++++++ .../BluetoothDashboardScreenTest.kt | 39 +++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 aconfig/catalyst/connected_devices.aconfig create mode 100644 src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt diff --git a/aconfig/catalyst/connected_devices.aconfig b/aconfig/catalyst/connected_devices.aconfig new file mode 100644 index 00000000000..7a335fa4675 --- /dev/null +++ b/aconfig/catalyst/connected_devices.aconfig @@ -0,0 +1,9 @@ +package: "com.android.settings.flags" +container: "system" + +flag { + name: "catalyst_bluetooth_switchbar_screen" + namespace: "android_settings" + description: "Flag for Bluetooth" + bug: "323791114" +} diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java index 66f2f1b8f31..90ef5b95b63 100644 --- a/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java @@ -21,6 +21,8 @@ import android.os.Bundle; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.settings.R; @@ -120,4 +122,9 @@ public class BluetoothDashboardFragment extends DashboardFragment { */ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.bluetooth_screen); + + @Override + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { + return BluetoothDashboardScreen.KEY; + } } diff --git a/src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt b/src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt new file mode 100644 index 00000000000..66fd8b17394 --- /dev/null +++ b/src/com/android/settings/connecteddevice/BluetoothDashboardScreen.kt @@ -0,0 +1,47 @@ +/* + * 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.connecteddevice + +import android.content.Context +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.metadata.ProvidePreferenceScreen +import com.android.settingslib.metadata.preferenceHierarchy +import com.android.settingslib.preference.PreferenceScreenCreator + +@ProvidePreferenceScreen +class BluetoothDashboardScreen : PreferenceScreenCreator { + override val key: String + get() = KEY + + override val title: Int + get() = R.string.bluetooth_settings_title + + override val icon: Int + get() = R.drawable.ic_settings_bluetooth + + override fun isFlagEnabled(context: Context) = Flags.catalystBluetoothSwitchbarScreen() + + override fun hasCompleteHierarchy() = false + + override fun fragmentClass() = BluetoothDashboardFragment::class.java + + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} + + companion object { + const val KEY = "bluetooth_switchbar_screen" + } +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt new file mode 100644 index 00000000000..39c029467b4 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/BluetoothDashboardScreenTest.kt @@ -0,0 +1,39 @@ +/* + * 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.connecteddevice + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.flags.Flags +import com.android.settingslib.preference.CatalystScreenTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class BluetoothDashboardScreenTest : CatalystScreenTestCase() { + override val preferenceScreenCreator = BluetoothDashboardScreen() + + override val flagName: String + get() = Flags.FLAG_CATALYST_BLUETOOTH_SWITCHBAR_SCREEN + + @Test + fun key() { + assertThat(preferenceScreenCreator.key).isEqualTo(BluetoothDashboardScreen.KEY) + } + + override fun migration() { + } +} From 7ae49a51eaf2732aa4a04e8fc307fe69f82c27b0 Mon Sep 17 00:00:00 2001 From: Fan Wu Date: Fri, 18 Oct 2024 09:15:49 +0000 Subject: [PATCH 08/11] Rename context variable and format code Bug: 372774754 Test: atest Flag: EXEMPT minor fix Change-Id: I6cb128afa54613b7c7dba97749f21976ef82a960 --- .../batteryusage/PowerUsageSummaryScreenTest.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt index ce045c66a96..993d39e81b0 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt @@ -38,8 +38,8 @@ class PowerUsageSummaryScreenTest : CatalystScreenTestCase() { private val mockResources = mock() - private val contextWrapper = - object : ContextWrapper(context) { + private val context = + object : ContextWrapper(appContext) { override fun getResources(): Resources = mockResources } @@ -52,26 +52,28 @@ class PowerUsageSummaryScreenTest : CatalystScreenTestCase() { fun isAvailable_configTrue_shouldReturnTrue() { mockResources.stub { on { getBoolean(anyInt()) } doReturn true } - assertThat(preferenceScreenCreator.isAvailable(contextWrapper)).isTrue() + assertThat(preferenceScreenCreator.isAvailable(context)).isTrue() } @Test fun isAvailable_configFalse_shouldReturnFalse() { mockResources.stub { on { getBoolean(anyInt()) } doReturn false } - assertThat(preferenceScreenCreator.isAvailable(contextWrapper)).isFalse() + assertThat(preferenceScreenCreator.isAvailable(context)).isFalse() } @Test @EnableFlags(Flags.FLAG_HOMEPAGE_REVAMP) fun getIcon_whenHomePageRevampFlagOn() { - assertThat(preferenceScreenCreator.getIcon(contextWrapper)).isEqualTo(R.drawable.ic_settings_battery_filled) + assertThat(preferenceScreenCreator.getIcon(context)) + .isEqualTo(R.drawable.ic_settings_battery_filled) } @Test @DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP) fun getIcon_whenHomePageRevampFlagOff() { - assertThat(preferenceScreenCreator.getIcon(contextWrapper)).isEqualTo(R.drawable.ic_settings_battery_white) + assertThat(preferenceScreenCreator.getIcon(context)) + .isEqualTo(R.drawable.ic_settings_battery_white) } override fun migration() {} From 99488fd10463d647aca3fd722c6a1d5b681b6c17 Mon Sep 17 00:00:00 2001 From: Jason Chiu Date: Thu, 17 Oct 2024 15:44:58 +0800 Subject: [PATCH 09/11] [Catalyst] Location screen migration - Add a flag for the migration - Add the skeleton of the screen Test: atest LocationScreenTest Bug: 368360458 Flag: com.android.settings.flags.catalyst_location_settings Change-Id: Id8b7d748210d1cacf99e3d61236706029b862289 --- aconfig/catalyst/location.aconfig | 9 +++ .../settings/location/LocationScreen.kt | 65 +++++++++++++++++ .../settings/location/LocationSettings.java | 7 ++ .../settings/location/LocationScreenTest.kt | 73 +++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 aconfig/catalyst/location.aconfig create mode 100644 src/com/android/settings/location/LocationScreen.kt create mode 100644 tests/robotests/src/com/android/settings/location/LocationScreenTest.kt diff --git a/aconfig/catalyst/location.aconfig b/aconfig/catalyst/location.aconfig new file mode 100644 index 00000000000..c656bf3ea58 --- /dev/null +++ b/aconfig/catalyst/location.aconfig @@ -0,0 +1,9 @@ +package: "com.android.settings.flags" +container: "system" + +flag { + name: "catalyst_location_settings" + namespace: "android_settings" + description: "Flag for Location" + bug: "323791114" +} diff --git a/src/com/android/settings/location/LocationScreen.kt b/src/com/android/settings/location/LocationScreen.kt new file mode 100644 index 00000000000..d45b762d102 --- /dev/null +++ b/src/com/android/settings/location/LocationScreen.kt @@ -0,0 +1,65 @@ +/* + * 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.location + +import android.content.Context +import android.location.LocationManager +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.metadata.PreferenceIconProvider +import com.android.settingslib.metadata.PreferenceSummaryProvider +import com.android.settingslib.metadata.ProvidePreferenceScreen +import com.android.settingslib.metadata.preferenceHierarchy +import com.android.settingslib.preference.PreferenceScreenCreator + +@ProvidePreferenceScreen +class LocationScreen : PreferenceScreenCreator, PreferenceSummaryProvider, PreferenceIconProvider { + override val key: String + get() = KEY + + override val title: Int + get() = R.string.location_settings_title + + override val keywords: Int + get() = R.string.keywords_location + + override fun getSummary(context: Context): CharSequence? { + var locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + return if (locationManager.isLocationEnabled) { + context.getString(R.string.location_settings_loading_app_permission_stats) + } else { + context.getString(R.string.location_settings_summary_location_off) + } + } + + override fun getIcon(context: Context) = + when { + Flags.homepageRevamp() -> R.drawable.ic_settings_location_filled + else -> R.drawable.ic_settings_location + } + + override fun isFlagEnabled(context: Context) = Flags.catalystLocationSettings() + + override fun hasCompleteHierarchy() = false + + override fun fragmentClass() = LocationSettings::class.java + + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} + + companion object { + const val KEY = "location_settings" + } +} diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index 87e8817808f..6a1d3d28dfb 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -29,6 +29,8 @@ import android.os.SystemProperties; import android.provider.Settings; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; @@ -185,4 +187,9 @@ public class LocationSettings extends DashboardFragment implements R.string.location_settings_tooltip_text_for_chrome)); } } + + @Override + public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) { + return LocationScreen.KEY; + } } diff --git a/tests/robotests/src/com/android/settings/location/LocationScreenTest.kt b/tests/robotests/src/com/android/settings/location/LocationScreenTest.kt new file mode 100644 index 00000000000..1d1696d2d1a --- /dev/null +++ b/tests/robotests/src/com/android/settings/location/LocationScreenTest.kt @@ -0,0 +1,73 @@ +/* + * 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.location + +import android.content.Context +import android.content.ContextWrapper +import android.location.LocationManager +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.R +import com.android.settings.flags.Flags +import com.android.settingslib.preference.CatalystScreenTestCase +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.stub + +@RunWith(AndroidJUnit4::class) +class LocationScreenTest : CatalystScreenTestCase() { + override val preferenceScreenCreator = LocationScreen() + + override val flagName: String + get() = Flags.FLAG_CATALYST_LOCATION_SETTINGS + + private val mockLocationManager = mock() + + private val context = + object : ContextWrapper(appContext) { + override fun getSystemService(name: String): Any = + when (name) { + Context.LOCATION_SERVICE -> mockLocationManager + else -> super.getSystemService(name) + } + } + + @Test + fun key() { + assertThat(preferenceScreenCreator.key).isEqualTo(LocationScreen.KEY) + } + + @Test + fun getSummary_enableLocation_shouldReturnLoading() { + mockLocationManager.stub { on { isLocationEnabled } doReturn true } + + assertThat(preferenceScreenCreator.getSummary(context)).isEqualTo( + context.getString(R.string.location_settings_loading_app_permission_stats)) + } + + @Test + fun getSummary_disableLocation_shouldReturnLocationOff() { + mockLocationManager.stub { on { isLocationEnabled } doReturn false } + + assertThat(preferenceScreenCreator.getSummary(context)).isEqualTo( + context.getString(R.string.location_settings_summary_location_off)) + } + + override fun migration() { + } +} From cc693e950f1160fd903686c562cd8e2d61d87ab7 Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Fri, 18 Oct 2024 19:55:14 +0800 Subject: [PATCH 10/11] Enable catalyst test for PowerUsageSummaryScreenTest Bug: 372774754 Flag: EXEMPT test Test: atest Change-Id: I5b35b0ff3416dde4781b7874f5bbc12f6b3f2475 --- .../PowerUsageSummaryScreenTest.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt index 993d39e81b0..80a6b2ef8f3 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryScreenTest.kt @@ -19,16 +19,22 @@ import android.content.ContextWrapper import android.content.res.Resources import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags +import androidx.fragment.app.testing.FragmentScenario +import androidx.preference.PreferenceFragmentCompat import com.android.settings.R import com.android.settings.flags.Flags +import com.android.settings.testutils.shadow.ShadowUtils import com.android.settingslib.preference.CatalystScreenTestCase import com.google.common.truth.Truth.assertThat +import org.junit.After import org.junit.Test import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.stub +import org.robolectric.annotation.Config +@Config(shadows = [ShadowUtils::class]) class PowerUsageSummaryScreenTest : CatalystScreenTestCase() { override val preferenceScreenCreator = PowerUsageSummaryScreen() @@ -43,6 +49,11 @@ class PowerUsageSummaryScreenTest : CatalystScreenTestCase() { override fun getResources(): Resources = mockResources } + @After + fun tearDown() { + ShadowUtils.reset() + } + @Test fun key() { assertThat(preferenceScreenCreator.key).isEqualTo(PowerUsageSummaryScreen.KEY) @@ -76,5 +87,15 @@ class PowerUsageSummaryScreenTest : CatalystScreenTestCase() { .isEqualTo(R.drawable.ic_settings_battery_white) } - override fun migration() {} + override fun migration() { + ShadowUtils.setIsBatteryPresent(false) + + super.migration() + } + + override fun launchFragmentScenario(fragmentClass: Class) = + FragmentScenario.launch( + fragmentClass, + themeResId = R.style.Theme_CollapsingToolbar_Settings, + ) } From 688cc9441388b9ce51c746a4de8f99faaa931f81 Mon Sep 17 00:00:00 2001 From: Chun-Ku Lin Date: Thu, 17 Oct 2024 19:16:51 +0000 Subject: [PATCH 11/11] Create an empty color and motion screen with Catalyst Infra Bug: 373451690 Test: atest ColorAndMotionScreenTest Flag: com.android.settings.flags.catalyst_accessibility_color_and_motion Change-Id: I4bfa5ec4d15bd745d691f586e49318b1b0a9bf6c --- aconfig/catalyst/accessibility.aconfig | 9 +++- .../accessibility/ColorAndMotionFragment.java | 9 ++++ .../accessibility/ColorAndMotionScreen.kt | 43 +++++++++++++++++++ tests/robotests/OWNERS | 3 +- .../accessibility/ColorAndMotionScreenTest.kt | 38 ++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/com/android/settings/accessibility/ColorAndMotionScreen.kt create mode 100644 tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt diff --git a/aconfig/catalyst/accessibility.aconfig b/aconfig/catalyst/accessibility.aconfig index 80a9d628de8..783706709a1 100644 --- a/aconfig/catalyst/accessibility.aconfig +++ b/aconfig/catalyst/accessibility.aconfig @@ -1,9 +1,16 @@ package: "com.android.settings.flags" container: "system" +flag { + name: "catalyst_accessibility_color_and_motion" + namespace: "android_settings" + description: "Migrate Color and motion screen to the Catalyst infrastructure" + bug: "323791114" +} + flag { name: "catalyst_text_reading_screen" namespace: "android_settings" description: "Flag for Display size and text" bug: "323791114" -} \ No newline at end of file +} diff --git a/src/com/android/settings/accessibility/ColorAndMotionFragment.java b/src/com/android/settings/accessibility/ColorAndMotionFragment.java index 4ea22260c79..7a7c21dd1af 100644 --- a/src/com/android/settings/accessibility/ColorAndMotionFragment.java +++ b/src/com/android/settings/accessibility/ColorAndMotionFragment.java @@ -17,12 +17,15 @@ package com.android.settings.accessibility; import android.app.settings.SettingsEnums; +import android.content.Context; import android.hardware.display.ColorDisplayManager; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; import android.view.accessibility.Flags; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.TwoStatePreference; @@ -148,6 +151,12 @@ public class ColorAndMotionFragment extends DashboardFragment { } } + @Nullable + @Override + public String getPreferenceScreenBindingKey(@NonNull Context context) { + return ColorAndMotionScreen.KEY; + } + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.accessibility_color_and_motion); } diff --git a/src/com/android/settings/accessibility/ColorAndMotionScreen.kt b/src/com/android/settings/accessibility/ColorAndMotionScreen.kt new file mode 100644 index 00000000000..20a71e31de4 --- /dev/null +++ b/src/com/android/settings/accessibility/ColorAndMotionScreen.kt @@ -0,0 +1,43 @@ +/* + * 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.accessibility + +import android.content.Context +import com.android.settings.flags.Flags +import com.android.settings.R +import com.android.settingslib.metadata.ProvidePreferenceScreen +import com.android.settingslib.metadata.preferenceHierarchy +import com.android.settingslib.preference.PreferenceScreenCreator + +@ProvidePreferenceScreen +class ColorAndMotionScreen : PreferenceScreenCreator { + override val key: String = KEY + override val title: Int = R.string.accessibility_color_and_motion_title + + override fun isFlagEnabled(context: Context) = Flags.catalystAccessibilityColorAndMotion() + + override fun hasCompleteHierarchy(): Boolean = false + + override fun fragmentClass() = ColorAndMotionFragment::class.java + + override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {} + + + companion object { + const val KEY = "accessibility_color_and_motion" + } +} \ No newline at end of file diff --git a/tests/robotests/OWNERS b/tests/robotests/OWNERS index 8a7a27ee4e2..e15af1c1e96 100644 --- a/tests/robotests/OWNERS +++ b/tests/robotests/OWNERS @@ -1,2 +1,3 @@ # We do not guard tests - everyone is welcomed to contribute to tests. -per-file *.java=* \ No newline at end of file +per-file *.java=* +per-file *.kt=* diff --git a/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt b/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt new file mode 100644 index 00000000000..6d7164eb2a0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ColorAndMotionScreenTest.kt @@ -0,0 +1,38 @@ +/* + * 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.accessibility + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.flags.Flags +import com.android.settingslib.preference.CatalystScreenTestCase +import com.android.settingslib.preference.PreferenceScreenCreator +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ColorAndMotionScreenTest : CatalystScreenTestCase() { + override val preferenceScreenCreator: PreferenceScreenCreator = ColorAndMotionScreen() + override val flagName: String = Flags.FLAG_CATALYST_ACCESSIBILITY_COLOR_AND_MOTION + + override fun migration() {} + + @Test + fun key() { + assertThat(preferenceScreenCreator.key).isEqualTo(ColorAndMotionScreen.KEY) + } +} \ No newline at end of file