Merge "Controls UI - Lock screen support" into rvc-dev

This commit is contained in:
Matt Pietal
2020-04-30 18:58:54 +00:00
committed by Android (Google) Code Review
13 changed files with 275 additions and 121 deletions

View File

@@ -30,6 +30,8 @@ import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.controls.management.ControlsRequestDialog
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.controls.ui.ControlsUiControllerImpl
import com.android.systemui.controls.ui.ControlActionCoordinator
import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
import dagger.Binds
import dagger.BindsOptionalOf
import dagger.Module
@@ -55,6 +57,11 @@ abstract class ControlsModule {
@Binds
abstract fun provideUiController(controller: ControlsUiControllerImpl): ControlsUiController
@Binds
abstract fun provideControlActionCoordinator(
coordinator: ControlActionCoordinatorImpl
): ControlActionCoordinator
@BindsOptionalOf
abstract fun optionalPersistenceWrapper(): ControlsFavoritePersistenceWrapper
@@ -85,4 +92,4 @@ abstract class ControlsModule {
abstract fun provideControlsRequestDialog(
activity: ControlsRequestDialog
): Activity
}
}

View File

@@ -16,89 +16,52 @@
package com.android.systemui.controls.ui
import android.app.Dialog
import android.content.Intent
import android.os.Vibrator
import android.os.VibrationEffect
import android.service.controls.Control
import android.service.controls.actions.BooleanAction
import android.service.controls.actions.CommandAction
import android.view.HapticFeedbackConstants
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.util.concurrency.DelayableExecutor
object ControlActionCoordinator {
const val MIN_LEVEL = 0
const val MAX_LEVEL = 10000
private var dialog: Dialog? = null
private var vibrator: Vibrator? = null
lateinit var bgExecutor: DelayableExecutor
fun closeDialog() {
dialog?.dismiss()
dialog = null
}
/**
* All control interactions should be routed through this coordinator. It handles dispatching of
* actions, haptic support, and all detail panels
*/
interface ControlActionCoordinator {
/**
* Create custom vibrations, all intended to create very subtle feedback while interacting
* with the controls.
* Close any dialogs which may have been open
*/
fun initialize(vibrator: Vibrator, bgExecutor: DelayableExecutor) {
this.vibrator = vibrator
this.bgExecutor = bgExecutor
}
fun closeDialogs()
fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect
vibrate(effect)
cvh.action(BooleanAction(templateId, !isChecked))
}
/**
* Create a [BooleanAction], and inform the service of a request to change the device state
*
* @param cvh [ControlViewHolder] for the control
* @param templateId id of the control's template, as given by the service
* @param isChecked new requested state of the control
*/
fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean)
fun touch(cvh: ControlViewHolder, templateId: String, control: Control) {
vibrate(Vibrations.toggleOnEffect)
if (cvh.usePanel()) {
showDialog(cvh, control.getAppIntent().getIntent())
} else {
cvh.action(CommandAction(templateId))
}
}
/**
* For non-toggle controls, touching may create a dialog or invoke a [CommandAction].
*
* @param cvh [ControlViewHolder] for the control
* @param templateId id of the control's template, as given by the service
* @param control the control as sent by the service
*/
fun touch(cvh: ControlViewHolder, templateId: String, control: Control)
fun drag(isEdge: Boolean) {
if (isEdge) {
vibrate(Vibrations.rangeEdgeEffect)
} else {
vibrate(Vibrations.rangeMiddleEffect)
}
}
/**
* When a ToggleRange control is interacting with, a drag event is sent.
*
* @param isEdge did the drag event reach a control edge
*/
fun drag(isEdge: Boolean)
/**
* All long presses will be shown in a 3/4 height bottomsheet panel, in order for the user to
* retain context with their favorited controls in the power menu.
*/
fun longPress(cvh: ControlViewHolder) {
// Long press snould only be called when there is valid control state, otherwise ignore
cvh.cws.control?.let {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
showDialog(cvh, it.getAppIntent().getIntent())
}
}
fun longPress(cvh: ControlViewHolder)
private fun vibrate(effect: VibrationEffect) {
vibrator?.let {
bgExecutor.execute { it.vibrate(effect) }
}
}
private fun showDialog(cvh: ControlViewHolder, intent: Intent) {
dialog = DetailDialog(cvh, intent).also {
it.setOnDismissListener { _ -> dialog = null }
it.show()
}
}
fun setFocusedElement(cvh: ControlViewHolder?, controlsController: ControlsController) {
controlsController.onFocusChanged(cvh?.cws)
}
/**
* Event to inform the UI that the user has has focused on a single control.
*/
fun setFocusedElement(cvh: ControlViewHolder?)
}

