1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 package com.android.systemui.statusbar; 17 18 import android.app.Notification; 19 import android.os.RemoteException; 20 import android.util.ArraySet; 21 22 import androidx.annotation.NonNull; 23 24 import com.android.internal.statusbar.IStatusBarService; 25 import com.android.internal.statusbar.NotificationVisibility; 26 import com.android.systemui.Dumpable; 27 import com.android.systemui.dump.DumpManager; 28 import com.android.systemui.statusbar.dagger.StatusBarModule; 29 import com.android.systemui.statusbar.notification.NotificationEntryManager; 30 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 31 import com.android.systemui.statusbar.notification.logging.NotificationLogger; 32 33 import java.io.FileDescriptor; 34 import java.io.PrintWriter; 35 import java.util.Set; 36 37 /** 38 * Handles when smart replies are added to a notification 39 * and clicked upon. 40 */ 41 public class SmartReplyController implements Dumpable { 42 private final IStatusBarService mBarService; 43 private final NotificationEntryManager mEntryManager; 44 private final NotificationClickNotifier mClickNotifier; 45 private final Set<String> mSendingKeys = new ArraySet<>(); 46 private Callback mCallback; 47 48 /** 49 * Injected constructor. See {@link StatusBarModule}. 50 */ SmartReplyController( DumpManager dumpManager, NotificationEntryManager entryManager, IStatusBarService statusBarService, NotificationClickNotifier clickNotifier)51 public SmartReplyController( 52 DumpManager dumpManager, 53 NotificationEntryManager entryManager, 54 IStatusBarService statusBarService, 55 NotificationClickNotifier clickNotifier) { 56 mBarService = statusBarService; 57 mEntryManager = entryManager; 58 mClickNotifier = clickNotifier; 59 dumpManager.registerDumpable(this); 60 } 61 setCallback(Callback callback)62 public void setCallback(Callback callback) { 63 mCallback = callback; 64 } 65 66 /** 67 * Notifies StatusBarService a smart reply is sent. 68 */ smartReplySent(NotificationEntry entry, int replyIndex, CharSequence reply, int notificationLocation, boolean modifiedBeforeSending)69 public void smartReplySent(NotificationEntry entry, int replyIndex, CharSequence reply, 70 int notificationLocation, boolean modifiedBeforeSending) { 71 mCallback.onSmartReplySent(entry, reply); 72 mSendingKeys.add(entry.getKey()); 73 try { 74 mBarService.onNotificationSmartReplySent(entry.getSbn().getKey(), replyIndex, reply, 75 notificationLocation, modifiedBeforeSending); 76 } catch (RemoteException e) { 77 // Nothing to do, system going down 78 } 79 } 80 81 /** 82 * Notifies StatusBarService a smart action is clicked. 83 */ smartActionClicked( NotificationEntry entry, int actionIndex, Notification.Action action, boolean generatedByAssistant)84 public void smartActionClicked( 85 NotificationEntry entry, int actionIndex, Notification.Action action, 86 boolean generatedByAssistant) { 87 // TODO(b/204183781): get this from the current pipeline 88 final int count = mEntryManager.getActiveNotificationsCount(); 89 final int rank = entry.getRanking().getRank(); 90 NotificationVisibility.NotificationLocation location = 91 NotificationLogger.getNotificationLocation(entry); 92 final NotificationVisibility nv = NotificationVisibility.obtain( 93 entry.getKey(), rank, count, true, location); 94 mClickNotifier.onNotificationActionClick( 95 entry.getKey(), actionIndex, action, nv, generatedByAssistant); 96 } 97 98 /** 99 * Have we posted an intent to an app about sending a smart reply from the 100 * notification with this key. 101 */ isSendingSmartReply(String key)102 public boolean isSendingSmartReply(String key) { 103 return mSendingKeys.contains(key); 104 } 105 106 /** 107 * Smart Replies and Actions have been added to the UI. 108 */ smartSuggestionsAdded(final NotificationEntry entry, int replyCount, int actionCount, boolean generatedByAssistant, boolean editBeforeSending)109 public void smartSuggestionsAdded(final NotificationEntry entry, int replyCount, 110 int actionCount, boolean generatedByAssistant, boolean editBeforeSending) { 111 try { 112 mBarService.onNotificationSmartSuggestionsAdded(entry.getSbn().getKey(), replyCount, 113 actionCount, generatedByAssistant, editBeforeSending); 114 } catch (RemoteException e) { 115 // Nothing to do, system going down 116 } 117 } 118 stopSending(final NotificationEntry entry)119 public void stopSending(final NotificationEntry entry) { 120 if (entry != null) { 121 mSendingKeys.remove(entry.getSbn().getKey()); 122 } 123 } 124 125 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args)126 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { 127 pw.println("mSendingKeys: " + mSendingKeys.size()); 128 for (String key : mSendingKeys) { 129 pw.println(" * " + key); 130 } 131 } 132 133 /** 134 * Callback for any class that needs to do something in response to a smart reply being sent. 135 */ 136 public interface Callback { 137 /** 138 * A smart reply has just been sent for a notification 139 * 140 * @param entry the entry for the notification 141 * @param reply the reply that was sent 142 */ onSmartReplySent(NotificationEntry entry, CharSequence reply)143 void onSmartReplySent(NotificationEntry entry, CharSequence reply); 144 } 145 } 146