Snap for 12524026 from abdb92453f to 25Q1-release

Change-Id: I65e614281f39a77f64273c37461a5d9aaf336718
This commit is contained in:
Android Build Coastguard Worker
2024-10-19 01:27:57 +00:00
36 changed files with 771 additions and 47 deletions

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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"
}
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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<Boolean>
fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean>
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<Boolean> =
override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> =
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)
}
}

View File

@@ -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<PointF> =
combine(
_guidedEnrollment,
accessibilityInteractor.isAccessibilityEnabled,
accessibilityInteractor.isEnabledFlow(MainScope()),
isGuidedEnrollment,
) { point, accessibilityEnabled, guidedEnrollmentEnabled ->
if (accessibilityEnabled || !guidedEnrollmentEnabled) {

View File

@@ -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(),

View File

@@ -84,7 +84,7 @@ class FingerprintEnrollFindSensorViewModel(
/** Represents the stream of showing udfps lottie and whether accessibility is enabled. */
val udfpsLottieInfo: Flow<Boolean> =
_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(),

View File

@@ -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;
}
}

View File

@@ -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"
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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;
}
}

View File

@@ -92,4 +92,6 @@ class MobileNetworkListFragment : DashboardFragment() {
simRepositoryFactory(context).canEnterMobileNetworkPage()
}
}
override fun getPreferenceScreenBindingKey(context: Context) = MobileNetworkListScreen.KEY
}

View File

@@ -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"
}
}

View File

@@ -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;
}
}

View File

@@ -1,2 +1,3 @@
# We do not guard tests - everyone is welcomed to contribute to tests.
per-file *.java=*
per-file *.java=*
per-file *.kt=*

View File

@@ -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)
}
}

View File

@@ -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<EditShortcutsPreferenceFragment> createFragScenario(
boolean isInSuw, String target) {
return createFragScenario(isInSuw, List.of(target), null);
}
private FragmentScenario<EditShortcutsPreferenceFragment> createFragScenario(
boolean isInSuw, List<String> 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<EditShortcutsPreferenceFragment> 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);

View File

@@ -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() {
}
}

View File

@@ -0,0 +1,101 @@
/*
* 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 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()
override val flagName: String
get() = Flags.FLAG_CATALYST_POWER_USAGE_SUMMARY_SCREEN
private val mockResources = mock<Resources>()
private val context =
object : ContextWrapper(appContext) {
override fun getResources(): Resources = mockResources
}
@After
fun tearDown() {
ShadowUtils.reset()
}
@Test
fun key() {
assertThat(preferenceScreenCreator.key).isEqualTo(PowerUsageSummaryScreen.KEY)
}
@Test
fun isAvailable_configTrue_shouldReturnTrue() {
mockResources.stub { on { getBoolean(anyInt()) } doReturn true }
assertThat(preferenceScreenCreator.isAvailable(context)).isTrue()
}
@Test
fun isAvailable_configFalse_shouldReturnFalse() {
mockResources.stub { on { getBoolean(anyInt()) } doReturn false }
assertThat(preferenceScreenCreator.isAvailable(context)).isFalse()
}
@Test
@EnableFlags(Flags.FLAG_HOMEPAGE_REVAMP)
fun getIcon_whenHomePageRevampFlagOn() {
assertThat(preferenceScreenCreator.getIcon(context))
.isEqualTo(R.drawable.ic_settings_battery_filled)
}
@Test
@DisableFlags(Flags.FLAG_HOMEPAGE_REVAMP)
fun getIcon_whenHomePageRevampFlagOff() {
assertThat(preferenceScreenCreator.getIcon(context))
.isEqualTo(R.drawable.ic_settings_battery_white)
}
override fun migration() {
ShadowUtils.setIsBatteryPresent(false)
super.migration()
}
override fun launchFragmentScenario(fragmentClass: Class<PreferenceFragmentCompat>) =
FragmentScenario.launch(
fragmentClass,
themeResId = R.style.Theme_CollapsingToolbar_Settings,
)
}

View File

@@ -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<LocationManager>()
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() {
}
}

View File

@@ -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)
}
}

View File

@@ -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<AccessibilityShortcutInfo> installedAccessibilityShortcutList) {
mInstalledAccessibilityShortcutList = installedAccessibilityShortcutList;
}
/**
* Implements the hidden method
* {@link AccessibilityManager#getAccessibilityShortcutTargets}.
*/
@Implementation
public List<String> getAccessibilityShortcutTargets(
@ShortcutConstants.UserShortcutType int shortcutType) {
return List.of();
}
}

View File

@@ -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<Boolean> = flowOf(true)
override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> = flowOf(true)
override val isEnabled: Boolean
get() = true
override fun announce(clazz: Class<*>, announcement: CharSequence?) {}
}
var foldStateInteractor =

View File

@@ -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<Boolean> = flowOf(false)
override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> = flowOf(true)
override val isEnabled: Boolean
get() = true
override fun announce(clazz: Class<*>, announcement: CharSequence?) {}
}
foldStateInteractor =
object : FoldStateInteractor {