diff options
| author | 2016-04-27 22:17:32 +0000 | |
|---|---|---|
| committer | 2016-04-27 22:17:33 +0000 | |
| commit | 1a101dbc81151942eafaa95762c2e3fd53ceb05f (patch) | |
| tree | d45e9bec1ce0934d7c702af737cf0033bb3b8d38 | |
| parent | fab88eab310c892654506b3ad6e0eae4c0a8649e (diff) | |
| parent | 4c1fcc892e802840e3daad8be9eedb2eb1887ef8 (diff) | |
Merge "Fix remote input view clobbering" into nyc-dev
3 files changed, 118 insertions, 4 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index d7705b9ca830..d2dc7b7a9fc1 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3351,7 +3351,8 @@ public class Notification implements Parcelable } private void resetStandardTemplateWithActions(RemoteViews big) { - big.setViewVisibility(R.id.actions_container, View.GONE); + // actions_container is only reset when there are no actions to avoid focus issues with + // remote inputs. big.setViewVisibility(R.id.actions, View.GONE); big.removeAllViews(R.id.actions); @@ -3396,6 +3397,8 @@ public class Notification implements Parcelable } big.addView(R.id.actions, button); } + } else { + big.setViewVisibility(R.id.actions_container, View.GONE); } CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 7be50c4ecc46..81303fe6be9c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar; import android.app.Notification; +import android.app.PendingIntent; import android.app.RemoteInput; import android.content.Context; import android.graphics.Rect; @@ -118,6 +119,8 @@ public class NotificationContentView extends FrameLayout { private int mTransformationStartVisibleType; private boolean mUserExpanding; private int mSingleLineWidthIndention; + private PendingIntent mPreviousExpandedRemoteInputIntent; + private PendingIntent mPreviousHeadsUpRemoteInputIntent; public NotificationContentView(Context context, AttributeSet attrs) { super(context, attrs); @@ -280,13 +283,19 @@ public class NotificationContentView extends FrameLayout { mContractedChild.animate().cancel(); removeView(mContractedChild); } + mPreviousExpandedRemoteInputIntent = + mExpandedRemoteInput != null ? mExpandedRemoteInput.getPendingIntent() : null; if (mExpandedChild != null) { mExpandedChild.animate().cancel(); removeView(mExpandedChild); + mExpandedRemoteInput = null; } + mPreviousHeadsUpRemoteInputIntent = + mHeadsUpRemoteInput != null ? mHeadsUpRemoteInput.getPendingIntent() : null; if (mHeadsUpChild != null) { mHeadsUpChild.animate().cancel(); removeView(mHeadsUpChild); + mHeadsUpRemoteInput = null; } mContractedChild = null; mExpandedChild = null; @@ -496,6 +505,12 @@ public class NotificationContentView extends FrameLayout { } int visibleType = calculateVisibleType(); if (visibleType != mVisibleType || force) { + View visibleView = getViewForVisibleType(visibleType); + if (visibleView != null) { + visibleView.setVisibility(VISIBLE); + transferRemoteInputFocus(visibleType); + } + if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null) || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null) || (visibleType == VISIBLE_TYPE_SINGLELINE && mSingleLineView != null) @@ -559,6 +574,19 @@ public class NotificationContentView extends FrameLayout { }); } + private void transferRemoteInputFocus(int visibleType) { + if (visibleType == VISIBLE_TYPE_HEADSUP + && mHeadsUpRemoteInput != null + && (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive())) { + mHeadsUpRemoteInput.stealFocusFrom(mExpandedRemoteInput); + } + if (visibleType == VISIBLE_TYPE_EXPANDED + && mExpandedRemoteInput != null + && (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive())) { + mExpandedRemoteInput.stealFocusFrom(mHeadsUpRemoteInput); + } + } + /** * @param visibleType one of the static enum types in this view * @return the corresponding transformable view according to the given visible type @@ -736,6 +764,8 @@ public class NotificationContentView extends FrameLayout { updateShowingLegacyBackground(); selectLayout(false /* animate */, true /* force */); setDark(mDark, false /* animate */, 0 /* delay */); + mPreviousExpandedRemoteInputIntent = null; + mPreviousHeadsUpRemoteInputIntent = null; } private void updateSingleLineView() { @@ -771,19 +801,23 @@ public class NotificationContentView extends FrameLayout { View bigContentView = mExpandedChild; if (bigContentView != null) { - mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput); + mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput, + mPreviousExpandedRemoteInputIntent); } else { mExpandedRemoteInput = null; } + View headsUpContentView = mHeadsUpChild; if (headsUpContentView != null) { - mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput); + mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput, + mPreviousHeadsUpRemoteInputIntent); } else { mHeadsUpRemoteInput = null; } } - private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, boolean hasRemoteInput) { + private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry, + boolean hasRemoteInput, PendingIntent existingPendingIntent) { View actionContainerCandidate = view.findViewById( com.android.internal.R.id.actions_container); if (actionContainerCandidate instanceof FrameLayout) { @@ -814,6 +848,24 @@ public class NotificationContentView extends FrameLayout { existing.setBackgroundColor(NotificationColorUtil.ensureTextBackgroundColor(color, mContext.getColor(R.color.remote_input_text), mContext.getColor(R.color.remote_input_hint))); + + if (existingPendingIntent != null || existing.isActive()) { + // The current action could be gone, or the pending intent no longer valid. + // If we find a matching action in the new notification, focus, otherwise close. + Notification.Action[] actions = entry.notification.getNotification().actions; + if (existingPendingIntent != null) { + existing.setPendingIntent(existingPendingIntent); + } + if (existing.updatePendingIntentFromActions(actions)) { + if (!existing.isActive()) { + existing.focus(); + } + } else { + if (existing.isActive()) { + existing.close(); + } + } + } } return existing; } 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 ecd1772890ef..0fdd99fe7f58 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.policy; +import android.app.Notification; import android.app.PendingIntent; import android.app.RemoteInput; import android.content.Context; @@ -197,6 +198,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } public void focus() { + setVisibility(VISIBLE); mController.addRemoteInput(mEntry); mEditText.setInnerFocusable(true); mEditText.mShowImeOnInputConnection = true; @@ -275,6 +277,63 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } } + public boolean isActive() { + return mEditText.isFocused(); + } + + public void stealFocusFrom(RemoteInputView other) { + other.close(); + setPendingIntent(other.mPendingIntent); + setRemoteInput(other.mRemoteInputs, other.mRemoteInput); + focus(); + } + + /** + * Tries to find an action in {@param actions} that matches the current pending intent + * of this view and updates its state to that of the found action + * + * @return true if a matching action was found, false otherwise + */ + public boolean updatePendingIntentFromActions(Notification.Action[] actions) { + boolean found = false; + if (mPendingIntent == null || actions == null) { + return false; + } + Intent current = mPendingIntent.getIntent(); + if (current == null) { + return false; + } + + for (Notification.Action a : actions) { + RemoteInput[] inputs = a.getRemoteInputs(); + if (a.actionIntent == null || inputs == null) { + continue; + } + Intent candidate = a.actionIntent.getIntent(); + if (!current.filterEquals(candidate)) { + continue; + } + + RemoteInput input = null; + for (RemoteInput i : inputs) { + if (i.getAllowFreeFormInput()) { + input = i; + } + } + if (input == null) { + continue; + } + setPendingIntent(a.actionIntent); + setRemoteInput(inputs, input); + return true; + } + return false; + } + + public PendingIntent getPendingIntent() { + return mPendingIntent; + } + /** * An EditText that changes appearance based on whether it's focusable and becomes * un-focusable whenever the user navigates away from it or it becomes invisible. |