Merge "A11y changes for notification controller of switch" into main
diff --git a/res/layout/clock_size_radio_button_group.xml b/res/layout/clock_size_radio_button_group.xml
index 5e8fcf5..4e7d1b4 100644
--- a/res/layout/clock_size_radio_button_group.xml
+++ b/res/layout/clock_size_radio_button_group.xml
@@ -32,7 +32,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
- android:clickable="false" />
+ android:clickable="false"
+ android:importantForAccessibility="no"/>
<LinearLayout
android:layout_width="match_parent"
@@ -71,7 +72,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
- android:clickable="false" />
+ android:clickable="false"
+ android:importantForAccessibility="no"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/src/com/android/customization/module/CustomizationInjector.kt b/src/com/android/customization/module/CustomizationInjector.kt
index 9b13119..4bb2b72 100644
--- a/src/com/android/customization/module/CustomizationInjector.kt
+++ b/src/com/android/customization/module/CustomizationInjector.kt
@@ -23,7 +23,6 @@
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.clock.utils.ClockDescriptionUtils
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
@@ -58,6 +57,8 @@
fun getClockCarouselViewModelFactory(
interactor: ClockPickerInteractor,
+ clockViewFactory: ClockViewFactory,
+ resources: Resources,
): ClockCarouselViewModel.Factory
fun getClockViewFactory(activity: ComponentActivity): ClockViewFactory
@@ -67,6 +68,4 @@
wallpaperColorsRepository: WallpaperColorsRepository,
clockViewFactory: ClockViewFactory,
): ClockSettingsViewModel.Factory
-
- fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils
}
diff --git a/src/com/android/customization/module/DefaultCustomizationSections.java b/src/com/android/customization/module/DefaultCustomizationSections.java
index a0aef2c..460a848 100644
--- a/src/com/android/customization/module/DefaultCustomizationSections.java
+++ b/src/com/android/customization/module/DefaultCustomizationSections.java
@@ -24,7 +24,6 @@
import com.android.customization.picker.notifications.ui.viewmodel.NotificationSectionViewModel;
import com.android.customization.picker.preview.ui.section.PreviewWithClockCarouselSectionController;
import com.android.customization.picker.preview.ui.section.PreviewWithThemeSectionController;
-import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor;
import com.android.customization.picker.quickaffordance.ui.section.KeyguardQuickAffordanceSectionController;
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel;
import com.android.customization.picker.settings.ui.section.MoreSettingsSectionController;
@@ -49,7 +48,6 @@
public final class DefaultCustomizationSections implements CustomizationSections {
private final ColorPickerViewModel.Factory mColorPickerViewModelFactory;
- private final KeyguardQuickAffordancePickerInteractor mKeyguardQuickAffordancePickerInteractor;
private final KeyguardQuickAffordancePickerViewModel.Factory
mKeyguardQuickAffordancePickerViewModelFactory;
private final NotificationSectionViewModel.Factory mNotificationSectionViewModelFactory;
@@ -63,7 +61,6 @@
public DefaultCustomizationSections(
ColorPickerViewModel.Factory colorPickerViewModelFactory,
- KeyguardQuickAffordancePickerInteractor keyguardQuickAffordancePickerInteractor,
KeyguardQuickAffordancePickerViewModel.Factory
keyguardQuickAffordancePickerViewModelFactory,
NotificationSectionViewModel.Factory notificationSectionViewModelFactory,
@@ -75,7 +72,6 @@
ThemedIconInteractor themedIconInteractor,
ColorPickerInteractor colorPickerInteractor) {
mColorPickerViewModelFactory = colorPickerViewModelFactory;
- mKeyguardQuickAffordancePickerInteractor = keyguardQuickAffordancePickerInteractor;
mKeyguardQuickAffordancePickerViewModelFactory =
keyguardQuickAffordancePickerViewModelFactory;
mNotificationSectionViewModelFactory = notificationSectionViewModelFactory;
@@ -166,7 +162,6 @@
sectionControllers.add(
new KeyguardQuickAffordanceSectionController(
sectionNavigationController,
- mKeyguardQuickAffordancePickerInteractor,
new ViewModelProvider(
activity,
mKeyguardQuickAffordancePickerViewModelFactory)
diff --git a/src/com/android/customization/module/ThemePickerInjector.kt b/src/com/android/customization/module/ThemePickerInjector.kt
index 21631eb..10bbd7a 100644
--- a/src/com/android/customization/module/ThemePickerInjector.kt
+++ b/src/com/android/customization/module/ThemePickerInjector.kt
@@ -47,8 +47,6 @@
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.clock.utils.ClockDescriptionUtils
-import com.android.customization.picker.clock.utils.ThemePickerClockDescriptionUtils
import com.android.customization.picker.color.data.repository.ColorPickerRepositoryImpl
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.domain.interactor.ColorPickerSnapshotRestorer
@@ -123,7 +121,6 @@
private var themedIconSnapshotRestorer: ThemedIconSnapshotRestorer? = null
private var themedIconInteractor: ThemedIconInteractor? = null
private var clockSettingsViewModelFactory: ClockSettingsViewModel.Factory? = null
- private var clockDescriptionUtils: ClockDescriptionUtils? = null
private var gridInteractor: GridInteractor? = null
private var gridSnapshotRestorer: GridSnapshotRestorer? = null
private var gridScreenViewModelFactory: GridScreenViewModel.Factory? = null
@@ -136,7 +133,6 @@
context = activity,
wallpaperColorsRepository = getWallpaperColorsRepository(),
),
- getKeyguardQuickAffordancePickerInteractor(activity),
getKeyguardQuickAffordancePickerViewModelFactory(activity),
NotificationSectionViewModel.Factory(
interactor = getNotificationsInteractor(activity),
@@ -144,6 +140,8 @@
getFlags(),
getClockCarouselViewModelFactory(
getClockPickerInteractor(activity.applicationContext),
+ getClockViewFactory(activity),
+ resources = activity.resources,
),
getClockViewFactory(activity),
getDarkModeSnapshotRestorer(activity),
@@ -256,7 +254,7 @@
val client = getKeyguardQuickAffordancePickerProviderClient(context)
val appContext = context.applicationContext
return KeyguardQuickAffordancePickerInteractor(
- KeyguardQuickAffordancePickerRepository(client, bgDispatcher),
+ KeyguardQuickAffordancePickerRepository(client),
client
) {
getKeyguardQuickAffordanceSnapshotRestorer(appContext)
@@ -364,11 +362,12 @@
override fun getClockCarouselViewModelFactory(
interactor: ClockPickerInteractor,
+ clockViewFactory: ClockViewFactory,
+ resources: Resources,
): ClockCarouselViewModel.Factory {
return clockCarouselViewModelFactory
- ?: ClockCarouselViewModel.Factory(interactor, bgDispatcher).also {
- clockCarouselViewModelFactory = it
- }
+ ?: ClockCarouselViewModel.Factory(interactor, bgDispatcher, clockViewFactory, resources)
+ .also { clockCarouselViewModelFactory = it }
}
override fun getClockViewFactory(activity: ComponentActivity): ClockViewFactory {
@@ -509,11 +508,6 @@
.also { clockSettingsViewModelFactory = it }
}
- override fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils {
- return clockDescriptionUtils
- ?: ThemePickerClockDescriptionUtils().also { clockDescriptionUtils = it }
- }
-
fun getGridScreenViewModelFactory(
context: Context,
): ViewModelProvider.Factory {
diff --git a/src/com/android/customization/module/logging/ThemesUserEventLogger.kt b/src/com/android/customization/module/logging/ThemesUserEventLogger.kt
index 1210343..087bef4 100644
--- a/src/com/android/customization/module/logging/ThemesUserEventLogger.kt
+++ b/src/com/android/customization/module/logging/ThemesUserEventLogger.kt
@@ -17,14 +17,13 @@
import android.stats.style.StyleEnums
import androidx.annotation.IntDef
-import com.android.customization.model.color.ColorOption
import com.android.customization.model.grid.GridOption
import com.android.wallpaper.module.logging.UserEventLogger
/** Extension of [UserEventLogger] that adds ThemePicker specific events. */
interface ThemesUserEventLogger : UserEventLogger {
- fun logThemeColorApplied(colorOption: ColorOption)
+ fun logThemeColorApplied(@ColorSource source: Int, variant: Int, seedColor: Int)
fun logGridApplied(grid: GridOption)
@@ -43,6 +42,15 @@
fun logDarkThemeApplied(useDarkTheme: Boolean)
@IntDef(
+ StyleEnums.COLOR_SOURCE_UNSPECIFIED,
+ StyleEnums.COLOR_SOURCE_HOME_SCREEN_WALLPAPER,
+ StyleEnums.COLOR_SOURCE_LOCK_SCREEN_WALLPAPER,
+ StyleEnums.COLOR_SOURCE_PRESET_COLOR,
+ )
+ @Retention(AnnotationRetention.SOURCE)
+ annotation class ColorSource
+
+ @IntDef(
StyleEnums.CLOCK_SIZE_UNSPECIFIED,
StyleEnums.CLOCK_SIZE_DYNAMIC,
StyleEnums.CLOCK_SIZE_SMALL,
diff --git a/src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt b/src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt
index 8eee709..78b5ca7 100644
--- a/src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt
+++ b/src/com/android/customization/module/logging/ThemesUserEventLoggerImpl.kt
@@ -19,9 +19,9 @@
import android.content.Intent
import android.stats.style.StyleEnums
import android.text.TextUtils
-import com.android.customization.model.color.ColorOption
import com.android.customization.model.grid.GridOption
import com.android.customization.module.logging.ThemesUserEventLogger.ClockSize
+import com.android.customization.module.logging.ThemesUserEventLogger.ColorSource
import com.android.systemui.shared.system.SysUiStatsLog
import com.android.wallpaper.module.WallpaperPersister.DEST_BOTH
import com.android.wallpaper.module.WallpaperPersister.DEST_HOME_SCREEN
@@ -115,10 +115,15 @@
SysUiStatsLogger(StyleEnums.WALLPAPER_EXPLORE).log()
}
- override fun logThemeColorApplied(colorOption: ColorOption) {
+ override fun logThemeColorApplied(
+ @ColorSource source: Int,
+ variant: Int,
+ seedColor: Int,
+ ) {
SysUiStatsLogger(StyleEnums.THEME_COLOR_APPLIED)
- .setColorPreference(colorOption.index)
- .setColorVariant(colorOption.style.ordinal + 1)
+ .setColorSource(source)
+ .setColorVariant(variant)
+ .setSeedColor(seedColor)
.log()
}
diff --git a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
index 004103f..8923b46 100644
--- a/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
+++ b/src/com/android/customization/picker/clock/data/repository/ClockPickerRepositoryImpl.kt
@@ -187,7 +187,6 @@
): ClockMetadataModel {
return ClockMetadataModel(
clockId = clockId,
- name = name,
isSelected = isSelected,
selectedColorId = selectedColorId,
colorToneProgress = colorTone,
diff --git a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
index 2522507..6e2bfb3 100644
--- a/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
+++ b/src/com/android/customization/picker/clock/shared/model/ClockMetadataModel.kt
@@ -23,7 +23,6 @@
/** Model for clock metadata. */
data class ClockMetadataModel(
val clockId: String,
- val name: String,
val isSelected: Boolean,
val selectedColorId: String?,
@IntRange(from = 0, to = 100) val colorToneProgress: Int,
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
index d4f501b..fbc8a96 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -384,7 +384,7 @@
) : Carousel.Adapter {
fun getContentDescription(index: Int, resources: Resources): String {
- return clocks[index].getContentDescription(resources)
+ return clocks[index].contentDescription
}
override fun count(): Int {
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt
index 9811426..e5ac953 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselItemViewModel.kt
@@ -15,20 +15,8 @@
*/
package com.android.customization.picker.clock.ui.viewmodel
-import android.content.res.Resources
-import com.android.customization.module.CustomizationInjector
-import com.android.wallpaper.R
-import com.android.wallpaper.module.InjectorProvider
-
-class ClockCarouselItemViewModel(val clockId: String, val isSelected: Boolean) {
-
- /** Description for accessibility purposes when a clock is selected. */
- fun getContentDescription(resources: Resources): String {
- val clockContent =
- (InjectorProvider.getInjector() as? CustomizationInjector)
- ?.getClockDescriptionUtils(resources)
- ?.getDescription(clockId)
- ?: ""
- return resources.getString(R.string.select_clock_action_description, clockContent)
- }
-}
+class ClockCarouselItemViewModel(
+ val clockId: String,
+ val isSelected: Boolean,
+ val contentDescription: String,
+)
diff --git a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
index 27c25a2..e4d5a8d 100644
--- a/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
+++ b/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModel.kt
@@ -15,12 +15,14 @@
*/
package com.android.customization.picker.clock.ui.viewmodel
+import android.content.res.Resources
import android.graphics.Color
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
import com.android.customization.picker.clock.shared.ClockSize
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.wallpaper.R
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -43,6 +45,8 @@
class ClockCarouselViewModel(
private val interactor: ClockPickerInteractor,
private val backgroundDispatcher: CoroutineDispatcher,
+ private val clockViewFactory: ClockViewFactory,
+ private val resources: Resources,
) : ViewModel() {
@OptIn(ExperimentalCoroutinesApi::class)
val allClocks: StateFlow<List<ClockCarouselItemViewModel>> =
@@ -50,7 +54,14 @@
.mapLatest { allClocks ->
// Delay to avoid the case that the full list of clocks is not initiated.
delay(CLOCKS_EVENT_UPDATE_DELAY_MILLIS)
- allClocks.map { ClockCarouselItemViewModel(it.clockId, it.isSelected) }
+ allClocks.map {
+ val contentDescription =
+ resources.getString(
+ R.string.select_clock_action_description,
+ clockViewFactory.getController(it.clockId).config.description
+ )
+ ClockCarouselItemViewModel(it.clockId, it.isSelected, contentDescription)
+ }
}
.stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
@@ -117,12 +128,16 @@
class Factory(
private val interactor: ClockPickerInteractor,
private val backgroundDispatcher: CoroutineDispatcher,
+ private val clockViewFactory: ClockViewFactory,
+ private val resources: Resources,
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return ClockCarouselViewModel(
interactor = interactor,
backgroundDispatcher = backgroundDispatcher,
+ clockViewFactory = clockViewFactory,
+ resources = resources,
)
as T
}
diff --git a/src/com/android/customization/picker/clock/utils/ClockDescriptionUtils.kt b/src/com/android/customization/picker/clock/utils/ClockDescriptionUtils.kt
deleted file mode 100644
index 28ea4a3..0000000
--- a/src/com/android/customization/picker/clock/utils/ClockDescriptionUtils.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2023 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.customization.picker.clock.utils
-
-/** Provides clock description for accessibility purposes. */
-interface ClockDescriptionUtils {
-
- /**
- * TODO (b/287507746) : Migrate the clock description to system UI or a shared library, instead
- * of preserving at the Wallpaper Picker side.
- */
- fun getDescription(clockId: String): String
-}
diff --git a/src/com/android/customization/picker/clock/utils/ThemePickerClockDescriptionUtils.kt b/src/com/android/customization/picker/clock/utils/ThemePickerClockDescriptionUtils.kt
deleted file mode 100644
index a04ebff..0000000
--- a/src/com/android/customization/picker/clock/utils/ThemePickerClockDescriptionUtils.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2023 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.customization.picker.clock.utils
-
-class ThemePickerClockDescriptionUtils : ClockDescriptionUtils {
- override fun getDescription(clockId: String): String {
- return ""
- }
-}
diff --git a/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt b/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt
index b17af80..10473a2 100644
--- a/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt
+++ b/src/com/android/customization/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepository.kt
@@ -21,11 +21,8 @@
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSelectionModel as SelectionModel
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSlotModel as SlotModel
import com.android.systemui.shared.customization.data.content.CustomizationProviderClient as Client
-import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
-import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.withContext
/**
* Abstracts access to application state related to functionality for selecting, picking, or setting
@@ -33,12 +30,7 @@
*/
class KeyguardQuickAffordancePickerRepository(
private val client: Client,
- private val backgroundDispatcher: CoroutineDispatcher,
) {
- /** Whether the feature is enabled. */
- val isFeatureEnabled: Flow<Boolean> =
- client.observeFlags().map { flags -> flags.isFeatureEnabled() }
-
/** List of slots available on the device. */
val slots: Flow<List<SlotModel>> =
client.observeSlots().map { slots -> slots.map { slot -> slot.toModel() } }
@@ -55,18 +47,6 @@
selections.map { selection -> selection.toModel() }
}
- suspend fun isFeatureEnabled(): Boolean {
- return withContext(backgroundDispatcher) { client.queryFlags().isFeatureEnabled() }
- }
-
- private fun List<Client.Flag>.isFeatureEnabled(): Boolean {
- return find { flag ->
- flag.name ==
- Contract.FlagsTable.FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED
- }
- ?.value == true
- }
-
private fun Client.Slot.toModel(): SlotModel {
return SlotModel(
id = id,
diff --git a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
index f154de6..6080194 100644
--- a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
+++ b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
@@ -78,9 +78,4 @@
): Drawable {
return client.getAffordanceIcon(iconResourceId)
}
-
- /** Returns `true` if the feature is enabled; `false` otherwise. */
- suspend fun isFeatureEnabled(): Boolean {
- return repository.isFeatureEnabled()
- }
}
diff --git a/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePickerBinder.kt b/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePickerBinder.kt
index 091f484..3ac52ad 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePickerBinder.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/binder/KeyguardQuickAffordancePickerBinder.kt
@@ -20,7 +20,11 @@
import android.app.Dialog
import android.content.Context
import android.view.View
+import android.view.ViewGroup
+import android.view.accessibility.AccessibilityEvent
import android.widget.ImageView
+import androidx.core.view.AccessibilityDelegateCompat
+import androidx.core.view.ViewCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
@@ -62,6 +66,26 @@
slotTabView.layoutManager =
LinearLayoutManager(view.context, RecyclerView.HORIZONTAL, false)
slotTabView.addItemDecoration(ItemSpacing(ItemSpacing.TAB_ITEM_SPACING_DP))
+
+ // Setting a custom accessibility delegate so that the default content descriptions
+ // for items in a list aren't announced (for left & right shortcuts). We populate
+ // the content description for these shortcuts later on with the right (expected)
+ // values.
+ val slotTabViewDelegate: AccessibilityDelegateCompat =
+ object : AccessibilityDelegateCompat() {
+ override fun onRequestSendAccessibilityEvent(
+ host: ViewGroup,
+ child: View,
+ event: AccessibilityEvent
+ ): Boolean {
+ if (event.eventType != AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ child.contentDescription = null
+ }
+ return super.onRequestSendAccessibilityEvent(host, child, event)
+ }
+ }
+
+ ViewCompat.setAccessibilityDelegate(slotTabView, slotTabViewDelegate)
val affordancesAdapter =
OptionItemAdapter(
layoutResourceId = R.layout.keyguard_quick_affordance,
diff --git a/src/com/android/customization/picker/quickaffordance/ui/section/KeyguardQuickAffordanceSectionController.kt b/src/com/android/customization/picker/quickaffordance/ui/section/KeyguardQuickAffordanceSectionController.kt
index e0beeff..0c7b250 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/section/KeyguardQuickAffordanceSectionController.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/section/KeyguardQuickAffordanceSectionController.kt
@@ -20,27 +20,23 @@
import android.content.Context
import android.view.LayoutInflater
import androidx.lifecycle.LifecycleOwner
-import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
import com.android.customization.picker.quickaffordance.ui.binder.KeyguardQuickAffordanceSectionViewBinder
import com.android.customization.picker.quickaffordance.ui.fragment.KeyguardQuickAffordancePickerFragment
import com.android.customization.picker.quickaffordance.ui.view.KeyguardQuickAffordanceSectionView
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel
import com.android.wallpaper.R
+import com.android.wallpaper.config.BaseFlags
import com.android.wallpaper.model.CustomizationSectionController
import com.android.wallpaper.model.CustomizationSectionController.CustomizationSectionNavigationController as NavigationController
-import kotlinx.coroutines.runBlocking
class KeyguardQuickAffordanceSectionController(
private val navigationController: NavigationController,
- private val interactor: KeyguardQuickAffordancePickerInteractor,
private val viewModel: KeyguardQuickAffordancePickerViewModel,
private val lifecycleOwner: LifecycleOwner,
) : CustomizationSectionController<KeyguardQuickAffordanceSectionView> {
- private val isFeatureEnabled: Boolean = runBlocking { interactor.isFeatureEnabled() }
-
override fun isAvailable(context: Context): Boolean {
- return isFeatureEnabled
+ return BaseFlags.get().isKeyguardQuickAffordanceEnabled(context)
}
override fun createView(context: Context): KeyguardQuickAffordanceSectionView {
diff --git a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
index 809d20e..d67ad1d 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
@@ -158,7 +158,8 @@
Icon.Loaded(
drawable =
getAffordanceIcon(affordanceModel.iconResourceId),
- contentDescription = null,
+ contentDescription =
+ Text.Loaded(getSlotContentDescription(slot.id)),
),
text = Text.Loaded(affordanceModel.name),
isSelected = MutableStateFlow(true) as StateFlow<Boolean>,
@@ -423,6 +424,18 @@
)
}
+ private fun getSlotContentDescription(slotId: String): String {
+ return applicationContext.getString(
+ when (slotId) {
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START ->
+ R.string.keyguard_slot_name_bottom_start
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END ->
+ R.string.keyguard_slot_name_bottom_end
+ else -> error("No accessibility label for slot with ID \"$slotId\"!")
+ }
+ )
+ }
+
private suspend fun getAffordanceIcon(@DrawableRes iconResourceId: Int): Drawable {
return quickAffordanceInteractor.getAffordanceIcon(iconResourceId)
}
diff --git a/tests/Android.bp b/tests/Android.bp
index 2ab3ebc..74dc6a1 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -59,7 +59,7 @@
"mockito-target-minus-junit4",
"junit",
"kotlinx_coroutines_test",
- "truth-prebuilt",
+ "truth",
],
libs: [
"android.test.runner",
diff --git a/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt b/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
index b2835f4..a8989c5 100644
--- a/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
+++ b/tests/common/src/com/android/customization/module/logging/TestThemesUserEventLogger.kt
@@ -15,14 +15,14 @@
*/
package com.android.customization.module.logging
-import com.android.customization.model.color.ColorOption
import com.android.customization.model.grid.GridOption
+import com.android.customization.module.logging.ThemesUserEventLogger.ColorSource
import com.android.wallpaper.module.logging.TestUserEventLogger
/** Test implementation of [ThemesUserEventLogger]. */
class TestThemesUserEventLogger : TestUserEventLogger(), ThemesUserEventLogger {
- override fun logThemeColorApplied(colorOption: ColorOption) {}
+ override fun logThemeColorApplied(@ColorSource source: Int, variant: Int, seedColor: Int) {}
override fun logGridApplied(grid: GridOption) {}
diff --git a/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt b/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
index 678fb90..e08209d 100644
--- a/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
+++ b/tests/common/src/com/android/customization/testing/TestCustomizationInjector.kt
@@ -12,7 +12,6 @@
import com.android.customization.picker.clock.ui.viewmodel.ClockCarouselViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSectionViewModel
import com.android.customization.picker.clock.ui.viewmodel.ClockSettingsViewModel
-import com.android.customization.picker.clock.utils.ClockDescriptionUtils
import com.android.customization.picker.color.domain.interactor.ColorPickerInteractor
import com.android.customization.picker.color.ui.viewmodel.ColorPickerViewModel
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
@@ -71,7 +70,9 @@
}
override fun getClockCarouselViewModelFactory(
- interactor: ClockPickerInteractor
+ interactor: ClockPickerInteractor,
+ clockViewFactory: ClockViewFactory,
+ resources: Resources,
): ClockCarouselViewModel.Factory {
throw UnsupportedOperationException("not implemented")
}
@@ -88,10 +89,6 @@
throw UnsupportedOperationException("not implemented")
}
- override fun getClockDescriptionUtils(resources: Resources): ClockDescriptionUtils {
- throw UnsupportedOperationException("not implemented")
- }
-
/////////////////
// TestInjector overrides
/////////////////
diff --git a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt
index 35dbadd..8a5d582 100644
--- a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/data/repository/KeyguardQuickAffordancePickerRepositoryTest.kt
@@ -19,21 +19,15 @@
import androidx.test.filters.SmallTest
import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
-import com.android.systemui.shared.customization.data.content.CustomizationProviderContract
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
-import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
-import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
-import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@@ -57,7 +51,6 @@
underTest =
KeyguardQuickAffordancePickerRepository(
client = client,
- backgroundDispatcher = coroutineDispatcher,
)
}
@@ -65,36 +58,4 @@
fun tearDown() {
Dispatchers.resetMain()
}
-
- @Test
- fun `isFeatureEnabled - enabled`() =
- testScope.runTest {
- client.setFlag(
- CustomizationProviderContract.FlagsTable
- .FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED,
- true,
- )
- val values = mutableListOf<Boolean>()
- val job = launch { underTest.isFeatureEnabled.toList(values) }
-
- assertThat(values.last()).isTrue()
-
- job.cancel()
- }
-
- @Test
- fun `isFeatureEnabled - not enabled`() =
- testScope.runTest {
- client.setFlag(
- CustomizationProviderContract.FlagsTable
- .FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED,
- false,
- )
- val values = mutableListOf<Boolean>()
- val job = launch { underTest.isFeatureEnabled.toList(values) }
-
- assertThat(values.last()).isFalse()
-
- job.cancel()
- }
}
diff --git a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
index efe9f64..11098ec 100644
--- a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
@@ -62,7 +62,6 @@
repository =
KeyguardQuickAffordancePickerRepository(
client = client,
- backgroundDispatcher = testDispatcher,
),
client = client,
snapshotRestorer = {
diff --git a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
index f71bfc7..43b872e 100644
--- a/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
@@ -86,7 +86,6 @@
repository =
KeyguardQuickAffordancePickerRepository(
client = client,
- backgroundDispatcher = testDispatcher,
),
client = client,
snapshotRestorer = {
diff --git a/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt b/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
index 95d7e35..4d8f32e 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/data/repository/FakeClockPickerRepository.kt
@@ -46,7 +46,6 @@
checkNotNull(selectedClock)
ClockMetadataModel(
clockId = selectedClock.clockId,
- name = selectedClock.name,
isSelected = true,
selectedColorId = selectedColor,
colorToneProgress = colorTone,
@@ -82,10 +81,10 @@
const val CLOCK_ID_3 = "clock3"
val fakeClocks =
listOf(
- ClockMetadataModel(CLOCK_ID_0, "clock0", true, null, 50, null),
- ClockMetadataModel(CLOCK_ID_1, "clock1", false, null, 50, null),
- ClockMetadataModel(CLOCK_ID_2, "clock2", false, null, 50, null),
- ClockMetadataModel(CLOCK_ID_3, "clock3", false, null, 50, null),
+ ClockMetadataModel(CLOCK_ID_0, true, null, 50, null),
+ ClockMetadataModel(CLOCK_ID_1, false, null, 50, null),
+ ClockMetadataModel(CLOCK_ID_2, false, null, 50, null),
+ ClockMetadataModel(CLOCK_ID_3, false, null, 50, null),
)
const val CLOCK_COLOR_ID = "RED"
const val CLOCK_COLOR_TONE_PROGRESS = 87
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
index 31999fb..c2b42c0 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/FakeClockViewFactory.kt
@@ -1,19 +1,44 @@
package com.android.customization.picker.clock.ui
+import android.content.res.Resources
import android.view.View
import androidx.lifecycle.LifecycleOwner
+import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
+import com.android.customization.picker.clock.ui.FakeClockViewFactory.Companion.fakeClocks
import com.android.customization.picker.clock.ui.view.ClockViewFactory
+import com.android.systemui.plugins.ClockConfig
import com.android.systemui.plugins.ClockController
+import com.android.systemui.plugins.ClockEvents
+import com.android.systemui.plugins.ClockFaceController
+import java.io.PrintWriter
/**
* This is a fake [ClockViewFactory]. Only implement the function if it's actually called in a test.
*/
-class FakeClockViewFactory : ClockViewFactory {
+class FakeClockViewFactory(
+ val clockControllers: MutableMap<String, ClockController> = fakeClocks.toMutableMap(),
+) : ClockViewFactory {
- override fun getController(clockId: String): ClockController {
- TODO("Not yet implemented")
+ class FakeClockController(
+ override var config: ClockConfig,
+ ) : ClockController {
+ override val smallClock: ClockFaceController
+ get() = TODO("Not yet implemented")
+
+ override val largeClock: ClockFaceController
+ get() = TODO("Not yet implemented")
+
+ override val events: ClockEvents
+ get() = TODO("Not yet implemented")
+
+ override fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) =
+ TODO("Not yet implemented")
+
+ override fun dump(pw: PrintWriter) = TODO("Not yet implemented")
}
+ override fun getController(clockId: String): ClockController = clockControllers.get(clockId)!!
+
override fun getLargeView(clockId: String): View {
TODO("Not yet implemented")
}
@@ -49,4 +74,20 @@
override fun unregisterTimeTicker(owner: LifecycleOwner) {
TODO("Not yet implemented")
}
+
+ companion object {
+ val fakeClocks =
+ FakeClockPickerRepository.fakeClocks
+ .map { clock ->
+ clock.clockId to
+ FakeClockController(
+ ClockConfig(
+ id = clock.clockId,
+ name = "Name: ${clock.clockId}",
+ description = "Desc: ${clock.clockId}"
+ )
+ )
+ }
+ .toMap()
+ }
}
diff --git a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
index ca6f8c7..813d888 100644
--- a/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
+++ b/tests/robotests/src/com/android/customization/picker/clock/ui/viewmodel/ClockCarouselViewModelTest.kt
@@ -16,11 +16,14 @@
package com.android.customization.picker.clock.ui.viewmodel
import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
import com.android.customization.picker.clock.data.repository.ClockPickerRepository
import com.android.customization.picker.clock.data.repository.FakeClockPickerRepository
import com.android.customization.picker.clock.domain.interactor.ClockPickerInteractor
import com.android.customization.picker.clock.domain.interactor.ClockPickerSnapshotRestorer
import com.android.customization.picker.clock.shared.model.ClockMetadataModel
+import com.android.customization.picker.clock.ui.FakeClockViewFactory
+import com.android.customization.picker.clock.ui.view.ClockViewFactory
import com.android.wallpaper.testing.FakeSnapshotStore
import com.android.wallpaper.testing.collectLastValue
import com.google.common.truth.Truth.assertThat
@@ -48,8 +51,7 @@
FakeClockPickerRepository(
listOf(
ClockMetadataModel(
- clockId = "clock0",
- name = "clock0",
+ clockId = FakeClockPickerRepository.CLOCK_ID_0,
isSelected = true,
selectedColorId = null,
colorToneProgress = ClockMetadataModel.DEFAULT_COLOR_TONE_PROGRESS,
@@ -58,13 +60,16 @@
)
)
}
+
private lateinit var testDispatcher: CoroutineDispatcher
private lateinit var underTest: ClockCarouselViewModel
private lateinit var interactor: ClockPickerInteractor
+ private lateinit var clockViewFactory: ClockViewFactory
@Before
fun setUp() {
testDispatcher = StandardTestDispatcher()
+ clockViewFactory = FakeClockViewFactory()
Dispatchers.setMain(testDispatcher)
}
@@ -78,7 +83,9 @@
underTest =
ClockCarouselViewModel(
getClockPickerInteractor(repositoryWithMultipleClocks),
- testDispatcher
+ backgroundDispatcher = testDispatcher,
+ clockViewFactory = clockViewFactory,
+ resources = InstrumentationRegistry.getInstrumentation().targetContext.resources,
)
val observedSelectedIndex = collectLastValue(underTest.selectedIndex)
advanceTimeBy(ClockCarouselViewModel.CLOCKS_EVENT_UPDATE_DELAY_MILLIS)