Merge "Controls UI - Add 'reset' option for seeding" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
7cbba76be9
@@ -45,7 +45,7 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "ControlsBindingControllerImpl"
|
private const val TAG = "ControlsBindingControllerImpl"
|
||||||
private const val MAX_CONTROLS_REQUEST = 100000L
|
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())
|
private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
|
||||||
@@ -61,6 +61,11 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
private var statefulControlSubscriber: StatefulControlSubscriber? = null
|
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() {
|
private val actionCallbackService = object : IControlsActionCallback.Stub() {
|
||||||
override fun accept(
|
override fun accept(
|
||||||
token: IBinder,
|
token: IBinder,
|
||||||
@@ -99,17 +104,24 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
component: ComponentName,
|
component: ComponentName,
|
||||||
callback: ControlsBindingController.LoadCallback
|
callback: ControlsBindingController.LoadCallback
|
||||||
): Runnable {
|
): Runnable {
|
||||||
val subscriber = LoadSubscriber(callback, MAX_CONTROLS_REQUEST)
|
loadSubscriber?.loadCancel()
|
||||||
retrieveLifecycleManager(component).maybeBindAndLoad(subscriber)
|
|
||||||
return subscriber.loadCancel()
|
val ls = LoadSubscriber(callback, MAX_CONTROLS_REQUEST)
|
||||||
|
loadSubscriber = ls
|
||||||
|
|
||||||
|
retrieveLifecycleManager(component).maybeBindAndLoad(ls)
|
||||||
|
return ls.loadCancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindAndLoadSuggested(
|
override fun bindAndLoadSuggested(
|
||||||
component: ComponentName,
|
component: ComponentName,
|
||||||
callback: ControlsBindingController.LoadCallback
|
callback: ControlsBindingController.LoadCallback
|
||||||
) {
|
) {
|
||||||
val subscriber = LoadSubscriber(callback, SUGGESTED_CONTROLS_REQUEST)
|
loadSubscriber?.loadCancel()
|
||||||
retrieveLifecycleManager(component).maybeBindAndLoadSuggested(subscriber)
|
val ls = LoadSubscriber(callback, SUGGESTED_CONTROLS_REQUEST)
|
||||||
|
loadSubscriber = ls
|
||||||
|
|
||||||
|
retrieveLifecycleManager(component).maybeBindAndLoadSuggested(ls)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun subscribe(structureInfo: StructureInfo) {
|
override fun subscribe(structureInfo: StructureInfo) {
|
||||||
@@ -152,13 +164,16 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
override fun changeUser(newUser: UserHandle) {
|
override fun changeUser(newUser: UserHandle) {
|
||||||
if (newUser == currentUser) return
|
if (newUser == currentUser) return
|
||||||
|
|
||||||
unsubscribe()
|
|
||||||
unbind()
|
unbind()
|
||||||
currentProvider = null
|
|
||||||
currentUser = newUser
|
currentUser = newUser
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unbind() {
|
private fun unbind() {
|
||||||
|
unsubscribe()
|
||||||
|
|
||||||
|
loadSubscriber?.loadCancel()
|
||||||
|
loadSubscriber = null
|
||||||
|
|
||||||
currentProvider?.unbindService()
|
currentProvider?.unbindService()
|
||||||
currentProvider = null
|
currentProvider = null
|
||||||
}
|
}
|
||||||
@@ -210,6 +225,20 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
val callback: ControlsBindingController.LoadCallback
|
val callback: ControlsBindingController.LoadCallback
|
||||||
) : CallbackRunnable(token) {
|
) : CallbackRunnable(token) {
|
||||||
override fun doRun() {
|
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)
|
callback.accept(list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,6 +249,7 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
val requestLimit: Long
|
val requestLimit: Long
|
||||||
) : CallbackRunnable(token) {
|
) : CallbackRunnable(token) {
|
||||||
override fun doRun() {
|
override fun doRun() {
|
||||||
|
Log.d(TAG, "LoadSubscription: Starting subscription")
|
||||||
provider?.startSubscription(subscription, requestLimit)
|
provider?.startSubscription(subscription, requestLimit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,34 +284,54 @@ open class ControlsBindingControllerImpl @Inject constructor(
|
|||||||
val requestLimit: Long
|
val requestLimit: Long
|
||||||
) : IControlsSubscriber.Stub() {
|
) : IControlsSubscriber.Stub() {
|
||||||
val loadedControls = ArrayList<Control>()
|
val loadedControls = ArrayList<Control>()
|
||||||
var hasError = false
|
private var isTerminated = false
|
||||||
private var _loadCancelInternal: (() -> Unit)? = null
|
private var _loadCancelInternal: (() -> Unit)? = null
|
||||||
|
private lateinit var subscription: IControlsSubscription
|
||||||
|
|
||||||
fun loadCancel() = Runnable {
|
fun loadCancel() = Runnable {
|
||||||
Log.d(TAG, "Cancel load requested")
|
Log.d(TAG, "Cancel load requested")
|
||||||
_loadCancelInternal?.invoke()
|
_loadCancelInternal?.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
|
override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
|
||||||
_loadCancelInternal = subs::cancel
|
subscription = subs
|
||||||
|
_loadCancelInternal = { currentProvider?.cancelSubscription(subscription) }
|
||||||
backgroundExecutor.execute(OnSubscribeRunnable(token, subs, requestLimit))
|
backgroundExecutor.execute(OnSubscribeRunnable(token, subs, requestLimit))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(token: IBinder, c: Control) {
|
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) {
|
override fun onError(token: IBinder, s: String) {
|
||||||
hasError = true
|
maybeTerminateAndRun(OnLoadErrorRunnable(token, s, callback))
|
||||||
_loadCancelInternal = {}
|
|
||||||
currentProvider?.cancelLoadTimeout()
|
|
||||||
backgroundExecutor.execute(OnLoadErrorRunnable(token, s, callback))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onComplete(token: IBinder) {
|
override fun onComplete(token: IBinder) {
|
||||||
|
maybeTerminateAndRun(OnLoadRunnable(token, loadedControls, callback))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maybeTerminateAndRun(postTerminateFn: Runnable) {
|
||||||
|
if (isTerminated) return
|
||||||
|
|
||||||
|
isTerminated = true
|
||||||
_loadCancelInternal = {}
|
_loadCancelInternal = {}
|
||||||
if (!hasError) {
|
currentProvider?.cancelLoadTimeout()
|
||||||
currentProvider?.cancelLoadTimeout()
|
|
||||||
backgroundExecutor.execute(OnLoadRunnable(token, loadedControls, callback))
|
backgroundExecutor.execute(postTerminateFn)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,6 +179,11 @@ interface ControlsController : UserAwareController {
|
|||||||
*/
|
*/
|
||||||
fun countFavoritesForComponent(componentName: ComponentName): Int
|
fun countFavoritesForComponent(componentName: ComponentName): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMPORARY for testing
|
||||||
|
*/
|
||||||
|
fun resetFavorites()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for structure to pass data to [ControlsFavoritingActivity].
|
* Interface for structure to pass data to [ControlsFavoritingActivity].
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -365,6 +365,8 @@ class ControlsControllerImpl @Inject constructor (
|
|||||||
componentName: ComponentName,
|
componentName: ComponentName,
|
||||||
callback: Consumer<Boolean>
|
callback: Consumer<Boolean>
|
||||||
) {
|
) {
|
||||||
|
if (seedingInProgress) return
|
||||||
|
|
||||||
Log.i(TAG, "Beginning request to seed favorites for: $componentName")
|
Log.i(TAG, "Beginning request to seed favorites for: $componentName")
|
||||||
if (!confirmAvailability()) {
|
if (!confirmAvailability()) {
|
||||||
if (userChanging) {
|
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) {
|
override fun refreshStatus(componentName: ComponentName, control: Control) {
|
||||||
if (!confirmAvailability()) {
|
if (!confirmAvailability()) {
|
||||||
Log.d(TAG, "Controls not available")
|
Log.d(TAG, "Controls not available")
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ class ControlsProviderLifecycleManager(
|
|||||||
) : IBinder.DeathRecipient {
|
) : IBinder.DeathRecipient {
|
||||||
|
|
||||||
val token: IBinder = Binder()
|
val token: IBinder = Binder()
|
||||||
@GuardedBy("subscriptions")
|
|
||||||
private val subscriptions = mutableListOf<IControlsSubscription>()
|
|
||||||
private var requiresBound = false
|
private var requiresBound = false
|
||||||
@GuardedBy("queuedServiceMethods")
|
@GuardedBy("queuedServiceMethods")
|
||||||
private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet()
|
private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet()
|
||||||
@@ -194,7 +192,7 @@ class ControlsProviderLifecycleManager(
|
|||||||
* Request a call to [IControlsProvider.loadSuggested].
|
* Request a call to [IControlsProvider.loadSuggested].
|
||||||
*
|
*
|
||||||
* If the service is not bound, the call will be queued and the service will be bound first.
|
* 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
|
* @param subscriber the subscriber that manages coordination for loading controls
|
||||||
*/
|
*/
|
||||||
@@ -245,9 +243,7 @@ class ControlsProviderLifecycleManager(
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "startSubscription: $subscription")
|
Log.d(TAG, "startSubscription: $subscription")
|
||||||
}
|
}
|
||||||
synchronized(subscriptions) {
|
|
||||||
subscriptions.add(subscription)
|
|
||||||
}
|
|
||||||
wrapper?.request(subscription, requestLimit)
|
wrapper?.request(subscription, requestLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,9 +257,7 @@ class ControlsProviderLifecycleManager(
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "cancelSubscription: $subscription")
|
Log.d(TAG, "cancelSubscription: $subscription")
|
||||||
}
|
}
|
||||||
synchronized(subscriptions) {
|
|
||||||
subscriptions.remove(subscription)
|
|
||||||
}
|
|
||||||
wrapper?.cancel(subscription)
|
wrapper?.cancel(subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,17 +275,6 @@ class ControlsProviderLifecycleManager(
|
|||||||
onLoadCanceller?.run()
|
onLoadCanceller?.run()
|
||||||
onLoadCanceller = null
|
onLoadCanceller = null
|
||||||
|
|
||||||
// be sure to cancel all subscriptions
|
|
||||||
val subs = synchronized(subscriptions) {
|
|
||||||
ArrayList(subscriptions).also {
|
|
||||||
subscriptions.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subs.forEach {
|
|
||||||
wrapper?.cancel(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
bindService(false)
|
bindService(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,18 +16,26 @@
|
|||||||
|
|
||||||
package com.android.systemui.controls.ui
|
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.app.Dialog
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.LayerDrawable
|
import android.graphics.drawable.LayerDrawable
|
||||||
|
import android.os.Process
|
||||||
import android.service.controls.Control
|
import android.service.controls.Control
|
||||||
import android.service.controls.actions.ControlAction
|
import android.service.controls.actions.ControlAction
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.animation.AccelerateInterpolator
|
||||||
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -77,6 +85,8 @@ class ControlsUiControllerImpl @Inject constructor (
|
|||||||
private const val PREF_COMPONENT = "controls_component"
|
private const val PREF_COMPONENT = "controls_component"
|
||||||
private const val PREF_STRUCTURE = "controls_structure"
|
private const val PREF_STRUCTURE = "controls_structure"
|
||||||
|
|
||||||
|
private const val FADE_IN_MILLIS = 225L
|
||||||
|
|
||||||
private val EMPTY_COMPONENT = ComponentName("", "")
|
private val EMPTY_COMPONENT = ComponentName("", "")
|
||||||
private val EMPTY_STRUCTURE = StructureInfo(
|
private val EMPTY_STRUCTURE = StructureInfo(
|
||||||
EMPTY_COMPONENT,
|
EMPTY_COMPONENT,
|
||||||
@@ -153,7 +163,20 @@ class ControlsUiControllerImpl @Inject constructor (
|
|||||||
|
|
||||||
private fun reload(parent: ViewGroup) {
|
private fun reload(parent: ViewGroup) {
|
||||||
if (hidden) return
|
if (hidden) return
|
||||||
show(parent)
|
|
||||||
|
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>) {
|
private fun showSeedingView(items: List<SelectionItem>) {
|
||||||
@@ -229,7 +252,8 @@ class ControlsUiControllerImpl @Inject constructor (
|
|||||||
|
|
||||||
private fun createMenu() {
|
private fun createMenu() {
|
||||||
val items = arrayOf(
|
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)
|
var adapter = ArrayAdapter<String>(context, R.layout.controls_more_item, items)
|
||||||
|
|
||||||
@@ -249,6 +273,8 @@ class ControlsUiControllerImpl @Inject constructor (
|
|||||||
when (pos) {
|
when (pos) {
|
||||||
// 0: Add Control
|
// 0: Add Control
|
||||||
0 -> startFavoritingActivity(view.context, selectedStructure)
|
0 -> startFavoritingActivity(view.context, selectedStructure)
|
||||||
|
// 1: TEMPORARY for reset controls
|
||||||
|
1 -> showResetConfirmation()
|
||||||
else -> Log.w(ControlsUiController.TAG,
|
else -> Log.w(ControlsUiController.TAG,
|
||||||
"Unsupported index ($pos) on 'more' menu selection")
|
"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>) {
|
private fun createDropDown(items: List<SelectionItem>) {
|
||||||
items.forEach {
|
items.forEach {
|
||||||
RenderInfo.registerComponentIcon(it.componentName, it.icon)
|
RenderInfo.registerComponentIcon(it.componentName, it.icon)
|
||||||
|
|||||||
@@ -205,7 +205,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
|||||||
private final IWindowManager mIWindowManager;
|
private final IWindowManager mIWindowManager;
|
||||||
private final Executor mBackgroundExecutor;
|
private final Executor mBackgroundExecutor;
|
||||||
private final ControlsListingController mControlsListingController;
|
private final ControlsListingController mControlsListingController;
|
||||||
private boolean mAnyControlsProviders = false;
|
private List<ControlsServiceInfo> mControlsServiceInfos = new ArrayList<>();
|
||||||
|
private ControlsController mControlsController;
|
||||||
|
private SharedPreferences mControlsPreferences;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
|
public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
|
||||||
@@ -271,6 +273,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
|||||||
mBackgroundExecutor = backgroundExecutor;
|
mBackgroundExecutor = backgroundExecutor;
|
||||||
mControlsListingController = controlsListingController;
|
mControlsListingController = controlsListingController;
|
||||||
mBlurUtils = blurUtils;
|
mBlurUtils = blurUtils;
|
||||||
|
mControlsController = controlsController;
|
||||||
|
|
||||||
// receive broadcasts
|
// receive broadcasts
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
@@ -309,45 +312,54 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
String preferredControlsPackage = mContext.getResources()
|
|
||||||
.getString(com.android.systemui.R.string.config_controlsPreferredPackage);
|
|
||||||
mControlsListingController.addCallback(list -> {
|
mControlsListingController.addCallback(list -> {
|
||||||
mAnyControlsProviders = !list.isEmpty();
|
mControlsServiceInfos = list;
|
||||||
|
|
||||||
/*
|
|
||||||
* See if any service providers match the preferred component. If they do,
|
|
||||||
* and there are no current favorites, and we haven't successfully loaded favorites to
|
|
||||||
* date, query the preferred component for a limited number of suggested controls.
|
|
||||||
*/
|
|
||||||
ComponentName preferredComponent = null;
|
|
||||||
for (ControlsServiceInfo info : list) {
|
|
||||||
if (info.componentName.getPackageName().equals(preferredControlsPackage)) {
|
|
||||||
preferredComponent = info.componentName;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preferredComponent == null) return;
|
|
||||||
|
|
||||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_CONTROLS_FILE,
|
|
||||||
Context.MODE_PRIVATE);
|
|
||||||
boolean isSeeded = prefs.getBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, false);
|
|
||||||
boolean hasFavorites = controlsController.getFavorites().size() > 0;
|
|
||||||
if (!isSeeded && !hasFavorites) {
|
|
||||||
controlsController.seedFavoritesForComponent(
|
|
||||||
preferredComponent,
|
|
||||||
(accepted) -> {
|
|
||||||
Log.i(TAG, "Controls seeded: " + accepted);
|
|
||||||
prefs.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED,
|
|
||||||
accepted).apply();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Need to be user-specific with the context to make sure we read the correct prefs
|
||||||
|
Context userContext = context.createContextAsUser(
|
||||||
|
new UserHandle(mUserManager.getUserHandle()), 0);
|
||||||
|
mControlsPreferences = userContext.getSharedPreferences(PREFS_CONTROLS_FILE,
|
||||||
|
Context.MODE_PRIVATE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void seedFavorites() {
|
||||||
|
if (mControlsServiceInfos.isEmpty()
|
||||||
|
|| mControlsController.getFavorites().size() > 0
|
||||||
|
|| mControlsPreferences.getBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if any service providers match the preferred component. If they do,
|
||||||
|
* and there are no current favorites, and we haven't successfully loaded favorites to
|
||||||
|
* date, query the preferred component for a limited number of suggested controls.
|
||||||
|
*/
|
||||||
|
String preferredControlsPackage = mContext.getResources()
|
||||||
|
.getString(com.android.systemui.R.string.config_controlsPreferredPackage);
|
||||||
|
|
||||||
|
ComponentName preferredComponent = null;
|
||||||
|
for (ControlsServiceInfo info : mControlsServiceInfos) {
|
||||||
|
if (info.componentName.getPackageName().equals(preferredControlsPackage)) {
|
||||||
|
preferredComponent = info.componentName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preferredComponent == null) {
|
||||||
|
Log.i(TAG, "Controls seeding: No preferred component has been set, will not seed");
|
||||||
|
mControlsPreferences.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, true).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
mControlsController.seedFavoritesForComponent(
|
||||||
|
preferredComponent,
|
||||||
|
(accepted) -> {
|
||||||
|
Log.i(TAG, "Controls seeded: " + accepted);
|
||||||
|
mControlsPreferences.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED,
|
||||||
|
accepted).apply();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the global actions dialog (creating if necessary)
|
* Show the global actions dialog (creating if necessary)
|
||||||
@@ -393,6 +405,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
|||||||
awakenIfNecessary();
|
awakenIfNecessary();
|
||||||
mDialog = createDialog();
|
mDialog = createDialog();
|
||||||
prepareDialog();
|
prepareDialog();
|
||||||
|
seedFavorites();
|
||||||
|
|
||||||
// If we only have 1 item and it's a simple press action, just do this action.
|
// If we only have 1 item and it's a simple press action, just do this action.
|
||||||
if (mAdapter.getCount() == 1
|
if (mAdapter.getCount() == 1
|
||||||
@@ -2017,6 +2030,6 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
|||||||
private boolean shouldShowControls() {
|
private boolean shouldShowControls() {
|
||||||
return mKeyguardStateController.isUnlocked()
|
return mKeyguardStateController.isUnlocked()
|
||||||
&& mControlsUiController.getAvailable()
|
&& mControlsUiController.getAvailable()
|
||||||
&& mAnyControlsProviders;
|
&& !mControlsServiceInfos.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class ControlsBindingControllerImplTest : SysuiTestCase() {
|
|||||||
loadSubscriberCaptor.value.onSubscribe(Binder(), subscription)
|
loadSubscriberCaptor.value.onSubscribe(Binder(), subscription)
|
||||||
|
|
||||||
canceller.run()
|
canceller.run()
|
||||||
verify(subscription).cancel()
|
verify(providers[0]).cancelSubscription(subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -145,7 +145,7 @@ class ControlsBindingControllerImplTest : SysuiTestCase() {
|
|||||||
|
|
||||||
loadSubscriberCaptor.value.onComplete(b)
|
loadSubscriberCaptor.value.onComplete(b)
|
||||||
canceller.run()
|
canceller.run()
|
||||||
verify(subscription, never()).cancel()
|
verify(providers[0], never()).cancelSubscription(subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -203,7 +203,7 @@ class ControlsBindingControllerImplTest : SysuiTestCase() {
|
|||||||
|
|
||||||
loadSubscriberCaptor.value.onError(b, "")
|
loadSubscriberCaptor.value.onError(b, "")
|
||||||
canceller.run()
|
canceller.run()
|
||||||
verify(subscription, never()).cancel()
|
verify(providers[0], never()).cancelSubscription(subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user