Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +48 −1 Original line number Diff line number Diff line Loading @@ -34,12 +34,17 @@ import android.widget.RemoteViews; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.ImageMessageConsumer; import com.android.systemui.Dependency; import com.android.systemui.statusbar.InflationTask; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.MediaNotificationProcessor; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplies; import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.util.Assert; import java.lang.annotation.Retention; Loading Loading @@ -278,6 +283,8 @@ public class NotificationContentInflater { InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(), mRow.getContext(), mRow.getHeadsUpManager()); apply( inflateSynchronously, result, Loading Loading @@ -306,6 +313,7 @@ public class NotificationContentInflater { if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) { mRow.getPrivateLayout().setHeadsUpChild(null); mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP); mRow.getPrivateLayout().setHeadsUpInflatedSmartReplies(null); } break; case FLAG_CONTENT_VIEW_AMBIENT: Loading Loading @@ -336,12 +344,33 @@ public class NotificationContentInflater { } } private static InflationProgress inflateSmartReplyViews(InflationProgress result, @InflationFlag int reInflateFlags, NotificationEntry entry, Context context, HeadsUpManager headsUpManager) { SmartReplyConstants smartReplyConstants = Dependency.get(SmartReplyConstants.class); SmartReplyController smartReplyController = Dependency.get(SmartReplyController.class); if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0 && result.newExpandedView != null) { result.expandedInflatedSmartReplies = InflatedSmartReplies.inflate( context, entry, smartReplyConstants, smartReplyController, headsUpManager); } if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0 && result.newHeadsUpView != null) { result.headsUpInflatedSmartReplies = InflatedSmartReplies.inflate( context, entry, smartReplyConstants, smartReplyController, headsUpManager); } return result; } private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags, Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient, Context packageContext) { InflationProgress result = new InflationProgress(); isLowPriority = isLowPriority && !isChildInGroup; if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight); } Loading Loading @@ -661,6 +690,12 @@ public class NotificationContentInflater { } else if (result.newExpandedView == null) { privateLayout.setExpandedChild(null); } if (result.newExpandedView != null) { privateLayout.setExpandedInflatedSmartReplies( result.expandedInflatedSmartReplies); } else { privateLayout.setExpandedInflatedSmartReplies(null); } cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); row.setExpandable(result.newExpandedView != null); } Loading @@ -671,6 +706,12 @@ public class NotificationContentInflater { } else if (result.newHeadsUpView == null) { privateLayout.setHeadsUpChild(null); } if (result.newHeadsUpView != null) { privateLayout.setHeadsUpInflatedSmartReplies( result.headsUpInflatedSmartReplies); } else { privateLayout.setHeadsUpInflatedSmartReplies(null); } cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); } Loading Loading @@ -846,9 +887,12 @@ public class NotificationContentInflater { packageContext); processor.processNotification(notification, recoveredBuilder); } return createRemoteViews(mReInflateFlags, recoveredBuilder, mIsLowPriority, InflationProgress inflationProgress = createRemoteViews(mReInflateFlags, recoveredBuilder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); return inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(), mRow.getContext(), mRow.getHeadsUpManager()); } catch (Exception e) { mError = e; return null; Loading Loading @@ -927,6 +971,9 @@ public class NotificationContentInflater { private View inflatedPublicView; private CharSequence headsUpStatusBarText; private CharSequence headsUpStatusBarTextPublic; private InflatedSmartReplies expandedInflatedSmartReplies; private InflatedSmartReplies headsUpInflatedSmartReplies; } @VisibleForTesting Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +70 −25 Original line number Diff line number Diff line Loading @@ -93,6 +93,8 @@ public class NotificationContentView extends FrameLayout { private SmartReplyView mExpandedSmartReplyView; private SmartReplyView mHeadsUpSmartReplyView; private SmartReplyController mSmartReplyController; private InflatedSmartReplies mExpandedInflatedSmartReplies; private InflatedSmartReplies mHeadsUpInflatedSmartReplies; private NotificationViewWrapper mContractedWrapper; private NotificationViewWrapper mExpandedWrapper; Loading Loading @@ -1316,8 +1318,22 @@ public class NotificationContentView extends FrameLayout { return; } SmartRepliesAndActions smartRepliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, entry); applyRemoteInput(entry, InflatedSmartReplies.hasFreeformRemoteInput(entry)); if (mExpandedInflatedSmartReplies == null && mHeadsUpInflatedSmartReplies == null) { if (DEBUG) { Log.d(TAG, "Both expanded, and heads-up InflatedSmartReplies are null, " + "don't add smart replies."); } return; } // The inflated smart-reply objects for the expanded view and the heads-up view both contain // the same SmartRepliesAndActions to avoid discrepancies between the two views. We here // reuse that object for our local SmartRepliesAndActions to avoid discrepancies between // this class and the InflatedSmartReplies classes. SmartRepliesAndActions smartRepliesAndActions = mExpandedInflatedSmartReplies != null ? mExpandedInflatedSmartReplies.getSmartRepliesAndActions() : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions(); if (DEBUG) { Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.", entry.notification.getKey(), Loading @@ -1326,7 +1342,6 @@ public class NotificationContentView extends FrameLayout { smartRepliesAndActions.smartReplies == null ? 0 : smartRepliesAndActions.smartReplies.choices.length)); } applyRemoteInput(entry, InflatedSmartReplies.hasFreeformRemoteInput(entry)); applySmartReplyView(smartRepliesAndActions, entry); } Loading Loading @@ -1429,11 +1444,12 @@ public class NotificationContentView extends FrameLayout { return null; } private void applySmartReplyView(SmartRepliesAndActions smartRepliesAndActions, private void applySmartReplyView( SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry) { if (mExpandedChild != null) { mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, smartRepliesAndActions, entry); mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, smartRepliesAndActions, entry, mExpandedInflatedSmartReplies); if (mExpandedSmartReplyView != null) { if (smartRepliesAndActions.smartReplies != null || smartRepliesAndActions.smartActions != null) { Loading @@ -1455,18 +1471,21 @@ public class NotificationContentView extends FrameLayout { } } if (mHeadsUpChild != null && mSmartReplyConstants.getShowInHeadsUp()) { mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, smartRepliesAndActions, entry); mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, smartRepliesAndActions, entry, mHeadsUpInflatedSmartReplies); } } @Nullable private SmartReplyView applySmartReplyView(View view, SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry) { SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry, InflatedSmartReplies inflatedSmartReplyView) { View smartReplyContainerCandidate = view.findViewById( com.android.internal.R.id.smart_reply_container); if (!(smartReplyContainerCandidate instanceof LinearLayout)) { return null; } LinearLayout smartReplyContainer = (LinearLayout) smartReplyContainerCandidate; if (!InflatedSmartReplies.shouldShowSmartReplyView(entry, smartRepliesAndActions)) { smartReplyContainer.setVisibility(View.GONE); Loading @@ -1474,31 +1493,57 @@ public class NotificationContentView extends FrameLayout { } SmartReplyView smartReplyView = null; if (smartReplyContainer.getChildCount() == 0) { smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer); if (smartReplyContainer.getChildCount() == 1 && smartReplyContainer.getChildAt(0) instanceof SmartReplyView) { // If we already have a SmartReplyView - replace it with the newly inflated one. The // newly inflated one is connected to the new inflated smart reply/action buttons. smartReplyContainer.removeAllViews(); } if (smartReplyContainer.getChildCount() == 0 && inflatedSmartReplyView != null && inflatedSmartReplyView.getSmartReplyView() != null) { smartReplyView = inflatedSmartReplyView.getSmartReplyView(); smartReplyContainer.addView(smartReplyView); } else if (smartReplyContainer.getChildCount() == 1) { View child = smartReplyContainer.getChildAt(0); if (child instanceof SmartReplyView) { smartReplyView = (SmartReplyView) child; } } if (smartReplyView != null) { smartReplyView.resetSmartSuggestions(smartReplyContainer); if (smartRepliesAndActions.smartReplies != null) { smartReplyView.addRepliesFromRemoteInput( smartRepliesAndActions.smartReplies, mSmartReplyController, entry); } if (smartRepliesAndActions.smartActions != null) { smartReplyView.addSmartActions( smartRepliesAndActions.smartActions, mSmartReplyController, entry, mContainingNotification.getHeadsUpManager()); } smartReplyView.addPreInflatedButtons( inflatedSmartReplyView.getSmartSuggestionButtons()); smartReplyContainer.setVisibility(View.VISIBLE); } return smartReplyView; } /** * Set pre-inflated views necessary to display smart replies and actions in the expanded * notification state. * * @param inflatedSmartReplies the pre-inflated state to add to this view. If null the existing * {@link SmartReplyView} related to the expanded notification state is cleared. */ public void setExpandedInflatedSmartReplies( @Nullable InflatedSmartReplies inflatedSmartReplies) { mExpandedInflatedSmartReplies = inflatedSmartReplies; if (inflatedSmartReplies == null) { mExpandedSmartReplyView = null; } } /** * Set pre-inflated views necessary to display smart replies and actions in the heads-up * notification state. * * @param inflatedSmartReplies the pre-inflated state to add to this view. If null the existing * {@link SmartReplyView} related to the heads-up notification state is cleared. */ public void setHeadsUpInflatedSmartReplies( @Nullable InflatedSmartReplies inflatedSmartReplies) { mHeadsUpInflatedSmartReplies = inflatedSmartReplies; if (inflatedSmartReplies == null) { mHeadsUpSmartReplyView = null; } } public void closeRemoteInput() { if (mHeadsUpRemoteInput != null) { mHeadsUpRemoteInput.close(); Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java +60 −1 Original line number Diff line number Diff line Loading @@ -20,13 +20,17 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.RemoteInput; import android.content.Context; import android.os.Build; import android.util.Log; import android.util.Pair; import android.widget.Button; import com.android.internal.util.ArrayUtils; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.ArrayList; import java.util.List; /** Loading @@ -36,8 +40,63 @@ import java.util.List; public class InflatedSmartReplies { private static final String TAG = "InflatedSmartReplies"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @Nullable private final SmartReplyView mSmartReplyView; @Nullable private final List<Button> mSmartSuggestionButtons; @NonNull private final SmartRepliesAndActions mSmartRepliesAndActions; private InflatedSmartReplies() { } private InflatedSmartReplies( @Nullable SmartReplyView smartReplyView, @Nullable List<Button> smartSuggestionButtons, @NonNull SmartRepliesAndActions smartRepliesAndActions) { mSmartReplyView = smartReplyView; mSmartSuggestionButtons = smartSuggestionButtons; mSmartRepliesAndActions = smartRepliesAndActions; } @Nullable public SmartReplyView getSmartReplyView() { return mSmartReplyView; } @Nullable public List<Button> getSmartSuggestionButtons() { return mSmartSuggestionButtons; } @NonNull public SmartRepliesAndActions getSmartRepliesAndActions() { return mSmartRepliesAndActions; } /** * Inflate a SmartReplyView and its smart suggestions. */ public static InflatedSmartReplies inflate( Context context, NotificationEntry entry, SmartReplyConstants smartReplyConstants, SmartReplyController smartReplyController, HeadsUpManager headsUpManager) { SmartRepliesAndActions smartRepliesAndActions = chooseSmartRepliesAndActions(smartReplyConstants, entry); if (!shouldShowSmartReplyView(entry, smartRepliesAndActions)) { return new InflatedSmartReplies(null /* smartReplyView */, null /* smartSuggestionButtons */, smartRepliesAndActions); } SmartReplyView smartReplyView = SmartReplyView.inflate(context); List<Button> suggestionButtons = new ArrayList<>(); if (smartRepliesAndActions.smartReplies != null) { suggestionButtons.addAll(smartReplyView.inflateRepliesFromRemoteInput( smartRepliesAndActions.smartReplies, smartReplyController, entry)); } if (smartRepliesAndActions.smartActions != null) { suggestionButtons.addAll( smartReplyView.inflateSmartActions(smartRepliesAndActions.smartActions, smartReplyController, entry, headsUpManager)); } return new InflatedSmartReplies(smartReplyView, suggestionButtons, smartRepliesAndActions); } /** * Returns whether we should show the smart reply view and its smart suggestions. Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +57 −33 File changed.Preview size limit exceeded, changes collapsed. Show changes packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +16 −12 Original line number Diff line number Diff line Loading @@ -113,7 +113,7 @@ public class SmartReplyViewTest extends SysuiTestCase { mDependency.injectTestDependency(SmartReplyConstants.class, mConstants); mContainer = new View(mContext, null); mView = SmartReplyView.inflate(mContext, null); mView = SmartReplyView.inflate(mContext); // Any number of replies are fine. when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(0); Loading Loading @@ -402,17 +402,18 @@ public class SmartReplyViewTest extends SysuiTestCase { } private void setSmartReplies(CharSequence[] choices) { setSmartReplies(choices, false /* fromAssistant */); mView.resetSmartSuggestions(mContainer); List<Button> replyButtons = inflateSmartReplies(choices, false /* fromAssistant */); mView.addPreInflatedButtons(replyButtons); } private void setSmartReplies(CharSequence[] choices, boolean fromAssistant) { private List<Button> inflateSmartReplies(CharSequence[] choices, boolean fromAssistant) { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(TEST_ACTION), 0); RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build(); SmartReplyView.SmartReplies smartReplies = new SmartReplyView.SmartReplies(choices, input, pendingIntent, fromAssistant); mView.resetSmartSuggestions(mContainer); mView.addRepliesFromRemoteInput(smartReplies, mLogger, mEntry); return mView.inflateRepliesFromRemoteInput(smartReplies, mLogger, mEntry); } private Notification.Action createAction(String actionTitle) { Loading @@ -431,11 +432,12 @@ public class SmartReplyViewTest extends SysuiTestCase { private void setSmartActions(String[] actionTitles) { mView.resetSmartSuggestions(mContainer); mView.addSmartActions( List<Button> actions = mView.inflateSmartActions( new SmartReplyView.SmartActions(createActions(actionTitles), false), mLogger, mEntry, mHeadsUpManager); mView.addPreInflatedButtons(actions); } private void setSmartRepliesAndActions(CharSequence[] choices, String[] actionTitles) { Loading @@ -444,12 +446,14 @@ public class SmartReplyViewTest extends SysuiTestCase { private void setSmartRepliesAndActions( CharSequence[] choices, String[] actionTitles, boolean fromAssistant) { setSmartReplies(choices, fromAssistant); mView.addSmartActions( mView.resetSmartSuggestions(mContainer); List<Button> smartSuggestions = inflateSmartReplies(choices, fromAssistant); smartSuggestions.addAll(mView.inflateSmartActions( new SmartReplyView.SmartActions(createActions(actionTitles), fromAssistant), mLogger, mEntry, mHeadsUpManager); mHeadsUpManager)); mView.addPreInflatedButtons(smartSuggestions); } private ViewGroup buildExpectedView(CharSequence[] choices, int lineCount) { Loading Loading @@ -485,8 +489,8 @@ public class SmartReplyViewTest extends SysuiTestCase { SmartReplyView.SmartReplies smartReplies = new SmartReplyView.SmartReplies(choices, null, null, false); for (int i = 0; i < choices.length; ++i) { Button current = mView.inflateReplyButton(mContext, mView, i, smartReplies, null, null); Button current = SmartReplyView.inflateReplyButton(mView, mContext, i, smartReplies, null /* SmartReplyController */, null /* NotificationEntry */); current.setPadding(paddingHorizontal, current.getPaddingTop(), paddingHorizontal, current.getPaddingBottom()); if (previous != null) { Loading Loading @@ -752,7 +756,7 @@ public class SmartReplyViewTest extends SysuiTestCase { } private Button inflateActionButton(Notification.Action action) { return mView.inflateActionButton(getContext(), mView, 0, return SmartReplyView.inflateActionButton(mView, getContext(), 0, new SmartReplyView.SmartActions(Collections.singletonList(action), false), mLogger, mEntry, mHeadsUpManager); } Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java +48 −1 Original line number Diff line number Diff line Loading @@ -34,12 +34,17 @@ import android.widget.RemoteViews; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.ImageMessageConsumer; import com.android.systemui.Dependency; import com.android.systemui.statusbar.InflationTask; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.InflationException; import com.android.systemui.statusbar.notification.MediaNotificationProcessor; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.InflatedSmartReplies; import com.android.systemui.statusbar.policy.SmartReplyConstants; import com.android.systemui.util.Assert; import java.lang.annotation.Retention; Loading Loading @@ -278,6 +283,8 @@ public class NotificationContentInflater { InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); result = inflateSmartReplyViews(result, reInflateFlags, mRow.getEntry(), mRow.getContext(), mRow.getHeadsUpManager()); apply( inflateSynchronously, result, Loading Loading @@ -306,6 +313,7 @@ public class NotificationContentInflater { if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) { mRow.getPrivateLayout().setHeadsUpChild(null); mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP); mRow.getPrivateLayout().setHeadsUpInflatedSmartReplies(null); } break; case FLAG_CONTENT_VIEW_AMBIENT: Loading Loading @@ -336,12 +344,33 @@ public class NotificationContentInflater { } } private static InflationProgress inflateSmartReplyViews(InflationProgress result, @InflationFlag int reInflateFlags, NotificationEntry entry, Context context, HeadsUpManager headsUpManager) { SmartReplyConstants smartReplyConstants = Dependency.get(SmartReplyConstants.class); SmartReplyController smartReplyController = Dependency.get(SmartReplyController.class); if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0 && result.newExpandedView != null) { result.expandedInflatedSmartReplies = InflatedSmartReplies.inflate( context, entry, smartReplyConstants, smartReplyController, headsUpManager); } if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0 && result.newHeadsUpView != null) { result.headsUpInflatedSmartReplies = InflatedSmartReplies.inflate( context, entry, smartReplyConstants, smartReplyController, headsUpManager); } return result; } private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags, Notification.Builder builder, boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight, boolean usesIncreasedHeadsUpHeight, boolean redactAmbient, Context packageContext) { InflationProgress result = new InflationProgress(); isLowPriority = isLowPriority && !isChildInGroup; if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) { result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight); } Loading Loading @@ -661,6 +690,12 @@ public class NotificationContentInflater { } else if (result.newExpandedView == null) { privateLayout.setExpandedChild(null); } if (result.newExpandedView != null) { privateLayout.setExpandedInflatedSmartReplies( result.expandedInflatedSmartReplies); } else { privateLayout.setExpandedInflatedSmartReplies(null); } cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView); row.setExpandable(result.newExpandedView != null); } Loading @@ -671,6 +706,12 @@ public class NotificationContentInflater { } else if (result.newHeadsUpView == null) { privateLayout.setHeadsUpChild(null); } if (result.newHeadsUpView != null) { privateLayout.setHeadsUpInflatedSmartReplies( result.headsUpInflatedSmartReplies); } else { privateLayout.setHeadsUpInflatedSmartReplies(null); } cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView); } Loading Loading @@ -846,9 +887,12 @@ public class NotificationContentInflater { packageContext); processor.processNotification(notification, recoveredBuilder); } return createRemoteViews(mReInflateFlags, recoveredBuilder, mIsLowPriority, InflationProgress inflationProgress = createRemoteViews(mReInflateFlags, recoveredBuilder, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight, mRedactAmbient, packageContext); return inflateSmartReplyViews(inflationProgress, mReInflateFlags, mRow.getEntry(), mRow.getContext(), mRow.getHeadsUpManager()); } catch (Exception e) { mError = e; return null; Loading Loading @@ -927,6 +971,9 @@ public class NotificationContentInflater { private View inflatedPublicView; private CharSequence headsUpStatusBarText; private CharSequence headsUpStatusBarTextPublic; private InflatedSmartReplies expandedInflatedSmartReplies; private InflatedSmartReplies headsUpInflatedSmartReplies; } @VisibleForTesting Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +70 −25 Original line number Diff line number Diff line Loading @@ -93,6 +93,8 @@ public class NotificationContentView extends FrameLayout { private SmartReplyView mExpandedSmartReplyView; private SmartReplyView mHeadsUpSmartReplyView; private SmartReplyController mSmartReplyController; private InflatedSmartReplies mExpandedInflatedSmartReplies; private InflatedSmartReplies mHeadsUpInflatedSmartReplies; private NotificationViewWrapper mContractedWrapper; private NotificationViewWrapper mExpandedWrapper; Loading Loading @@ -1316,8 +1318,22 @@ public class NotificationContentView extends FrameLayout { return; } SmartRepliesAndActions smartRepliesAndActions = InflatedSmartReplies.chooseSmartRepliesAndActions(mSmartReplyConstants, entry); applyRemoteInput(entry, InflatedSmartReplies.hasFreeformRemoteInput(entry)); if (mExpandedInflatedSmartReplies == null && mHeadsUpInflatedSmartReplies == null) { if (DEBUG) { Log.d(TAG, "Both expanded, and heads-up InflatedSmartReplies are null, " + "don't add smart replies."); } return; } // The inflated smart-reply objects for the expanded view and the heads-up view both contain // the same SmartRepliesAndActions to avoid discrepancies between the two views. We here // reuse that object for our local SmartRepliesAndActions to avoid discrepancies between // this class and the InflatedSmartReplies classes. SmartRepliesAndActions smartRepliesAndActions = mExpandedInflatedSmartReplies != null ? mExpandedInflatedSmartReplies.getSmartRepliesAndActions() : mHeadsUpInflatedSmartReplies.getSmartRepliesAndActions(); if (DEBUG) { Log.d(TAG, String.format("Adding suggestions for %s, %d actions, and %d replies.", entry.notification.getKey(), Loading @@ -1326,7 +1342,6 @@ public class NotificationContentView extends FrameLayout { smartRepliesAndActions.smartReplies == null ? 0 : smartRepliesAndActions.smartReplies.choices.length)); } applyRemoteInput(entry, InflatedSmartReplies.hasFreeformRemoteInput(entry)); applySmartReplyView(smartRepliesAndActions, entry); } Loading Loading @@ -1429,11 +1444,12 @@ public class NotificationContentView extends FrameLayout { return null; } private void applySmartReplyView(SmartRepliesAndActions smartRepliesAndActions, private void applySmartReplyView( SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry) { if (mExpandedChild != null) { mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, smartRepliesAndActions, entry); mExpandedSmartReplyView = applySmartReplyView(mExpandedChild, smartRepliesAndActions, entry, mExpandedInflatedSmartReplies); if (mExpandedSmartReplyView != null) { if (smartRepliesAndActions.smartReplies != null || smartRepliesAndActions.smartActions != null) { Loading @@ -1455,18 +1471,21 @@ public class NotificationContentView extends FrameLayout { } } if (mHeadsUpChild != null && mSmartReplyConstants.getShowInHeadsUp()) { mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, smartRepliesAndActions, entry); mHeadsUpSmartReplyView = applySmartReplyView(mHeadsUpChild, smartRepliesAndActions, entry, mHeadsUpInflatedSmartReplies); } } @Nullable private SmartReplyView applySmartReplyView(View view, SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry) { SmartRepliesAndActions smartRepliesAndActions, NotificationEntry entry, InflatedSmartReplies inflatedSmartReplyView) { View smartReplyContainerCandidate = view.findViewById( com.android.internal.R.id.smart_reply_container); if (!(smartReplyContainerCandidate instanceof LinearLayout)) { return null; } LinearLayout smartReplyContainer = (LinearLayout) smartReplyContainerCandidate; if (!InflatedSmartReplies.shouldShowSmartReplyView(entry, smartRepliesAndActions)) { smartReplyContainer.setVisibility(View.GONE); Loading @@ -1474,31 +1493,57 @@ public class NotificationContentView extends FrameLayout { } SmartReplyView smartReplyView = null; if (smartReplyContainer.getChildCount() == 0) { smartReplyView = SmartReplyView.inflate(mContext, smartReplyContainer); if (smartReplyContainer.getChildCount() == 1 && smartReplyContainer.getChildAt(0) instanceof SmartReplyView) { // If we already have a SmartReplyView - replace it with the newly inflated one. The // newly inflated one is connected to the new inflated smart reply/action buttons. smartReplyContainer.removeAllViews(); } if (smartReplyContainer.getChildCount() == 0 && inflatedSmartReplyView != null && inflatedSmartReplyView.getSmartReplyView() != null) { smartReplyView = inflatedSmartReplyView.getSmartReplyView(); smartReplyContainer.addView(smartReplyView); } else if (smartReplyContainer.getChildCount() == 1) { View child = smartReplyContainer.getChildAt(0); if (child instanceof SmartReplyView) { smartReplyView = (SmartReplyView) child; } } if (smartReplyView != null) { smartReplyView.resetSmartSuggestions(smartReplyContainer); if (smartRepliesAndActions.smartReplies != null) { smartReplyView.addRepliesFromRemoteInput( smartRepliesAndActions.smartReplies, mSmartReplyController, entry); } if (smartRepliesAndActions.smartActions != null) { smartReplyView.addSmartActions( smartRepliesAndActions.smartActions, mSmartReplyController, entry, mContainingNotification.getHeadsUpManager()); } smartReplyView.addPreInflatedButtons( inflatedSmartReplyView.getSmartSuggestionButtons()); smartReplyContainer.setVisibility(View.VISIBLE); } return smartReplyView; } /** * Set pre-inflated views necessary to display smart replies and actions in the expanded * notification state. * * @param inflatedSmartReplies the pre-inflated state to add to this view. If null the existing * {@link SmartReplyView} related to the expanded notification state is cleared. */ public void setExpandedInflatedSmartReplies( @Nullable InflatedSmartReplies inflatedSmartReplies) { mExpandedInflatedSmartReplies = inflatedSmartReplies; if (inflatedSmartReplies == null) { mExpandedSmartReplyView = null; } } /** * Set pre-inflated views necessary to display smart replies and actions in the heads-up * notification state. * * @param inflatedSmartReplies the pre-inflated state to add to this view. If null the existing * {@link SmartReplyView} related to the heads-up notification state is cleared. */ public void setHeadsUpInflatedSmartReplies( @Nullable InflatedSmartReplies inflatedSmartReplies) { mHeadsUpInflatedSmartReplies = inflatedSmartReplies; if (inflatedSmartReplies == null) { mHeadsUpSmartReplyView = null; } } public void closeRemoteInput() { if (mHeadsUpRemoteInput != null) { mHeadsUpRemoteInput.close(); Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplies.java +60 −1 Original line number Diff line number Diff line Loading @@ -20,13 +20,17 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.RemoteInput; import android.content.Context; import android.os.Build; import android.util.Log; import android.util.Pair; import android.widget.Button; import com.android.internal.util.ArrayUtils; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.ArrayList; import java.util.List; /** Loading @@ -36,8 +40,63 @@ import java.util.List; public class InflatedSmartReplies { private static final String TAG = "InflatedSmartReplies"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @Nullable private final SmartReplyView mSmartReplyView; @Nullable private final List<Button> mSmartSuggestionButtons; @NonNull private final SmartRepliesAndActions mSmartRepliesAndActions; private InflatedSmartReplies() { } private InflatedSmartReplies( @Nullable SmartReplyView smartReplyView, @Nullable List<Button> smartSuggestionButtons, @NonNull SmartRepliesAndActions smartRepliesAndActions) { mSmartReplyView = smartReplyView; mSmartSuggestionButtons = smartSuggestionButtons; mSmartRepliesAndActions = smartRepliesAndActions; } @Nullable public SmartReplyView getSmartReplyView() { return mSmartReplyView; } @Nullable public List<Button> getSmartSuggestionButtons() { return mSmartSuggestionButtons; } @NonNull public SmartRepliesAndActions getSmartRepliesAndActions() { return mSmartRepliesAndActions; } /** * Inflate a SmartReplyView and its smart suggestions. */ public static InflatedSmartReplies inflate( Context context, NotificationEntry entry, SmartReplyConstants smartReplyConstants, SmartReplyController smartReplyController, HeadsUpManager headsUpManager) { SmartRepliesAndActions smartRepliesAndActions = chooseSmartRepliesAndActions(smartReplyConstants, entry); if (!shouldShowSmartReplyView(entry, smartRepliesAndActions)) { return new InflatedSmartReplies(null /* smartReplyView */, null /* smartSuggestionButtons */, smartRepliesAndActions); } SmartReplyView smartReplyView = SmartReplyView.inflate(context); List<Button> suggestionButtons = new ArrayList<>(); if (smartRepliesAndActions.smartReplies != null) { suggestionButtons.addAll(smartReplyView.inflateRepliesFromRemoteInput( smartRepliesAndActions.smartReplies, smartReplyController, entry)); } if (smartRepliesAndActions.smartActions != null) { suggestionButtons.addAll( smartReplyView.inflateSmartActions(smartRepliesAndActions.smartActions, smartReplyController, entry, headsUpManager)); } return new InflatedSmartReplies(smartReplyView, suggestionButtons, smartRepliesAndActions); } /** * Returns whether we should show the smart reply view and its smart suggestions. Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +57 −33 File changed.Preview size limit exceeded, changes collapsed. Show changes
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java +16 −12 Original line number Diff line number Diff line Loading @@ -113,7 +113,7 @@ public class SmartReplyViewTest extends SysuiTestCase { mDependency.injectTestDependency(SmartReplyConstants.class, mConstants); mContainer = new View(mContext, null); mView = SmartReplyView.inflate(mContext, null); mView = SmartReplyView.inflate(mContext); // Any number of replies are fine. when(mConstants.getMinNumSystemGeneratedReplies()).thenReturn(0); Loading Loading @@ -402,17 +402,18 @@ public class SmartReplyViewTest extends SysuiTestCase { } private void setSmartReplies(CharSequence[] choices) { setSmartReplies(choices, false /* fromAssistant */); mView.resetSmartSuggestions(mContainer); List<Button> replyButtons = inflateSmartReplies(choices, false /* fromAssistant */); mView.addPreInflatedButtons(replyButtons); } private void setSmartReplies(CharSequence[] choices, boolean fromAssistant) { private List<Button> inflateSmartReplies(CharSequence[] choices, boolean fromAssistant) { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(TEST_ACTION), 0); RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).setChoices(choices).build(); SmartReplyView.SmartReplies smartReplies = new SmartReplyView.SmartReplies(choices, input, pendingIntent, fromAssistant); mView.resetSmartSuggestions(mContainer); mView.addRepliesFromRemoteInput(smartReplies, mLogger, mEntry); return mView.inflateRepliesFromRemoteInput(smartReplies, mLogger, mEntry); } private Notification.Action createAction(String actionTitle) { Loading @@ -431,11 +432,12 @@ public class SmartReplyViewTest extends SysuiTestCase { private void setSmartActions(String[] actionTitles) { mView.resetSmartSuggestions(mContainer); mView.addSmartActions( List<Button> actions = mView.inflateSmartActions( new SmartReplyView.SmartActions(createActions(actionTitles), false), mLogger, mEntry, mHeadsUpManager); mView.addPreInflatedButtons(actions); } private void setSmartRepliesAndActions(CharSequence[] choices, String[] actionTitles) { Loading @@ -444,12 +446,14 @@ public class SmartReplyViewTest extends SysuiTestCase { private void setSmartRepliesAndActions( CharSequence[] choices, String[] actionTitles, boolean fromAssistant) { setSmartReplies(choices, fromAssistant); mView.addSmartActions( mView.resetSmartSuggestions(mContainer); List<Button> smartSuggestions = inflateSmartReplies(choices, fromAssistant); smartSuggestions.addAll(mView.inflateSmartActions( new SmartReplyView.SmartActions(createActions(actionTitles), fromAssistant), mLogger, mEntry, mHeadsUpManager); mHeadsUpManager)); mView.addPreInflatedButtons(smartSuggestions); } private ViewGroup buildExpectedView(CharSequence[] choices, int lineCount) { Loading Loading @@ -485,8 +489,8 @@ public class SmartReplyViewTest extends SysuiTestCase { SmartReplyView.SmartReplies smartReplies = new SmartReplyView.SmartReplies(choices, null, null, false); for (int i = 0; i < choices.length; ++i) { Button current = mView.inflateReplyButton(mContext, mView, i, smartReplies, null, null); Button current = SmartReplyView.inflateReplyButton(mView, mContext, i, smartReplies, null /* SmartReplyController */, null /* NotificationEntry */); current.setPadding(paddingHorizontal, current.getPaddingTop(), paddingHorizontal, current.getPaddingBottom()); if (previous != null) { Loading Loading @@ -752,7 +756,7 @@ public class SmartReplyViewTest extends SysuiTestCase { } private Button inflateActionButton(Notification.Action action) { return mView.inflateActionButton(getContext(), mView, 0, return SmartReplyView.inflateActionButton(mView, getContext(), 0, new SmartReplyView.SmartActions(Collections.singletonList(action), false), mLogger, mEntry, mHeadsUpManager); } Loading