Merge "Renames customization content provider (1/7)." into tm-qpr-dev am: bba346acb4
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20821842 Change-Id: Iaede5345693e651148ae69e823b8ae0af0f650b3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -193,7 +193,7 @@
|
||||
<permission android:name="com.android.systemui.permission.FLAGS"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<permission android:name="android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES"
|
||||
<permission android:name="android.permission.CUSTOMIZE_SYSTEM_UI"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<!-- Adding Quick Settings tiles -->
|
||||
@@ -1003,10 +1003,10 @@
|
||||
</receiver>
|
||||
|
||||
<provider
|
||||
android:authorities="com.android.systemui.keyguard.quickaffordance"
|
||||
android:name="com.android.systemui.keyguard.KeyguardQuickAffordanceProvider"
|
||||
android:authorities="com.android.systemui.customization"
|
||||
android:name="com.android.systemui.keyguard.CustomizationProvider"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES"
|
||||
android:permission="android.permission.CUSTOMIZE_SYSTEM_UI"
|
||||
/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
android:enabled="false"
|
||||
tools:replace="android:authorities"
|
||||
tools:node="remove" />
|
||||
<provider android:name="com.android.systemui.keyguard.KeyguardQuickAffordanceProvider"
|
||||
<provider android:name="com.android.systemui.keyguard.CustomizationProvider"
|
||||
android:authorities="com.android.systemui.test.keyguard.quickaffordance.disabled"
|
||||
android:enabled="false"
|
||||
tools:replace="android:authorities"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.quickaffordance.data.content
|
||||
package com.android.systemui.shared.customization.data.content
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ContentValues
|
||||
@@ -25,7 +25,7 @@ import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -35,7 +35,7 @@ import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/** Client for using a content provider implementing the [Contract]. */
|
||||
interface KeyguardQuickAffordanceProviderClient {
|
||||
interface CustomizationProviderClient {
|
||||
|
||||
/**
|
||||
* Selects an affordance with the given ID for a slot on the lock screen with the given ID.
|
||||
@@ -190,10 +190,10 @@ interface KeyguardQuickAffordanceProviderClient {
|
||||
)
|
||||
}
|
||||
|
||||
class KeyguardQuickAffordanceProviderClientImpl(
|
||||
class CustomizationProviderClientImpl(
|
||||
private val context: Context,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
) : KeyguardQuickAffordanceProviderClient {
|
||||
) : CustomizationProviderClient {
|
||||
|
||||
override suspend fun insertSelection(
|
||||
slotId: String,
|
||||
@@ -201,20 +201,23 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
) {
|
||||
withContext(backgroundDispatcher) {
|
||||
context.contentResolver.insert(
|
||||
Contract.SelectionTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
ContentValues().apply {
|
||||
put(Contract.SelectionTable.Columns.SLOT_ID, slotId)
|
||||
put(Contract.SelectionTable.Columns.AFFORDANCE_ID, affordanceId)
|
||||
put(Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID, slotId)
|
||||
put(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID,
|
||||
affordanceId
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun querySlots(): List<KeyguardQuickAffordanceProviderClient.Slot> {
|
||||
override suspend fun querySlots(): List<CustomizationProviderClient.Slot> {
|
||||
return withContext(backgroundDispatcher) {
|
||||
context.contentResolver
|
||||
.query(
|
||||
Contract.SlotTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SlotTable.URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -222,16 +225,21 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
)
|
||||
?.use { cursor ->
|
||||
buildList {
|
||||
val idColumnIndex = cursor.getColumnIndex(Contract.SlotTable.Columns.ID)
|
||||
val idColumnIndex =
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.Columns.ID
|
||||
)
|
||||
val capacityColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SlotTable.Columns.CAPACITY)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.Columns.CAPACITY
|
||||
)
|
||||
if (idColumnIndex == -1 || capacityColumnIndex == -1) {
|
||||
return@buildList
|
||||
}
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
add(
|
||||
KeyguardQuickAffordanceProviderClient.Slot(
|
||||
CustomizationProviderClient.Slot(
|
||||
id = cursor.getString(idColumnIndex),
|
||||
capacity = cursor.getInt(capacityColumnIndex),
|
||||
)
|
||||
@@ -243,7 +251,7 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
override suspend fun queryFlags(): List<KeyguardQuickAffordanceProviderClient.Flag> {
|
||||
override suspend fun queryFlags(): List<CustomizationProviderClient.Flag> {
|
||||
return withContext(backgroundDispatcher) {
|
||||
context.contentResolver
|
||||
.query(
|
||||
@@ -265,7 +273,7 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
add(
|
||||
KeyguardQuickAffordanceProviderClient.Flag(
|
||||
CustomizationProviderClient.Flag(
|
||||
name = cursor.getString(nameColumnIndex),
|
||||
value = cursor.getInt(valueColumnIndex) == 1,
|
||||
)
|
||||
@@ -277,20 +285,19 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
override fun observeSlots(): Flow<List<KeyguardQuickAffordanceProviderClient.Slot>> {
|
||||
return observeUri(Contract.SlotTable.URI).map { querySlots() }
|
||||
override fun observeSlots(): Flow<List<CustomizationProviderClient.Slot>> {
|
||||
return observeUri(Contract.LockScreenQuickAffordances.SlotTable.URI).map { querySlots() }
|
||||
}
|
||||
|
||||
override fun observeFlags(): Flow<List<KeyguardQuickAffordanceProviderClient.Flag>> {
|
||||
override fun observeFlags(): Flow<List<CustomizationProviderClient.Flag>> {
|
||||
return observeUri(Contract.FlagsTable.URI).map { queryFlags() }
|
||||
}
|
||||
|
||||
override suspend fun queryAffordances():
|
||||
List<KeyguardQuickAffordanceProviderClient.Affordance> {
|
||||
override suspend fun queryAffordances(): List<CustomizationProviderClient.Affordance> {
|
||||
return withContext(backgroundDispatcher) {
|
||||
context.contentResolver
|
||||
.query(
|
||||
Contract.AffordanceTable.URI,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -299,24 +306,36 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
?.use { cursor ->
|
||||
buildList {
|
||||
val idColumnIndex =
|
||||
cursor.getColumnIndex(Contract.AffordanceTable.Columns.ID)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ID
|
||||
)
|
||||
val nameColumnIndex =
|
||||
cursor.getColumnIndex(Contract.AffordanceTable.Columns.NAME)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.NAME
|
||||
)
|
||||
val iconColumnIndex =
|
||||
cursor.getColumnIndex(Contract.AffordanceTable.Columns.ICON)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ICON
|
||||
)
|
||||
val isEnabledColumnIndex =
|
||||
cursor.getColumnIndex(Contract.AffordanceTable.Columns.IS_ENABLED)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.IS_ENABLED
|
||||
)
|
||||
val enablementInstructionsColumnIndex =
|
||||
cursor.getColumnIndex(
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_INSTRUCTIONS
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.ENABLEMENT_INSTRUCTIONS
|
||||
)
|
||||
val enablementActionTextColumnIndex =
|
||||
cursor.getColumnIndex(
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_ACTION_TEXT
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.ENABLEMENT_ACTION_TEXT
|
||||
)
|
||||
val enablementComponentNameColumnIndex =
|
||||
cursor.getColumnIndex(
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_COMPONENT_NAME
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.ENABLEMENT_COMPONENT_NAME
|
||||
)
|
||||
if (
|
||||
idColumnIndex == -1 ||
|
||||
@@ -332,7 +351,7 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
add(
|
||||
KeyguardQuickAffordanceProviderClient.Affordance(
|
||||
CustomizationProviderClient.Affordance(
|
||||
id = cursor.getString(idColumnIndex),
|
||||
name = cursor.getString(nameColumnIndex),
|
||||
iconResourceId = cursor.getInt(iconColumnIndex),
|
||||
@@ -341,7 +360,7 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
cursor
|
||||
.getString(enablementInstructionsColumnIndex)
|
||||
?.split(
|
||||
Contract.AffordanceTable
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable
|
||||
.ENABLEMENT_INSTRUCTIONS_DELIMITER
|
||||
),
|
||||
enablementActionText =
|
||||
@@ -357,16 +376,17 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
override fun observeAffordances():
|
||||
Flow<List<KeyguardQuickAffordanceProviderClient.Affordance>> {
|
||||
return observeUri(Contract.AffordanceTable.URI).map { queryAffordances() }
|
||||
override fun observeAffordances(): Flow<List<CustomizationProviderClient.Affordance>> {
|
||||
return observeUri(Contract.LockScreenQuickAffordances.AffordanceTable.URI).map {
|
||||
queryAffordances()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun querySelections(): List<KeyguardQuickAffordanceProviderClient.Selection> {
|
||||
override suspend fun querySelections(): List<CustomizationProviderClient.Selection> {
|
||||
return withContext(backgroundDispatcher) {
|
||||
context.contentResolver
|
||||
.query(
|
||||
Contract.SelectionTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -375,11 +395,19 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
?.use { cursor ->
|
||||
buildList {
|
||||
val slotIdColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SelectionTable.Columns.SLOT_ID)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID
|
||||
)
|
||||
val affordanceIdColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_ID)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns
|
||||
.AFFORDANCE_ID
|
||||
)
|
||||
val affordanceNameColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_NAME)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns
|
||||
.AFFORDANCE_NAME
|
||||
)
|
||||
if (
|
||||
slotIdColumnIndex == -1 ||
|
||||
affordanceIdColumnIndex == -1 ||
|
||||
@@ -390,7 +418,7 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
add(
|
||||
KeyguardQuickAffordanceProviderClient.Selection(
|
||||
CustomizationProviderClient.Selection(
|
||||
slotId = cursor.getString(slotIdColumnIndex),
|
||||
affordanceId = cursor.getString(affordanceIdColumnIndex),
|
||||
affordanceName = cursor.getString(affordanceNameColumnIndex),
|
||||
@@ -403,8 +431,10 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
override fun observeSelections(): Flow<List<KeyguardQuickAffordanceProviderClient.Selection>> {
|
||||
return observeUri(Contract.SelectionTable.URI).map { querySelections() }
|
||||
override fun observeSelections(): Flow<List<CustomizationProviderClient.Selection>> {
|
||||
return observeUri(Contract.LockScreenQuickAffordances.SelectionTable.URI).map {
|
||||
querySelections()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deleteSelection(
|
||||
@@ -413,9 +443,10 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
) {
|
||||
withContext(backgroundDispatcher) {
|
||||
context.contentResolver.delete(
|
||||
Contract.SelectionTable.URI,
|
||||
"${Contract.SelectionTable.Columns.SLOT_ID} = ? AND" +
|
||||
" ${Contract.SelectionTable.Columns.AFFORDANCE_ID} = ?",
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
"${Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID} = ? AND" +
|
||||
" ${Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID}" +
|
||||
" = ?",
|
||||
arrayOf(
|
||||
slotId,
|
||||
affordanceId,
|
||||
@@ -429,8 +460,8 @@ class KeyguardQuickAffordanceProviderClientImpl(
|
||||
) {
|
||||
withContext(backgroundDispatcher) {
|
||||
context.contentResolver.delete(
|
||||
Contract.SelectionTable.URI,
|
||||
Contract.SelectionTable.Columns.SLOT_ID,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID,
|
||||
arrayOf(
|
||||
slotId,
|
||||
),
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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.systemui.shared.customization.data.content
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
|
||||
/** Contract definitions for querying content about keyguard quick affordances. */
|
||||
object CustomizationProviderContract {
|
||||
|
||||
const val AUTHORITY = "com.android.systemui.customization"
|
||||
const val PERMISSION = "android.permission.CUSTOMIZE_SYSTEM_UI"
|
||||
|
||||
private val BASE_URI: Uri =
|
||||
Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build()
|
||||
|
||||
/** Namespace for lock screen shortcut (quick affordance) tables. */
|
||||
object LockScreenQuickAffordances {
|
||||
|
||||
const val NAMESPACE = "lockscreen_quickaffordance"
|
||||
|
||||
private val LOCK_SCREEN_QUICK_AFFORDANCE_BASE_URI: Uri =
|
||||
BASE_URI.buildUpon().path(NAMESPACE).build()
|
||||
|
||||
fun qualifiedTablePath(tableName: String): String {
|
||||
return "$NAMESPACE/$tableName"
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for slots.
|
||||
*
|
||||
* Slots are positions where affordances can be placed on the lock screen. Affordances that
|
||||
* are placed on slots are said to be "selected". The system supports the idea of multiple
|
||||
* affordances per slot, though the implementation may limit the number of affordances on
|
||||
* each slot.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result
|
||||
* set will contain rows with the [SlotTable.Columns] columns.
|
||||
*/
|
||||
object SlotTable {
|
||||
const val TABLE_NAME = "slots"
|
||||
val URI: Uri =
|
||||
LOCK_SCREEN_QUICK_AFFORDANCE_BASE_URI.buildUpon().appendPath(TABLE_NAME).build()
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for this slot. */
|
||||
const val ID = "id"
|
||||
/** Integer. The maximum number of affordances that can be placed in the slot. */
|
||||
const val CAPACITY = "capacity"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for affordances.
|
||||
*
|
||||
* Affordances are actions/buttons that the user can execute. They are placed on slots on
|
||||
* the lock screen.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Query - to know about all the affordances that are available on the device, regardless
|
||||
* of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
|
||||
* set will contain rows, each with the columns specified in [AffordanceTable.Columns].
|
||||
*/
|
||||
object AffordanceTable {
|
||||
const val TABLE_NAME = "affordances"
|
||||
val URI: Uri =
|
||||
LOCK_SCREEN_QUICK_AFFORDANCE_BASE_URI.buildUpon().appendPath(TABLE_NAME).build()
|
||||
const val ENABLEMENT_INSTRUCTIONS_DELIMITER = "]["
|
||||
const val COMPONENT_NAME_SEPARATOR = "/"
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for this affordance. */
|
||||
const val ID = "id"
|
||||
/** String. User-visible name for this affordance. */
|
||||
const val NAME = "name"
|
||||
/**
|
||||
* Integer. Resource ID for the drawable to load for this affordance. This is a
|
||||
* resource ID from the system UI package.
|
||||
*/
|
||||
const val ICON = "icon"
|
||||
/** Integer. `1` if the affordance is enabled or `0` if it disabled. */
|
||||
const val IS_ENABLED = "is_enabled"
|
||||
/**
|
||||
* String. List of strings, delimited by [ENABLEMENT_INSTRUCTIONS_DELIMITER] to be
|
||||
* shown to the user if the affordance is disabled and the user selects the
|
||||
* affordance.
|
||||
*/
|
||||
const val ENABLEMENT_INSTRUCTIONS = "enablement_instructions"
|
||||
/**
|
||||
* String. Optional label for a button that, when clicked, opens a destination
|
||||
* activity where the user can re-enable the disabled affordance.
|
||||
*/
|
||||
const val ENABLEMENT_ACTION_TEXT = "enablement_action_text"
|
||||
/**
|
||||
* String. Optional package name and activity action string, delimited by
|
||||
* [COMPONENT_NAME_SEPARATOR] to use with an `Intent` to start an activity that
|
||||
* opens a destination where the user can re-enable the disabled affordance.
|
||||
*/
|
||||
const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for selections.
|
||||
*
|
||||
* Selections are pairs of slot and affordance IDs.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Insert - to insert an affordance and place it in a slot, insert values for the columns
|
||||
* into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
|
||||
* Selecting a new affordance for a slot that is already full will automatically remove the
|
||||
* oldest affordance from the slot.
|
||||
* - Query - to know which affordances are set on which slots, query the
|
||||
* [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
|
||||
* columns from [SelectionTable.Columns].
|
||||
* - Delete - to unselect an affordance, removing it from a slot, delete from the
|
||||
* [SelectionTable.URI] [Uri], passing in values for each column.
|
||||
*/
|
||||
object SelectionTable {
|
||||
const val TABLE_NAME = "selections"
|
||||
val URI: Uri =
|
||||
LOCK_SCREEN_QUICK_AFFORDANCE_BASE_URI.buildUpon().appendPath(TABLE_NAME).build()
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for the slot. */
|
||||
const val SLOT_ID = "slot_id"
|
||||
/** String. Unique ID for the selected affordance. */
|
||||
const val AFFORDANCE_ID = "affordance_id"
|
||||
/** String. Human-readable name for the affordance. */
|
||||
const val AFFORDANCE_NAME = "affordance_name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for flags.
|
||||
*
|
||||
* Flags are key-value pairs.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
|
||||
* contain rows, each of which with the columns from [FlagsTable.Columns].
|
||||
*/
|
||||
object FlagsTable {
|
||||
const val TABLE_NAME = "flags"
|
||||
val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
|
||||
|
||||
/** Flag denoting whether the Wallpaper Picker should use the new, revamped UI. */
|
||||
const val FLAG_NAME_REVAMPED_WALLPAPER_UI = "revamped_wallpaper_ui"
|
||||
|
||||
/**
|
||||
* Flag denoting whether the customizable lock screen quick affordances feature is enabled.
|
||||
*/
|
||||
const val FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED =
|
||||
"is_custom_lock_screen_quick_affordances_feature_enabled"
|
||||
|
||||
/** Flag denoting whether the customizable clocks feature is enabled. */
|
||||
const val FLAG_NAME_CUSTOM_CLOCKS_ENABLED = "is_custom_clocks_feature_enabled"
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for the flag. */
|
||||
const val NAME = "name"
|
||||
/** Int. Value of the flag. `1` means `true` and `0` means `false`. */
|
||||
const val VALUE = "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.quickaffordance.data.content
|
||||
package com.android.systemui.shared.customization.data.content
|
||||
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
@@ -25,46 +25,46 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
class FakeKeyguardQuickAffordanceProviderClient(
|
||||
slots: List<KeyguardQuickAffordanceProviderClient.Slot> =
|
||||
class FakeCustomizationProviderClient(
|
||||
slots: List<CustomizationProviderClient.Slot> =
|
||||
listOf(
|
||||
KeyguardQuickAffordanceProviderClient.Slot(
|
||||
CustomizationProviderClient.Slot(
|
||||
id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
|
||||
capacity = 1,
|
||||
),
|
||||
KeyguardQuickAffordanceProviderClient.Slot(
|
||||
CustomizationProviderClient.Slot(
|
||||
id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
|
||||
capacity = 1,
|
||||
),
|
||||
),
|
||||
affordances: List<KeyguardQuickAffordanceProviderClient.Affordance> =
|
||||
affordances: List<CustomizationProviderClient.Affordance> =
|
||||
listOf(
|
||||
KeyguardQuickAffordanceProviderClient.Affordance(
|
||||
CustomizationProviderClient.Affordance(
|
||||
id = AFFORDANCE_1,
|
||||
name = AFFORDANCE_1,
|
||||
iconResourceId = 1,
|
||||
),
|
||||
KeyguardQuickAffordanceProviderClient.Affordance(
|
||||
CustomizationProviderClient.Affordance(
|
||||
id = AFFORDANCE_2,
|
||||
name = AFFORDANCE_2,
|
||||
iconResourceId = 2,
|
||||
),
|
||||
KeyguardQuickAffordanceProviderClient.Affordance(
|
||||
CustomizationProviderClient.Affordance(
|
||||
id = AFFORDANCE_3,
|
||||
name = AFFORDANCE_3,
|
||||
iconResourceId = 3,
|
||||
),
|
||||
),
|
||||
flags: List<KeyguardQuickAffordanceProviderClient.Flag> =
|
||||
flags: List<CustomizationProviderClient.Flag> =
|
||||
listOf(
|
||||
KeyguardQuickAffordanceProviderClient.Flag(
|
||||
CustomizationProviderClient.Flag(
|
||||
name =
|
||||
KeyguardQuickAffordanceProviderContract.FlagsTable
|
||||
CustomizationProviderContract.FlagsTable
|
||||
.FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED,
|
||||
value = true,
|
||||
)
|
||||
),
|
||||
) : KeyguardQuickAffordanceProviderClient {
|
||||
) : CustomizationProviderClient {
|
||||
|
||||
private val slots = MutableStateFlow(slots)
|
||||
private val affordances = MutableStateFlow(affordances)
|
||||
@@ -85,37 +85,35 @@ class FakeKeyguardQuickAffordanceProviderClient(
|
||||
selections.value = selections.value.toMutableMap().apply { this[slotId] = affordances }
|
||||
}
|
||||
|
||||
override suspend fun querySlots(): List<KeyguardQuickAffordanceProviderClient.Slot> {
|
||||
override suspend fun querySlots(): List<CustomizationProviderClient.Slot> {
|
||||
return slots.value
|
||||
}
|
||||
|
||||
override suspend fun queryFlags(): List<KeyguardQuickAffordanceProviderClient.Flag> {
|
||||
override suspend fun queryFlags(): List<CustomizationProviderClient.Flag> {
|
||||
return flags.value
|
||||
}
|
||||
|
||||
override fun observeSlots(): Flow<List<KeyguardQuickAffordanceProviderClient.Slot>> {
|
||||
override fun observeSlots(): Flow<List<CustomizationProviderClient.Slot>> {
|
||||
return slots.asStateFlow()
|
||||
}
|
||||
|
||||
override fun observeFlags(): Flow<List<KeyguardQuickAffordanceProviderClient.Flag>> {
|
||||
override fun observeFlags(): Flow<List<CustomizationProviderClient.Flag>> {
|
||||
return flags.asStateFlow()
|
||||
}
|
||||
|
||||
override suspend fun queryAffordances():
|
||||
List<KeyguardQuickAffordanceProviderClient.Affordance> {
|
||||
override suspend fun queryAffordances(): List<CustomizationProviderClient.Affordance> {
|
||||
return affordances.value
|
||||
}
|
||||
|
||||
override fun observeAffordances():
|
||||
Flow<List<KeyguardQuickAffordanceProviderClient.Affordance>> {
|
||||
override fun observeAffordances(): Flow<List<CustomizationProviderClient.Affordance>> {
|
||||
return affordances.asStateFlow()
|
||||
}
|
||||
|
||||
override suspend fun querySelections(): List<KeyguardQuickAffordanceProviderClient.Selection> {
|
||||
override suspend fun querySelections(): List<CustomizationProviderClient.Selection> {
|
||||
return toSelectionList(selections.value, affordances.value)
|
||||
}
|
||||
|
||||
override fun observeSelections(): Flow<List<KeyguardQuickAffordanceProviderClient.Selection>> {
|
||||
override fun observeSelections(): Flow<List<CustomizationProviderClient.Selection>> {
|
||||
return combine(selections, affordances) { selections, affordances ->
|
||||
toSelectionList(selections, affordances)
|
||||
}
|
||||
@@ -148,7 +146,7 @@ class FakeKeyguardQuickAffordanceProviderClient(
|
||||
flags.value =
|
||||
flags.value.toMutableList().apply {
|
||||
removeIf { it.name == name }
|
||||
add(KeyguardQuickAffordanceProviderClient.Flag(name = name, value = value))
|
||||
add(CustomizationProviderClient.Flag(name = name, value = value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,29 +155,26 @@ class FakeKeyguardQuickAffordanceProviderClient(
|
||||
slots.value.toMutableList().apply {
|
||||
val index = indexOfFirst { it.id == slotId }
|
||||
check(index != -1) { "Slot with ID \"$slotId\" doesn't exist!" }
|
||||
set(
|
||||
index,
|
||||
KeyguardQuickAffordanceProviderClient.Slot(id = slotId, capacity = capacity)
|
||||
)
|
||||
set(index, CustomizationProviderClient.Slot(id = slotId, capacity = capacity))
|
||||
}
|
||||
}
|
||||
|
||||
fun addAffordance(affordance: KeyguardQuickAffordanceProviderClient.Affordance): Int {
|
||||
fun addAffordance(affordance: CustomizationProviderClient.Affordance): Int {
|
||||
affordances.value = affordances.value + listOf(affordance)
|
||||
return affordances.value.size - 1
|
||||
}
|
||||
|
||||
private fun toSelectionList(
|
||||
selections: Map<String, List<String>>,
|
||||
affordances: List<KeyguardQuickAffordanceProviderClient.Affordance>,
|
||||
): List<KeyguardQuickAffordanceProviderClient.Selection> {
|
||||
affordances: List<CustomizationProviderClient.Affordance>,
|
||||
): List<CustomizationProviderClient.Selection> {
|
||||
return selections
|
||||
.map { (slotId, affordanceIds) ->
|
||||
affordanceIds.map { affordanceId ->
|
||||
val affordanceName =
|
||||
affordances.find { it.id == affordanceId }?.name
|
||||
?: error("No affordance with ID of \"$affordanceId\"!")
|
||||
KeyguardQuickAffordanceProviderClient.Selection(
|
||||
CustomizationProviderClient.Selection(
|
||||
slotId = slotId,
|
||||
affordanceId = affordanceId,
|
||||
affordanceName = affordanceName,
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* 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.systemui.shared.quickaffordance.data.content
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
|
||||
/** Contract definitions for querying content about keyguard quick affordances. */
|
||||
object KeyguardQuickAffordanceProviderContract {
|
||||
|
||||
const val AUTHORITY = "com.android.systemui.keyguard.quickaffordance"
|
||||
const val PERMISSION = "android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES"
|
||||
|
||||
private val BASE_URI: Uri =
|
||||
Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build()
|
||||
|
||||
/**
|
||||
* Table for slots.
|
||||
*
|
||||
* Slots are positions where affordances can be placed on the lock screen. Affordances that are
|
||||
* placed on slots are said to be "selected". The system supports the idea of multiple
|
||||
* affordances per slot, though the implementation may limit the number of affordances on each
|
||||
* slot.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result set
|
||||
* will contain rows with the [SlotTable.Columns] columns.
|
||||
*/
|
||||
object SlotTable {
|
||||
const val TABLE_NAME = "slots"
|
||||
val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for this slot. */
|
||||
const val ID = "id"
|
||||
/** Integer. The maximum number of affordances that can be placed in the slot. */
|
||||
const val CAPACITY = "capacity"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for affordances.
|
||||
*
|
||||
* Affordances are actions/buttons that the user can execute. They are placed on slots on the
|
||||
* lock screen.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Query - to know about all the affordances that are available on the device, regardless of
|
||||
* which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result set will
|
||||
* contain rows, each with the columns specified in [AffordanceTable.Columns].
|
||||
*/
|
||||
object AffordanceTable {
|
||||
const val TABLE_NAME = "affordances"
|
||||
val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
|
||||
const val ENABLEMENT_INSTRUCTIONS_DELIMITER = "]["
|
||||
const val COMPONENT_NAME_SEPARATOR = "/"
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for this affordance. */
|
||||
const val ID = "id"
|
||||
/** String. User-visible name for this affordance. */
|
||||
const val NAME = "name"
|
||||
/**
|
||||
* Integer. Resource ID for the drawable to load for this affordance. This is a resource
|
||||
* ID from the system UI package.
|
||||
*/
|
||||
const val ICON = "icon"
|
||||
/** Integer. `1` if the affordance is enabled or `0` if it disabled. */
|
||||
const val IS_ENABLED = "is_enabled"
|
||||
/**
|
||||
* String. List of strings, delimited by [ENABLEMENT_INSTRUCTIONS_DELIMITER] to be shown
|
||||
* to the user if the affordance is disabled and the user selects the affordance.
|
||||
*/
|
||||
const val ENABLEMENT_INSTRUCTIONS = "enablement_instructions"
|
||||
/**
|
||||
* String. Optional label for a button that, when clicked, opens a destination activity
|
||||
* where the user can re-enable the disabled affordance.
|
||||
*/
|
||||
const val ENABLEMENT_ACTION_TEXT = "enablement_action_text"
|
||||
/**
|
||||
* String. Optional package name and activity action string, delimited by
|
||||
* [COMPONENT_NAME_SEPARATOR] to use with an `Intent` to start an activity that opens a
|
||||
* destination where the user can re-enable the disabled affordance.
|
||||
*/
|
||||
const val ENABLEMENT_COMPONENT_NAME = "enablement_action_intent"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for selections.
|
||||
*
|
||||
* Selections are pairs of slot and affordance IDs.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Insert - to insert an affordance and place it in a slot, insert values for the columns into
|
||||
* the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
|
||||
* Selecting a new affordance for a slot that is already full will automatically remove the
|
||||
* oldest affordance from the slot.
|
||||
* - Query - to know which affordances are set on which slots, query the [SelectionTable.URI]
|
||||
* [Uri]. The result set will contain rows, each of which with the columns from
|
||||
* [SelectionTable.Columns].
|
||||
* - Delete - to unselect an affordance, removing it from a slot, delete from the
|
||||
* [SelectionTable.URI] [Uri], passing in values for each column.
|
||||
*/
|
||||
object SelectionTable {
|
||||
const val TABLE_NAME = "selections"
|
||||
val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for the slot. */
|
||||
const val SLOT_ID = "slot_id"
|
||||
/** String. Unique ID for the selected affordance. */
|
||||
const val AFFORDANCE_ID = "affordance_id"
|
||||
/** String. Human-readable name for the affordance. */
|
||||
const val AFFORDANCE_NAME = "affordance_name"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Table for flags.
|
||||
*
|
||||
* Flags are key-value pairs.
|
||||
*
|
||||
* Supported operations:
|
||||
* - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
|
||||
* contain rows, each of which with the columns from [FlagsTable.Columns].
|
||||
*/
|
||||
object FlagsTable {
|
||||
const val TABLE_NAME = "flags"
|
||||
val URI: Uri = BASE_URI.buildUpon().path(TABLE_NAME).build()
|
||||
|
||||
/** Flag denoting whether the Wallpaper Picker should use the new, revamped UI. */
|
||||
const val FLAG_NAME_REVAMPED_WALLPAPER_UI = "revamped_wallpaper_ui"
|
||||
|
||||
/**
|
||||
* Flag denoting whether the customizable lock screen quick affordances feature is enabled.
|
||||
*/
|
||||
const val FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED =
|
||||
"is_custom_lock_screen_quick_affordances_feature_enabled"
|
||||
|
||||
/** Flag denoting whether the customizable clocks feature is enabled. */
|
||||
const val FLAG_NAME_CUSTOM_CLOCKS_ENABLED = "is_custom_clocks_feature_enabled"
|
||||
|
||||
object Columns {
|
||||
/** String. Unique ID for the flag. */
|
||||
const val NAME = "name"
|
||||
/** Int. Value of the flag. `1` means `true` and `0` means `false`. */
|
||||
const val VALUE = "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ This section describes how to implement a potential picker, selector, or configu
|
||||
### Accessing Quick Affordance Data
|
||||
Quick Affordances structured data are exposed to other applications through the `KeyguardQuickAffordanceProvider` content provider which is owned by the System UI process.
|
||||
|
||||
To access this content provider, applications must have the `android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES` permission which is a signature and privileged permission, limiting access to system apps or apps signed by the same signature as System UI. The `KeyguardQuickAffordanceProviderContract` file defines the content provider schema for consumers.
|
||||
To access this content provider, applications must have the `android.permission.CUSTOMIZE_SYSTEM_UI` permission which is a signature and privileged permission, limiting access to system apps or apps signed by the same signature as System UI. The `KeyguardQuickAffordanceProviderContract` file defines the content provider schema for consumers.
|
||||
|
||||
Generally speaking, there are three important tables served by the content provider: `slots`, `affordances`, and `selections`. There is also a `flags` table, but that's not important and may be ignored.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.android.systemui.dagger;
|
||||
|
||||
import com.android.systemui.keyguard.KeyguardQuickAffordanceProvider;
|
||||
import com.android.systemui.keyguard.CustomizationProvider;
|
||||
import com.android.systemui.statusbar.NotificationInsetsModule;
|
||||
import com.android.systemui.statusbar.QsFrameTranslateModule;
|
||||
|
||||
@@ -49,5 +49,5 @@ public interface ReferenceSysUIComponent extends SysUIComponent {
|
||||
/**
|
||||
* Member injection into the supplied argument.
|
||||
*/
|
||||
void inject(KeyguardQuickAffordanceProvider keyguardQuickAffordanceProvider);
|
||||
void inject(CustomizationProvider customizationProvider);
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@ import com.android.systemui.SystemUIAppComponentFactoryBase
|
||||
import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback
|
||||
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
|
||||
import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
class KeyguardQuickAffordanceProvider :
|
||||
class CustomizationProvider :
|
||||
ContentProvider(), SystemUIAppComponentFactoryBase.ContextInitializer {
|
||||
|
||||
@Inject lateinit var interactor: KeyguardQuickAffordanceInteractor
|
||||
@@ -49,17 +49,23 @@ class KeyguardQuickAffordanceProvider :
|
||||
UriMatcher(UriMatcher.NO_MATCH).apply {
|
||||
addURI(
|
||||
Contract.AUTHORITY,
|
||||
Contract.SlotTable.TABLE_NAME,
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME,
|
||||
),
|
||||
MATCH_CODE_ALL_SLOTS,
|
||||
)
|
||||
addURI(
|
||||
Contract.AUTHORITY,
|
||||
Contract.AffordanceTable.TABLE_NAME,
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME,
|
||||
),
|
||||
MATCH_CODE_ALL_AFFORDANCES,
|
||||
)
|
||||
addURI(
|
||||
Contract.AUTHORITY,
|
||||
Contract.SelectionTable.TABLE_NAME,
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME,
|
||||
),
|
||||
MATCH_CODE_ALL_SELECTIONS,
|
||||
)
|
||||
addURI(
|
||||
@@ -94,9 +100,18 @@ class KeyguardQuickAffordanceProvider :
|
||||
|
||||
val tableName =
|
||||
when (uriMatcher.match(uri)) {
|
||||
MATCH_CODE_ALL_SLOTS -> Contract.SlotTable.TABLE_NAME
|
||||
MATCH_CODE_ALL_AFFORDANCES -> Contract.AffordanceTable.TABLE_NAME
|
||||
MATCH_CODE_ALL_SELECTIONS -> Contract.SelectionTable.TABLE_NAME
|
||||
MATCH_CODE_ALL_SLOTS ->
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME,
|
||||
)
|
||||
MATCH_CODE_ALL_AFFORDANCES ->
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME,
|
||||
)
|
||||
MATCH_CODE_ALL_SELECTIONS ->
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME,
|
||||
)
|
||||
MATCH_CODE_ALL_FLAGS -> Contract.FlagsTable.TABLE_NAME
|
||||
else -> null
|
||||
}
|
||||
@@ -174,22 +189,34 @@ class KeyguardQuickAffordanceProvider :
|
||||
throw IllegalArgumentException("Cannot insert selection, no values passed in!")
|
||||
}
|
||||
|
||||
if (!values.containsKey(Contract.SelectionTable.Columns.SLOT_ID)) {
|
||||
if (
|
||||
!values.containsKey(Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID)
|
||||
) {
|
||||
throw IllegalArgumentException(
|
||||
"Cannot insert selection, " +
|
||||
"\"${Contract.SelectionTable.Columns.SLOT_ID}\" not specified!"
|
||||
"\"${Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID}\"" +
|
||||
" not specified!"
|
||||
)
|
||||
}
|
||||
|
||||
if (!values.containsKey(Contract.SelectionTable.Columns.AFFORDANCE_ID)) {
|
||||
if (
|
||||
!values.containsKey(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID
|
||||
)
|
||||
) {
|
||||
throw IllegalArgumentException(
|
||||
"Cannot insert selection, " +
|
||||
"\"${Contract.SelectionTable.Columns.AFFORDANCE_ID}\" not specified!"
|
||||
"\"${Contract.LockScreenQuickAffordances
|
||||
.SelectionTable.Columns.AFFORDANCE_ID}\" not specified!"
|
||||
)
|
||||
}
|
||||
|
||||
val slotId = values.getAsString(Contract.SelectionTable.Columns.SLOT_ID)
|
||||
val affordanceId = values.getAsString(Contract.SelectionTable.Columns.AFFORDANCE_ID)
|
||||
val slotId =
|
||||
values.getAsString(Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID)
|
||||
val affordanceId =
|
||||
values.getAsString(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID
|
||||
)
|
||||
|
||||
if (slotId.isNullOrEmpty()) {
|
||||
throw IllegalArgumentException("Cannot insert selection, slot ID was empty!")
|
||||
@@ -207,8 +234,10 @@ class KeyguardQuickAffordanceProvider :
|
||||
|
||||
return if (success) {
|
||||
Log.d(TAG, "Successfully selected $affordanceId for slot $slotId")
|
||||
context?.contentResolver?.notifyChange(Contract.SelectionTable.URI, null)
|
||||
Contract.SelectionTable.URI
|
||||
context
|
||||
?.contentResolver
|
||||
?.notifyChange(Contract.LockScreenQuickAffordances.SelectionTable.URI, null)
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI
|
||||
} else {
|
||||
Log.d(TAG, "Failed to select $affordanceId for slot $slotId")
|
||||
null
|
||||
@@ -218,9 +247,9 @@ class KeyguardQuickAffordanceProvider :
|
||||
private suspend fun querySelections(): Cursor {
|
||||
return MatrixCursor(
|
||||
arrayOf(
|
||||
Contract.SelectionTable.Columns.SLOT_ID,
|
||||
Contract.SelectionTable.Columns.AFFORDANCE_ID,
|
||||
Contract.SelectionTable.Columns.AFFORDANCE_NAME,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_NAME,
|
||||
)
|
||||
)
|
||||
.apply {
|
||||
@@ -243,13 +272,16 @@ class KeyguardQuickAffordanceProvider :
|
||||
private suspend fun queryAffordances(): Cursor {
|
||||
return MatrixCursor(
|
||||
arrayOf(
|
||||
Contract.AffordanceTable.Columns.ID,
|
||||
Contract.AffordanceTable.Columns.NAME,
|
||||
Contract.AffordanceTable.Columns.ICON,
|
||||
Contract.AffordanceTable.Columns.IS_ENABLED,
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_INSTRUCTIONS,
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_ACTION_TEXT,
|
||||
Contract.AffordanceTable.Columns.ENABLEMENT_COMPONENT_NAME,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ID,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.NAME,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ICON,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.IS_ENABLED,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.ENABLEMENT_INSTRUCTIONS,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.ENABLEMENT_ACTION_TEXT,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns
|
||||
.ENABLEMENT_COMPONENT_NAME,
|
||||
)
|
||||
)
|
||||
.apply {
|
||||
@@ -261,7 +293,8 @@ class KeyguardQuickAffordanceProvider :
|
||||
representation.iconResourceId,
|
||||
if (representation.isEnabled) 1 else 0,
|
||||
representation.instructions?.joinToString(
|
||||
Contract.AffordanceTable.ENABLEMENT_INSTRUCTIONS_DELIMITER
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable
|
||||
.ENABLEMENT_INSTRUCTIONS_DELIMITER
|
||||
),
|
||||
representation.actionText,
|
||||
representation.actionComponentName,
|
||||
@@ -274,8 +307,8 @@ class KeyguardQuickAffordanceProvider :
|
||||
private fun querySlots(): Cursor {
|
||||
return MatrixCursor(
|
||||
arrayOf(
|
||||
Contract.SlotTable.Columns.ID,
|
||||
Contract.SlotTable.Columns.CAPACITY,
|
||||
Contract.LockScreenQuickAffordances.SlotTable.Columns.ID,
|
||||
Contract.LockScreenQuickAffordances.SlotTable.Columns.CAPACITY,
|
||||
)
|
||||
)
|
||||
.apply {
|
||||
@@ -22,7 +22,7 @@ import android.content.Intent
|
||||
import com.android.systemui.animation.Expandable
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Defines interface that can act as data source for a single quick affordance model. */
|
||||
@@ -90,8 +90,9 @@ interface KeyguardQuickAffordanceConfig {
|
||||
* the user to be able to set up the quick affordance and make it enabled.
|
||||
*
|
||||
* This is either just an action for the `Intent` or a package name and action,
|
||||
* separated by [Contract.AffordanceTable.COMPONENT_NAME_SEPARATOR] for convenience, you
|
||||
* can use the [componentName] function.
|
||||
* separated by
|
||||
* [Contract.LockScreenQuickAffordances.AffordanceTable.COMPONENT_NAME_SEPARATOR] for
|
||||
* convenience, you can use the [componentName] function.
|
||||
*/
|
||||
val actionComponentName: String? = null,
|
||||
) : PickerScreenState() {
|
||||
@@ -145,8 +146,8 @@ interface KeyguardQuickAffordanceConfig {
|
||||
|
||||
/**
|
||||
* Returning this as a result from the [onTriggered] method means that the implementation
|
||||
* has _not_ taken care of the action and the system should show a Dialog using the
|
||||
* given [AlertDialog] and [Expandable].
|
||||
* has _not_ taken care of the action and the system should show a Dialog using the given
|
||||
* [AlertDialog] and [Expandable].
|
||||
*/
|
||||
data class ShowDialog(
|
||||
val dialog: AlertDialog,
|
||||
@@ -162,7 +163,8 @@ interface KeyguardQuickAffordanceConfig {
|
||||
return when {
|
||||
action.isNullOrEmpty() -> null
|
||||
!packageName.isNullOrEmpty() ->
|
||||
"$packageName${Contract.AffordanceTable.COMPONENT_NAME_SEPARATOR}$action"
|
||||
"$packageName${Contract.LockScreenQuickAffordances.AffordanceTable
|
||||
.COMPONENT_NAME_SEPARATOR}$action"
|
||||
else -> action
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ package com.android.systemui.keyguard.data.quickaffordance
|
||||
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClientImpl
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderClientImpl
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
|
||||
interface KeyguardQuickAffordanceProviderClientFactory {
|
||||
fun create(): KeyguardQuickAffordanceProviderClient
|
||||
fun create(): CustomizationProviderClient
|
||||
}
|
||||
|
||||
class KeyguardQuickAffordanceProviderClientFactoryImpl
|
||||
@@ -34,8 +34,8 @@ constructor(
|
||||
private val userTracker: UserTracker,
|
||||
@Background private val backgroundDispatcher: CoroutineDispatcher,
|
||||
) : KeyguardQuickAffordanceProviderClientFactory {
|
||||
override fun create(): KeyguardQuickAffordanceProviderClient {
|
||||
return KeyguardQuickAffordanceProviderClientImpl(
|
||||
override fun create(): CustomizationProviderClient {
|
||||
return CustomizationProviderClientImpl(
|
||||
context = userTracker.userContext,
|
||||
backgroundDispatcher = backgroundDispatcher,
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -69,7 +69,7 @@ constructor(
|
||||
awaitClose { userTracker.removeCallback(callback) }
|
||||
}
|
||||
|
||||
private val clientOrNull: StateFlow<KeyguardQuickAffordanceProviderClient?> =
|
||||
private val clientOrNull: StateFlow<CustomizationProviderClient?> =
|
||||
userId
|
||||
.distinctUntilChanged()
|
||||
.map { selectedUserId ->
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentati
|
||||
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
|
||||
import com.android.systemui.statusbar.phone.SystemUIDialog
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import dagger.Lazy
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
tools:replace="android:authorities"
|
||||
tools:node="remove" />
|
||||
|
||||
<provider android:name="com.android.systemui.keyguard.KeyguardQuickAffordanceProvider"
|
||||
<provider android:name="com.android.systemui.keyguard.CustomizationProvider"
|
||||
android:authorities="com.android.systemui.test.keyguard.quickaffordance.disabled"
|
||||
android:enabled="false"
|
||||
tools:replace="android:authorities"
|
||||
|
||||
@@ -49,8 +49,8 @@ import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.settings.UserFileManager
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
|
||||
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderContract as Contract
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.util.FakeSharedPreferences
|
||||
import com.android.systemui.util.mockito.any
|
||||
@@ -75,7 +75,7 @@ import org.mockito.MockitoAnnotations
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||
class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
class CustomizationProviderTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var lockPatternUtils: LockPatternUtils
|
||||
@Mock private lateinit var keyguardStateController: KeyguardStateController
|
||||
@@ -87,7 +87,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
@Mock private lateinit var previewSurfacePackage: SurfaceControlViewHost.SurfacePackage
|
||||
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
|
||||
|
||||
private lateinit var underTest: KeyguardQuickAffordanceProvider
|
||||
private lateinit var underTest: CustomizationProvider
|
||||
|
||||
private lateinit var testScope: TestScope
|
||||
|
||||
@@ -98,7 +98,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
whenever(previewRendererFactory.create(any())).thenReturn(previewRenderer)
|
||||
whenever(backgroundHandler.looper).thenReturn(TestableLooper.get(this).looper)
|
||||
|
||||
underTest = KeyguardQuickAffordanceProvider()
|
||||
underTest = CustomizationProvider()
|
||||
val testDispatcher = StandardTestDispatcher()
|
||||
testScope = TestScope(testDispatcher)
|
||||
val localUserSelectionManager =
|
||||
@@ -205,19 +205,34 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun getType() {
|
||||
assertThat(underTest.getType(Contract.AffordanceTable.URI))
|
||||
assertThat(underTest.getType(Contract.LockScreenQuickAffordances.AffordanceTable.URI))
|
||||
.isEqualTo(
|
||||
"vnd.android.cursor.dir/vnd." +
|
||||
"${Contract.AUTHORITY}.${Contract.AffordanceTable.TABLE_NAME}"
|
||||
"${Contract.AUTHORITY}." +
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.TABLE_NAME
|
||||
)
|
||||
)
|
||||
assertThat(underTest.getType(Contract.SlotTable.URI))
|
||||
assertThat(underTest.getType(Contract.LockScreenQuickAffordances.SlotTable.URI))
|
||||
.isEqualTo(
|
||||
"vnd.android.cursor.dir/vnd.${Contract.AUTHORITY}.${Contract.SlotTable.TABLE_NAME}"
|
||||
"vnd.android.cursor.dir/vnd.${Contract.AUTHORITY}." +
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.TABLE_NAME
|
||||
)
|
||||
)
|
||||
assertThat(underTest.getType(Contract.SelectionTable.URI))
|
||||
assertThat(underTest.getType(Contract.LockScreenQuickAffordances.SelectionTable.URI))
|
||||
.isEqualTo(
|
||||
"vnd.android.cursor.dir/vnd." +
|
||||
"${Contract.AUTHORITY}.${Contract.SelectionTable.TABLE_NAME}"
|
||||
"${Contract.AUTHORITY}." +
|
||||
Contract.LockScreenQuickAffordances.qualifiedTablePath(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.TABLE_NAME
|
||||
)
|
||||
)
|
||||
assertThat(underTest.getType(Contract.FlagsTable.URI))
|
||||
.isEqualTo(
|
||||
"vnd.android.cursor.dir/vnd." +
|
||||
"${Contract.AUTHORITY}." +
|
||||
Contract.FlagsTable.TABLE_NAME
|
||||
)
|
||||
}
|
||||
|
||||
@@ -296,9 +311,10 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
)
|
||||
|
||||
context.contentResolver.delete(
|
||||
Contract.SelectionTable.URI,
|
||||
"${Contract.SelectionTable.Columns.SLOT_ID} = ? AND" +
|
||||
" ${Contract.SelectionTable.Columns.AFFORDANCE_ID} = ?",
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
"${Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID} = ? AND" +
|
||||
" ${Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID}" +
|
||||
" = ?",
|
||||
arrayOf(
|
||||
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
|
||||
AFFORDANCE_2,
|
||||
@@ -330,8 +346,8 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
)
|
||||
|
||||
context.contentResolver.delete(
|
||||
Contract.SelectionTable.URI,
|
||||
Contract.SelectionTable.Columns.SLOT_ID,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID,
|
||||
arrayOf(
|
||||
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
|
||||
),
|
||||
@@ -371,10 +387,13 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
affordanceId: String,
|
||||
) {
|
||||
context.contentResolver.insert(
|
||||
Contract.SelectionTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
ContentValues().apply {
|
||||
put(Contract.SelectionTable.Columns.SLOT_ID, slotId)
|
||||
put(Contract.SelectionTable.Columns.AFFORDANCE_ID, affordanceId)
|
||||
put(Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID, slotId)
|
||||
put(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID,
|
||||
affordanceId
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -382,7 +401,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
private fun querySelections(): List<Selection> {
|
||||
return context.contentResolver
|
||||
.query(
|
||||
Contract.SelectionTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -391,11 +410,18 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
?.use { cursor ->
|
||||
buildList {
|
||||
val slotIdColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SelectionTable.Columns.SLOT_ID)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.SLOT_ID
|
||||
)
|
||||
val affordanceIdColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_ID)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns.AFFORDANCE_ID
|
||||
)
|
||||
val affordanceNameColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_NAME)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SelectionTable.Columns
|
||||
.AFFORDANCE_NAME
|
||||
)
|
||||
if (
|
||||
slotIdColumnIndex == -1 ||
|
||||
affordanceIdColumnIndex == -1 ||
|
||||
@@ -421,7 +447,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
private fun querySlots(): List<Slot> {
|
||||
return context.contentResolver
|
||||
.query(
|
||||
Contract.SlotTable.URI,
|
||||
Contract.LockScreenQuickAffordances.SlotTable.URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -429,9 +455,14 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
)
|
||||
?.use { cursor ->
|
||||
buildList {
|
||||
val idColumnIndex = cursor.getColumnIndex(Contract.SlotTable.Columns.ID)
|
||||
val idColumnIndex =
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.Columns.ID
|
||||
)
|
||||
val capacityColumnIndex =
|
||||
cursor.getColumnIndex(Contract.SlotTable.Columns.CAPACITY)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.SlotTable.Columns.CAPACITY
|
||||
)
|
||||
if (idColumnIndex == -1 || capacityColumnIndex == -1) {
|
||||
return@buildList
|
||||
}
|
||||
@@ -452,7 +483,7 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
private fun queryAffordances(): List<Affordance> {
|
||||
return context.contentResolver
|
||||
.query(
|
||||
Contract.AffordanceTable.URI,
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.URI,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
@@ -460,11 +491,18 @@ class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
|
||||
)
|
||||
?.use { cursor ->
|
||||
buildList {
|
||||
val idColumnIndex = cursor.getColumnIndex(Contract.AffordanceTable.Columns.ID)
|
||||
val idColumnIndex =
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ID
|
||||
)
|
||||
val nameColumnIndex =
|
||||
cursor.getColumnIndex(Contract.AffordanceTable.Columns.NAME)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.NAME
|
||||
)
|
||||
val iconColumnIndex =
|
||||
cursor.getColumnIndex(Contract.AffordanceTable.Columns.ICON)
|
||||
cursor.getColumnIndex(
|
||||
Contract.LockScreenQuickAffordances.AffordanceTable.Columns.ICON
|
||||
)
|
||||
if (idColumnIndex == -1 || nameColumnIndex == -1 || iconColumnIndex == -1) {
|
||||
return@buildList
|
||||
}
|
||||
@@ -22,8 +22,8 @@ import android.os.UserHandle
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.settings.FakeUserTracker
|
||||
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
|
||||
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
|
||||
import com.android.systemui.shared.quickaffordance.data.content.FakeKeyguardQuickAffordanceProviderClient
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -54,16 +54,16 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
private lateinit var testScope: TestScope
|
||||
private lateinit var testDispatcher: TestDispatcher
|
||||
private lateinit var userTracker: FakeUserTracker
|
||||
private lateinit var client1: FakeKeyguardQuickAffordanceProviderClient
|
||||
private lateinit var client2: FakeKeyguardQuickAffordanceProviderClient
|
||||
private lateinit var client1: FakeCustomizationProviderClient
|
||||
private lateinit var client2: FakeCustomizationProviderClient
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
whenever(userHandle.identifier).thenReturn(UserHandle.USER_SYSTEM)
|
||||
whenever(userHandle.isSystem).thenReturn(true)
|
||||
client1 = FakeKeyguardQuickAffordanceProviderClient()
|
||||
client2 = FakeKeyguardQuickAffordanceProviderClient()
|
||||
client1 = FakeCustomizationProviderClient()
|
||||
client2 = FakeCustomizationProviderClient()
|
||||
|
||||
userTracker = FakeUserTracker()
|
||||
userTracker.set(
|
||||
@@ -122,11 +122,11 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
|
||||
client1.insertSelection(
|
||||
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
|
||||
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
|
||||
affordanceId = FakeCustomizationProviderClient.AFFORDANCE_1,
|
||||
)
|
||||
client2.insertSelection(
|
||||
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
|
||||
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2,
|
||||
affordanceId = FakeCustomizationProviderClient.AFFORDANCE_2,
|
||||
)
|
||||
|
||||
userTracker.set(
|
||||
@@ -139,7 +139,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
mapOf(
|
||||
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
|
||||
listOf(
|
||||
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
|
||||
FakeCustomizationProviderClient.AFFORDANCE_1,
|
||||
),
|
||||
)
|
||||
)
|
||||
@@ -154,7 +154,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
mapOf(
|
||||
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END to
|
||||
listOf(
|
||||
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2,
|
||||
FakeCustomizationProviderClient.AFFORDANCE_2,
|
||||
),
|
||||
)
|
||||
)
|
||||
@@ -174,7 +174,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
|
||||
client1.insertSelection(
|
||||
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
|
||||
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
|
||||
affordanceId = FakeCustomizationProviderClient.AFFORDANCE_1,
|
||||
)
|
||||
userTracker.set(
|
||||
userInfos = userTracker.userProfiles,
|
||||
@@ -197,7 +197,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
|
||||
underTest.setSelections(
|
||||
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
|
||||
affordanceIds = listOf(FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1),
|
||||
affordanceIds = listOf(FakeCustomizationProviderClient.AFFORDANCE_1),
|
||||
)
|
||||
runCurrent()
|
||||
|
||||
@@ -206,7 +206,7 @@ class KeyguardQuickAffordanceRemoteUserSelectionManagerTest : SysuiTestCase() {
|
||||
mapOf(
|
||||
KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
|
||||
listOf(
|
||||
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1,
|
||||
FakeCustomizationProviderClient.AFFORDANCE_1,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -32,8 +32,8 @@ import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePickerR
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardSlotPickerRepresentation
|
||||
import com.android.systemui.settings.FakeUserTracker
|
||||
import com.android.systemui.settings.UserFileManager
|
||||
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
|
||||
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
|
||||
import com.android.systemui.shared.quickaffordance.data.content.FakeKeyguardQuickAffordanceProviderClient
|
||||
import com.android.systemui.util.FakeSharedPreferences
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
@@ -63,19 +63,13 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
|
||||
private lateinit var config1: FakeKeyguardQuickAffordanceConfig
|
||||
private lateinit var config2: FakeKeyguardQuickAffordanceConfig
|
||||
private lateinit var userTracker: FakeUserTracker
|
||||
private lateinit var client1: FakeKeyguardQuickAffordanceProviderClient
|
||||
private lateinit var client2: FakeKeyguardQuickAffordanceProviderClient
|
||||
private lateinit var client1: FakeCustomizationProviderClient
|
||||
private lateinit var client2: FakeCustomizationProviderClient
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
config1 =
|
||||
FakeKeyguardQuickAffordanceConfig(
|
||||
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_1
|
||||
)
|
||||
config2 =
|
||||
FakeKeyguardQuickAffordanceConfig(
|
||||
FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2
|
||||
)
|
||||
config1 = FakeKeyguardQuickAffordanceConfig(FakeCustomizationProviderClient.AFFORDANCE_1)
|
||||
config2 = FakeKeyguardQuickAffordanceConfig(FakeCustomizationProviderClient.AFFORDANCE_2)
|
||||
val scope = CoroutineScope(IMMEDIATE)
|
||||
userTracker = FakeUserTracker()
|
||||
val localUserSelectionManager =
|
||||
@@ -95,8 +89,8 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
|
||||
userTracker = userTracker,
|
||||
broadcastDispatcher = fakeBroadcastDispatcher,
|
||||
)
|
||||
client1 = FakeKeyguardQuickAffordanceProviderClient()
|
||||
client2 = FakeKeyguardQuickAffordanceProviderClient()
|
||||
client1 = FakeCustomizationProviderClient()
|
||||
client2 = FakeCustomizationProviderClient()
|
||||
val remoteUserSelectionManager =
|
||||
KeyguardQuickAffordanceRemoteUserSelectionManager(
|
||||
scope = scope,
|
||||
@@ -256,7 +250,7 @@ class KeyguardQuickAffordanceRepositoryTest : SysuiTestCase() {
|
||||
)
|
||||
client2.insertSelection(
|
||||
slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
|
||||
affordanceId = FakeKeyguardQuickAffordanceProviderClient.AFFORDANCE_2,
|
||||
affordanceId = FakeCustomizationProviderClient.AFFORDANCE_2,
|
||||
)
|
||||
val observed = mutableListOf<Map<String, List<KeyguardQuickAffordanceConfig>>>()
|
||||
val job = underTest.selections.onEach { observed.add(it) }.launchIn(this)
|
||||
|
||||
@@ -18,17 +18,17 @@
|
||||
package com.android.systemui.keyguard.data.quickaffordance
|
||||
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.shared.quickaffordance.data.content.FakeKeyguardQuickAffordanceProviderClient
|
||||
import com.android.systemui.shared.quickaffordance.data.content.KeyguardQuickAffordanceProviderClient
|
||||
import com.android.systemui.shared.customization.data.content.CustomizationProviderClient
|
||||
import com.android.systemui.shared.customization.data.content.FakeCustomizationProviderClient
|
||||
|
||||
class FakeKeyguardQuickAffordanceProviderClientFactory(
|
||||
private val userTracker: UserTracker,
|
||||
private val callback: (Int) -> KeyguardQuickAffordanceProviderClient = {
|
||||
FakeKeyguardQuickAffordanceProviderClient()
|
||||
private val callback: (Int) -> CustomizationProviderClient = {
|
||||
FakeCustomizationProviderClient()
|
||||
},
|
||||
) : KeyguardQuickAffordanceProviderClientFactory {
|
||||
|
||||
override fun create(): KeyguardQuickAffordanceProviderClient {
|
||||
override fun create(): CustomizationProviderClient {
|
||||
return callback(userTracker.userId)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user