diff options
| author | 2019-08-20 13:10:34 +0200 | |
|---|---|---|
| committer | 2019-11-12 10:58:24 +0100 | |
| commit | 60e51fe1b9fb306ca45837b84e6d431c353965c8 (patch) | |
| tree | e212004341036058416b2ef6fcc6adc62cd8ebb2 | |
| parent | 5560f38654dc972700fdb0bfdc247ff3892a514c (diff) | |
Fade out inattentive sleep warning overlay
After long user inactivity, a warning overlay is shown that the device
will go to sleep soon unless a button is pressed.
Currently, the overlay is hidden immediately on user activity.
This causes the overlay to be dismissed on an ACTION_DOWN KeyEvent,
and the following ACTION_UP KeyEvent to be delivered to the app
underneath the overlay.
We want to consume the ACTION_UP KeyEvent, as eg. an ACTION_UP KeyEvent
for the back button causes YouTube to quit out of a currently playing
video (even if the KeyEvent is cancelled).
With this change, the overlay fades out, and during the animation
continues to receive KeyEvents.
For quick button presses, this prevents the app from seeing the
ACTION_UP KeyEvent.
For long button presses, the app continues to see key repeats
and ACTION_UP events.
Bug: 137633812
Test: 1. Set timeout lower:
`adb shell settings put secure attentive_timeout 35000`
2. Play YouTube video
3. Wait for overlay to show
4. Press back
5. Verify: Video keeps playing, overlay disappears
Change-Id: Ie6eab2b381f3ba9638b231cfeab3b90ad349b6e8
9 files changed, 79 insertions, 28 deletions
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 20706bb4b21f..aa0ac37b007a 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -197,5 +197,5 @@ oneway interface IStatusBar /** * Dismiss the warning that the device is about to go to sleep due to user inactivity. */ - void dismissInattentiveSleepWarning(); + void dismissInattentiveSleepWarning(boolean animated); } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 76235a4a892e..a9f7b8455807 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -122,5 +122,5 @@ interface IStatusBarService /** * Dismiss the warning that the device is about to go to sleep due to user inactivity. */ - void dismissInattentiveSleepWarning(); + void dismissInattentiveSleepWarning(boolean animated); } diff --git a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java index 716943164b61..7d4bd019e72b 100644 --- a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java +++ b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningController.java @@ -54,9 +54,9 @@ public class InattentiveSleepWarningController extends SystemUI implements Comma } @Override - public void dismissInattentiveSleepWarning() { + public void dismissInattentiveSleepWarning(boolean animated) { if (mOverlayView != null) { - mOverlayView.dismiss(); + mOverlayView.dismiss(animated); } } } diff --git a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java index 8ccc679d32b0..cf1bc7dc115d 100644 --- a/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java +++ b/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java @@ -16,11 +16,15 @@ package com.android.systemui.power; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.graphics.PixelFormat; import android.os.Binder; import android.os.IBinder; import android.view.LayoutInflater; +import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; @@ -34,6 +38,8 @@ import com.android.systemui.R; public class InattentiveSleepWarningView extends FrameLayout { private final IBinder mWindowToken = new Binder(); private final WindowManager mWindowManager; + private Animator mFadeOutAnimator; + private boolean mDismissing; InattentiveSleepWarningView(Context context) { super(context); @@ -47,23 +53,62 @@ public class InattentiveSleepWarningView extends FrameLayout { // overlay consumes key presses return true; }); + + mFadeOutAnimator = AnimatorInflater.loadAnimator(getContext(), + com.android.internal.R.animator.fade_out); + mFadeOutAnimator.setTarget(this); + mFadeOutAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + removeView(); + } + + @Override + public void onAnimationCancel(Animator animation) { + mDismissing = false; + setAlpha(1f); + setVisibility(View.VISIBLE); + } + }); + } + + private void removeView() { + if (mDismissing) { + setVisibility(View.INVISIBLE); + mWindowManager.removeView(InattentiveSleepWarningView.this); + } } /** * Show the warning. */ public void show() { - if (getParent() == null) { - mWindowManager.addView(this, getLayoutParams(mWindowToken)); + if (getParent() != null) { + if (mFadeOutAnimator.isStarted()) { + mFadeOutAnimator.cancel(); + } + return; } + + setAlpha(1f); + setVisibility(View.VISIBLE); + mWindowManager.addView(this, getLayoutParams(mWindowToken)); } /** * Dismiss the warning. */ - public void dismiss() { - if (getParent() != null) { - mWindowManager.removeView(this); + public void dismiss(boolean animated) { + if (getParent() == null) { + return; + } + + mDismissing = true; + + if (animated) { + postOnAnimation(mFadeOutAnimator::start); + } else { + removeView(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 88b6fdda3dd5..ca1143065ded 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -307,7 +307,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< * Called to notify System UI that the warning about the device going to sleep * due to prolonged user inactivity should be dismissed. */ - default void dismissInattentiveSleepWarning() { } + default void dismissInattentiveSleepWarning(boolean animated) { } } public CommandQueue(Context context) { @@ -816,9 +816,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } @Override - public void dismissInattentiveSleepWarning() { + public void dismissInattentiveSleepWarning(boolean animated) { synchronized (mLock) { - mHandler.obtainMessage(MSG_DISMISS_INATTENTIVE_SLEEP_WARNING) + mHandler.obtainMessage(MSG_DISMISS_INATTENTIVE_SLEEP_WARNING, animated) .sendToTarget(); } } @@ -1175,7 +1175,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< break; case MSG_DISMISS_INATTENTIVE_SLEEP_WARNING: for (int i = 0; i < mCallbacks.size(); i++) { - mCallbacks.get(i).dismissInattentiveSleepWarning(); + mCallbacks.get(i).dismissInattentiveSleepWarning((Boolean) msg.obj); } break; } diff --git a/services/core/java/com/android/server/power/InattentiveSleepWarningController.java b/services/core/java/com/android/server/power/InattentiveSleepWarningController.java index db8a63f44cbc..dbedde6b5822 100644 --- a/services/core/java/com/android/server/power/InattentiveSleepWarningController.java +++ b/services/core/java/com/android/server/power/InattentiveSleepWarningController.java @@ -75,18 +75,18 @@ public class InattentiveSleepWarningController { * Dismiss the warning. */ @GuardedBy("PowerManagerService.mLock") - public void dismiss() { + public void dismiss(boolean animated) { if (!isShown()) { return; } - mHandler.post(this::dismissInternal); + mHandler.post(() -> dismissInternal(animated)); mIsShown = false; } - private void dismissInternal() { + private void dismissInternal(boolean animated) { try { - getStatusBar().dismissInattentiveSleepWarning(); + getStatusBar().dismissInattentiveSleepWarning(animated); } catch (RemoteException e) { Log.e(TAG, "Failed to dismiss inattentive sleep warning", e); } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 00e0f7124714..fce7f049107b 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -2240,10 +2240,16 @@ public final class PowerManagerService extends SystemService private boolean maybeHideInattentiveSleepWarningLocked(long now, long showWarningTime) { long attentiveTimeout = getAttentiveTimeoutLocked(); - if (mInattentiveSleepWarningOverlayController.isShown() && (attentiveTimeout < 0 - || isBeingKeptFromShowingInattentiveSleepWarningLocked() - || now < showWarningTime)) { - mInattentiveSleepWarningOverlayController.dismiss(); + if (!mInattentiveSleepWarningOverlayController.isShown()) { + return false; + } + + if (mWakefulness != WAKEFULNESS_AWAKE) { + mInattentiveSleepWarningOverlayController.dismiss(false); + return true; + } else if (attentiveTimeout < 0 || isBeingKeptFromShowingInattentiveSleepWarningLocked() + || now < showWarningTime) { + mInattentiveSleepWarningOverlayController.dismiss(true); return true; } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index c256b8499ee8..6ea08fe1a19d 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -1387,11 +1387,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } @Override - public void dismissInattentiveSleepWarning() { + public void dismissInattentiveSleepWarning(boolean animated) { enforceStatusBarService(); if (mBar != null) { try { - mBar.dismissInattentiveSleepWarning(); + mBar.dismissInattentiveSleepWarning(animated); } catch (RemoteException ex) { } } diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 592f4ec7caab..0ca62e2dcdff 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -668,11 +668,11 @@ public class PowerManagerServiceTest { startSystem(); verify(mInattentiveSleepWarningControllerMock, times(1)).show(); - verify(mInattentiveSleepWarningControllerMock, never()).dismiss(); + verify(mInattentiveSleepWarningControllerMock, never()).dismiss(anyBoolean()); when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true); setPluggedIn(true); - verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss(); + verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss(true); } @Test @@ -690,12 +690,12 @@ public class PowerManagerServiceTest { SystemClock.sleep(70); verify(mInattentiveSleepWarningControllerMock, times(1)).show(); - verify(mInattentiveSleepWarningControllerMock, never()).dismiss(); + verify(mInattentiveSleepWarningControllerMock, never()).dismiss(anyBoolean()); when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true); mService.getBinderServiceInstance().userActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); - verify(mInattentiveSleepWarningControllerMock, times(1)).dismiss(); + verify(mInattentiveSleepWarningControllerMock, times(1)).dismiss(true); } @Test @@ -711,7 +711,7 @@ public class PowerManagerServiceTest { when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true); SystemClock.sleep(30); forceAwake(); - verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss(); + verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).dismiss(false); } @Test |