Merge "Hold a wake-lock for battery % changes in AOD" into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b81195b5fb
@@ -599,10 +599,6 @@ public class KeyguardIndicationController {
|
|||||||
mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
|
mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
|
||||||
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
|
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
|
||||||
mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
|
mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK);
|
||||||
if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
|
|
||||||
// Make sure this doesn't get stuck and burns in. Acquire wakelock until its cleared.
|
|
||||||
mWakeLock.setAcquired(true);
|
|
||||||
}
|
|
||||||
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
|
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
|
||||||
|
|
||||||
updateIndication(false);
|
updateIndication(false);
|
||||||
@@ -622,10 +618,6 @@ public class KeyguardIndicationController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected final void updateIndication(boolean animate) {
|
protected final void updateIndication(boolean animate) {
|
||||||
if (TextUtils.isEmpty(mTransientIndication)) {
|
|
||||||
mWakeLock.setAcquired(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mVisible) {
|
if (!mVisible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -643,24 +635,31 @@ public class KeyguardIndicationController {
|
|||||||
// colors can be hard to read in low brightness.
|
// colors can be hard to read in low brightness.
|
||||||
mTopIndicationView.setTextColor(Color.WHITE);
|
mTopIndicationView.setTextColor(Color.WHITE);
|
||||||
if (!TextUtils.isEmpty(mTransientIndication)) {
|
if (!TextUtils.isEmpty(mTransientIndication)) {
|
||||||
mTopIndicationView.switchIndication(mTransientIndication, null);
|
mWakeLock.setAcquired(true);
|
||||||
|
mTopIndicationView.switchIndication(mTransientIndication, null,
|
||||||
|
true, () -> mWakeLock.setAcquired(false));
|
||||||
} else if (!mBatteryPresent) {
|
} else if (!mBatteryPresent) {
|
||||||
// If there is no battery detected, hide the indication and bail
|
// If there is no battery detected, hide the indication and bail
|
||||||
mIndicationArea.setVisibility(GONE);
|
mIndicationArea.setVisibility(GONE);
|
||||||
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
|
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
|
||||||
mTopIndicationView.switchIndication(mAlignmentIndication, null);
|
mTopIndicationView.switchIndication(mAlignmentIndication, null,
|
||||||
|
false /* animate */, null /* onAnimationEndCallback */);
|
||||||
mTopIndicationView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
|
mTopIndicationView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
|
||||||
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
|
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
|
||||||
String indication = computePowerIndication();
|
String indication = computePowerIndication();
|
||||||
if (animate) {
|
if (animate) {
|
||||||
animateText(mTopIndicationView, indication);
|
mWakeLock.setAcquired(true);
|
||||||
|
mTopIndicationView.switchIndication(indication, null, true /* animate */,
|
||||||
|
() -> mWakeLock.setAcquired(false));
|
||||||
} else {
|
} else {
|
||||||
mTopIndicationView.switchIndication(indication, null);
|
mTopIndicationView.switchIndication(indication, null, false /* animate */,
|
||||||
|
null /* onAnimationEndCallback */);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String percentage = NumberFormat.getPercentInstance()
|
String percentage = NumberFormat.getPercentInstance()
|
||||||
.format(mBatteryLevel / 100f);
|
.format(mBatteryLevel / 100f);
|
||||||
mTopIndicationView.switchIndication(percentage, null);
|
mTopIndicationView.switchIndication(percentage, null /* indication */,
|
||||||
|
false /* animate */, null /* onAnimationEnd*/);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,44 +95,85 @@ public class KeyguardIndicationTextView extends TextView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the text with an animation and makes sure a single indication is shown long enough.
|
* Changes the text with an animation. Makes sure a single indication is shown long enough.
|
||||||
|
*/
|
||||||
|
public void switchIndication(CharSequence text, KeyguardIndication indication) {
|
||||||
|
switchIndication(text, indication, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the text with an optional animation. For animating text, makes sure a single
|
||||||
|
* indication is shown long enough.
|
||||||
*
|
*
|
||||||
* @param text The text to show.
|
* @param text The text to show.
|
||||||
* @param indication optional display information for the text
|
* @param indication optional display information for the text
|
||||||
|
* @param animate whether to animate this indication in - we may not want this on AOD
|
||||||
|
* @param onAnimationEndCallback runnable called after this indication is animated in
|
||||||
*/
|
*/
|
||||||
public void switchIndication(CharSequence text, KeyguardIndication indication) {
|
public void switchIndication(CharSequence text, KeyguardIndication indication,
|
||||||
|
boolean animate, Runnable onAnimationEndCallback) {
|
||||||
if (text == null) text = "";
|
if (text == null) text = "";
|
||||||
|
|
||||||
CharSequence lastPendingMessage = mMessages.peekLast();
|
CharSequence lastPendingMessage = mMessages.peekLast();
|
||||||
if (TextUtils.equals(lastPendingMessage, text)
|
if (TextUtils.equals(lastPendingMessage, text)
|
||||||
|| (lastPendingMessage == null && TextUtils.equals(text, getText()))) {
|
|| (lastPendingMessage == null && TextUtils.equals(text, getText()))) {
|
||||||
|
if (onAnimationEndCallback != null) {
|
||||||
|
onAnimationEndCallback.run();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mMessages.add(text);
|
mMessages.add(text);
|
||||||
mKeyguardIndicationInfo.add(indication);
|
mKeyguardIndicationInfo.add(indication);
|
||||||
|
|
||||||
final boolean hasIcon = indication != null && indication.getIcon() != null;
|
if (animate) {
|
||||||
final AnimatorSet animSet = new AnimatorSet();
|
final boolean hasIcon = indication != null && indication.getIcon() != null;
|
||||||
final AnimatorSet.Builder animSetBuilder = animSet.play(getOutAnimator());
|
final AnimatorSet animator = new AnimatorSet();
|
||||||
|
// Make sure each animation is visible for a minimum amount of time, while not worrying
|
||||||
|
// about fading in blank text
|
||||||
|
long timeInMillis = System.currentTimeMillis();
|
||||||
|
long delay = Math.max(0, mNextAnimationTime - timeInMillis);
|
||||||
|
setNextAnimationTime(timeInMillis + delay + getFadeOutDuration());
|
||||||
|
final long minDurationMillis =
|
||||||
|
(indication != null && indication.getMinVisibilityMillis() != null)
|
||||||
|
? indication.getMinVisibilityMillis()
|
||||||
|
: MSG_MIN_DURATION_MILLIS_DEFAULT;
|
||||||
|
if (!text.equals("") || hasIcon) {
|
||||||
|
setNextAnimationTime(mNextAnimationTime + minDurationMillis);
|
||||||
|
Animator inAnimator = getInAnimator();
|
||||||
|
inAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
if (onAnimationEndCallback != null) {
|
||||||
|
onAnimationEndCallback.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
animator.playSequentially(getOutAnimator(), inAnimator);
|
||||||
|
} else {
|
||||||
|
Animator outAnimator = getOutAnimator();
|
||||||
|
outAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
if (onAnimationEndCallback != null) {
|
||||||
|
onAnimationEndCallback.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
animator.play(outAnimator);
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure each animation is visible for a minimum amount of time, while not worrying
|
animator.setStartDelay(delay);
|
||||||
// about fading in blank text
|
animator.start();
|
||||||
long timeInMillis = System.currentTimeMillis();
|
} else {
|
||||||
long delay = Math.max(0, mNextAnimationTime - timeInMillis);
|
setAlpha(1f);
|
||||||
setNextAnimationTime(timeInMillis + delay + getFadeOutDuration());
|
setTranslationY(0f);
|
||||||
|
setNextIndication();
|
||||||
final long minDurationMillis =
|
if (onAnimationEndCallback != null) {
|
||||||
(indication != null && indication.getMinVisibilityMillis() != null)
|
onAnimationEndCallback.run();
|
||||||
? indication.getMinVisibilityMillis()
|
}
|
||||||
: MSG_MIN_DURATION_MILLIS_DEFAULT;
|
|
||||||
|
|
||||||
if (!text.equals("") || hasIcon) {
|
|
||||||
setNextAnimationTime(mNextAnimationTime + minDurationMillis);
|
|
||||||
animSetBuilder.before(getInAnimator());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
animSet.setStartDelay(delay);
|
|
||||||
animSet.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnimatorSet getOutAnimator() {
|
private AnimatorSet getOutAnimator() {
|
||||||
@@ -143,29 +184,8 @@ public class KeyguardIndicationTextView extends TextView {
|
|||||||
fadeOut.addListener(new AnimatorListenerAdapter() {
|
fadeOut.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animator) {
|
public void onAnimationEnd(Animator animator) {
|
||||||
KeyguardIndication info = mKeyguardIndicationInfo.poll();
|
super.onAnimationEnd(animator);
|
||||||
if (info != null) {
|
setNextIndication();
|
||||||
// First, update the style.
|
|
||||||
// If a background is set on the text, we don't want shadow on the text
|
|
||||||
if (info.getBackground() != null) {
|
|
||||||
setTextAppearance(sButtonStyleId);
|
|
||||||
} else {
|
|
||||||
setTextAppearance(sStyleId);
|
|
||||||
}
|
|
||||||
setBackground(info.getBackground());
|
|
||||||
setTextColor(info.getTextColor());
|
|
||||||
setOnClickListener(info.getClickListener());
|
|
||||||
setClickable(info.getClickListener() != null);
|
|
||||||
final Drawable icon = info.getIcon();
|
|
||||||
if (icon != null) {
|
|
||||||
icon.setTint(getCurrentTextColor());
|
|
||||||
if (icon instanceof AnimatedVectorDrawable) {
|
|
||||||
((AnimatedVectorDrawable) icon).start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null);
|
|
||||||
}
|
|
||||||
setText(mMessages.poll());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -177,6 +197,32 @@ public class KeyguardIndicationTextView extends TextView {
|
|||||||
return animatorSet;
|
return animatorSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setNextIndication() {
|
||||||
|
KeyguardIndication info = mKeyguardIndicationInfo.poll();
|
||||||
|
if (info != null) {
|
||||||
|
// First, update the style.
|
||||||
|
// If a background is set on the text, we don't want shadow on the text
|
||||||
|
if (info.getBackground() != null) {
|
||||||
|
setTextAppearance(sButtonStyleId);
|
||||||
|
} else {
|
||||||
|
setTextAppearance(sStyleId);
|
||||||
|
}
|
||||||
|
setBackground(info.getBackground());
|
||||||
|
setTextColor(info.getTextColor());
|
||||||
|
setOnClickListener(info.getClickListener());
|
||||||
|
setClickable(info.getClickListener() != null);
|
||||||
|
final Drawable icon = info.getIcon();
|
||||||
|
if (icon != null) {
|
||||||
|
icon.setTint(getCurrentTextColor());
|
||||||
|
if (icon instanceof AnimatedVectorDrawable) {
|
||||||
|
((AnimatedVectorDrawable) icon).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null);
|
||||||
|
}
|
||||||
|
setText(mMessages.poll());
|
||||||
|
}
|
||||||
|
|
||||||
private AnimatorSet getInAnimator() {
|
private AnimatorSet getInAnimator() {
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
AnimatorSet animatorSet = new AnimatorSet();
|
||||||
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(this, View.ALPHA, 1f);
|
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(this, View.ALPHA, 1f);
|
||||||
@@ -190,6 +236,7 @@ public class KeyguardIndicationTextView extends TextView {
|
|||||||
yTranslate.addListener(new AnimatorListenerAdapter() {
|
yTranslate.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationCancel(Animator animation) {
|
public void onAnimationCancel(Animator animation) {
|
||||||
|
super.onAnimationCancel(animation);
|
||||||
setTranslationY(0);
|
setTranslationY(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
private BroadcastReceiver mBroadcastReceiver;
|
private BroadcastReceiver mBroadcastReceiver;
|
||||||
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
|
|
||||||
private KeyguardIndicationTextView mTextView;
|
private KeyguardIndicationTextView mTextView; // AOD text
|
||||||
|
|
||||||
private KeyguardIndicationController mController;
|
private KeyguardIndicationController mController;
|
||||||
private WakeLockFake.Builder mWakeLockBuilder;
|
private WakeLockFake.Builder mWakeLockBuilder;
|
||||||
@@ -412,41 +412,32 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void transientIndication_holdsWakeLock_whenDozing() {
|
public void transientIndication_holdsWakeLock_whenDozing() {
|
||||||
|
// GIVEN animations are enabled and text is visible
|
||||||
|
mTextView.setAnimationsEnabled(true);
|
||||||
createController();
|
createController();
|
||||||
|
mController.setVisible(true);
|
||||||
|
|
||||||
|
// WHEN transient text is shown
|
||||||
mStatusBarStateListener.onDozingChanged(true);
|
mStatusBarStateListener.onDozingChanged(true);
|
||||||
mController.showTransientIndication("Test");
|
mController.showTransientIndication("Test");
|
||||||
|
|
||||||
assertTrue(mWakeLock.isHeld());
|
// THEN wake lock is held while the animation is running
|
||||||
|
assertTrue("WakeLock expected: HELD, was: RELEASED", mWakeLock.isHeld());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void transientIndication_releasesWakeLock_afterHiding() {
|
public void transientIndication_releasesWakeLock_whenDozing() {
|
||||||
|
// GIVEN animations aren't enabled
|
||||||
|
mTextView.setAnimationsEnabled(false);
|
||||||
createController();
|
createController();
|
||||||
|
mController.setVisible(true);
|
||||||
|
|
||||||
|
// WHEN we show the transient indication
|
||||||
mStatusBarStateListener.onDozingChanged(true);
|
mStatusBarStateListener.onDozingChanged(true);
|
||||||
mController.showTransientIndication("Test");
|
mController.showTransientIndication("Test");
|
||||||
mController.hideTransientIndication();
|
|
||||||
|
|
||||||
assertFalse(mWakeLock.isHeld());
|
// THEN wake lock is RELEASED, not held
|
||||||
}
|
assertFalse("WakeLock expected: RELEASED, was: HELD", mWakeLock.isHeld());
|
||||||
|
|
||||||
@Test
|
|
||||||
public void transientIndication_releasesWakeLock_afterHidingDelayed() throws Throwable {
|
|
||||||
mInstrumentation.runOnMainSync(() -> {
|
|
||||||
createController();
|
|
||||||
|
|
||||||
mStatusBarStateListener.onDozingChanged(true);
|
|
||||||
mController.showTransientIndication("Test");
|
|
||||||
mController.hideTransientIndicationDelayed(0);
|
|
||||||
});
|
|
||||||
mInstrumentation.waitForIdleSync();
|
|
||||||
|
|
||||||
Boolean[] held = new Boolean[1];
|
|
||||||
mInstrumentation.runOnMainSync(() -> {
|
|
||||||
held[0] = mWakeLock.isHeld();
|
|
||||||
});
|
|
||||||
assertFalse("WakeLock expected: RELEASED, was: HELD", held[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user