Keep notifications with active remote inputs
Fixes a bad interaction when the app cancels the notification into which the user is typing. This happens for example when the user initiates direct reply from the lock screen and the app is currently open underneath the lockscreen. Also cleans up the code that clears notification effects by moving it into the appropriate place (without functional changes). Fixes: 28745456 Change-Id: I69e076642e93930d41cfb06f2a48836aea34d92d
This commit is contained in:
@@ -189,6 +189,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
|
||||
protected boolean mVisible;
|
||||
protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
|
||||
protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>();
|
||||
|
||||
/**
|
||||
* Notifications with keys in this set are not actually around anymore. We kept them around
|
||||
@@ -968,7 +969,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
return vetoButton;
|
||||
}
|
||||
|
||||
private void performRemoveNotification(StatusBarNotification n, boolean removeView) {
|
||||
protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
|
||||
final String pkg = n.getPackageName();
|
||||
final String tag = n.getTag();
|
||||
final int id = n.getId();
|
||||
@@ -980,6 +981,9 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
mKeysKeptForRemoteInput.remove(n.getKey());
|
||||
removeView = true;
|
||||
}
|
||||
if (mRemoteInputEntriesToRemoveOnCollapse.remove(mNotificationData.get(n.getKey()))) {
|
||||
removeView = true;
|
||||
}
|
||||
if (removeView) {
|
||||
removeNotification(n.getKey(), null);
|
||||
}
|
||||
@@ -2085,8 +2089,7 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
|
||||
/**
|
||||
* The LEDs are turned off when the notification panel is shown, even just a little bit.
|
||||
* See also NotificationStackScrollLayout.setIsExpanded() for another place where we
|
||||
* attempt to do this.
|
||||
* See also PhoneStatusBar.setPanelExpanded for another place where we attempt to do this.
|
||||
*/
|
||||
protected void handleVisibleToUserChanged(boolean visibleToUser) {
|
||||
try {
|
||||
@@ -2326,8 +2329,9 @@ public abstract class BaseStatusBar extends SystemUI implements
|
||||
Entry entry = mNotificationData.get(key);
|
||||
if (entry == null) {
|
||||
return;
|
||||
} else if (mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
|
||||
} else {
|
||||
mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
|
||||
mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
|
||||
}
|
||||
|
||||
Notification n = notification.getNotification();
|
||||
|
||||
@@ -263,6 +263,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
* This affects the status bar UI. */
|
||||
private static final boolean FREEFORM_WINDOW_MANAGEMENT;
|
||||
|
||||
/**
|
||||
* How long to wait before auto-dismissing a notification that was kept for remote input, and
|
||||
* has now sent a remote input. We auto-dismiss, because the app may not see a reason to cancel
|
||||
* these given that they technically don't exist anymore. We wait a bit in case the app issues
|
||||
* an update.
|
||||
*/
|
||||
private static final int REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY = 200;
|
||||
|
||||
static {
|
||||
boolean onlyCoreApps;
|
||||
boolean freeformWindowManagement;
|
||||
@@ -1181,16 +1189,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
mIconPolicy.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
|
||||
mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
|
||||
|
||||
if (FORCE_REMOTE_INPUT_HISTORY) {
|
||||
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
|
||||
@Override
|
||||
public void onRemoteInputSent(Entry entry) {
|
||||
if (mKeysKeptForRemoteInput.contains(entry.key)) {
|
||||
removeNotification(entry.key, null);
|
||||
}
|
||||
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
|
||||
@Override
|
||||
public void onRemoteInputSent(Entry entry) {
|
||||
if (FORCE_REMOTE_INPUT_HISTORY && mKeysKeptForRemoteInput.contains(entry.key)) {
|
||||
removeNotification(entry.key, null);
|
||||
} else if (mRemoteInputEntriesToRemoveOnCollapse.contains(entry)) {
|
||||
// We're currently holding onto this notification, but from the apps point of
|
||||
// view it is already canceled, so we'll need to cancel it on the apps behalf
|
||||
// after sending - unless the app posts an update in the mean time, so wait a
|
||||
// bit.
|
||||
mHandler.postDelayed(() -> {
|
||||
if (mRemoteInputEntriesToRemoveOnCollapse.remove(entry)) {
|
||||
removeNotification(entry.key, null);
|
||||
}
|
||||
}, REMOTE_INPUT_KEPT_ENTRY_AUTO_CANCEL_DELAY);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
|
||||
mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
|
||||
@@ -1507,6 +1523,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
return;
|
||||
}
|
||||
Entry entry = mNotificationData.get(key);
|
||||
|
||||
if (entry != null && mRemoteInputController.isRemoteInputActive(entry)) {
|
||||
mLatestRankingMap = ranking;
|
||||
mRemoteInputEntriesToRemoveOnCollapse.add(entry);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry != null && entry.row != null) {
|
||||
entry.row.setRemoved(true);
|
||||
}
|
||||
@@ -1567,6 +1590,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
|
||||
Entry entry = mNotificationData.get(n.getKey());
|
||||
if (mRemoteInputController.isRemoteInputActive(entry)) {
|
||||
mRemoteInputController.removeRemoteInput(entry);
|
||||
}
|
||||
super.performRemoveNotification(n, removeView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refreshLayout(int layoutDirection) {
|
||||
if (mNavigationBarView != null) {
|
||||
@@ -2464,6 +2496,26 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
|
||||
public void setPanelExpanded(boolean isExpanded) {
|
||||
mStatusBarWindowManager.setPanelExpanded(isExpanded);
|
||||
|
||||
if (isExpanded && getBarState() != StatusBarState.KEYGUARD) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "clearing notification effects from setPanelExpanded");
|
||||
}
|
||||
clearNotificationEffects();
|
||||
}
|
||||
|
||||
if (!isExpanded) {
|
||||
removeRemoteInputEntriesKeptUntilCollapsed();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeRemoteInputEntriesKeptUntilCollapsed() {
|
||||
for (int i = 0; i < mRemoteInputEntriesToRemoveOnCollapse.size(); i++) {
|
||||
Entry entry = mRemoteInputEntriesToRemoveOnCollapse.valueAt(i);
|
||||
mRemoteInputController.removeRemoteInput(entry);
|
||||
removeNotification(entry.key, mLatestRankingMap);
|
||||
}
|
||||
mRemoteInputEntriesToRemoveOnCollapse.clear();
|
||||
}
|
||||
|
||||
public void onScreenTurnedOff() {
|
||||
@@ -4206,6 +4258,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
|| (state == StatusBarState.SHADE && isGoingToNotificationShade()))) {
|
||||
clearNotificationEffects();
|
||||
}
|
||||
if (state == StatusBarState.KEYGUARD) {
|
||||
removeRemoteInputEntriesKeptUntilCollapsed();
|
||||
}
|
||||
mState = state;
|
||||
mGroupManager.setStatusBarState(state);
|
||||
mFalsingManager.setStatusBarState(state);
|
||||
|
||||
@@ -2927,16 +2927,6 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
if (changed) {
|
||||
if (!mIsExpanded) {
|
||||
mGroupManager.collapseAllGroups();
|
||||
} else {
|
||||
// XXX: HACK: we should not be clearing notification effects from way down here.
|
||||
// But at the moment we don't have a reliable way to know when the window is
|
||||
// actually exposed to the air, so
|
||||
if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "clearing notification effects from scroller");
|
||||
}
|
||||
mPhoneStatusBar.clearNotificationEffects();
|
||||
}
|
||||
}
|
||||
updateNotificationAnimationStates();
|
||||
updateChronometers();
|
||||
|
||||
Reference in New Issue
Block a user