658 lines
26 KiB
Java
658 lines
26 KiB
Java
/*
|
||
* Copyright (C) 2015 The Android Open Source Project
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
package android.service.notification;
|
||
|
||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||
|
||
import android.annotation.IntDef;
|
||
import android.annotation.NonNull;
|
||
import android.annotation.Nullable;
|
||
import android.annotation.SdkConstant;
|
||
import android.annotation.SuppressLint;
|
||
import android.annotation.SystemApi;
|
||
import android.app.Notification;
|
||
import android.app.NotificationChannel;
|
||
import android.app.NotificationManager;
|
||
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;
|
||
import android.os.Message;
|
||
import android.os.RemoteException;
|
||
import android.util.Log;
|
||
import com.android.internal.os.SomeArgs;
|
||
import java.lang.annotation.Retention;
|
||
import java.util.List;
|
||
|
||
/**
|
||
* A service that helps the user manage notifications.
|
||
* <p>
|
||
* Only one notification assistant can be active at a time. Unlike notification listener services,
|
||
* assistant services can additionally modify certain aspects about notifications
|
||
* (see {@link Adjustment}) before they are posted.
|
||
*<p>
|
||
* A note about managed profiles: Unlike {@link NotificationListenerService listener services},
|
||
* NotificationAssistantServices are allowed to run in managed profiles
|
||
* (see {@link DevicePolicyManager#isManagedProfile(ComponentName)}), so they can access the
|
||
* information they need to create good {@link Adjustment adjustments}. To maintain the contract
|
||
* with {@link NotificationListenerService}, an assistant service will receive all of the
|
||
* callbacks from {@link NotificationListenerService} for the current user, managed profiles of
|
||
* that user, and ones that affect all users. However,
|
||
* {@link #onNotificationEnqueued(StatusBarNotification)} will only be called for notifications
|
||
* sent to the current user, and {@link Adjustment adjuments} will only be accepted for the
|
||
* current user.
|
||
* <p>
|
||
* All callbacks are called on the main thread.
|
||
* </p>
|
||
* @hide
|
||
*/
|
||
@SystemApi
|
||
public abstract class NotificationAssistantService extends NotificationListenerService {
|
||
private static final String TAG = "NotificationAssistants";
|
||
|
||
/** @hide */
|
||
@Retention(SOURCE)
|
||
@IntDef({SOURCE_FROM_APP, SOURCE_FROM_ASSISTANT})
|
||
public @interface Source {}
|
||
|
||
/**
|
||
* To indicate an adjustment is from an app.
|
||
*/
|
||
public static final int SOURCE_FROM_APP = 0;
|
||
/**
|
||
* To indicate an adjustment is from a {@link NotificationAssistantService}.
|
||
*/
|
||
public static final int SOURCE_FROM_ASSISTANT = 1;
|
||
|
||
/**
|
||
* The {@link Intent} that must be declared as handled by the service.
|
||
*/
|
||
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
|
||
public static final String SERVICE_INTERFACE
|
||
= "android.service.notification.NotificationAssistantService";
|
||
|
||
/**
|
||
* Activity Action: Show notification assistant detail setting page in NAS app.
|
||
* <p>
|
||
* In some cases, a matching Activity may not exist, so ensure you
|
||
* safeguard against this.
|
||
* <p>
|
||
* Input: Nothing.
|
||
* <p>
|
||
* Output: Nothing.
|
||
*/
|
||
@SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||
public static final String ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS =
|
||
"android.service.notification.action.NOTIFICATION_ASSISTANT_DETAIL_SETTINGS";
|
||
|
||
|
||
/**
|
||
* Data type: int, the feedback rating score provided by user. The score can be any integer
|
||
* value depends on the experimental and feedback UX design.
|
||
*/
|
||
public static final String FEEDBACK_RATING = "feedback.rating";
|
||
|
||
/**
|
||
* @hide
|
||
*/
|
||
protected Handler mHandler;
|
||
|
||
@SuppressLint("OnNameExpected")
|
||
@Override
|
||
protected void attachBaseContext(Context base) {
|
||
super.attachBaseContext(base);
|
||
mHandler = new MyHandler(getContext().getMainLooper());
|
||
}
|
||
|
||
@Override
|
||
public final @NonNull IBinder onBind(@Nullable Intent intent) {
|
||
if (mWrapper == null) {
|
||
mWrapper = new NotificationAssistantServiceWrapper();
|
||
}
|
||
return mWrapper;
|
||
}
|
||
|
||
/**
|
||
* A notification was snoozed until a context. For use with
|
||
* {@link Adjustment#KEY_SNOOZE_CRITERIA}. When the device reaches the given context, the
|
||
* assistant should restore the notification with {@link #unsnoozeNotification(String)}.
|
||
*
|
||
* @param sbn the notification to snooze
|
||
* @param snoozeCriterionId the {@link SnoozeCriterion#getId()} representing a device context.
|
||
*/
|
||
abstract public void onNotificationSnoozedUntilContext(@NonNull StatusBarNotification sbn,
|
||
@NonNull String snoozeCriterionId);
|
||
|
||
/**
|
||
* A notification was posted by an app. Called before post.
|
||
*
|
||
* <p>Note: this method is only called if you don't override
|
||
* {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel)} or
|
||
* {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel, RankingMap)}.</p>
|
||
*
|
||
* @param sbn the new notification
|
||
* @return an adjustment or null to take no action, within 200ms.
|
||
*/
|
||
abstract public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn);
|
||
|
||
/**
|
||
* A notification was posted by an app. Called before post.
|
||
*
|
||
* <p>Note: this method is only called if you don't override
|
||
* {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel, RankingMap)}.</p>
|
||
*
|
||
* @param sbn the new notification
|
||
* @param channel the channel the notification was posted to
|
||
* @return an adjustment or null to take no action, within 200ms.
|
||
*/
|
||
public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn,
|
||
@NonNull NotificationChannel channel) {
|
||
return onNotificationEnqueued(sbn);
|
||
}
|
||
|
||
/**
|
||
* A notification was posted by an app. Called before post.
|
||
*
|
||
* @param sbn the new notification
|
||
* @param channel the channel the notification was posted to
|
||
* @param rankingMap The current ranking map that can be used to retrieve ranking information
|
||
* for active notifications.
|
||
* @return an adjustment or null to take no action, within 200ms.
|
||
*/
|
||
public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn,
|
||
@NonNull NotificationChannel channel, @NonNull RankingMap rankingMap) {
|
||
return onNotificationEnqueued(sbn, channel);
|
||
}
|
||
|
||
/**
|
||
* Implement this method to learn when notifications are removed, how they were interacted with
|
||
* before removal, and why they were removed.
|
||
* <p>
|
||
* This might occur because the user has dismissed the notification using system UI (or another
|
||
* notification listener) or because the app has withdrawn the notification.
|
||
* <p>
|
||
* NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
|
||
* result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
|
||
* fields such as {@link android.app.Notification#contentView} and
|
||
* {@link android.app.Notification#largeIcon}. However, all other fields on
|
||
* {@link StatusBarNotification}, sufficient to match this call with a prior call to
|
||
* {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
|
||
*
|
||
** @param sbn A data structure encapsulating at least the original information (tag and id)
|
||
* and source (package name) used to post the {@link android.app.Notification} that
|
||
* was just removed.
|
||
* @param rankingMap The current ranking map that can be used to retrieve ranking information
|
||
* for active notifications.
|
||
* @param stats Stats about how the user interacted with the notification before it was removed.
|
||
* @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
|
||
*/
|
||
@Override
|
||
public void onNotificationRemoved(@NonNull StatusBarNotification sbn,
|
||
@NonNull RankingMap rankingMap,
|
||
@NonNull NotificationStats stats, int reason) {
|
||
onNotificationRemoved(sbn, rankingMap, reason);
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when a user has seen notifications, as triggered by
|
||
* {@link #setNotificationsShown(String[])}.
|
||
*/
|
||
public void onNotificationsSeen(@NonNull List<String> keys) {
|
||
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when the notification panel is revealed
|
||
*
|
||
* @param items Number of notifications on the panel at time of opening
|
||
*/
|
||
public void onPanelRevealed(int items) {
|
||
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when the notification panel is hidden
|
||
*/
|
||
public void onPanelHidden() {
|
||
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when a notification becomes visible or hidden from the user.
|
||
*
|
||
* @param key the notification key
|
||
* @param isVisible whether the notification is visible.
|
||
*/
|
||
public void onNotificationVisibilityChanged(@NonNull String key, boolean isVisible) {
|
||
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when a notification change (expanded / collapsed) is visible to user.
|
||
*
|
||
* @param key the notification key
|
||
* @param isUserAction whether the expanded change is caused by user action.
|
||
* @param isExpanded whether the notification is expanded.
|
||
*/
|
||
public void onNotificationExpansionChanged(
|
||
@NonNull String key, boolean isUserAction, boolean isExpanded) {}
|
||
|
||
/**
|
||
* Implement this to know when a direct reply is sent from a notification.
|
||
* @param key the notification key
|
||
*/
|
||
public void onNotificationDirectReplied(@NonNull String key) {}
|
||
|
||
/**
|
||
* Implement this to know when a suggested reply is sent.
|
||
* @param key the notification key
|
||
* @param reply the reply that is just sent
|
||
* @param source the source that provided the reply, e.g. SOURCE_FROM_APP
|
||
*/
|
||
public void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
|
||
@Source int source) {
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when an action is clicked.
|
||
* @param key the notification key
|
||
* @param action the action that is just clicked
|
||
* @param source the source that provided the action, e.g. SOURCE_FROM_APP
|
||
*/
|
||
public void onActionInvoked(@NonNull String key, @NonNull Notification.Action action,
|
||
@Source int source) {
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when a notification is clicked by user.
|
||
* @param key the notification key
|
||
*/
|
||
public void onNotificationClicked(@NonNull String key) {
|
||
}
|
||
|
||
/**
|
||
* Implement this to know when a user has changed which features of
|
||
* their notifications the assistant can modify.
|
||
* <p> Query {@link NotificationManager#getAllowedAssistantAdjustments()} to see what
|
||
* {@link Adjustment adjustments} you are currently allowed to make.</p>
|
||
*
|
||
* @deprecated changing allowed adjustments is no longer supported.
|
||
*/
|
||
@Deprecated
|
||
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 received feedback, such as {@link #FEEDBACK_RATING rating score}
|
||
*/
|
||
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
|
||
* this notification to alert.
|
||
*
|
||
* @param adjustment the adjustment with an explanation
|
||
*/
|
||
public final void adjustNotification(@NonNull Adjustment adjustment) {
|
||
if (!isBound()) return;
|
||
try {
|
||
setAdjustmentIssuer(adjustment);
|
||
getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(mWrapper, adjustment);
|
||
} catch (android.os.RemoteException ex) {
|
||
Log.v(TAG, "Unable to contact notification manager", ex);
|
||
throw ex.rethrowFromSystemServer();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Updates existing notifications. Re-ranking won't occur until all adjustments are applied.
|
||
* N.B. this won’t cause an existing notification to alert, but might allow a future update to
|
||
* these notifications to alert.
|
||
*
|
||
* @param adjustments a list of adjustments with explanations
|
||
*/
|
||
public final void adjustNotifications(@NonNull List<Adjustment> adjustments) {
|
||
if (!isBound()) return;
|
||
try {
|
||
for (Adjustment adjustment : adjustments) {
|
||
setAdjustmentIssuer(adjustment);
|
||
}
|
||
getNotificationInterface().applyAdjustmentsFromAssistant(mWrapper, adjustments);
|
||
} catch (android.os.RemoteException ex) {
|
||
Log.v(TAG, "Unable to contact notification manager", ex);
|
||
throw ex.rethrowFromSystemServer();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Inform the notification manager about un-snoozing a specific notification.
|
||
* <p>
|
||
* This should only be used for notifications snoozed because of a contextual snooze suggestion
|
||
* you provided via {@link Adjustment#KEY_SNOOZE_CRITERIA}. Once un-snoozed, you will get a
|
||
* {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
|
||
* notification.
|
||
* @param key The key of the notification to snooze
|
||
*/
|
||
public final void unsnoozeNotification(@NonNull String key) {
|
||
if (!isBound()) return;
|
||
try {
|
||
getNotificationInterface().unsnoozeNotificationFromAssistant(mWrapper, key);
|
||
} catch (android.os.RemoteException ex) {
|
||
Log.v(TAG, "Unable to contact notification manager", ex);
|
||
}
|
||
}
|
||
|
||
private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
|
||
@Override
|
||
public void onNotificationEnqueuedWithChannel(IStatusBarNotificationHolder sbnHolder,
|
||
NotificationChannel channel, NotificationRankingUpdate update) {
|
||
StatusBarNotification sbn;
|
||
try {
|
||
sbn = sbnHolder.get();
|
||
} catch (RemoteException e) {
|
||
Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
|
||
return;
|
||
}
|
||
if (sbn == null) {
|
||
Log.w(TAG, "onNotificationEnqueuedWithChannel: "
|
||
+ "Error receiving StatusBarNotification");
|
||
return;
|
||
}
|
||
|
||
applyUpdateLocked(update);
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = sbn;
|
||
args.arg2 = channel;
|
||
args.arg3 = getCurrentRanking();
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
|
||
args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onNotificationSnoozedUntilContext(
|
||
IStatusBarNotificationHolder sbnHolder, String snoozeCriterionId) {
|
||
StatusBarNotification sbn;
|
||
try {
|
||
sbn = sbnHolder.get();
|
||
} catch (RemoteException e) {
|
||
Log.w(TAG, "onNotificationSnoozed: Error receiving StatusBarNotification", e);
|
||
return;
|
||
}
|
||
if (sbn == null) {
|
||
Log.w(TAG, "onNotificationSnoozed: Error receiving StatusBarNotification");
|
||
return;
|
||
}
|
||
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = sbn;
|
||
args.arg2 = snoozeCriterionId;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_SNOOZED,
|
||
args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onNotificationsSeen(List<String> keys) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = keys;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATIONS_SEEN,
|
||
args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onPanelRevealed(int items) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.argi1 = items;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_PANEL_REVEALED,
|
||
args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onPanelHidden() {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_PANEL_HIDDEN,
|
||
args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onNotificationVisibilityChanged(String key, boolean isVisible) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = key;
|
||
args.argi1 = isVisible ? 1 : 0;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_VISIBILITY_CHANGED,
|
||
args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onNotificationExpansionChanged(String key, boolean isUserAction,
|
||
boolean isExpanded) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = key;
|
||
args.argi1 = isUserAction ? 1 : 0;
|
||
args.argi2 = isExpanded ? 1 : 0;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_EXPANSION_CHANGED, args)
|
||
.sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onNotificationDirectReply(String key) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = key;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT, args)
|
||
.sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onSuggestedReplySent(String key, CharSequence reply, int source) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = key;
|
||
args.arg2 = reply;
|
||
args.argi2 = source;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_SUGGESTED_REPLY_SENT, args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onActionClicked(String key, Notification.Action action, int source) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = key;
|
||
args.arg2 = action;
|
||
args.argi2 = source;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_ACTION_INVOKED, args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
public void onNotificationClicked(String key) {
|
||
SomeArgs args = SomeArgs.obtain();
|
||
args.arg1 = key;
|
||
mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_CLICKED, args).sendToTarget();
|
||
}
|
||
|
||
@Override
|
||
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) {
|
||
if (adjustment != null) {
|
||
adjustment.setIssuer(getOpPackageName() + "/" + getClass().getName());
|
||
}
|
||
}
|
||
|
||
private final class MyHandler extends Handler {
|
||
public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
|
||
public static final int MSG_ON_NOTIFICATION_SNOOZED = 2;
|
||
public static final int MSG_ON_NOTIFICATIONS_SEEN = 3;
|
||
public static final int MSG_ON_NOTIFICATION_EXPANSION_CHANGED = 4;
|
||
public static final int MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT = 5;
|
||
public static final int MSG_ON_SUGGESTED_REPLY_SENT = 6;
|
||
public static final int MSG_ON_ACTION_INVOKED = 7;
|
||
public static final int MSG_ON_ALLOWED_ADJUSTMENTS_CHANGED = 8;
|
||
public static final int MSG_ON_PANEL_REVEALED = 9;
|
||
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);
|
||
}
|
||
|
||
@Override
|
||
public void handleMessage(Message msg) {
|
||
switch (msg.what) {
|
||
case MSG_ON_NOTIFICATION_ENQUEUED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
StatusBarNotification sbn = (StatusBarNotification) args.arg1;
|
||
NotificationChannel channel = (NotificationChannel) args.arg2;
|
||
RankingMap ranking = (RankingMap) args.arg3;
|
||
args.recycle();
|
||
Adjustment adjustment = onNotificationEnqueued(sbn, channel, ranking);
|
||
setAdjustmentIssuer(adjustment);
|
||
if (adjustment != null) {
|
||
if (!isBound()) {
|
||
Log.w(TAG, "MSG_ON_NOTIFICATION_ENQUEUED: service not bound, skip.");
|
||
return;
|
||
}
|
||
try {
|
||
getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(
|
||
mWrapper, adjustment);
|
||
} catch (android.os.RemoteException ex) {
|
||
Log.v(TAG, "Unable to contact notification manager", ex);
|
||
throw ex.rethrowFromSystemServer();
|
||
} catch (SecurityException e) {
|
||
// app cannot catch and recover from this, so do on their behalf
|
||
Log.w(TAG, "Enqueue adjustment failed; no longer connected", e);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case MSG_ON_NOTIFICATION_SNOOZED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
StatusBarNotification sbn = (StatusBarNotification) args.arg1;
|
||
String snoozeCriterionId = (String) args.arg2;
|
||
args.recycle();
|
||
onNotificationSnoozedUntilContext(sbn, snoozeCriterionId);
|
||
break;
|
||
}
|
||
case MSG_ON_NOTIFICATIONS_SEEN: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
List<String> keys = (List<String>) args.arg1;
|
||
args.recycle();
|
||
onNotificationsSeen(keys);
|
||
break;
|
||
}
|
||
case MSG_ON_NOTIFICATION_EXPANSION_CHANGED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
String key = (String) args.arg1;
|
||
boolean isUserAction = args.argi1 == 1;
|
||
boolean isExpanded = args.argi2 == 1;
|
||
args.recycle();
|
||
onNotificationExpansionChanged(key, isUserAction, isExpanded);
|
||
break;
|
||
}
|
||
case MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
String key = (String) args.arg1;
|
||
args.recycle();
|
||
onNotificationDirectReplied(key);
|
||
break;
|
||
}
|
||
case MSG_ON_SUGGESTED_REPLY_SENT: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
String key = (String) args.arg1;
|
||
CharSequence reply = (CharSequence) args.arg2;
|
||
int source = args.argi2;
|
||
args.recycle();
|
||
onSuggestedReplySent(key, reply, source);
|
||
break;
|
||
}
|
||
case MSG_ON_ACTION_INVOKED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
String key = (String) args.arg1;
|
||
Notification.Action action = (Notification.Action) args.arg2;
|
||
int source = args.argi2;
|
||
args.recycle();
|
||
onActionInvoked(key, action, source);
|
||
break;
|
||
}
|
||
case MSG_ON_ALLOWED_ADJUSTMENTS_CHANGED: {
|
||
onAllowedAdjustmentsChanged();
|
||
break;
|
||
}
|
||
case MSG_ON_PANEL_REVEALED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
int items = args.argi1;
|
||
args.recycle();
|
||
onPanelRevealed(items);
|
||
break;
|
||
}
|
||
case MSG_ON_PANEL_HIDDEN: {
|
||
onPanelHidden();
|
||
break;
|
||
}
|
||
case MSG_ON_NOTIFICATION_VISIBILITY_CHANGED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
String key = (String) args.arg1;
|
||
boolean isVisible = args.argi1 == 1;
|
||
args.recycle();
|
||
onNotificationVisibilityChanged(key, isVisible);
|
||
break;
|
||
}
|
||
case MSG_ON_NOTIFICATION_CLICKED: {
|
||
SomeArgs args = (SomeArgs) msg.obj;
|
||
String key = (String) args.arg1;
|
||
args.recycle();
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|