Fix brightness dialog

- the dialog shouldn't cause YouTube to go into PIP mode
- the dialog should disappear after a timeout if triggered by a brightness key

Bug: 280081278
Bug: 280082939
Test: atest BrightnessDialogTest
Change-Id: I4d6fe7dbbaa9b6d6ce8da04711ee117fea78d246
This commit is contained in:
Piotr Wilczyński
2023-06-19 14:40:37 +00:00
parent 54d58e5a64
commit 71f8ad2cb6
4 changed files with 132 additions and 14 deletions

View File

@@ -97,6 +97,12 @@ public interface WindowManagerPolicyConstants {
*/
String EXTRA_START_REASON = "android.intent.extra.EXTRA_START_REASON";
/**
* Set to {@code true} when intent was invoked from pressing one of the brightness keys.
* @hide
*/
String EXTRA_FROM_BRIGHTNESS_KEY = "android.intent.extra.FROM_BRIGHTNESS_KEY";
// TODO: move this to a more appropriate place.
interface PointerEventListener {
/**

View File

@@ -18,6 +18,7 @@ package com.android.systemui.settings.brightness;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KEY;
import android.app.Activity;
import android.graphics.Rect;
@@ -29,8 +30,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
@@ -38,34 +41,42 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.util.concurrency.DelayableExecutor;
import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
/** A dialog that provides controls for adjusting the screen brightness. */
public class BrightnessDialog extends Activity {
@VisibleForTesting
static final int DIALOG_TIMEOUT_MILLIS = 3000;
private BrightnessController mBrightnessController;
private final BrightnessSliderController.Factory mToggleSliderFactory;
private final UserTracker mUserTracker;
private final DisplayTracker mDisplayTracker;
private final Executor mMainExecutor;
private final DelayableExecutor mMainExecutor;
private final Handler mBackgroundHandler;
private final AccessibilityManagerWrapper mAccessibilityMgr;
private Runnable mCancelTimeoutRunnable;
@Inject
public BrightnessDialog(
UserTracker userTracker,
DisplayTracker displayTracker,
BrightnessSliderController.Factory factory,
@Main Executor mainExecutor,
@Background Handler bgHandler) {
@Main DelayableExecutor mainExecutor,
@Background Handler bgHandler,
AccessibilityManagerWrapper accessibilityMgr) {
mUserTracker = userTracker;
mDisplayTracker = displayTracker;
mToggleSliderFactory = factory;
mMainExecutor = mainExecutor;
mBackgroundHandler = bgHandler;
mAccessibilityMgr = accessibilityMgr;
}
@@ -121,6 +132,14 @@ public class BrightnessDialog extends Activity {
MetricsLogger.visible(this, MetricsEvent.BRIGHTNESS_DIALOG);
}
@Override
protected void onResume() {
super.onResume();
if (triggeredByBrightnessKey()) {
scheduleTimeout();
}
}
@Override
protected void onPause() {
super.onPause();
@@ -139,9 +158,25 @@ public class BrightnessDialog extends Activity {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
|| keyCode == KeyEvent.KEYCODE_VOLUME_UP
|| keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
if (mCancelTimeoutRunnable != null) {
mCancelTimeoutRunnable.run();
}
finish();
}
return super.onKeyDown(keyCode, event);
}
private boolean triggeredByBrightnessKey() {
return getIntent().getBooleanExtra(EXTRA_FROM_BRIGHTNESS_KEY, false);
}
private void scheduleTimeout() {
if (mCancelTimeoutRunnable != null) {
mCancelTimeoutRunnable.run();
}
final int timeout = mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS,
AccessibilityManager.FLAG_CONTENT_CONTROLS);
mCancelTimeoutRunnable = mMainExecutor.executeDelayed(this::finish, timeout);
}
}

View File

@@ -16,12 +16,14 @@
package com.android.systemui.settings.brightness
import android.content.Intent
import android.graphics.Rect
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.View
import android.view.ViewGroup
import android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KEY
import androidx.test.filters.SmallTest
import androidx.test.rule.ActivityTestRule
import com.android.systemui.R
@@ -29,15 +31,20 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.activity.SingleActivityFactory
import com.android.systemui.settings.FakeDisplayTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.Executor
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.eq
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@@ -48,9 +55,12 @@ class BrightnessDialogTest : SysuiTestCase() {
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var brightnessSliderControllerFactory: BrightnessSliderController.Factory
@Mock private lateinit var mainExecutor: Executor
@Mock private lateinit var backgroundHandler: Handler
@Mock private lateinit var brightnessSliderController: BrightnessSliderController
@Mock private lateinit var accessibilityMgr: AccessibilityManagerWrapper
private val clock = FakeSystemClock()
private val mainExecutor = FakeExecutor(clock)
private var displayTracker = FakeDisplayTracker(mContext)
@@ -64,7 +74,8 @@ class BrightnessDialogTest : SysuiTestCase() {
displayTracker,
brightnessSliderControllerFactory,
mainExecutor,
backgroundHandler
backgroundHandler,
accessibilityMgr
)
},
/* initialTouchMode= */ false,
@@ -77,8 +88,6 @@ class BrightnessDialogTest : SysuiTestCase() {
`when`(brightnessSliderControllerFactory.create(any(), any()))
.thenReturn(brightnessSliderController)
`when`(brightnessSliderController.rootView).thenReturn(View(context))
activityRule.launchActivity(null)
}
@After
@@ -88,6 +97,7 @@ class BrightnessDialogTest : SysuiTestCase() {
@Test
fun testGestureExclusion() {
activityRule.launchActivity(Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG))
val frame = activityRule.activity.requireViewById<View>(R.id.brightness_mirror_container)
val lp = frame.layoutParams as ViewGroup.MarginLayoutParams
@@ -104,18 +114,83 @@ class BrightnessDialogTest : SysuiTestCase() {
.isEqualTo(Rect(-horizontalMargin, 0, frame.width + horizontalMargin, frame.height))
}
@Test
fun testTimeout() {
`when`(
accessibilityMgr.getRecommendedTimeoutMillis(
eq(BrightnessDialog.DIALOG_TIMEOUT_MILLIS),
anyInt()
)
)
.thenReturn(BrightnessDialog.DIALOG_TIMEOUT_MILLIS)
val intent = Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG)
intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true)
activityRule.launchActivity(intent)
assertThat(activityRule.activity.isFinishing()).isFalse()
clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong())
assertThat(activityRule.activity.isFinishing()).isTrue()
}
@Test
fun testRestartTimeout() {
`when`(
accessibilityMgr.getRecommendedTimeoutMillis(
eq(BrightnessDialog.DIALOG_TIMEOUT_MILLIS),
anyInt()
)
)
.thenReturn(BrightnessDialog.DIALOG_TIMEOUT_MILLIS)
val intent = Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG)
intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true)
activityRule.launchActivity(intent)
assertThat(activityRule.activity.isFinishing()).isFalse()
clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong() / 2)
// Restart the timeout
activityRule.activity.onResume()
clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong() / 2)
// The dialog should not have disappeared yet
assertThat(activityRule.activity.isFinishing()).isFalse()
clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong() / 2)
assertThat(activityRule.activity.isFinishing()).isTrue()
}
@Test
fun testNoTimeoutIfNotStartedByBrightnessKey() {
`when`(
accessibilityMgr.getRecommendedTimeoutMillis(
eq(BrightnessDialog.DIALOG_TIMEOUT_MILLIS),
anyInt()
)
)
.thenReturn(BrightnessDialog.DIALOG_TIMEOUT_MILLIS)
activityRule.launchActivity(Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG))
assertThat(activityRule.activity.isFinishing()).isFalse()
clock.advanceTime(BrightnessDialog.DIALOG_TIMEOUT_MILLIS.toLong())
assertThat(activityRule.activity.isFinishing()).isFalse()
}
class TestDialog(
userTracker: UserTracker,
displayTracker: FakeDisplayTracker,
brightnessSliderControllerFactory: BrightnessSliderController.Factory,
mainExecutor: Executor,
backgroundHandler: Handler
mainExecutor: DelayableExecutor,
backgroundHandler: Handler,
accessibilityMgr: AccessibilityManagerWrapper
) :
BrightnessDialog(
userTracker,
displayTracker,
brightnessSliderControllerFactory,
mainExecutor,
backgroundHandler
backgroundHandler,
accessibilityMgr
)
}

View File

@@ -3211,8 +3211,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
minLinearBrightness, maxLinearBrightness);
mDisplayManager.setBrightness(screenDisplayId, adjustedLinearBrightness);
startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
UserHandle.CURRENT_OR_SELF);
Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
intent.putExtra(EXTRA_FROM_BRIGHTNESS_KEY, true);
startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
}
return true;
case KeyEvent.KEYCODE_KEYBOARD_BACKLIGHT_DOWN: