Fixed a bug where the HUN would interfere with the normal touches

When a hun came in or went away, the touchable regions were not
enforced correctly due to a race condition. This lead to the user
grabing the notification panel unintentionally and ripping him
out of the normal touch state.
Also fixed a small bug where the alpha was not correctly animating
sometimes and the HUN shadow would still draw.

Bug: 20956211
Change-Id: Iae1fef5825b3d2b8b4128cc8c3272019194cd819
(cherry picked from commit 8b4a06e9e2)
This commit is contained in:
Selim Cinek
2015-05-08 16:08:35 -07:00
parent 981de3c57c
commit 737bff3476
4 changed files with 106 additions and 15 deletions

View File

@@ -619,7 +619,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
R.color.notification_panel_solid_background)));
}
mHeadsUpManager = new HeadsUpManager(context, mNotificationPanel.getViewTreeObserver());
mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow);
mHeadsUpManager.setBar(this);
mHeadsUpManager.addListener(this);
mHeadsUpManager.addListener(mNotificationPanel);
@@ -1869,21 +1869,34 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
if (inPinnedMode) {
// We need to ensure that the touchable region is updated before the window will be
// resized, in order to not catch any touches. A layout will ensure that
// onComputeInternalInsets will be called and after that we can resize the layout. Let's
// make sure that the window stays small for one frame until the touchableRegion is set.
mNotificationPanel.requestLayout();
mStatusBarWindowManager.setHeadsUpShowing(true);
mStatusBarWindowManager.setForceStatusBarVisible(true);
} else {
Runnable endRunnable = new Runnable() {
mStatusBarWindowManager.setForceWindowCollapsed(true);
mNotificationPanel.post(new Runnable() {
@Override
public void run() {
if (!mHeadsUpManager.hasPinnedHeadsUp()) {
mStatusBarWindowManager.setHeadsUpShowing(false);
}
mStatusBarWindowManager.setForceWindowCollapsed(false);
}
};
});
} else {
if (!mNotificationPanel.isFullyCollapsed()) {
endRunnable.run();
mStatusBarWindowManager.setHeadsUpShowing(false);
} else {
mStackScroller.runAfterAnimationFinished(endRunnable);
mHeadsUpManager.setHeadsUpGoingAway(true);
mStackScroller.runAfterAnimationFinished(new Runnable() {
@Override
public void run() {
if (!mHeadsUpManager.hasPinnedHeadsUp()) {
mStatusBarWindowManager.setHeadsUpShowing(false);
mHeadsUpManager.setHeadsUpGoingAway(false);
}
}
});
}
}
}

View File

