Wallpaper picker reset support (2/3).
Creates system to support reverting changes made to the home or lock
screen via the wallpaper picker.
The system itself is in WPP2/.../picker/undo.
Bug: 262924056
Test: included unit tests and updated existing ones
Test: manually verified that I can reset changes made to quick
affordances both from the quick affordance screen or the main WPP screen
Change-Id: Id84b27db4264b14436bd73fe6adaac570cffbf37
diff --git a/src/com/android/customization/module/ThemePickerInjector.java b/src/com/android/customization/module/ThemePickerInjector.java
index 263b44e..93c4d5f 100644
--- a/src/com/android/customization/module/ThemePickerInjector.java
+++ b/src/com/android/customization/module/ThemePickerInjector.java
@@ -35,6 +35,7 @@
import com.android.customization.model.theme.ThemeManager;
import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository;
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor;
+import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer;
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel;
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient;
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClientImpl;
@@ -49,6 +50,9 @@
import com.android.wallpaper.picker.ImagePreviewFragment;
import com.android.wallpaper.picker.LivePreviewFragment;
import com.android.wallpaper.picker.PreviewFragment;
+import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer;
+
+import java.util.Map;
import kotlinx.coroutines.Dispatchers;
@@ -66,6 +70,7 @@
private KeyguardQuickAffordanceProviderClient mKeyguardQuickAffordanceProviderClient;
private FragmentFactory mFragmentFactory;
private BaseFlags mFlags;
+ private KeyguardQuickAffordanceSnapshotRestorer mKeyguardQuickAffordanceSnapshotRestorer;
@Override
public CustomizationSections getCustomizationSections(Activity activity) {
@@ -149,7 +154,8 @@
getKeyguardQuickAffordancePickerProviderClient(context);
mKeyguardQuickAffordancePickerInteractor = new KeyguardQuickAffordancePickerInteractor(
new KeyguardQuickAffordancePickerRepository(client, Dispatchers.getIO()),
- client);
+ client,
+ () -> getKeyguardQuickAffordanceSnapshotRestorer(context));
}
return mKeyguardQuickAffordancePickerInteractor;
}
@@ -163,7 +169,8 @@
mKeyguardQuickAffordancePickerViewModelFactory =
new KeyguardQuickAffordancePickerViewModel.Factory(
context,
- getKeyguardQuickAffordancePickerInteractor(context));
+ getKeyguardQuickAffordancePickerInteractor(context),
+ getUndoInteractor(context));
}
return mKeyguardQuickAffordancePickerViewModelFactory;
}
@@ -176,8 +183,26 @@
return mFragmentFactory;
}
+ @Override
+ public BaseFlags getFlags() {
+ if (mFlags == null) {
+ mFlags = new BaseFlags() {};
+ }
+
+ return mFlags;
+ }
+
+ @Override
+ public Map<Integer, SnapshotRestorer> getSnapshotRestorers(Context context) {
+ final Map<Integer, SnapshotRestorer> restorers = super.getSnapshotRestorers(context);
+ restorers.put(
+ KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER,
+ getKeyguardQuickAffordanceSnapshotRestorer(context));
+ return restorers;
+ }
+
/** Returns the {@link KeyguardQuickAffordanceProviderClient}. */
- public KeyguardQuickAffordanceProviderClient getKeyguardQuickAffordancePickerProviderClient(
+ protected KeyguardQuickAffordanceProviderClient getKeyguardQuickAffordancePickerProviderClient(
Context context) {
if (mKeyguardQuickAffordanceProviderClient == null) {
mKeyguardQuickAffordanceProviderClient =
@@ -187,12 +212,24 @@
return mKeyguardQuickAffordanceProviderClient;
}
- @Override
- public BaseFlags getFlags() {
- if (mFlags == null) {
- mFlags = new BaseFlags() {};
+ protected KeyguardQuickAffordanceSnapshotRestorer getKeyguardQuickAffordanceSnapshotRestorer(
+ Context context) {
+ if (mKeyguardQuickAffordanceSnapshotRestorer == null) {
+ mKeyguardQuickAffordanceSnapshotRestorer = new KeyguardQuickAffordanceSnapshotRestorer(
+ getKeyguardQuickAffordancePickerInteractor(context),
+ getKeyguardQuickAffordancePickerProviderClient(context));
}
- return mFlags;
+ return mKeyguardQuickAffordanceSnapshotRestorer;
}
+
+ private static final int KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER =
+ WallpaperPicker2Injector.MIN_SNAPSHOT_RESTORER_KEY;
+
+ /**
+ * When this injector is overridden, this is the minimal value that should be used by restorers
+ * returns in {@link #getSnapshotRestorers(Context)}.
+ */
+ protected static final int MIN_SNAPSHOT_RESTORER_KEY =
+ KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER + 1;
}
diff --git a/src/com/android/customization/picker/clock/domain/interactor/ClocksSnapshotRestorer.kt b/src/com/android/customization/picker/clock/domain/interactor/ClocksSnapshotRestorer.kt
new file mode 100644
index 0000000..63b4a9b
--- /dev/null
+++ b/src/com/android/customization/picker/clock/domain/interactor/ClocksSnapshotRestorer.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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.domain.interactor
+
+import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
+import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
+
+/** Handles state restoration for clocks. */
+class ClocksSnapshotRestorer : SnapshotRestorer {
+ override suspend fun setUpSnapshotRestorer(
+ updater: (RestorableSnapshot) -> Unit,
+ ): RestorableSnapshot {
+ // TODO(b/262924055): implement as part of the clock settings screen.
+ return RestorableSnapshot(mapOf())
+ }
+
+ override suspend fun restoreToSnapshot(snapshot: RestorableSnapshot) {
+ // TODO(b/262924055): implement as part of the clock settings screen.
+ }
+}
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 87cedf5..c2d2e5a 100644
--- a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
+++ b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractor.kt
@@ -24,6 +24,7 @@
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.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient as Client
+import javax.inject.Provider
import kotlinx.coroutines.flow.Flow
/**
@@ -33,10 +34,8 @@
class KeyguardQuickAffordancePickerInteractor(
private val repository: KeyguardQuickAffordancePickerRepository,
private val client: Client,
+ private val snapshotRestorer: Provider<KeyguardQuickAffordanceSnapshotRestorer>,
) {
- /** Whether the feature is enabled. */
- val isFeatureEnabled: Flow<Boolean> = repository.isFeatureEnabled
-
/** List of slots available on the device. */
val slots: Flow<List<SlotModel>> = repository.slots
@@ -60,6 +59,8 @@
slotId = slotId,
affordanceId = affordanceId,
)
+
+ snapshotRestorer.get().storeSnapshot()
}
/** Unselects an affordance with the given ID from the slot with the given ID. */
@@ -68,6 +69,8 @@
slotId = slotId,
affordanceId = affordanceId,
)
+
+ snapshotRestorer.get().storeSnapshot()
}
/** Unselects all affordances from the slot with the given ID. */
@@ -75,6 +78,8 @@
client.deleteAllSelections(
slotId = slotId,
)
+
+ snapshotRestorer.get().storeSnapshot()
}
/** Returns a [Drawable] for the given resource ID, from the system UI package. */
diff --git a/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt
new file mode 100644
index 0000000..f0544a1
--- /dev/null
+++ b/src/com/android/customization/picker/quickaffordance/domain/interactor/KeyguardQuickAffordanceSnapshotRestorer.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 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.quickaffordance.domain.interactor
+
+import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient
+import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer
+import com.android.wallpaper.picker.undo.shared.model.RestorableSnapshot
+
+/** Handles state restoration for the quick affordances system. */
+class KeyguardQuickAffordanceSnapshotRestorer(
+ private val interactor: KeyguardQuickAffordancePickerInteractor,
+ private val client: KeyguardQuickAffordanceProviderClient,
+) : SnapshotRestorer {
+
+ private lateinit var snapshotUpdater: (RestorableSnapshot) -> Unit
+
+ suspend fun storeSnapshot() {
+ snapshotUpdater(snapshot())
+ }
+
+ override suspend fun setUpSnapshotRestorer(
+ updater: (RestorableSnapshot) -> Unit,
+ ): RestorableSnapshot {
+ snapshotUpdater = updater
+ return snapshot()
+ }
+
+ override suspend fun restoreToSnapshot(snapshot: RestorableSnapshot) {
+ val selections: List<Pair<String, String>> =
+ checkNotNull(snapshot.args[KEY_SELECTIONS]).split(SELECTION_SEPARATOR).map { selection
+ ->
+ val (slotId, affordanceId) = selection.split(SLOT_AFFORDANCE_SEPARATOR)
+ slotId to affordanceId
+ }
+
+ selections.forEach { (slotId, affordanceId) ->
+ interactor.select(
+ slotId,
+ affordanceId,
+ )
+ }
+ }
+
+ private suspend fun snapshot(): RestorableSnapshot {
+ return RestorableSnapshot(
+ mapOf(
+ KEY_SELECTIONS to
+ client.querySelections().joinToString(SELECTION_SEPARATOR) { selection ->
+ "${selection.slotId}${SLOT_AFFORDANCE_SEPARATOR}${selection.affordanceId}"
+ }
+ )
+ )
+ }
+
+ companion object {
+ private const val KEY_SELECTIONS = "selections"
+ private const val SLOT_AFFORDANCE_SEPARATOR = "->"
+ private const val SELECTION_SEPARATOR = "|"
+ }
+}
diff --git a/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt b/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt
index 251cdca..f37b246 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/fragment/KeyguardQuickAffordancePickerFragment.kt
@@ -30,6 +30,7 @@
import com.android.wallpaper.R
import com.android.wallpaper.module.InjectorProvider
import com.android.wallpaper.picker.AppbarFragment
+import com.android.wallpaper.picker.undo.ui.binder.RevertToolbarButtonBinder
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.suspendCancellableCoroutine
@@ -63,6 +64,13 @@
injector.getKeyguardQuickAffordancePickerViewModelFactory(requireContext()),
)
.get()
+ setUpToolbarMenu(R.menu.undoable_customization_menu)
+ RevertToolbarButtonBinder.bind(
+ view = view.requireViewById(toolbarId),
+ viewModel = viewModel.undo,
+ lifecycleOwner = this,
+ )
+
KeyguardQuickAffordancePreviewBinder.bind(
activity = requireActivity(),
previewView = view.requireViewById(R.id.preview),
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 774ff22..fa43edd 100644
--- a/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
+++ b/src/com/android/customization/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModel.kt
@@ -29,6 +29,8 @@
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
import com.android.wallpaper.R
+import com.android.wallpaper.picker.undo.domain.interactor.UndoInteractor
+import com.android.wallpaper.picker.undo.ui.viewmodel.UndoViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -43,20 +45,26 @@
class KeyguardQuickAffordancePickerViewModel
private constructor(
context: Context,
- private val interactor: KeyguardQuickAffordancePickerInteractor,
+ private val quickAffordanceInteractor: KeyguardQuickAffordancePickerInteractor,
+ undoInteractor: UndoInteractor,
) : ViewModel() {
@SuppressLint("StaticFieldLeak") private val applicationContext = context.applicationContext
+ val undo: UndoViewModel =
+ UndoViewModel(
+ interactor = undoInteractor,
+ )
+
private val _selectedSlotId = MutableStateFlow<String?>(null)
val selectedSlotId: StateFlow<String?> = _selectedSlotId.asStateFlow()
/** View-models for each slot, keyed by slot ID. */
val slots: Flow<Map<String, KeyguardQuickAffordanceSlotViewModel>> =
combine(
- interactor.slots,
- interactor.affordances,
- interactor.selections,
+ quickAffordanceInteractor.slots,
+ quickAffordanceInteractor.affordances,
+ quickAffordanceInteractor.selections,
selectedSlotId,
) { slots, affordances, selections, selectedSlotIdOrNull ->
slots
@@ -102,9 +110,9 @@
/** The list of all available quick affordances for the selected slot. */
val quickAffordances: Flow<List<KeyguardQuickAffordanceViewModel>> =
combine(
- interactor.slots,
- interactor.affordances,
- interactor.selections,
+ quickAffordanceInteractor.slots,
+ quickAffordanceInteractor.affordances,
+ quickAffordanceInteractor.selections,
selectedSlotId,
) { slots, affordances, selections, selectedSlotIdOrNull ->
val selectedSlot =
@@ -131,12 +139,12 @@
{
viewModelScope.launch {
if (isSelected) {
- interactor.unselect(
+ quickAffordanceInteractor.unselect(
slotId = selectedSlot.id,
affordanceId = affordance.id,
)
} else {
- interactor.select(
+ quickAffordanceInteractor.select(
slotId = selectedSlot.id,
affordanceId = affordance.id,
)
@@ -229,7 +237,9 @@
return KeyguardQuickAffordanceViewModel.none(
context = applicationContext,
isSelected = isSelected,
- onSelected = { viewModelScope.launch { interactor.unselectAll(slotId) } },
+ onSelected = {
+ viewModelScope.launch { quickAffordanceInteractor.unselectAll(slotId) }
+ },
)
}
@@ -246,7 +256,7 @@
}
private suspend fun getAffordanceIcon(@DrawableRes iconResourceId: Int): Drawable {
- return interactor.getAffordanceIcon(iconResourceId)
+ return quickAffordanceInteractor.getAffordanceIcon(iconResourceId)
}
private fun String?.toIntent(): Intent? {
@@ -318,13 +328,15 @@
class Factory(
private val context: Context,
- private val interactor: KeyguardQuickAffordancePickerInteractor,
+ private val quickAffordanceInteractor: KeyguardQuickAffordancePickerInteractor,
+ private val undoInteractor: UndoInteractor,
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return KeyguardQuickAffordancePickerViewModel(
context = context,
- interactor = interactor,
+ quickAffordanceInteractor = quickAffordanceInteractor,
+ undoInteractor = undoInteractor,
)
as T
}
diff --git a/tests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt b/tests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
index d8a136d..87f47fa 100644
--- a/tests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
+++ b/tests/src/com/android/customization/model/picker/quickaffordance/domain/interactor/KeyguardQuickAffordancePickerInteractorTest.kt
@@ -20,16 +20,17 @@
import androidx.test.filters.SmallTest
import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
+import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer
import com.android.customization.picker.quickaffordance.shared.model.KeyguardQuickAffordancePickerSelectionModel
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.shared.quickaffordance.data.content.FakeKeyguardQuickAffordanceProviderClient
+import com.android.wallpaper.testing.collectLastValue
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.runBlocking
+import kotlinx.coroutines.test.StandardTestDispatcher
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
@@ -51,18 +52,25 @@
@Before
fun setUp() {
- val coroutineDispatcher = UnconfinedTestDispatcher()
- testScope = TestScope(coroutineDispatcher)
- Dispatchers.setMain(coroutineDispatcher)
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
+ Dispatchers.setMain(testDispatcher)
client = FakeKeyguardQuickAffordanceProviderClient()
underTest =
KeyguardQuickAffordancePickerInteractor(
repository =
KeyguardQuickAffordancePickerRepository(
client = client,
- backgroundDispatcher = coroutineDispatcher,
+ backgroundDispatcher = testDispatcher,
),
client = client,
+ snapshotRestorer = {
+ KeyguardQuickAffordanceSnapshotRestorer(
+ interactor = underTest,
+ client = client,
+ )
+ .apply { runBlocking { setUpSnapshotRestorer {} } }
+ },
)
}
@@ -74,14 +82,13 @@
@Test
fun select() =
testScope.runTest {
- val selections = mutableListOf<List<KeyguardQuickAffordancePickerSelectionModel>>()
- val job = launch { underTest.selections.toList(selections) }
+ val selections = collectLastValue(underTest.selections)
underTest.select(
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
)
- assertThat(selections.last())
+ assertThat(selections())
.isEqualTo(
listOf(
KeyguardQuickAffordancePickerSelectionModel(
@@ -95,7 +102,7 @@
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2,
)
- assertThat(selections.last())
+ assertThat(selections())
.isEqualTo(
listOf(
KeyguardQuickAffordancePickerSelectionModel(
@@ -104,15 +111,12 @@
),
)
)
-
- job.cancel()
}
@Test
fun unselect() =
testScope.runTest {
- val selections = mutableListOf<List<KeyguardQuickAffordancePickerSelectionModel>>()
- val job = launch { underTest.selections.toList(selections) }
+ val selections = collectLastValue(underTest.selections)
underTest.select(
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
@@ -123,17 +127,14 @@
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
)
- assertThat(selections.last()).isEmpty()
-
- job.cancel()
+ assertThat(selections()).isEmpty()
}
@Test
fun unselectAll() =
testScope.runTest {
client.setSlotCapacity(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END, 3)
- val selections = mutableListOf<List<KeyguardQuickAffordancePickerSelectionModel>>()
- val job = launch { underTest.selections.toList(selections) }
+ val selections = collectLastValue(underTest.selections)
underTest.select(
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
@@ -151,8 +152,6 @@
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
)
- assertThat(selections.last()).isEmpty()
-
- job.cancel()
+ assertThat(selections()).isEmpty()
}
}
diff --git a/tests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt b/tests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
index d446e1b..3ec893a 100644
--- a/tests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
+++ b/tests/src/com/android/customization/model/picker/quickaffordance/ui/viewmodel/KeyguardQuickAffordancePickerViewModelTest.kt
@@ -22,6 +22,7 @@
import androidx.test.platform.app.InstrumentationRegistry
import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor
+import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceSlotViewModel
import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordanceSummaryViewModel
@@ -29,14 +30,17 @@
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.shared.quickaffordance.data.content.FakeKeyguardQuickAffordanceProviderClient
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient
+import com.android.wallpaper.picker.undo.data.repository.UndoRepository
+import com.android.wallpaper.picker.undo.domain.interactor.UndoInteractor
+import com.android.wallpaper.testing.FAKE_RESTORERS
+import com.android.wallpaper.testing.collectLastValue
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.toList
-import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.StandardTestDispatcher
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
@@ -56,27 +60,43 @@
private lateinit var context: Context
private lateinit var testScope: TestScope
private lateinit var client: FakeKeyguardQuickAffordanceProviderClient
+ private lateinit var quickAffordanceInteractor: KeyguardQuickAffordancePickerInteractor
@Before
fun setUp() {
context = InstrumentationRegistry.getInstrumentation().targetContext
- val coroutineDispatcher = UnconfinedTestDispatcher()
- testScope = TestScope(coroutineDispatcher)
- Dispatchers.setMain(coroutineDispatcher)
+ val testDispatcher = StandardTestDispatcher()
+ testScope = TestScope(testDispatcher)
+ Dispatchers.setMain(testDispatcher)
client = FakeKeyguardQuickAffordanceProviderClient()
+ quickAffordanceInteractor =
+ KeyguardQuickAffordancePickerInteractor(
+ repository =
+ KeyguardQuickAffordancePickerRepository(
+ client = client,
+ backgroundDispatcher = testDispatcher,
+ ),
+ client = client,
+ snapshotRestorer = {
+ KeyguardQuickAffordanceSnapshotRestorer(
+ interactor = quickAffordanceInteractor,
+ client = client,
+ )
+ .apply { runBlocking { setUpSnapshotRestorer {} } }
+ },
+ )
+ val undoInteractor =
+ UndoInteractor(
+ scope = testScope.backgroundScope,
+ repository = UndoRepository(),
+ restorerByOwnerId = FAKE_RESTORERS,
+ )
underTest =
KeyguardQuickAffordancePickerViewModel.Factory(
context = context,
- interactor =
- KeyguardQuickAffordancePickerInteractor(
- repository =
- KeyguardQuickAffordancePickerRepository(
- client = client,
- backgroundDispatcher = coroutineDispatcher,
- ),
- client = client,
- ),
+ quickAffordanceInteractor = quickAffordanceInteractor,
+ undoInteractor = undoInteractor,
)
.create(KeyguardQuickAffordancePickerViewModel::class.java)
}
@@ -89,23 +109,18 @@
@Test
fun `Select an affordance for each side`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
-
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- }
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
// Initially, the first slot is selected with the "none" affordance selected.
assertPickerUiState(
- slots = slots.last(),
- affordances = quickAffordances.last(),
+ slots = slots(),
+ affordances = quickAffordances(),
selectedSlotText = "Left button",
selectedAffordanceText = "None",
)
assertPreviewUiState(
- slots = slots.last(),
+ slots = slots(),
expectedAffordanceNameBySlotId =
mapOf(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to null,
@@ -114,15 +129,15 @@
)
// Select "affordance 1" for the first slot.
- quickAffordances.last()[1].onClicked?.invoke()
+ quickAffordances()?.get(1)?.onClicked?.invoke()
assertPickerUiState(
- slots = slots.last(),
- affordances = quickAffordances.last(),
+ slots = slots(),
+ affordances = quickAffordances(),
selectedSlotText = "Left button",
selectedAffordanceText = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
)
assertPreviewUiState(
- slots = slots.last(),
+ slots = slots(),
expectedAffordanceNameBySlotId =
mapOf(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
@@ -133,17 +148,17 @@
// Select an affordance for the second slot.
// First, switch to the second slot:
- slots.last()[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END]?.onClicked?.invoke()
+ slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
// Second, select the "affordance 3" affordance:
- quickAffordances.last()[3].onClicked?.invoke()
+ quickAffordances()?.get(3)?.onClicked?.invoke()
assertPickerUiState(
- slots = slots.last(),
- affordances = quickAffordances.last(),
+ slots = slots(),
+ affordances = quickAffordances(),
selectedSlotText = "Right button",
selectedAffordanceText = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_3,
)
assertPreviewUiState(
- slots = slots.last(),
+ slots = slots(),
expectedAffordanceNameBySlotId =
mapOf(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
@@ -154,15 +169,15 @@
)
// Select a different affordance for the second slot.
- quickAffordances.last()[2].onClicked?.invoke()
+ quickAffordances()?.get(2)?.onClicked?.invoke()
assertPickerUiState(
- slots = slots.last(),
- affordances = quickAffordances.last(),
+ slots = slots(),
+ affordances = quickAffordances(),
selectedSlotText = "Right button",
selectedAffordanceText = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2,
)
assertPreviewUiState(
- slots = slots.last(),
+ slots = slots(),
expectedAffordanceNameBySlotId =
mapOf(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
@@ -171,42 +186,35 @@
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2,
),
)
-
- jobs.forEach { it.cancel() }
}
@Test
fun `Unselect - AKA selecting the none affordance - on one side`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
-
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- }
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
// Select "affordance 1" for the first slot.
- quickAffordances.last()[1].onClicked?.invoke()
+ quickAffordances()?.get(1)?.onClicked?.invoke()
// Select an affordance for the second slot.
// First, switch to the second slot:
- slots.last()[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END]?.onClicked?.invoke()
+ slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
// Second, select the "affordance 3" affordance:
- quickAffordances.last()[3].onClicked?.invoke()
+ quickAffordances()?.get(3)?.onClicked?.invoke()
// Switch back to the first slot:
- slots.last()[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START]?.onClicked?.invoke()
+ slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START)?.onClicked?.invoke()
// Select the "none" affordance, which is always in position 0:
- quickAffordances.last()[0].onClicked?.invoke()
+ quickAffordances()?.get(0)?.onClicked?.invoke()
assertPickerUiState(
- slots = slots.last(),
- affordances = quickAffordances.last(),
+ slots = slots(),
+ affordances = quickAffordances(),
selectedSlotText = "Left button",
selectedAffordanceText = "None",
)
assertPreviewUiState(
- slots = slots.last(),
+ slots = slots(),
expectedAffordanceNameBySlotId =
mapOf(
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to null,
@@ -214,22 +222,15 @@
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_3,
),
)
-
- jobs.forEach { it.cancel() }
}
@Test
fun `Show enablement dialog when selecting a disabled affordance`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
- val dialog = mutableListOf<KeyguardQuickAffordancePickerViewModel.DialogViewModel?>()
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
+ val dialog = collectLastValue(underTest.dialog)
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- add(launch { underTest.dialog.toList(dialog) })
- }
val enablementInstructions = listOf("header", "enablementInstructions")
val enablementActionText = "enablementActionText"
val packageName = "packageName"
@@ -250,46 +251,39 @@
)
// Lets try to select that disabled affordance:
- quickAffordances.last()[affordanceIndex + 1].onClicked?.invoke()
+ quickAffordances()?.get(affordanceIndex + 1)?.onClicked?.invoke()
// We expect there to be a dialog that should be shown:
- assertThat(dialog.last()?.instructionHeader).isEqualTo(enablementInstructions[0])
- assertThat(dialog.last()?.instructions)
+ assertThat(dialog()?.instructionHeader).isEqualTo(enablementInstructions[0])
+ assertThat(dialog()?.instructions)
.isEqualTo(enablementInstructions.subList(1, enablementInstructions.size))
- assertThat(dialog.last()?.actionText).isEqualTo(enablementActionText)
- assertThat(dialog.last()?.intent?.`package`).isEqualTo(packageName)
- assertThat(dialog.last()?.intent?.action).isEqualTo(action)
+ assertThat(dialog()?.actionText).isEqualTo(enablementActionText)
+ assertThat(dialog()?.intent?.`package`).isEqualTo(packageName)
+ assertThat(dialog()?.intent?.action).isEqualTo(action)
// Once we report that the dialog has been dismissed by the user, we expect there to be
// no
// dialog to be shown:
underTest.onDialogDismissed()
- assertThat(dialog.last()).isNull()
-
- jobs.forEach { it.cancel() }
+ assertThat(dialog()).isNull()
}
@Test
fun `summary - affordance selected in both bottom-start and bottom-end`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
- val summary = mutableListOf<KeyguardQuickAffordanceSummaryViewModel>()
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- add(launch { underTest.summary.toList(summary) })
- }
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
+ val summary = collectLastValue(underTest.summary)
// Select "affordance 1" for the first slot.
- quickAffordances.last()[1].onClicked?.invoke()
+ quickAffordances()?.get(1)?.onClicked?.invoke()
// Select an affordance for the second slot.
// First, switch to the second slot:
- slots.last()[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END]?.onClicked?.invoke()
+ slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
// Second, select the "affordance 3" affordance:
- quickAffordances.last()[3].onClicked?.invoke()
+ quickAffordances()?.get(3)?.onClicked?.invoke()
- assertThat(summary.last())
+ assertThat(summary())
.isEqualTo(
KeyguardQuickAffordanceSummaryViewModel(
description =
@@ -299,25 +293,19 @@
icon2 = FakeKeyguardQuickAffordanceProviderClient.ICON_3,
)
)
- jobs.forEach { it.cancel() }
}
@Test
fun `summary - affordance selected only on bottom-start`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
- val summary = mutableListOf<KeyguardQuickAffordanceSummaryViewModel>()
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- add(launch { underTest.summary.toList(summary) })
- }
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
+ val summary = collectLastValue(underTest.summary)
// Select "affordance 1" for the first slot.
- quickAffordances.last()[1].onClicked?.invoke()
+ quickAffordances()?.get(1)?.onClicked?.invoke()
- assertThat(summary.last())
+ assertThat(summary())
.isEqualTo(
KeyguardQuickAffordanceSummaryViewModel(
description = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
@@ -325,28 +313,22 @@
icon2 = null,
)
)
- jobs.forEach { it.cancel() }
}
@Test
fun `summary - affordance selected only on bottom-end`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
- val summary = mutableListOf<KeyguardQuickAffordanceSummaryViewModel>()
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- add(launch { underTest.summary.toList(summary) })
- }
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
+ val summary = collectLastValue(underTest.summary)
// Select an affordance for the second slot.
// First, switch to the second slot:
- slots.last()[KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END]?.onClicked?.invoke()
+ slots()?.get(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END)?.onClicked?.invoke()
// Second, select the "affordance 3" affordance:
- quickAffordances.last()[3].onClicked?.invoke()
+ quickAffordances()?.get(3)?.onClicked?.invoke()
- assertThat(summary.last())
+ assertThat(summary())
.isEqualTo(
KeyguardQuickAffordanceSummaryViewModel(
description = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_3,
@@ -354,25 +336,18 @@
icon2 = FakeKeyguardQuickAffordanceProviderClient.ICON_3,
)
)
- jobs.forEach { it.cancel() }
}
@Test
fun `summary - no affordances selected`() =
testScope.runTest {
- val slots = mutableListOf<Map<String, KeyguardQuickAffordanceSlotViewModel>>()
- val quickAffordances = mutableListOf<List<KeyguardQuickAffordanceViewModel>>()
- val summary = mutableListOf<KeyguardQuickAffordanceSummaryViewModel>()
- val jobs = buildList {
- add(launch { underTest.slots.toList(slots) })
- add(launch { underTest.quickAffordances.toList(quickAffordances) })
- add(launch { underTest.summary.toList(summary) })
- }
+ val slots = collectLastValue(underTest.slots)
+ val quickAffordances = collectLastValue(underTest.quickAffordances)
+ val summary = collectLastValue(underTest.summary)
- assertThat(summary.last().description).isEqualTo("None")
- assertThat(summary.last().icon1).isNotNull()
- assertThat(summary.last().icon2).isNull()
- jobs.forEach { it.cancel() }
+ assertThat(summary()?.description).isEqualTo("None")
+ assertThat(summary()?.icon1).isNotNull()
+ assertThat(summary()?.icon2).isNull()
}
/**
@@ -385,8 +360,8 @@
* @param selectedAffordanceText The text of the affordance that's expected to be selected
*/
private fun assertPickerUiState(
- slots: Map<String, KeyguardQuickAffordanceSlotViewModel>,
- affordances: List<KeyguardQuickAffordanceViewModel>,
+ slots: Map<String, KeyguardQuickAffordanceSlotViewModel>?,
+ affordances: List<KeyguardQuickAffordanceViewModel>?,
selectedSlotText: String,
selectedAffordanceText: String,
) {
@@ -402,7 +377,8 @@
)
var foundSelectedAffordance = false
- affordances.forEach { affordance ->
+ assertThat(affordances).isNotNull()
+ affordances?.forEach { affordance ->
val nameMatchesSelectedName = affordance.contentDescription == selectedAffordanceText
assertWithMessage(
"Expected affordance with name \"${affordance.contentDescription}\" to have" +
@@ -423,11 +399,11 @@
* @param isSelected Whether that slot should be selected
*/
private fun assertSlotTabUiState(
- slots: Map<String, KeyguardQuickAffordanceSlotViewModel>,
+ slots: Map<String, KeyguardQuickAffordanceSlotViewModel>?,
slotId: String,
isSelected: Boolean,
) {
- val viewModel = slots[slotId] ?: error("No slot with ID \"$slotId\"!")
+ val viewModel = slots?.get(slotId) ?: error("No slot with ID \"$slotId\"!")
assertThat(viewModel.isSelected).isEqualTo(isSelected)
}
@@ -436,13 +412,15 @@
*
* @param slots The observed slot view-models, keyed by slot ID
* @param expectedAffordanceNameBySlotId The expected name of the selected affordance for each
- * slot ID or `null` if it's expected for there to be no affordance for that slot in the preview
+ * slot ID or `null` if it's expected for there to be no affordance for that slot in the
+ * preview
*/
private fun assertPreviewUiState(
- slots: Map<String, KeyguardQuickAffordanceSlotViewModel>,
+ slots: Map<String, KeyguardQuickAffordanceSlotViewModel>?,
expectedAffordanceNameBySlotId: Map<String, String?>,
) {
- slots.forEach { (slotId, slotViewModel) ->
+ assertThat(slots).isNotNull()
+ slots?.forEach { (slotId, slotViewModel) ->
val expectedAffordanceName = expectedAffordanceNameBySlotId[slotId]
val actualAffordanceName =
slotViewModel.selectedQuickAffordances.firstOrNull()?.contentDescription
diff --git a/tests/src/com/android/customization/testing/TestCustomizationInjector.java b/tests/src/com/android/customization/testing/TestCustomizationInjector.java
index ed53751..f4a659c 100644
--- a/tests/src/com/android/customization/testing/TestCustomizationInjector.java
+++ b/tests/src/com/android/customization/testing/TestCustomizationInjector.java
@@ -12,15 +12,19 @@
import com.android.customization.module.ThemesUserEventLogger;
import com.android.customization.picker.quickaffordance.data.repository.KeyguardQuickAffordancePickerRepository;
import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordancePickerInteractor;
-import com.android.customization.picker.quickaffordance.ui.viewmodel.KeyguardQuickAffordancePickerViewModel;
+import com.android.customization.picker.quickaffordance.domain.interactor.KeyguardQuickAffordanceSnapshotRestorer;
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient;
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClientImpl;
import com.android.wallpaper.config.BaseFlags;
import com.android.wallpaper.module.DrawableLayerResolver;
import com.android.wallpaper.module.PackageStatusNotifier;
import com.android.wallpaper.module.UserEventLogger;
+import com.android.wallpaper.picker.undo.domain.interactor.SnapshotRestorer;
import com.android.wallpaper.testing.TestInjector;
+import java.util.HashMap;
+import java.util.Map;
+
import kotlinx.coroutines.Dispatchers;
/**
@@ -33,9 +37,9 @@
private DrawableLayerResolver mDrawableLayerResolver;
private UserEventLogger mUserEventLogger;
private KeyguardQuickAffordancePickerInteractor mKeyguardQuickAffordancePickerInteractor;
- private KeyguardQuickAffordancePickerViewModel.Factory
- mKeyguardQuickAffordancePickerViewModelFactory;
private BaseFlags mFlags;
+ private KeyguardQuickAffordanceProviderClient mKeyguardQuickAffordanceProviderClient;
+ private KeyguardQuickAffordanceSnapshotRestorer mKeyguardQuickAffordanceSnapshotRestorer;
@Override
public CustomizationPreferences getCustomizationPreferences(Context context) {
@@ -89,7 +93,8 @@
new KeyguardQuickAffordanceProviderClientImpl(context, Dispatchers.getIO());
mKeyguardQuickAffordancePickerInteractor = new KeyguardQuickAffordancePickerInteractor(
new KeyguardQuickAffordancePickerRepository(client, Dispatchers.getIO()),
- client);
+ client,
+ () -> getKeyguardQuickAffordanceSnapshotRestorer(context));
}
return mKeyguardQuickAffordancePickerInteractor;
}
@@ -102,4 +107,37 @@
return mFlags;
}
+
+ @Override
+ public Map<Integer, SnapshotRestorer> getSnapshotRestorers(Context context) {
+ final Map<Integer, SnapshotRestorer> restorers = new HashMap<>();
+ restorers.put(
+ KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER,
+ getKeyguardQuickAffordanceSnapshotRestorer(context));
+ return restorers;
+ }
+
+ /** Returns the {@link KeyguardQuickAffordanceProviderClient}. */
+ private KeyguardQuickAffordanceProviderClient getKeyguardQuickAffordancePickerProviderClient(
+ Context context) {
+ if (mKeyguardQuickAffordanceProviderClient == null) {
+ mKeyguardQuickAffordanceProviderClient =
+ new KeyguardQuickAffordanceProviderClientImpl(context, Dispatchers.getIO());
+ }
+
+ return mKeyguardQuickAffordanceProviderClient;
+ }
+
+ private KeyguardQuickAffordanceSnapshotRestorer getKeyguardQuickAffordanceSnapshotRestorer(
+ Context context) {
+ if (mKeyguardQuickAffordanceSnapshotRestorer == null) {
+ mKeyguardQuickAffordanceSnapshotRestorer = new KeyguardQuickAffordanceSnapshotRestorer(
+ getKeyguardQuickAffordancePickerInteractor(context),
+ getKeyguardQuickAffordancePickerProviderClient(context));
+ }
+
+ return mKeyguardQuickAffordanceSnapshotRestorer;
+ }
+
+ private static final int KEY_QUICK_AFFORDANCE_SNAPSHOT_RESTORER = 1;
}