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

Commit 8f659543 authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

Introduce a CustomIconCache for editing favorites

The cache will store custom icons for the current component and will
clear whenever the current component changes (as only the current
component can be edited).

Test: manual
Test: atest com.android.systemui.controls
Bug: 161440353
Change-Id: I8ac2e1ee983ad8ab714f050edaa8981a2307beca
parent 07514b61
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.controls

import android.content.ComponentName
import android.graphics.drawable.Icon
import androidx.annotation.GuardedBy
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Icon cache for custom icons sent with controls.
 *
 * It assumes that only one component can be current at the time, to minimize the number of icons
 * stored at a given time.
 */
@Singleton
class CustomIconCache @Inject constructor() {

    private var currentComponent: ComponentName? = null
    @GuardedBy("cache")
    private val cache: MutableMap<String, Icon> = LinkedHashMap()

    /**
     * Store an icon in the cache.
     *
     * If the icons currently stored do not correspond to the component to be stored, the cache is
     * cleared first.
     */
    fun store(component: ComponentName, controlId: String, icon: Icon?) {
        if (component != currentComponent) {
            clear()
            currentComponent = component
        }
        synchronized(cache) {
            if (icon != null) {
                cache.put(controlId, icon)
            } else {
                cache.remove(controlId)
            }
        }
    }

    /**
     * Retrieves a custom icon stored in the cache.
     *
     * It will return null if the component requested is not the one whose icons are stored, or if
     * there is no icon cached for that id.
     */
    fun retrieve(component: ComponentName, controlId: String): Icon? {
        if (component != currentComponent) return null
        return synchronized(cache) {
            cache.get(controlId)
        }
    }

    private fun clear() {
        synchronized(cache) {
            cache.clear()
        }
    }
}
 No newline at end of file
+4 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.globalactions.GlobalActionsComponent
@@ -42,7 +43,8 @@ import javax.inject.Inject
class ControlsEditingActivity @Inject constructor(
    private val controller: ControlsControllerImpl,
    broadcastDispatcher: BroadcastDispatcher,
    private val globalActionsComponent: GlobalActionsComponent
    private val globalActionsComponent: GlobalActionsComponent,
    private val customIconCache: CustomIconCache
) : LifecycleActivity() {

    companion object {
@@ -170,7 +172,7 @@ class ControlsEditingActivity @Inject constructor(

    private fun setUpList() {
        val controls = controller.getFavoritesForStructure(component, structure)
        model = FavoritesModel(component, controls, favoritesModelCallback)
        model = FavoritesModel(customIconCache, component, controls, favoritesModelCallback)
        val elevation = resources.getFloat(R.dimen.control_card_elevation)
        val recyclerView = requireViewById<RecyclerView>(R.id.list)
        recyclerView.alpha = 0.0f
+17 −2
Original line number Diff line number Diff line
@@ -114,11 +114,27 @@ data class ControlStatusWrapper(
    val controlStatus: ControlStatus
) : ElementWrapper(), ControlInterface by controlStatus

private fun nullIconGetter(_a: ComponentName, _b: String): Icon? = null

data class ControlInfoWrapper(
    override val component: ComponentName,
    val controlInfo: ControlInfo,
    override var favorite: Boolean
) : ElementWrapper(), ControlInterface {

    var customIconGetter: (ComponentName, String) -> Icon? = ::nullIconGetter
        private set

    // Separate constructor so the getter is not used in auto-generated methods
    constructor(
        component: ComponentName,
        controlInfo: ControlInfo,
        favorite: Boolean,
        customIconGetter: (ComponentName, String) -> Icon?
    ): this(component, controlInfo, favorite) {
        this.customIconGetter = customIconGetter
    }

    override val controlId: String
        get() = controlInfo.controlId
    override val title: CharSequence
@@ -128,8 +144,7 @@ data class ControlInfoWrapper(
    override val deviceType: Int
        get() = controlInfo.deviceType
    override val customIcon: Icon?
        // Will need to address to support for edit activity
        get() = null
        get() = customIconGetter(component, controlId)
}

data class DividerWrapper(
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.util.Log
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.controls.ControlInterface
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlInfo
import java.util.Collections

@@ -35,6 +36,7 @@ import java.util.Collections
 * @property favoritesModelCallback callback to notify on first change and empty favorites
 */
class FavoritesModel(
    private val customIconCache: CustomIconCache,
    private val componentName: ComponentName,
    favorites: List<ControlInfo>,
    private val favoritesModelCallback: FavoritesModelCallback
@@ -83,7 +85,7 @@ class FavoritesModel(
        }

    override val elements: List<ElementWrapper> = favorites.map {
        ControlInfoWrapper(componentName, it, true)
        ControlInfoWrapper(componentName, it, true, customIconCache::retrieve)
    } + DividerWrapper()

    /**
+4 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.widget.Space
import android.widget.TextView
import com.android.systemui.R
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.CustomIconCache
import com.android.systemui.controls.controller.ControlInfo
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
@@ -75,7 +76,8 @@ class ControlsUiControllerImpl @Inject constructor (
    @Main val sharedPreferences: SharedPreferences,
    val controlActionCoordinator: ControlActionCoordinator,
    private val activityStarter: ActivityStarter,
    private val shadeController: ShadeController
    private val shadeController: ShadeController,
    private val iconCache: CustomIconCache
) : ControlsUiController {

    companion object {
@@ -502,6 +504,7 @@ class ControlsUiControllerImpl @Inject constructor (
        controls.forEach { c ->
            controlsById.get(ControlKey(componentName, c.getControlId()))?.let {
                Log.d(ControlsUiController.TAG, "onRefreshState() for id: " + c.getControlId())
                iconCache.store(componentName, c.controlId, c.customIcon)
                val cws = ControlWithState(componentName, it.ci, c)
                val key = ControlKey(componentName, c.getControlId())
                controlsById.put(key, cws)
Loading