@@ -378,8 +378,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
if (previousAnimator != null) {
if (animate || alpha == mCurrentHeadsUpAlpha) {
previousAnimator.cancel();
} else {
animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_END_ALPHA);
}
animEndValue = StackStateAnimator.getChildTag(mHeadsUpScrim, TAG_HUN_START_ALPHA);
}
if (alpha != mCurrentHeadsUpAlpha && alpha != animEndValue) {
if (animate) {

View File

@@ -129,8 +129,9 @@ public class StatusBarWindowManager {
}
private void applyHeight(State state) {
boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded
|| state.keyguardFadingAway || state.bouncerShowing || state.headsUpShowing;
boolean expanded = !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded()
|| state.statusBarExpanded || state.keyguardFadingAway || state.bouncerShowing
|| state.headsUpShowing);
if (expanded) {
mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
} else {
@@ -256,6 +257,16 @@ public class StatusBarWindowManager {
apply(mCurrentState);
}
/**
* Force the window to be collapsed, even if it should theoretically be expanded.
* Used for when a heads-up comes in but we still need to wait for the touchable regions to
* be computed.
*/
public void setForceWindowCollapsed(boolean force) {
mCurrentState.forceCollapsed = force;
apply(mCurrentState);
}
private static class State {
boolean keyguardShowing;
boolean keyguardOccluded;
@@ -267,6 +278,7 @@ public class StatusBarWindowManager {
boolean qsExpanded;
boolean headsUpShowing;
boolean forceStatusBarVisible;
boolean forceCollapsed;
/**
* The {@link BaseStatusBar} state from the status bar.

View File

@@ -25,6 +25,7 @@ import android.provider.Settings;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pools;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
@@ -78,6 +79,8 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
}
};
private final View mStatusBarWindowView;
private final int mStatusBarHeight;
private PhoneStatusBar mBar;
private int mSnoozeLengthMs;
private ContentObserver mSettingsObserver;
@@ -92,8 +95,11 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
private boolean mIsExpanded;
private boolean mHasPinnedNotification;
private int[] mTmpTwoArray = new int[2];
private boolean mHeadsUpGoingAway;
private boolean mWaitingOnCollapseWhenGoingAway;
private boolean mIsObserving;
public HeadsUpManager(final Context context, ViewTreeObserver observer) {
public HeadsUpManager(final Context context, View statusBarWindowView) {
Resources resources = context.getResources();
mTouchAcceptanceDelay = resources.getInteger(R.integer.touch_acceptance_delay);
mSnoozedPackages = new ArrayMap<>();
@@ -119,7 +125,24 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
context.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(SETTING_HEADS_UP_SNOOZE_LENGTH_MS), false,
mSettingsObserver);
observer.addOnComputeInternalInsetsListener(this);
mStatusBarWindowView = statusBarWindowView;
mStatusBarHeight = resources.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
}
private void updateTouchableRegionListener() {
boolean shouldObserve = mHasPinnedNotification || mHeadsUpGoingAway
|| mWaitingOnCollapseWhenGoingAway;
if (shouldObserve == mIsObserving) {
return;
}
if (shouldObserve) {
mStatusBarWindowView.getViewTreeObserver().addOnComputeInternalInsetsListener(this);
mStatusBarWindowView.requestLayout();
} else {
mStatusBarWindowView.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
}
mIsObserving = shouldObserve;
}
public void setBar(PhoneStatusBar bar) {
@@ -207,6 +230,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
return;
}
mHasPinnedNotification = hasPinnedNotification;
updateTouchableRegionListener();
for (OnHeadsUpChangedListener listener : mListeners) {
listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
}
@@ -326,7 +350,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
}
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
if (!mIsExpanded && mHasPinnedNotification) {
if (mHasPinnedNotification) {
int minX = Integer.MAX_VALUE;
int maxX = 0;
int minY = Integer.MAX_VALUE;
@@ -344,6 +368,9 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
info.touchableRegion.set(minX, minY, maxX, maxY);
} else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
}
}
@@ -419,6 +446,10 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
mIsExpanded = isExpanded;
if (isExpanded) {
unpinAll();
// make sure our state is sane
mWaitingOnCollapseWhenGoingAway = false;
mHeadsUpGoingAway = false;
updateTouchableRegionListener();
}
}
}
@@ -443,6 +474,40 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
return aEntry.compareTo(bEntry);
}
/**
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
* animating out. This is used to keep the touchable regions in a sane state.
*/
public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
if (headsUpGoingAway != mHeadsUpGoingAway) {
mHeadsUpGoingAway = headsUpGoingAway;
if (!headsUpGoingAway) {
waitForStatusBarLayout();
}
updateTouchableRegionListener();
}
}
/**
* We need to wait on the whole panel to collapse, before we can remove the touchable region
* listener.
*/
private void waitForStatusBarLayout() {
mWaitingOnCollapseWhenGoingAway = true;
mStatusBarWindowView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft,
int oldTop, int oldRight, int oldBottom) {
if (mStatusBarWindowView.getHeight() <= mStatusBarHeight) {
mStatusBarWindowView.removeOnLayoutChangeListener(this);
mWaitingOnCollapseWhenGoingAway = false;
updateTouchableRegionListener();
}
}
});
}
/**
* This represents a notification and how long it is in a heads up mode. It also manages its