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

Commit 7cbba76b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Controls UI - Add 'reset' option for seeding" into rvc-dev

parents 9f990ded cd757c89
Loading
Loading
Loading
Loading
+72 −22
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ open class ControlsBindingControllerImpl @Inject constructor(
    companion object {
        private const val TAG = "ControlsBindingControllerImpl"
        private const val MAX_CONTROLS_REQUEST = 100000L
        private const val SUGGESTED_CONTROLS_REQUEST = 4L
        private const val SUGGESTED_CONTROLS_REQUEST = 6L
    }

    private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
@@ -61,6 +61,11 @@ open class ControlsBindingControllerImpl @Inject constructor(
     */
    private var statefulControlSubscriber: StatefulControlSubscriber? = null

    /*
     * Will track any active load subscriber. Only one can be active at any time.
     */
    private var loadSubscriber: LoadSubscriber? = null

    private val actionCallbackService = object : IControlsActionCallback.Stub() {
        override fun accept(
            token: IBinder,
@@ -99,17 +104,24 @@ open class ControlsBindingControllerImpl @Inject constructor(
        component: ComponentName,
        callback: ControlsBindingController.LoadCallback
    ): Runnable {
        val subscriber = LoadSubscriber(callback, MAX_CONTROLS_REQUEST)
        retrieveLifecycleManager(component).maybeBindAndLoad(subscriber)
        return subscriber.loadCancel()
        loadSubscriber?.loadCancel()

        val ls = LoadSubscriber(callback, MAX_CONTROLS_REQUEST)
        loadSubscriber = ls

        retrieveLifecycleManager(component).maybeBindAndLoad(ls)
        return ls.loadCancel()
    }

    override fun bindAndLoadSuggested(
        component: ComponentName,
        callback: ControlsBindingController.LoadCallback
    ) {
        val subscriber = LoadSubscriber(callback, SUGGESTED_CONTROLS_REQUEST)
        retrieveLifecycleManager(component).maybeBindAndLoadSuggested(subscriber)
        loadSubscriber?.loadCancel()
        val ls = LoadSubscriber(callback, SUGGESTED_CONTROLS_REQUEST)
        loadSubscriber = ls

        retrieveLifecycleManager(component).maybeBindAndLoadSuggested(ls)
    }

    override fun subscribe(structureInfo: StructureInfo) {
@@ -152,13 +164,16 @@ open class ControlsBindingControllerImpl @Inject constructor(
    override fun changeUser(newUser: UserHandle) {
        if (newUser == currentUser) return

        unsubscribe()
        unbind()
        currentProvider = null
        currentUser = newUser
    }

    private fun unbind() {
        unsubscribe()

        loadSubscriber?.loadCancel()
        loadSubscriber = null

        currentProvider?.unbindService()
        currentProvider = null
    }
@@ -210,6 +225,20 @@ open class ControlsBindingControllerImpl @Inject constructor(
        val callback: ControlsBindingController.LoadCallback
    ) : CallbackRunnable(token) {
        override fun doRun() {
            Log.d(TAG, "LoadSubscription: Complete and loading controls")
            callback.accept(list)
        }
    }

    private inner class OnCancelAndLoadRunnable(
        token: IBinder,
        val list: List<Control>,
        val subscription: IControlsSubscription,
        val callback: ControlsBindingController.LoadCallback
    ) : CallbackRunnable(token) {
        override fun doRun() {
            Log.d(TAG, "LoadSubscription: Canceling and loading controls")
            provider?.cancelSubscription(subscription)
            callback.accept(list)
        }
    }
@@ -220,6 +249,7 @@ open class ControlsBindingControllerImpl @Inject constructor(
        val requestLimit: Long
    ) : CallbackRunnable(token) {
        override fun doRun() {
            Log.d(TAG, "LoadSubscription: Starting subscription")
            provider?.startSubscription(subscription, requestLimit)
        }
    }
@@ -254,34 +284,54 @@ open class ControlsBindingControllerImpl @Inject constructor(
        val requestLimit: Long
    ) : IControlsSubscriber.Stub() {
        val loadedControls = ArrayList<Control>()
        var hasError = false
        private var isTerminated = false
        private var _loadCancelInternal: (() -> Unit)? = null
        private lateinit var subscription: IControlsSubscription

        fun loadCancel() = Runnable {
            Log.d(TAG, "Cancel load requested")
            _loadCancelInternal?.invoke()
        }

        override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
            _loadCancelInternal = subs::cancel
            subscription = subs
            _loadCancelInternal = { currentProvider?.cancelSubscription(subscription) }
            backgroundExecutor.execute(OnSubscribeRunnable(token, subs, requestLimit))
        }

        override fun onNext(token: IBinder, c: Control) {
            backgroundExecutor.execute { loadedControls.add(c) }
            backgroundExecutor.execute {
                if (isTerminated) return@execute

                loadedControls.add(c)

                // Once we have reached our requestLimit, send a request to cancel, and immediately
                // load the results. Calls to onError() and onComplete() are not required after
                // cancel.
                if (loadedControls.size >= requestLimit) {
                    maybeTerminateAndRun(
                        OnCancelAndLoadRunnable(token, loadedControls, subscription, callback)
                    )
                }
            }
        }

        override fun onError(token: IBinder, s: String) {
            hasError = true
            _loadCancelInternal = {}
            currentProvider?.cancelLoadTimeout()
            backgroundExecutor.execute(OnLoadErrorRunnable(token, s, callback))
            maybeTerminateAndRun(OnLoadErrorRunnable(token, s, callback))
        }

        override fun onComplete(token: IBinder) {
            maybeTerminateAndRun(OnLoadRunnable(token, loadedControls, callback))
        }

        private fun maybeTerminateAndRun(postTerminateFn: Runnable) {
            if (isTerminated) return

            isTerminated = true
            _loadCancelInternal = {}
            if (!hasError) {
            currentProvider?.cancelLoadTimeout()
                backgroundExecutor.execute(OnLoadRunnable(token, loadedControls, callback))
            }

            backgroundExecutor.execute(postTerminateFn)
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -179,6 +179,11 @@ interface ControlsController : UserAwareController {
     */
    fun countFavoritesForComponent(componentName: ComponentName): Int

    /**
     * TEMPORARY for testing
     */
    fun resetFavorites()

    /**
     * Interface for structure to pass data to [ControlsFavoritingActivity].
     */
+9 −0
Original line number Diff line number Diff line
@@ -365,6 +365,8 @@ class ControlsControllerImpl @Inject constructor (
        componentName: ComponentName,
        callback: Consumer<Boolean>
    ) {
        if (seedingInProgress) return

        Log.i(TAG, "Beginning request to seed favorites for: $componentName")
        if (!confirmAvailability()) {
            if (userChanging) {
@@ -495,6 +497,13 @@ class ControlsControllerImpl @Inject constructor (
        }
    }

    override fun resetFavorites() {
        executor.execute {
            Favorites.clear()
            persistenceWrapper.storeFavorites(Favorites.getAllStructures())
        }
    }

    override fun refreshStatus(componentName: ComponentName, control: Control) {
        if (!confirmAvailability()) {
            Log.d(TAG, "Controls not available")
+3 −20
Original line number Diff line number Diff line
@@ -63,8 +63,6 @@ class ControlsProviderLifecycleManager(
) : IBinder.DeathRecipient {

    val token: IBinder = Binder()
    @GuardedBy("subscriptions")
    private val subscriptions = mutableListOf<IControlsSubscription>()
    private var requiresBound = false
    @GuardedBy("queuedServiceMethods")
    private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet()
@@ -194,7 +192,7 @@ class ControlsProviderLifecycleManager(
     * Request a call to [IControlsProvider.loadSuggested].
     *
     * If the service is not bound, the call will be queued and the service will be bound first.
     * The service will be unbound after the controls are returned or the call times out.
     * The service will be unbound if the call times out.
     *
     * @param subscriber the subscriber that manages coordination for loading controls
     */
@@ -245,9 +243,7 @@ class ControlsProviderLifecycleManager(
        if (DEBUG) {
            Log.d(TAG, "startSubscription: $subscription")
        }
        synchronized(subscriptions) {
            subscriptions.add(subscription)
        }

        wrapper?.request(subscription, requestLimit)
    }

@@ -261,9 +257,7 @@ class ControlsProviderLifecycleManager(
        if (DEBUG) {
            Log.d(TAG, "cancelSubscription: $subscription")
        }
        synchronized(subscriptions) {
            subscriptions.remove(subscription)
        }

        wrapper?.cancel(subscription)
    }

@@ -281,17 +275,6 @@ class ControlsProviderLifecycleManager(
        onLoadCanceller?.run()
        onLoadCanceller = null

        // be sure to cancel all subscriptions
        val subs = synchronized(subscriptions) {
            ArrayList(subscriptions).also {
                subscriptions.clear()
            }
        }

        subs.forEach {
            wrapper?.cancel(it)
        }

        bindService(false)
    }

+61 −2
Original line number Diff line number Diff line
@@ -16,18 +16,26 @@

package com.android.systemui.controls.ui

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.app.AlertDialog
import android.app.Dialog
import android.content.ComponentName
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Process
import android.service.controls.Control
import android.service.controls.actions.ControlAction
import android.util.TypedValue
import android.util.Log
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
@@ -77,6 +85,8 @@ class ControlsUiControllerImpl @Inject constructor (
        private const val PREF_COMPONENT = "controls_component"
        private const val PREF_STRUCTURE = "controls_structure"

        private const val FADE_IN_MILLIS = 225L

        private val EMPTY_COMPONENT = ComponentName("", "")
        private val EMPTY_STRUCTURE = StructureInfo(
            EMPTY_COMPONENT,
@@ -153,7 +163,20 @@ class ControlsUiControllerImpl @Inject constructor (

    private fun reload(parent: ViewGroup) {
        if (hidden) return

        val fadeAnim = ObjectAnimator.ofFloat(parent, "alpha", 1.0f, 0.0f)
        fadeAnim.setInterpolator(AccelerateInterpolator(1.0f))
        fadeAnim.setDuration(FADE_IN_MILLIS)
        fadeAnim.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                show(parent)
                val showAnim = ObjectAnimator.ofFloat(parent, "alpha", 0.0f, 1.0f)
                showAnim.setInterpolator(DecelerateInterpolator(1.0f))
                showAnim.setDuration(FADE_IN_MILLIS)
                showAnim.start()
            }
        })
        fadeAnim.start()
    }

    private fun showSeedingView(items: List<SelectionItem>) {
@@ -229,7 +252,8 @@ class ControlsUiControllerImpl @Inject constructor (

    private fun createMenu() {
        val items = arrayOf(
            context.resources.getString(R.string.controls_menu_add)
            context.resources.getString(R.string.controls_menu_add),
            "Reset"
        )
        var adapter = ArrayAdapter<String>(context, R.layout.controls_more_item, items)

@@ -249,6 +273,8 @@ class ControlsUiControllerImpl @Inject constructor (
                            when (pos) {
                                // 0: Add Control
                                0 -> startFavoritingActivity(view.context, selectedStructure)
                                // 1: TEMPORARY for reset controls
                                1 -> showResetConfirmation()
                                else -> Log.w(ControlsUiController.TAG,
                                    "Unsupported index ($pos) on 'more' menu selection")
                            }
@@ -275,6 +301,39 @@ class ControlsUiControllerImpl @Inject constructor (
        })
    }

    private fun showResetConfirmation() {
        val builder = AlertDialog.Builder(
            context,
            android.R.style.Theme_DeviceDefault_Dialog_Alert
        ).apply {
            setMessage("For testing purposes: Would you like to " +
                "reset your favorited device controls?")
            setPositiveButton(
                android.R.string.ok,
                DialogInterface.OnClickListener { dialog, _ ->
                    val userHandle = Process.myUserHandle()
                    val userContext = context.createContextAsUser(userHandle, 0)
                    val prefs = userContext.getSharedPreferences(
                        "controls_prefs", Context.MODE_PRIVATE)
                    prefs.edit().putBoolean("ControlsSeedingCompleted", false).apply()
                    controlsController.get().resetFavorites()
                    dialog.dismiss()
                    context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
            })
            setNegativeButton(
                android.R.string.cancel,
                DialogInterface.OnClickListener {
                    dialog, _ -> dialog.cancel()
                }
            )
        }
        builder.create().apply {
            getWindow().apply {
                setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
            }
        }.show()
    }

    private fun createDropDown(items: List<SelectionItem>) {
        items.forEach {
            RenderInfo.registerComponentIcon(it.componentName, it.icon)
Loading