Merge "NAS Feedback API Change" into sc-dev
This commit is contained in:
@@ -5556,6 +5556,7 @@ package android.app {
|
||||
method public android.graphics.drawable.Icon getSmallIcon();
|
||||
method public String getSortKey();
|
||||
method public long getTimeoutAfter();
|
||||
method public boolean hasImage();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.media.AudioAttributes AUDIO_ATTRIBUTES_DEFAULT;
|
||||
field public static final int BADGE_ICON_LARGE = 2; // 0x2
|
||||
|
||||
@@ -10180,6 +10180,7 @@ package android.service.notification {
|
||||
method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel);
|
||||
method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel, @NonNull android.service.notification.NotificationListenerService.RankingMap);
|
||||
method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
|
||||
method public void onNotificationFeedbackReceived(@NonNull String, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.os.Bundle);
|
||||
method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
|
||||
method public void onNotificationVisibilityChanged(@NonNull String, boolean);
|
||||
method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
|
||||
@@ -10187,6 +10188,7 @@ package android.service.notification {
|
||||
method public void onPanelRevealed(int);
|
||||
method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
|
||||
method public final void unsnoozeNotification(@NonNull String);
|
||||
field public static final String FEEDBACK_RATING = "feedback.rating";
|
||||
field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
|
||||
field public static final int SOURCE_FROM_APP = 0; // 0x0
|
||||
field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
|
||||
|
||||
@@ -300,6 +300,7 @@ package android.app {
|
||||
method public void clickNotification(@Nullable String, int, int, boolean);
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels();
|
||||
method public void expandNotificationsPanel();
|
||||
method public void sendNotificationFeedback(@Nullable String, @Nullable android.os.Bundle);
|
||||
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
|
||||
}
|
||||
|
||||
|
||||
@@ -6766,6 +6766,31 @@ public class Notification implements Parcelable
|
||||
return when != 0 && extras.getBoolean(EXTRA_SHOW_CHRONOMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the notification has image
|
||||
*/
|
||||
public boolean hasImage() {
|
||||
if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) {
|
||||
final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
|
||||
if (!ArrayUtils.isEmpty(messages)) {
|
||||
for (MessagingStyle.Message m : MessagingStyle.Message
|
||||
.getMessagesFromBundleArray(messages)) {
|
||||
if (m.getDataUri() != null
|
||||
&& m.getDataMimeType() != null
|
||||
&& m.getDataMimeType().startsWith("image/")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (hasLargeIcon()) {
|
||||
return true;
|
||||
} else if (extras.containsKey(EXTRA_BACKGROUND_IMAGE_URI)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @removed
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
@@ -285,6 +286,23 @@ public class StatusBarManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate notification feedback for testing
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void sendNotificationFeedback(@Nullable String key, @Nullable Bundle feedback) {
|
||||
try {
|
||||
final IStatusBarService svc = getService();
|
||||
if (svc != null) {
|
||||
svc.onNotificationFeedbackReceived(key, feedback);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the notifications panel.
|
||||
*
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.NotificationStats;
|
||||
import android.service.notification.IStatusBarNotificationHolder;
|
||||
@@ -58,4 +59,5 @@ oneway interface INotificationListener
|
||||
void onActionClicked(String key, in Notification.Action action, int source);
|
||||
void onNotificationClicked(String key);
|
||||
void onAllowedAdjustmentsChanged();
|
||||
void onNotificationFeedbackReceived(String key, in NotificationRankingUpdate update, in Bundle feedback);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -89,6 +90,11 @@ public abstract class NotificationAssistantService extends NotificationListenerS
|
||||
public static final String SERVICE_INTERFACE
|
||||
= "android.service.notification.NotificationAssistantService";
|
||||
|
||||
/**
|
||||
* Data type: int, the feedback rating score provided by user
|
||||
*/
|
||||
public static final String FEEDBACK_RATING = "feedback.rating";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -271,6 +277,17 @@ public abstract class NotificationAssistantService extends NotificationListenerS
|
||||
public void onAllowedAdjustmentsChanged() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this to know when user provides a feedback.
|
||||
* @param key the notification key
|
||||
* @param rankingMap The current ranking map that can be used to retrieve ranking information
|
||||
* for active notifications.
|
||||
* @param feedback the feedback detail
|
||||
*/
|
||||
public void onNotificationFeedbackReceived(@NonNull String key, @NonNull RankingMap rankingMap,
|
||||
@NonNull Bundle feedback) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a notification. N.B. this won’t cause
|
||||
* an existing notification to alert, but might allow a future update to
|
||||
@@ -455,6 +472,18 @@ public abstract class NotificationAssistantService extends NotificationListenerS
|
||||
public void onAllowedAdjustmentsChanged() {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_ALLOWED_ADJUSTMENTS_CHANGED).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationFeedbackReceived(String key, NotificationRankingUpdate update,
|
||||
Bundle feedback) {
|
||||
applyUpdateLocked(update);
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = key;
|
||||
args.arg2 = getCurrentRanking();
|
||||
args.arg3 = feedback;
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_FEEDBACK_RECEIVED,
|
||||
args).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void setAdjustmentIssuer(@Nullable Adjustment adjustment) {
|
||||
@@ -476,6 +505,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS
|
||||
public static final int MSG_ON_PANEL_HIDDEN = 10;
|
||||
public static final int MSG_ON_NOTIFICATION_VISIBILITY_CHANGED = 11;
|
||||
public static final int MSG_ON_NOTIFICATION_CLICKED = 12;
|
||||
public static final int MSG_ON_NOTIFICATION_FEEDBACK_RECEIVED = 13;
|
||||
|
||||
public MyHandler(Looper looper) {
|
||||
super(looper, null, false);
|
||||
@@ -589,6 +619,15 @@ public abstract class NotificationAssistantService extends NotificationListenerS
|
||||
onNotificationClicked(key);
|
||||
break;
|
||||
}
|
||||
case MSG_ON_NOTIFICATION_FEEDBACK_RECEIVED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
String key = (String) args.arg1;
|
||||
RankingMap ranking = (RankingMap) args.arg2;
|
||||
Bundle feedback = (Bundle) args.arg3;
|
||||
args.recycle();
|
||||
onNotificationFeedbackReceived(key, ranking, feedback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -1543,6 +1544,14 @@ public abstract class NotificationListenerService extends Service {
|
||||
mHandler.obtainMessage(MyHandler.MSG_ON_STATUS_BAR_ICON_BEHAVIOR_CHANGED,
|
||||
hideSilentStatusIcons).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationFeedbackReceived(String key, NotificationRankingUpdate update,
|
||||
Bundle feedback) {
|
||||
// no-op in the listener
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1628,6 +1637,7 @@ public abstract class NotificationListenerService extends Service {
|
||||
private int mSuppressedVisualEffects;
|
||||
private @NotificationManager.Importance int mImportance;
|
||||
private CharSequence mImportanceExplanation;
|
||||
private float mRankingScore;
|
||||
// System specified group key.
|
||||
private String mOverrideGroupKey;
|
||||
// Notification assistant channel override.
|
||||
@@ -1668,6 +1678,7 @@ public abstract class NotificationListenerService extends Service {
|
||||
out.writeInt(mSuppressedVisualEffects);
|
||||
out.writeInt(mImportance);
|
||||
out.writeCharSequence(mImportanceExplanation);
|
||||
out.writeFloat(mRankingScore);
|
||||
out.writeString(mOverrideGroupKey);
|
||||
out.writeParcelable(mChannel, flags);
|
||||
out.writeStringList(mOverridePeople);
|
||||
@@ -1705,6 +1716,7 @@ public abstract class NotificationListenerService extends Service {
|
||||
mSuppressedVisualEffects = in.readInt();
|
||||
mImportance = in.readInt();
|
||||
mImportanceExplanation = in.readCharSequence(); // may be null
|
||||
mRankingScore = in.readFloat();
|
||||
mOverrideGroupKey = in.readString(); // may be null
|
||||
mChannel = in.readParcelable(cl); // may be null
|
||||
mOverridePeople = in.createStringArrayList();
|
||||
@@ -1801,6 +1813,17 @@ public abstract class NotificationListenerService extends Service {
|
||||
return mImportanceExplanation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ranking score provided by the {@link NotificationAssistantService} to
|
||||
* sort the notifications in the shade
|
||||
*
|
||||
* @return the ranking score of the notification, range from -1 to 1
|
||||
* @hide
|
||||
*/
|
||||
public float getRankingScore() {
|
||||
return mRankingScore;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the system has overridden the group key, then this will be non-null, and this
|
||||
* key should be used to bundle notifications.
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.graphics.Rect;
|
||||
import android.hardware.biometrics.IBiometricSysuiReceiver;
|
||||
import android.hardware.biometrics.PromptInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
@@ -82,6 +83,7 @@ interface IStatusBarService
|
||||
void hideCurrentInputMethodForBubbles();
|
||||
void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
|
||||
void clearInlineReplyUriPermissions(String key);
|
||||
void onNotificationFeedbackReceived(String key, in Bundle feedback);
|
||||
|
||||
void onGlobalActionsShown();
|
||||
void onGlobalActionsHidden();
|
||||
|
||||
@@ -109,10 +109,10 @@ public class AssistantFeedbackController {
|
||||
&& newImportance < NotificationManager.IMPORTANCE_DEFAULT) {
|
||||
return STATUS_SILENCED;
|
||||
} else if (oldImportance < newImportance
|
||||
|| ranking.getRankingAdjustment() == ranking.RANKING_PROMOTED) {
|
||||
|| ranking.getRankingAdjustment() == Ranking.RANKING_PROMOTED) {
|
||||
return STATUS_PROMOTED;
|
||||
} else if (oldImportance > newImportance
|
||||
|| ranking.getRankingAdjustment() == ranking.RANKING_DEMOTED) {
|
||||
|| ranking.getRankingAdjustment() == Ranking.RANKING_DEMOTED) {
|
||||
return STATUS_DEMOTED;
|
||||
} else {
|
||||
return STATUS_UNCHANGED;
|
||||
|
||||
@@ -16,8 +16,14 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import static android.service.notification.NotificationAssistantService.FEEDBACK_RATING;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_ALERTED;
|
||||
import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED;
|
||||
import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED;
|
||||
import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -36,20 +42,17 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.statusbar.notification.AssistantFeedbackController;
|
||||
import com.android.systemui.statusbar.notification.NotificationEntryManager;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
|
||||
|
||||
public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsContent {
|
||||
|
||||
private static final String TAG = "FeedbackInfo";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final String FEEDBACK_KEY = "feedback_key";
|
||||
|
||||
private NotificationGuts mGutsContainer;
|
||||
private NotificationListenerService.Ranking mRanking;
|
||||
@@ -146,15 +149,15 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC
|
||||
sb.append(String.format(
|
||||
"[DEBUG]: oldImportance=%d, newImportance=%d, ranking=%d\n\n",
|
||||
mRanking.getChannel().getImportance(), mRanking.getImportance(),
|
||||
mRanking.getRankingAdjustment()));
|
||||
mRanking.getRankingScore()));
|
||||
}
|
||||
if (status == mFeedbackController.STATUS_ALERTED) {
|
||||
if (status == STATUS_ALERTED) {
|
||||
sb.append(mContext.getText(R.string.feedback_alerted));
|
||||
} else if (status == mFeedbackController.STATUS_SILENCED) {
|
||||
} else if (status == STATUS_SILENCED) {
|
||||
sb.append(mContext.getText(R.string.feedback_silenced));
|
||||
} else if (status == mFeedbackController.STATUS_PROMOTED) {
|
||||
} else if (status == STATUS_PROMOTED) {
|
||||
sb.append(mContext.getText(R.string.feedback_promoted));
|
||||
} else if (status == mFeedbackController.STATUS_DEMOTED) {
|
||||
} else if (status == STATUS_DEMOTED) {
|
||||
sb.append(mContext.getText(R.string.feedback_demoted));
|
||||
}
|
||||
sb.append(" ");
|
||||
@@ -182,7 +185,8 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC
|
||||
|
||||
private void handleFeedback(boolean positive) {
|
||||
Bundle feedback = new Bundle();
|
||||
feedback.putBoolean(FEEDBACK_KEY, positive);
|
||||
feedback.putInt(FEEDBACK_RATING, positive ? 1 : -1);
|
||||
|
||||
sendFeedbackToAssistant(feedback);
|
||||
}
|
||||
|
||||
@@ -191,19 +195,8 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO(b/154257994): remove this when feedback apis are in place
|
||||
final int count = mNotificationEntryManager.getActiveNotificationsCount();
|
||||
final int rank = mEntry.getRanking().getRank();
|
||||
NotificationVisibility.NotificationLocation location =
|
||||
NotificationLogger.getNotificationLocation(mEntry);
|
||||
final NotificationVisibility nv = NotificationVisibility.obtain(
|
||||
mEntry.getKey(), rank, count, true, location);
|
||||
Notification.Action action = new Notification.Action.Builder(null, null,
|
||||
null)
|
||||
.addExtras(feedback)
|
||||
.build();
|
||||
try {
|
||||
mStatusBarService.onNotificationActionClick(mRanking.getKey(), -1, action, nv, true);
|
||||
mStatusBarService.onNotificationFeedbackReceived(mRanking.getKey(), feedback);
|
||||
} catch (RemoteException e) {
|
||||
if (DEBUG) {
|
||||
Log.e(TAG, "Failed to send feedback to assistant", e);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.notification;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.NotificationStats;
|
||||
|
||||
@@ -88,5 +89,13 @@ public interface NotificationDelegate {
|
||||
void onNotificationSmartReplySent(String key, int clickedIndex, CharSequence reply,
|
||||
int notificationLocation, boolean modifiedBeforeSending);
|
||||
|
||||
/**
|
||||
* Notifies a user feedback is provided.
|
||||
*
|
||||
* @param key the notification key
|
||||
* @param feedback the feedback detail
|
||||
*/
|
||||
void onNotificationFeedbackReceived(String key, Bundle feedback);
|
||||
|
||||
void prepareForPossibleShutdown();
|
||||
}
|
||||
|
||||
@@ -172,7 +172,6 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutServiceInternal;
|
||||
@@ -215,7 +214,6 @@ import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.Adjustment;
|
||||
import android.service.notification.Condition;
|
||||
import android.service.notification.ConditionProviderService;
|
||||
import android.service.notification.ConversationChannelWrapper;
|
||||
import android.service.notification.IConditionProvider;
|
||||
import android.service.notification.INotificationListener;
|
||||
@@ -383,7 +381,8 @@ public class NotificationManagerService extends SystemService {
|
||||
Adjustment.KEY_TEXT_REPLIES,
|
||||
Adjustment.KEY_NOT_CONVERSATION,
|
||||
Adjustment.KEY_IMPORTANCE,
|
||||
Adjustment.KEY_RANKING_SCORE};
|
||||
Adjustment.KEY_RANKING_SCORE
|
||||
};
|
||||
|
||||
static final String[] NON_BLOCKABLE_DEFAULT_ROLES = new String[] {
|
||||
RoleManager.ROLE_DIALER,
|
||||
@@ -432,8 +431,6 @@ public class NotificationManagerService extends SystemService {
|
||||
private static final String SCHEME_TIMEOUT = "timeout";
|
||||
private static final String EXTRA_KEY = "key";
|
||||
|
||||
private static final String FEEDBACK_KEY = "feedback_key";
|
||||
|
||||
private static final int NOTIFICATION_INSTANCE_ID_MAX = (1 << 13);
|
||||
|
||||
/**
|
||||
@@ -1020,30 +1017,26 @@ public class NotificationManagerService extends SystemService {
|
||||
return;
|
||||
}
|
||||
final long now = System.currentTimeMillis();
|
||||
//TODO(b/154257994): remove this when feedback apis are in place
|
||||
boolean isFeedback = action.getExtras().containsKey(FEEDBACK_KEY);
|
||||
if (!isFeedback) {
|
||||
MetricsLogger.action(r.getLogMaker(now)
|
||||
.setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION)
|
||||
.setType(MetricsEvent.TYPE_ACTION)
|
||||
.setSubtype(actionIndex)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, nv.rank)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_COUNT, nv.count)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_ACTION_IS_SMART,
|
||||
action.isContextual() ? 1 : 0)
|
||||
.addTaggedData(
|
||||
MetricsEvent.NOTIFICATION_SMART_SUGGESTION_ASSISTANT_GENERATED,
|
||||
generatedByAssistant ? 1 : 0)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_LOCATION,
|
||||
nv.location.toMetricsEventEnum()));
|
||||
mNotificationRecordLogger.log(
|
||||
NotificationRecordLogger.NotificationEvent.fromAction(actionIndex,
|
||||
generatedByAssistant, action.isContextual()), r);
|
||||
EventLogTags.writeNotificationActionClicked(key, actionIndex,
|
||||
r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
|
||||
nv.rank, nv.count);
|
||||
nv.recycle();
|
||||
}
|
||||
MetricsLogger.action(r.getLogMaker(now)
|
||||
.setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION)
|
||||
.setType(MetricsEvent.TYPE_ACTION)
|
||||
.setSubtype(actionIndex)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, nv.rank)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_COUNT, nv.count)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_ACTION_IS_SMART,
|
||||
action.isContextual() ? 1 : 0)
|
||||
.addTaggedData(
|
||||
MetricsEvent.NOTIFICATION_SMART_SUGGESTION_ASSISTANT_GENERATED,
|
||||
generatedByAssistant ? 1 : 0)
|
||||
.addTaggedData(MetricsEvent.NOTIFICATION_LOCATION,
|
||||
nv.location.toMetricsEventEnum()));
|
||||
mNotificationRecordLogger.log(
|
||||
NotificationRecordLogger.NotificationEvent.fromAction(actionIndex,
|
||||
generatedByAssistant, action.isContextual()), r);
|
||||
EventLogTags.writeNotificationActionClicked(key, actionIndex,
|
||||
r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
|
||||
nv.rank, nv.count);
|
||||
nv.recycle();
|
||||
reportUserInteraction(r);
|
||||
mAssistants.notifyAssistantActionClicked(r, action, generatedByAssistant);
|
||||
}
|
||||
@@ -1386,6 +1379,20 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationFeedbackReceived(String key, Bundle feedback) {
|
||||
exitIdle();
|
||||
synchronized (mNotificationLock) {
|
||||
NotificationRecord r = mNotificationsByKey.get(key);
|
||||
if (r == null) {
|
||||
if (DBG) Slog.w(TAG, "No notification with key: " + key);
|
||||
return;
|
||||
}
|
||||
mAssistants.notifyAssistantFeedbackReceived(r, feedback);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -9505,6 +9512,26 @@ public class NotificationManagerService extends SystemService {
|
||||
});
|
||||
}
|
||||
|
||||
@GuardedBy("mNotificationLock")
|
||||
void notifyAssistantFeedbackReceived(final NotificationRecord r, Bundle feedback) {
|
||||
final StatusBarNotification sbn = r.getSbn();
|
||||
|
||||
for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
|
||||
boolean sbnVisible = isVisibleToListener(
|
||||
sbn, r.getNotificationType(), info)
|
||||
&& info.isSameUser(r.getUserId());
|
||||
if (sbnVisible) {
|
||||
final INotificationListener assistant = (INotificationListener) info.service;
|
||||
try {
|
||||
final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
|
||||
assistant.onNotificationFeedbackReceived(sbn.getKey(), update, feedback);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "unable to notify assistant (feedback): " + assistant, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the assistant something about the specified notification, only assistant
|
||||
* that is visible to the notification will be notified.
|
||||
|
||||
@@ -1500,6 +1500,18 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationFeedbackReceived(String key, Bundle feedback) {
|
||||
enforceStatusBarService();
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mNotificationDelegate.onNotificationFeedbackReceived(key, feedback);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
|
||||
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
|
||||
|
||||
Reference in New Issue
Block a user