Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 102b4d67 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

Renames customization content provider (1/7).

KeyguardQuickAffordanceProvider has started to be used for more than
just lock screen shortcuts. This collection of CLs updates its name,
authority, and table schema to become more generically about "system UI
customization".

Fix: 262879277
Test: manually verified Settings > Display > Lock screen shows the
"shortcuts" item
Test: manually verified that the Wallpaper picker properly renders the
preview and can change the quick affordances
Test: manually verified that system UI displays the right lock screen
shortcuts

Change-Id: Ib1e33d0ddc0be8e0cd3533301cee340f95a27ddd
parent 78a04abb
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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>
+1 −1
Original line number Diff line number Diff line
@@ -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"
+77 −46
Original line number Diff line number Diff line
@@ -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,
                ),
+183 −0
Original line number Diff line number Diff line
/*
 * 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"
        }
    }
}
+27 −32

File changed and moved.

Preview size limit exceeded, changes collapsed.

Loading