View File

@@ -0,0 +1,126 @@
/*
* 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.ui
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.os.Vibrator
import android.os.VibrationEffect
import android.service.controls.Control
import android.service.controls.actions.BooleanAction
import android.service.controls.actions.CommandAction
import android.util.Log
import android.view.HapticFeedbackConstants
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
import dagger.Lazy
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class ControlActionCoordinatorImpl @Inject constructor(
private val context: Context,
private val bgExecutor: DelayableExecutor,
private val controlsController: Lazy<ControlsController>,
private val activityStarter: ActivityStarter,
private val keyguardStateController: KeyguardStateController,
private val globalActionsComponent: GlobalActionsComponent
) : ControlActionCoordinator {
private var dialog: Dialog? = null
private val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
private var lastAction: (() -> Unit)? = null
override fun closeDialogs() {
dialog?.dismiss()
dialog = null
}
override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
bouncerOrRun {
val effect = if (isChecked) Vibrations.toggleOnEffect else Vibrations.toggleOffEffect
vibrate(effect)
cvh.action(BooleanAction(templateId, !isChecked))
}
}
override fun touch(cvh: ControlViewHolder, templateId: String, control: Control) {
vibrate(Vibrations.toggleOnEffect)
bouncerOrRun {
if (cvh.usePanel()) {
showDialog(cvh, control.getAppIntent().getIntent())
} else {
cvh.action(CommandAction(templateId))
}
}
}
override fun drag(isEdge: Boolean) {
bouncerOrRun {
if (isEdge) {
vibrate(Vibrations.rangeEdgeEffect)
} else {
vibrate(Vibrations.rangeMiddleEffect)
}
}
}
override fun longPress(cvh: ControlViewHolder) {
bouncerOrRun {
// Long press snould only be called when there is valid control state, otherwise ignore
cvh.cws.control?.let {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
showDialog(cvh, it.getAppIntent().getIntent())
}
}
}
override fun setFocusedElement(cvh: ControlViewHolder?) {
controlsController.get().onFocusChanged(cvh?.cws)
}
private fun bouncerOrRun(f: () -> Unit) {
if (!keyguardStateController.isUnlocked()) {
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
activityStarter.dismissKeyguardThenExecute({
Log.d(ControlsUiController.TAG, "Device unlocked, invoking controls action")
globalActionsComponent.handleShowGlobalActionsMenu()
f()
true
}, null, true)
} else {
f()
}
}
private fun vibrate(effect: VibrationEffect) {
bgExecutor.execute { vibrator.vibrate(effect) }
}
private fun showDialog(cvh: ControlViewHolder, intent: Intent) {
dialog = DetailDialog(cvh, intent).also {
it.setOnDismissListener { _ -> dialog = null }
it.show()
}
}
}

View File

@@ -53,7 +53,8 @@ class ControlViewHolder(
val layout: ViewGroup,
val controlsController: ControlsController,
val uiExecutor: DelayableExecutor,
val bgExecutor: DelayableExecutor
val bgExecutor: DelayableExecutor,
val controlActionCoordinator: ControlActionCoordinator
) {
companion object {
@@ -65,6 +66,9 @@ class ControlViewHolder(
DeviceTypes.TYPE_THERMOSTAT,
DeviceTypes.TYPE_CAMERA
)
const val MIN_LEVEL = 0
const val MAX_LEVEL = 10000
}
private val toggleBackgroundIntensity: Float = layout.context.resources
@@ -121,7 +125,7 @@ class ControlViewHolder(
cws.control?.let {
layout.setClickable(true)
layout.setOnLongClickListener(View.OnLongClickListener() {
ControlActionCoordinator.longPress(this@ControlViewHolder)
controlActionCoordinator.longPress(this@ControlViewHolder)
true
})
}

View File

@@ -29,7 +29,6 @@ import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
import android.os.Process
import android.os.Vibrator
import android.service.controls.Control
import android.util.Log
import android.util.TypedValue
@@ -59,6 +58,8 @@ import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
import dagger.Lazy
import java.text.Collator
@@ -75,7 +76,10 @@ class ControlsUiControllerImpl @Inject constructor (
@Main val uiExecutor: DelayableExecutor,
@Background val bgExecutor: DelayableExecutor,
val controlsListingController: Lazy<ControlsListingController>,
@Main val sharedPreferences: SharedPreferences
@Main val sharedPreferences: SharedPreferences,
val controlActionCoordinator: ControlActionCoordinator,
private val activityStarter: ActivityStarter,
private val keyguardStateController: KeyguardStateController
) : ControlsUiController {
companion object {
@@ -107,11 +111,6 @@ class ControlsUiControllerImpl @Inject constructor (
private lateinit var listingCallback: ControlsListingController.ControlsListingCallback
init {
val vibratorService = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
ControlActionCoordinator.initialize(vibratorService, bgExecutor)
}
private fun createCallback(
onResult: (List<SelectionItem>) -> Unit
): ControlsListingController.ControlsListingCallback {
@@ -267,8 +266,16 @@ class ControlsUiControllerImpl @Inject constructor (
private fun startActivity(context: Context, intent: Intent) {
// Force animations when transitioning from a dialog to an activity
intent.putExtra(ControlsUiController.EXTRA_ANIMATE, true)
context.startActivity(intent)
dismissGlobalActions.run()
if (!keyguardStateController.isUnlocked()) {
activityStarter.dismissKeyguardThenExecute({
context.startActivity(intent)
true
}, null, true)
} else {
context.startActivity(intent)
}
}
private fun showControlsView(items: List<SelectionItem>) {
@@ -463,7 +470,8 @@ class ControlsUiControllerImpl @Inject constructor (
baseLayout,
controlsController.get(),
uiExecutor,
bgExecutor
bgExecutor,
controlActionCoordinator
)
cvh.bindData(it)
controlViewsById.put(key, cvh)
@@ -545,9 +553,7 @@ class ControlsUiControllerImpl @Inject constructor (
controlViewsById.forEach {
it.value.dismiss()
}
ControlActionCoordinator.closeDialog()
controlActionCoordinator.closeDialogs()
controlsController.get().unsubscribe()
parent.removeAllViews()

View File

@@ -22,8 +22,8 @@ import android.service.controls.Control
import android.service.controls.templates.TemperatureControlTemplate
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
class TemperatureControlBehavior : Behavior {
lateinit var clipLayer: Drawable
@@ -35,7 +35,7 @@ class TemperatureControlBehavior : Behavior {
this.cvh = cvh
cvh.layout.setOnClickListener { _ ->
ControlActionCoordinator.touch(cvh, template.getTemplateId(), control)
cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control)
}
}

View File

@@ -22,7 +22,7 @@ import android.service.controls.Control
import android.service.controls.templates.ToggleTemplate
import android.view.View
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
class ToggleBehavior : Behavior {
lateinit var clipLayer: Drawable
@@ -35,7 +35,7 @@ class ToggleBehavior : Behavior {
cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)
cvh.layout.setOnClickListener(View.OnClickListener() {
ControlActionCoordinator.toggle(cvh, template.getTemplateId(), template.isChecked())
cvh.controlActionCoordinator.toggle(cvh, template.getTemplateId(), template.isChecked())
})
}

View File

@@ -40,8 +40,8 @@ import android.view.accessibility.AccessibilityNodeInfo
import android.widget.TextView
import com.android.systemui.Interpolators
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL
import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
import java.util.IllegalFormatException
class ToggleRangeBehavior : Behavior {
@@ -141,7 +141,7 @@ class ToggleRangeBehavior : Behavior {
): Boolean {
val handled = when (action) {
AccessibilityNodeInfo.ACTION_CLICK -> {
ControlActionCoordinator.toggle(cvh, template.getTemplateId(),
cvh.controlActionCoordinator.toggle(cvh, template.getTemplateId(),
template.isChecked())
true
}
@@ -175,7 +175,7 @@ class ToggleRangeBehavior : Behavior {
fun beginUpdateRange() {
status.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources()
.getDimensionPixelSize(R.dimen.control_status_expanded).toFloat())
ControlActionCoordinator.setFocusedElement(cvh, cvh.controlsController)
cvh.controlActionCoordinator.setFocusedElement(cvh)
}
fun updateRange(level: Int, checked: Boolean, isDragging: Boolean) {
@@ -187,7 +187,7 @@ class ToggleRangeBehavior : Behavior {
if (isDragging) {
clipLayer.level = newLevel
val isEdge = newLevel == MIN_LEVEL || newLevel == MAX_LEVEL
ControlActionCoordinator.drag(isEdge)
cvh.controlActionCoordinator.drag(isEdge)
} else {
rangeAnimator = ValueAnimator.ofInt(cvh.clipLayer.level, newLevel).apply {
addUpdateListener {
@@ -248,7 +248,7 @@ class ToggleRangeBehavior : Behavior {
status.setText("$currentStatusText $currentRangeValue")
cvh.action(FloatAction(rangeTemplate.getTemplateId(),
findNearestStep(levelToRangeValue(clipLayer.getLevel()))))
ControlActionCoordinator.setFocusedElement(null, cvh.controlsController)
cvh.controlActionCoordinator.setFocusedElement(null)
}
fun findNearestStep(value: Float): Float {
@@ -282,7 +282,7 @@ class ToggleRangeBehavior : Behavior {
if (isDragging) {
return
}
ControlActionCoordinator.longPress(this@ToggleRangeBehavior.cvh)
cvh.controlActionCoordinator.longPress(this@ToggleRangeBehavior.cvh)
}
override fun onScroll(
@@ -309,7 +309,7 @@ class ToggleRangeBehavior : Behavior {
override fun onSingleTapUp(e: MotionEvent): Boolean {
val th = this@ToggleRangeBehavior
ControlActionCoordinator.toggle(th.cvh, th.template.getTemplateId(),
cvh.controlActionCoordinator.toggle(th.cvh, th.template.getTemplateId(),
th.template.isChecked())
return true
}

View File

@@ -23,7 +23,7 @@ import android.service.controls.Control
import android.service.controls.templates.ControlTemplate
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL
import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL
/**
* Supports touch events, but has no notion of state as the {@link ToggleBehavior} does. Must be
@@ -40,7 +40,7 @@ class TouchBehavior : Behavior {
cvh.applyRenderInfo(false /* enabled */, 0 /* offset */, false /* animated */)
cvh.layout.setOnClickListener(View.OnClickListener() {
ControlActionCoordinator.touch(cvh, template.getTemplateId(), control)
cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control)
})
}

