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

Commit 84371de9 authored by Fabian Kozynski's avatar Fabian Kozynski
Browse files

Remove favorites when app is uninstalled

Whenever an ControlsProviderService is removed, its favorites are
removed and the new set of favorites are stored.

Test: atest ControlsControllerImplTest ControlsBindingControllerImplTest
Test: manual remove and update package
Fixes: 150137085

Change-Id: I64aba1f2513bbd5d1b171ece036555a530e80939
parent 10398d29
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ interface ControlsBindingController : UserAwareController {
     */
    fun unsubscribe()

    /**
     * Notify this controller that this component has been removed (uninstalled).
     */
    fun onComponentRemoved(componentName: ComponentName)

    /**
     * Consumer for load calls.
     *
+12 −0
Original line number Diff line number Diff line
@@ -186,6 +186,18 @@ open class ControlsBindingControllerImpl @Inject constructor(
        }
    }

    override fun onComponentRemoved(componentName: ComponentName) {
        backgroundExecutor.execute {
            synchronized(componentMap) {
                val removed = componentMap.remove(Key(componentName, currentUser))
                removed?.let {
                    it.unbindService()
                    tokenMap.remove(it.token)
                }
            }
        }
    }

    override fun toString(): String {
        return StringBuilder("  ControlsBindingController:\n").apply {
            append("    refreshing=${refreshing.get()}\n")
+31 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.ControlStatus
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Background
@@ -122,6 +123,7 @@ class ControlsControllerImpl @Inject constructor (
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == Intent.ACTION_USER_SWITCHED) {
                userChanging = true
                listingController.removeCallback(listingCallback)
                val newUser =
                        UserHandle.of(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, sendingUserId))
                if (currentUser == newUser) {
@@ -152,6 +154,34 @@ class ControlsControllerImpl @Inject constructor (
        }
    }

    // Handling of removed components

    /**
     * Check if any component has been removed and if so, remove all its favorites.
     *
     * If some component has been removed, the new set of favorites will also be saved.
     */
    private val listingCallback = object : ControlsListingController.ControlsListingCallback {
        override fun onServicesUpdated(candidates: List<ControlsServiceInfo>) {
            executor.execute {
                val candidateComponents = candidates.map(ControlsServiceInfo::componentName)
                synchronized(currentFavorites) {
                    val components = currentFavorites.keys.toSet() // create a copy
                    components.forEach {
                        if (it !in candidateComponents) {
                            currentFavorites.remove(it)
                            bindingController.onComponentRemoved(it)
                        }
                    }
                    // Check if something has been removed, if so, store the new list
                    if (components.size > currentFavorites.size) {
                        persistenceWrapper.storeFavorites(favoritesAsListLocked())
                    }
                }
            }
        }
    }

    init {
        dumpManager.registerDumpable(javaClass.name, this)
        if (available) {
@@ -186,6 +216,7 @@ class ControlsControllerImpl @Inject constructor (
                currentFavorites.getOrPut(it.component, { mutableListOf() }).add(it)
            }
        }
        listingController.addCallback(listingCallback)
    }

    override fun loadForComponent(
+2 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.android.settingslib.applications.DefaultAppInfo
import com.android.settingslib.widget.CandidateInfo
import com.android.systemui.R
import com.android.systemui.controls.ControlsServiceInfo
import java.text.Collator
import java.util.concurrent.Executor

@@ -58,7 +59,7 @@ class AppAdapter(
    private var listOfServices = emptyList<CandidateInfo>()

    private val callback = object : ControlsListingController.ControlsListingCallback {
        override fun onServicesUpdated(candidates: List<CandidateInfo>) {
        override fun onServicesUpdated(candidates: List<ControlsServiceInfo>) {
            backgroundExecutor.execute {
                val collator = Collator.getInstance(resources.configuration.locales[0])
                val localeComparator = compareBy<CandidateInfo, CharSequence>(collator) {
+3 −3
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
package com.android.systemui.controls.management

import android.content.ComponentName
import com.android.settingslib.widget.CandidateInfo
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.UserAwareController
import com.android.systemui.statusbar.policy.CallbackController

@@ -31,7 +31,7 @@ interface ControlsListingController :
    /**
     * @return the current list of services that satisfies the [ServiceListing].
     */
    fun getCurrentServices(): List<CandidateInfo>
    fun getCurrentServices(): List<ControlsServiceInfo>

    /**
     * Get the app label for a given component.
@@ -45,6 +45,6 @@ interface ControlsListingController :

    @FunctionalInterface
    interface ControlsListingCallback {
        fun onServicesUpdated(candidates: List<CandidateInfo>)
        fun onServicesUpdated(candidates: List<ControlsServiceInfo>)
    }
}
Loading