From c0a579e5752b38257c31acb2f0b5b08447355205 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 30 Mar 2016 16:43:58 -0700 Subject: [PATCH] Add option to force remote input history Bug: 27851227 Change-Id: Iced5d24d6cc0894ce7c7e9565722d0ef016a50a5 --- .../systemui/statusbar/BaseStatusBar.java | 17 ++++++- .../statusbar/RemoteInputController.java | 38 +++++++++++--- .../statusbar/phone/PhoneStatusBar.java | 50 ++++++++++++++++++- .../statusbar/policy/RemoteInputView.java | 5 ++ 4 files changed, 100 insertions(+), 10 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 2d2a08a062273..51cc0a06ce450 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -127,6 +127,8 @@ public abstract class BaseStatusBar extends SystemUI implements SystemProperties.getBoolean("debug.enable_remote_input", true); public static final boolean ENABLE_CHILD_NOTIFICATIONS = SystemProperties.getBoolean("debug.child_notifs", true); + public static final boolean FORCE_REMOTE_INPUT_HISTORY = + SystemProperties.getBoolean("debug.force_remoteinput_history", false); protected static final int MSG_SHOW_RECENT_APPS = 1019; protected static final int MSG_HIDE_RECENT_APPS = 1020; @@ -182,6 +184,13 @@ public abstract class BaseStatusBar extends SystemUI implements protected boolean mVisible; protected ArraySet mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>(); + /** + * Notifications with keys in this set are not actually around anymore. We kept them around + * when they were canceled in response to a remote input interaction. This allows us to show + * what you replied and allows you to continue typing into it. + */ + protected ArraySet mKeysKeptForRemoteInput = new ArraySet<>(); + // mScreenOnFromKeyguard && mVisible. private boolean mVisibleToUser; @@ -566,6 +575,7 @@ public abstract class BaseStatusBar extends SystemUI implements public void run() { processForRemoteInput(sbn.getNotification()); String key = sbn.getKey(); + mKeysKeptForRemoteInput.remove(key); boolean isUpdate = mNotificationData.get(key) != null; // In case we don't allow child notifications, we ignore children of // notifications that have a summary, since we're not going to show them @@ -904,7 +914,7 @@ public abstract class BaseStatusBar extends SystemUI implements } } - protected View bindVetoButtonClickListener(View row, StatusBarNotification n) { + protected View bindVetoButtonClickListener(View row, final StatusBarNotification n) { View vetoButton = row.findViewById(R.id.veto); final String _pkg = n.getPackageName(); final String _tag = n.getTag(); @@ -917,6 +927,11 @@ public abstract class BaseStatusBar extends SystemUI implements mContext.getString(R.string.accessibility_notification_dismissed)); try { mBarService.onNotificationClear(_pkg, _tag, _id, _userId); + if (FORCE_REMOTE_INPUT_HISTORY + && mKeysKeptForRemoteInput.contains(n.getKey())) { + removeNotification(n.getKey(), null); + mKeysKeptForRemoteInput.remove(n.getKey()); + } } catch (RemoteException ex) { // system process is dead if we're here. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java index d7e47c27dc718..5fea674f47b1f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java @@ -21,6 +21,8 @@ import com.android.systemui.statusbar.phone.StatusBarWindowManager; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.RemoteInputView; +import android.util.ArraySet; + import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -29,7 +31,8 @@ import java.util.ArrayList; */ public class RemoteInputController { - private final ArrayList> mRemoteInputs = new ArrayList<>(); + private final ArrayList> mOpen = new ArrayList<>(); + private final ArraySet mSpinning = new ArraySet<>(); private final ArrayList mCallbacks = new ArrayList<>(3); private final HeadsUpManager mHeadsUpManager; @@ -44,7 +47,7 @@ public class RemoteInputController { boolean found = pruneWeakThenRemoveAndContains( entry /* contains */, null /* remove */); if (!found) { - mRemoteInputs.add(new WeakReference<>(entry)); + mOpen.add(new WeakReference<>(entry)); } apply(entry); @@ -58,6 +61,18 @@ public class RemoteInputController { apply(entry); } + public void addSpinning(String key) { + mSpinning.add(key); + } + + public void removeSpinning(String key) { + mSpinning.remove(key); + } + + public boolean isSpinning(String key) { + return mSpinning.contains(key); + } + private void apply(NotificationData.Entry entry) { mHeadsUpManager.setRemoteInputActive(entry, isRemoteInputActive(entry)); boolean remoteInputActive = isRemoteInputActive(); @@ -79,7 +94,7 @@ public class RemoteInputController { */ public boolean isRemoteInputActive() { pruneWeakThenRemoveAndContains(null /* contains */, null /* remove */); - return !mRemoteInputs.isEmpty(); + return !mOpen.isEmpty(); } /** @@ -91,10 +106,10 @@ public class RemoteInputController { private boolean pruneWeakThenRemoveAndContains( NotificationData.Entry contains, NotificationData.Entry remove) { boolean found = false; - for (int i = mRemoteInputs.size() - 1; i >= 0; i--) { - NotificationData.Entry item = mRemoteInputs.get(i).get(); + for (int i = mOpen.size() - 1; i >= 0; i--) { + NotificationData.Entry item = mOpen.get(i).get(); if (item == null || item == remove) { - mRemoteInputs.remove(i); + mOpen.remove(i); } else if (item == contains) { found = true; } @@ -108,7 +123,16 @@ public class RemoteInputController { mCallbacks.add(callback); } + public void remoteInputSent(NotificationData.Entry entry) { + int N = mCallbacks.size(); + for (int i = 0; i < N; i++) { + mCallbacks.get(i).onRemoteInputSent(entry); + } + } + public interface Callback { - void onRemoteInputActive(boolean active); + default void onRemoteInputActive(boolean active) {} + + default void onRemoteInputSent(NotificationData.Entry entry) {} } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index e84d8fc819033..bfe8446ce4428 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -48,7 +48,6 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; -import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.media.AudioAttributes; import android.media.MediaMetadata; @@ -132,7 +131,6 @@ import com.android.systemui.statusbar.DismissView; import com.android.systemui.statusbar.DragDownHelper; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.ExpandableNotificationRow; -import com.android.systemui.statusbar.ExpandableView; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.KeyguardIndicationController; import com.android.systemui.statusbar.NotificationData; @@ -1106,6 +1104,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarKeyguardViewManager); mFingerprintUnlockController.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); + } + } + }); + } + mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController); } @@ -1374,6 +1384,42 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, clearCurrentMediaNotification(); updateMediaMetaData(true, true); } + if (FORCE_REMOTE_INPUT_HISTORY && mRemoteInputController.isSpinning(key)) { + Entry entry = mNotificationData.get(key); + StatusBarNotification sbn = entry.notification; + + Notification.Builder b = Notification.Builder + .recoverBuilder(mContext, sbn.getNotification().clone()); + CharSequence[] oldHistory = sbn.getNotification().extras + .getCharSequenceArray(Notification.EXTRA_REMOTE_INPUT_HISTORY); + CharSequence[] newHistory; + if (oldHistory == null) { + newHistory = new CharSequence[1]; + } else { + newHistory = new CharSequence[oldHistory.length + 1]; + for (int i = 0; i < oldHistory.length; i++) { + newHistory[i + 1] = oldHistory[i]; + } + } + newHistory[0] = String.valueOf(entry.remoteInputText); + b.setRemoteInputHistory(newHistory); + + Notification newNotification = b.build(); + + // Undo any compatibility view inflation + newNotification.contentView = sbn.getNotification().contentView; + newNotification.bigContentView = sbn.getNotification().bigContentView; + newNotification.headsUpContentView = sbn.getNotification().headsUpContentView; + + StatusBarNotification newSbn = new StatusBarNotification(sbn.getPackageName(), + sbn.getOpPkg(), + sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), + 0, newNotification, sbn.getUser(), sbn.getPostTime()); + + updateNotification(newSbn, null); + mKeysKeptForRemoteInput.add(entry.key); + return; + } if (deferRemoval) { mLatestRankingMap = ranking; mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index 3a0336bff9051..ec8e3ffc45a00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -119,8 +119,11 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mEditText.setEnabled(false); mSendButton.setVisibility(INVISIBLE); mProgressBar.setVisibility(VISIBLE); + mEntry.remoteInputText = mEditText.getText(); + mController.addSpinning(mEntry.key); mController.removeRemoteInput(mEntry); mEditText.mShowImeOnInputConnection = false; + mController.remoteInputSent(mEntry); try { mPendingIntent.send(mContext, 0, fillInIntent); @@ -175,6 +178,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return; } mController.removeRemoteInput(mEntry); + mController.removeSpinning(mEntry.key); } public void setPendingIntent(PendingIntent pendingIntent) { @@ -211,6 +215,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mEditText.setEnabled(true); mSendButton.setVisibility(VISIBLE); mProgressBar.setVisibility(INVISIBLE); + mController.removeSpinning(mEntry.key); updateSendButton(); onDefocus(); }