View File

@@ -24,6 +24,7 @@ import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.ExtensionController.Extension;
@@ -43,15 +44,18 @@ public class GlobalActionsComponent extends SystemUI implements Callbacks, Globa
private GlobalActions mPlugin;
private Extension<GlobalActions> mExtension;
private IStatusBarService mBarService;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
public GlobalActionsComponent(Context context, CommandQueue commandQueue,
ExtensionController extensionController,
Provider<GlobalActions> globalActionsProvider) {
Provider<GlobalActions> globalActionsProvider,
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
super(context);
mCommandQueue = commandQueue;
mExtensionController = extensionController;
mGlobalActionsProvider = globalActionsProvider;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
}
@Override
@@ -81,6 +85,7 @@ public class GlobalActionsComponent extends SystemUI implements Callbacks, Globa
@Override
public void handleShowGlobalActionsMenu() {
mStatusBarKeyguardViewManager.setGlobalActionsVisible(true);
mExtension.get().showGlobalActions(this);
}
@@ -95,6 +100,7 @@ public class GlobalActionsComponent extends SystemUI implements Callbacks, Globa
@Override
public void onGlobalActionsHidden() {
try {
mStatusBarKeyguardViewManager.setGlobalActionsVisible(false);
mBarService.onGlobalActionsHidden();
} catch (RemoteException e) {
}

View File

@@ -234,6 +234,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private SharedPreferences mControlsPreferences;
private final RingerModeTracker mRingerModeTracker;
private int mDialogPressDelay = DIALOG_PRESS_DELAY; // ms
private Handler mMainHandler;
private boolean mShowLockScreenCardsAndControls = false;
@VisibleForTesting
public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
@@ -288,7 +290,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
@Background Executor backgroundExecutor,
ControlsListingController controlsListingController,
ControlsController controlsController, UiEventLogger uiEventLogger,
RingerModeTracker ringerModeTracker) {
RingerModeTracker ringerModeTracker, @Main Handler handler) {
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
mWindowManagerFuncs = windowManagerFuncs;
mAudioManager = audioManager;
@@ -317,6 +319,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mBlurUtils = blurUtils;
mRingerModeTracker = ringerModeTracker;
mControlsController = controlsController;
mMainHandler = handler;
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -352,10 +355,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
public void onUnlockedChanged() {
if (mDialog != null && mDialog.mPanelController != null) {
if (mDialog != null) {
boolean unlocked = keyguardStateController.isUnlocked()
|| keyguardStateController.canDismissLockScreen();
mDialog.mPanelController.onDeviceLockStateChanged(unlocked);
if (mDialog.mPanelController != null) {
mDialog.mPanelController.onDeviceLockStateChanged(unlocked);
}
if (!mDialog.isShowingControls() && shouldShowControls()) {
mDialog.showControls(mControlsUiController);
}
}
}
});
@@ -370,6 +378,17 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
mControlsPreferences = userContext.getSharedPreferences(PREFS_CONTROLS_FILE,
Context.MODE_PRIVATE);
// Listen for changes to show controls on the power menu while locked
onPowerMenuLockScreenSettingsChanged();
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT),
false /* notifyForDescendants */,
new ContentObserver(mMainHandler) {
@Override
public void onChange(boolean selfChange) {
onPowerMenuLockScreenSettingsChanged();
}
});
}
private void seedFavorites() {
@@ -485,15 +504,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
@VisibleForTesting
protected int getMaxShownPowerItems() {
if (shouldUseControlsLayout()) {
int maxColumns =
mResources.getInteger(com.android.systemui.R.integer.power_menu_max_columns);
// TODO: Overflow temporarily disabled on keyguard to prevent touch issues.
// Show an extra item on the keyguard because the overflow button currently disabled.
if (mKeyguardShowing) {
return maxColumns + 1;
} else {
return maxColumns;
}
return mResources.getInteger(com.android.systemui.R.integer.power_menu_max_columns);
} else {
return Integer.MAX_VALUE;
}
@@ -1804,7 +1815,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
};
private ContentObserver mAirplaneModeObserver = new ContentObserver(new Handler()) {
private ContentObserver mAirplaneModeObserver = new ContentObserver(mMainHandler) {
@Override
public void onChange(boolean selfChange) {
onAirplaneModeChanged();
@@ -1950,6 +1961,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
initializeLayout();
}
private boolean isShowingControls() {
return mControlsUiController != null;
}
private void showControls(ControlsUiController controller) {
mControlsUiController = controller;
mControlsUiController.show(mControlsView, this::dismissForControlsActivity);
}
private boolean shouldUsePanel() {
return mPanelController != null && mPanelController.getPanelContent() != null;
}
@@ -2066,8 +2086,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
View overflowButton = findViewById(
com.android.systemui.R.id.global_actions_overflow_button);
if (overflowButton != null) {
// TODO: Overflow button hidden on keyguard to temporarily prevent touch issues.
if (mOverflowAdapter.getCount() > 0 && !mKeyguardShowing) {
if (mOverflowAdapter.getCount() > 0) {
overflowButton.setOnClickListener((view) -> showPowerOverflowMenu());
LinearLayout.LayoutParams params =
(LinearLayout.LayoutParams) mGlobalActionsLayout.getLayoutParams();
@@ -2354,7 +2373,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
@VisibleForTesting
protected boolean shouldShowControls() {
return mKeyguardStateController.isUnlocked()
boolean isUnlocked = mKeyguardStateController.isUnlocked()
|| mKeyguardStateController.canDismissLockScreen();
return (isUnlocked || mShowLockScreenCardsAndControls)
&& mControlsUiController.getAvailable()
&& !mControlsServiceInfos.isEmpty();
}
@@ -2363,4 +2384,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
// always use new controls layout
return true;
}
private void onPowerMenuLockScreenSettingsChanged() {
mShowLockScreenCardsAndControls = Settings.Secure.getInt(mContentResolver,
Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 0) != 0;
}
}

View File

@@ -152,6 +152,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
protected boolean mShowing;
protected boolean mOccluded;
protected boolean mRemoteInputActive;
private boolean mGlobalActionsVisible = false;
private boolean mLastGlobalActionsVisible = false;
private boolean mDozing;
private boolean mPulsing;
private boolean mGesturalNav;
@@ -293,6 +295,14 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
updateLockIcon();
}
/**
* Update the global actions visibility state in order to show the navBar when active.
*/
public void setGlobalActionsVisible(boolean isVisible) {
mGlobalActionsVisible = isVisible;
updateStates();
}
private void updateLockIcon() {
// Not all form factors have a lock icon
if (mLockIconContainer == null) {
@@ -820,6 +830,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mFirstUpdate = false;
mLastShowing = showing;
mLastGlobalActionsVisible = mGlobalActionsVisible;
mLastOccluded = occluded;
mLastBouncerShowing = bouncerShowing;
mLastBouncerDismissible = bouncerDismissible;
@@ -864,7 +875,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
boolean keyguardWithGestureNav = (keyguardShowing && !mDozing || mPulsing && !mIsDocked)
&& mGesturalNav;
return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing()
|| mRemoteInputActive || keyguardWithGestureNav);
|| mRemoteInputActive || keyguardWithGestureNav
|| mGlobalActionsVisible);
}
/**
@@ -876,7 +888,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
boolean keyguardWithGestureNav = (keyguardShowing && !mLastDozing
|| mLastPulsing && !mLastIsDocked) && mLastGesturalNav;
return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing
|| mLastRemoteInputActive || keyguardWithGestureNav);
|| mLastRemoteInputActive || keyguardWithGestureNav
|| mLastGlobalActionsVisible);
}
public boolean shouldDismissOnMenuPressed() {

View File

@@ -32,6 +32,7 @@ import android.content.ContentResolver;
import android.content.res.Resources;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.UserManager;
import android.service.dreams.IDreamManager;
import android.telephony.TelephonyManager;
@@ -106,6 +107,7 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
@Mock private UiEventLogger mUiEventLogger;
@Mock private RingerModeTracker mRingerModeTracker;
@Mock private RingerModeLiveData mRingerModeLiveData;
@Mock private Handler mHandler;
private TestableLooper mTestableLooper;
@@ -147,7 +149,8 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
mControlsListingController,
mControlsController,
mUiEventLogger,
mRingerModeTracker
mRingerModeTracker,
mHandler
);
mGlobalActionsDialog.setZeroDialogPressDelayForTesting();
}