blob: 780b576d71f39fac73fc9ea493e14b73d76b75fa [file] [log] [blame]
Chris Wren9fa689f2015-11-20 16:44:53 -05001/*
2 * Copyright (C) 2015 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
17package android.service.notification;
18
Tony Mak29996702018-11-26 16:23:34 +000019import static java.lang.annotation.RetentionPolicy.SOURCE;
20
21import android.annotation.IntDef;
Tony Make94e0782018-12-14 11:57:54 +080022import android.annotation.NonNull;
Fabian Kozynski867550e2019-02-28 12:59:57 -050023import android.annotation.Nullable;
Julia Reynolds7eba5932015-12-11 16:40:39 -050024import android.annotation.SdkConstant;
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -050025import android.annotation.SystemApi;
Tony Mak7d4b3a52018-11-27 17:29:36 +000026import android.app.Notification;
Julia Reynolds901bf282018-08-14 10:09:36 -040027import android.app.NotificationChannel;
Julia Reynolds70aaea72018-07-13 13:38:34 -040028import android.app.admin.DevicePolicyManager;
29import android.content.ComponentName;
Chris Wrenab41eec2016-01-04 18:01:27 -050030import android.content.Context;
Julia Reynolds7eba5932015-12-11 16:40:39 -050031import android.content.Intent;
Svet Ganovb8f53ee2016-02-18 08:38:56 -080032import android.os.Handler;
Chris Wren51017d02015-12-15 15:34:46 -050033import android.os.IBinder;
Svet Ganovb8f53ee2016-02-18 08:38:56 -080034import android.os.Looper;
35import android.os.Message;
Chris Wren51017d02015-12-15 15:34:46 -050036import android.os.RemoteException;
37import android.util.Log;
Julia Reynolds503ed942017-10-04 16:04:56 -040038
Svet Ganovb8f53ee2016-02-18 08:38:56 -080039import com.android.internal.os.SomeArgs;
Chris Wren9fa689f2015-11-20 16:44:53 -050040
Tony Mak29996702018-11-26 16:23:34 +000041import java.lang.annotation.Retention;
Julia Reynoldse46bb372016-03-17 11:05:58 -040042import java.util.List;
43
Chris Wren9fa689f2015-11-20 16:44:53 -050044/**
Julia Reynolds77b2cc92016-11-08 14:41:09 -050045 * A service that helps the user manage notifications.
Julia Reynolds70aaea72018-07-13 13:38:34 -040046 * <p>
47 * Only one notification assistant can be active at a time. Unlike notification listener services,
48 * assistant services can additionally modify certain aspects about notifications
49 * (see {@link Adjustment}) before they are posted.
50 *<p>
51 * A note about managed profiles: Unlike {@link NotificationListenerService listener services},
52 * NotificationAssistantServices are allowed to run in managed profiles
53 * (see {@link DevicePolicyManager#isManagedProfile(ComponentName)}), so they can access the
54 * information they need to create good {@link Adjustment adjustments}. To maintain the contract
55 * with {@link NotificationListenerService}, an assistant service will receive all of the
56 * callbacks from {@link NotificationListenerService} for the current user, managed profiles of
57 * that user, and ones that affect all users. However,
58 * {@link #onNotificationEnqueued(StatusBarNotification)} will only be called for notifications
59 * sent to the current user, and {@link Adjustment adjuments} will only be accepted for the
60 * current user.
Julia Reynoldsfe992192018-09-07 10:33:19 -040061 * <p>
62 * All callbacks are called on the main thread.
63 * </p>
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -050064 * @hide
Chris Wren9fa689f2015-11-20 16:44:53 -050065 */
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -050066@SystemApi
Julia Reynolds77b2cc92016-11-08 14:41:09 -050067public abstract class NotificationAssistantService extends NotificationListenerService {
68 private static final String TAG = "NotificationAssistants";
Chris Wren51017d02015-12-15 15:34:46 -050069
Tony Mak29996702018-11-26 16:23:34 +000070 /** @hide */
71 @Retention(SOURCE)
72 @IntDef({SOURCE_FROM_APP, SOURCE_FROM_ASSISTANT})
73 public @interface Source {}
Tony Mak9f4e0842019-03-05 16:24:36 +000074
75 /**
76 * To indicate an adjustment is from an app.
77 */
Tony Mak29996702018-11-26 16:23:34 +000078 public static final int SOURCE_FROM_APP = 0;
Tony Mak9f4e0842019-03-05 16:24:36 +000079 /**
80 * To indicate an adjustment is from a {@link NotificationAssistantService}.
81 */
Tony Mak29996702018-11-26 16:23:34 +000082 public static final int SOURCE_FROM_ASSISTANT = 1;
83
Julia Reynolds7eba5932015-12-11 16:40:39 -050084 /**
85 * The {@link Intent} that must be declared as handled by the service.
86 */
87 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
88 public static final String SERVICE_INTERFACE
Julia Reynolds77b2cc92016-11-08 14:41:09 -050089 = "android.service.notification.NotificationAssistantService";
Julia Reynolds7eba5932015-12-11 16:40:39 -050090
Rohan Shah0350dab2018-05-04 13:42:18 -070091 /**
92 * @hide
93 */
94 protected Handler mHandler;
Svet Ganovb8f53ee2016-02-18 08:38:56 -080095
Svet Ganovb8f53ee2016-02-18 08:38:56 -080096 @Override
97 protected void attachBaseContext(Context base) {
98 super.attachBaseContext(base);
99 mHandler = new MyHandler(getContext().getMainLooper());
100 }
101
102 @Override
Fabian Kozynski867550e2019-02-28 12:59:57 -0500103 public final @NonNull IBinder onBind(@Nullable Intent intent) {
Chris Wren51017d02015-12-15 15:34:46 -0500104 if (mWrapper == null) {
Julia Reynolds77b2cc92016-11-08 14:41:09 -0500105 mWrapper = new NotificationAssistantServiceWrapper();
Chris Wren51017d02015-12-15 15:34:46 -0500106 }
107 return mWrapper;
108 }
109
Chris Wren9fa689f2015-11-20 16:44:53 -0500110 /**
Julia Reynolds79672302017-01-12 08:30:16 -0500111 * A notification was snoozed until a context. For use with
112 * {@link Adjustment#KEY_SNOOZE_CRITERIA}. When the device reaches the given context, the
113 * assistant should restore the notification with {@link #unsnoozeNotification(String)}.
114 *
115 * @param sbn the notification to snooze
116 * @param snoozeCriterionId the {@link SnoozeCriterion#getId()} representing a device context.
117 */
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -0500118 abstract public void onNotificationSnoozedUntilContext(@NonNull StatusBarNotification sbn,
119 @NonNull String snoozeCriterionId);
Julia Reynolds79672302017-01-12 08:30:16 -0500120
121 /**
Julia Reynolds503ed942017-10-04 16:04:56 -0400122 * A notification was posted by an app. Called before post.
Chris Wren9fa689f2015-11-20 16:44:53 -0500123 *
Julia Reynolds79f02772019-02-15 11:38:48 -0500124 * <p>Note: this method is only called if you don't override
125 * {@link #onNotificationEnqueued(StatusBarNotification, NotificationChannel)}.</p>
126 *
Chris Wren9fa689f2015-11-20 16:44:53 -0500127 * @param sbn the new notification
Chris Wren9fa689f2015-11-20 16:44:53 -0500128 * @return an adjustment or null to take no action, within 100ms.
129 */
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -0500130 abstract public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn);
Julia Reynolds901bf282018-08-14 10:09:36 -0400131
132 /**
133 * A notification was posted by an app. Called before post.
134 *
135 * @param sbn the new notification
136 * @param channel the channel the notification was posted to
137 * @return an adjustment or null to take no action, within 100ms.
138 */
Fabian Kozynski867550e2019-02-28 12:59:57 -0500139 public @Nullable Adjustment onNotificationEnqueued(@NonNull StatusBarNotification sbn,
140 @NonNull NotificationChannel channel) {
Julia Reynolds901bf282018-08-14 10:09:36 -0400141 return onNotificationEnqueued(sbn);
142 }
143
Chris Wren9fa689f2015-11-20 16:44:53 -0500144
145 /**
Julia Reynolds503ed942017-10-04 16:04:56 -0400146 * Implement this method to learn when notifications are removed, how they were interacted with
147 * before removal, and why they were removed.
148 * <p>
149 * This might occur because the user has dismissed the notification using system UI (or another
150 * notification listener) or because the app has withdrawn the notification.
151 * <p>
152 * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
153 * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
154 * fields such as {@link android.app.Notification#contentView} and
155 * {@link android.app.Notification#largeIcon}. However, all other fields on
156 * {@link StatusBarNotification}, sufficient to match this call with a prior call to
157 * {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
158 *
159 ** @param sbn A data structure encapsulating at least the original information (tag and id)
160 * and source (package name) used to post the {@link android.app.Notification} that
161 * was just removed.
162 * @param rankingMap The current ranking map that can be used to retrieve ranking information
163 * for active notifications.
164 * @param stats Stats about how the user interacted with the notification before it was removed.
165 * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
166 */
167 @Override
Fabian Kozynski867550e2019-02-28 12:59:57 -0500168 public void onNotificationRemoved(@NonNull StatusBarNotification sbn,
169 @NonNull RankingMap rankingMap,
170 @NonNull NotificationStats stats, int reason) {
Julia Reynolds503ed942017-10-04 16:04:56 -0400171 onNotificationRemoved(sbn, rankingMap, reason);
172 }
173
174 /**
Julia Reynolds6a63d1b2018-08-14 16:59:33 -0400175 * Implement this to know when a user has seen notifications, as triggered by
176 * {@link #setNotificationsShown(String[])}.
177 */
Fabian Kozynski867550e2019-02-28 12:59:57 -0500178 public void onNotificationsSeen(@NonNull List<String> keys) {
Julia Reynolds6a63d1b2018-08-14 16:59:33 -0400179
180 }
181
182 /**
Tony Mak202f25d2019-01-07 14:40:39 +0000183 * Implement this to know when a notification change (expanded / collapsed) is visible to user.
184 *
Tony Makeda84a72018-11-19 17:01:32 +0000185 * @param key the notification key
186 * @param isUserAction whether the expanded change is caused by user action.
187 * @param isExpanded whether the notification is expanded.
188 */
189 public void onNotificationExpansionChanged(
Tony Make94e0782018-12-14 11:57:54 +0800190 @NonNull String key, boolean isUserAction, boolean isExpanded) {}
Tony Makeda84a72018-11-19 17:01:32 +0000191
192 /**
193 * Implement this to know when a direct reply is sent from a notification.
194 * @param key the notification key
195 */
Tony Mak836147e2019-01-08 14:48:31 +0000196 public void onNotificationDirectReplied(@NonNull String key) {}
Tony Makeda84a72018-11-19 17:01:32 +0000197
198 /**
Tony Mak29996702018-11-26 16:23:34 +0000199 * Implement this to know when a suggested reply is sent.
200 * @param key the notification key
201 * @param reply the reply that is just sent
Tony Mak7d4b3a52018-11-27 17:29:36 +0000202 * @param source the source that provided the reply, e.g. SOURCE_FROM_APP
Tony Mak29996702018-11-26 16:23:34 +0000203 */
Tony Make94e0782018-12-14 11:57:54 +0800204 public void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
205 @Source int source) {
206 }
Tony Mak29996702018-11-26 16:23:34 +0000207
208 /**
Tony Mak7d4b3a52018-11-27 17:29:36 +0000209 * Implement this to know when an action is clicked.
210 * @param key the notification key
211 * @param action the action that is just clicked
212 * @param source the source that provided the action, e.g. SOURCE_FROM_APP
213 */
Gustav Senntonced1d002019-01-11 16:19:45 +0000214 public void onActionInvoked(@NonNull String key, @NonNull Notification.Action action,
Tony Make94e0782018-12-14 11:57:54 +0800215 @Source int source) {
Tony Mak7d4b3a52018-11-27 17:29:36 +0000216 }
217
218 /**
Julia Reynoldse46bb372016-03-17 11:05:58 -0400219 * Updates a notification. N.B. this won’t cause
Chris Wren9fa689f2015-11-20 16:44:53 -0500220 * an existing notification to alert, but might allow a future update to
221 * this notification to alert.
222 *
Julia Reynoldse46bb372016-03-17 11:05:58 -0400223 * @param adjustment the adjustment with an explanation
Chris Wren9fa689f2015-11-20 16:44:53 -0500224 */
Fabian Kozynski867550e2019-02-28 12:59:57 -0500225 public final void adjustNotification(@NonNull Adjustment adjustment) {
Chris Wren51017d02015-12-15 15:34:46 -0500226 if (!isBound()) return;
227 try {
Julia Reynolds52e64d02016-12-09 15:36:12 -0500228 getNotificationInterface().applyAdjustmentFromAssistant(mWrapper, adjustment);
Julia Reynoldse46bb372016-03-17 11:05:58 -0400229 } catch (android.os.RemoteException ex) {
230 Log.v(TAG, "Unable to contact notification manager", ex);
Julia Reynolds52e64d02016-12-09 15:36:12 -0500231 throw ex.rethrowFromSystemServer();
Julia Reynoldse46bb372016-03-17 11:05:58 -0400232 }
233 }
234
235 /**
236 * Updates existing notifications. Re-ranking won't occur until all adjustments are applied.
237 * N.B. this won’t cause an existing notification to alert, but might allow a future update to
238 * these notifications to alert.
239 *
240 * @param adjustments a list of adjustments with explanations
241 */
Fabian Kozynski867550e2019-02-28 12:59:57 -0500242 public final void adjustNotifications(@NonNull List<Adjustment> adjustments) {
Julia Reynoldse46bb372016-03-17 11:05:58 -0400243 if (!isBound()) return;
244 try {
Julia Reynolds52e64d02016-12-09 15:36:12 -0500245 getNotificationInterface().applyAdjustmentsFromAssistant(mWrapper, adjustments);
Chris Wren51017d02015-12-15 15:34:46 -0500246 } catch (android.os.RemoteException ex) {
247 Log.v(TAG, "Unable to contact notification manager", ex);
Julia Reynolds52e64d02016-12-09 15:36:12 -0500248 throw ex.rethrowFromSystemServer();
Chris Wren51017d02015-12-15 15:34:46 -0500249 }
Chris Wren9fa689f2015-11-20 16:44:53 -0500250 }
251
Julia Reynolds52e64d02016-12-09 15:36:12 -0500252 /**
Julia Reynoldscf63ff12017-01-24 13:55:48 -0500253 * Inform the notification manager about un-snoozing a specific notification.
254 * <p>
Julia Reynolds79f02772019-02-15 11:38:48 -0500255 * This should only be used for notifications snoozed because of a contextual snooze suggestion
256 * you provided via {@link Adjustment#KEY_SNOOZE_CRITERIA}. Once un-snoozed, you will get a
Julia Reynoldscf63ff12017-01-24 13:55:48 -0500257 * {@link #onNotificationPosted(StatusBarNotification, RankingMap)} callback for the
258 * notification.
259 * @param key The key of the notification to snooze
260 */
Julia Reynoldsd0ceefa2019-03-03 16:10:52 -0500261 public final void unsnoozeNotification(@NonNull String key) {
Julia Reynoldscf63ff12017-01-24 13:55:48 -0500262 if (!isBound()) return;
263 try {
264 getNotificationInterface().unsnoozeNotificationFromAssistant(mWrapper, key);
265 } catch (android.os.RemoteException ex) {
266 Log.v(TAG, "Unable to contact notification manager", ex);
267 }
268 }
269
Julia Reynolds77b2cc92016-11-08 14:41:09 -0500270 private class NotificationAssistantServiceWrapper extends NotificationListenerWrapper {
Chris Wren51017d02015-12-15 15:34:46 -0500271 @Override
Julia Reynolds901bf282018-08-14 10:09:36 -0400272 public void onNotificationEnqueuedWithChannel(IStatusBarNotificationHolder sbnHolder,
273 NotificationChannel channel) {
Chris Wren51017d02015-12-15 15:34:46 -0500274 StatusBarNotification sbn;
275 try {
276 sbn = sbnHolder.get();
277 } catch (RemoteException e) {
278 Log.w(TAG, "onNotificationEnqueued: Error receiving StatusBarNotification", e);
279 return;
280 }
281
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800282 SomeArgs args = SomeArgs.obtain();
283 args.arg1 = sbn;
Julia Reynolds901bf282018-08-14 10:09:36 -0400284 args.arg2 = channel;
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800285 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_ENQUEUED,
286 args).sendToTarget();
Chris Wren51017d02015-12-15 15:34:46 -0500287 }
Julia Reynolds79672302017-01-12 08:30:16 -0500288
289 @Override
290 public void onNotificationSnoozedUntilContext(
Julia Reynolds901bf282018-08-14 10:09:36 -0400291 IStatusBarNotificationHolder sbnHolder, String snoozeCriterionId) {
Julia Reynolds79672302017-01-12 08:30:16 -0500292 StatusBarNotification sbn;
293 try {
294 sbn = sbnHolder.get();
295 } catch (RemoteException e) {
296 Log.w(TAG, "onNotificationSnoozed: Error receiving StatusBarNotification", e);
297 return;
298 }
299
300 SomeArgs args = SomeArgs.obtain();
301 args.arg1 = sbn;
302 args.arg2 = snoozeCriterionId;
303 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_SNOOZED,
304 args).sendToTarget();
305 }
Julia Reynolds6a63d1b2018-08-14 16:59:33 -0400306
307 @Override
308 public void onNotificationsSeen(List<String> keys) {
309 SomeArgs args = SomeArgs.obtain();
310 args.arg1 = keys;
311 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATIONS_SEEN,
312 args).sendToTarget();
313 }
Tony Makeda84a72018-11-19 17:01:32 +0000314
315 @Override
316 public void onNotificationExpansionChanged(String key, boolean isUserAction,
317 boolean isExpanded) {
318 SomeArgs args = SomeArgs.obtain();
319 args.arg1 = key;
320 args.argi1 = isUserAction ? 1 : 0;
321 args.argi2 = isExpanded ? 1 : 0;
322 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_EXPANSION_CHANGED, args)
323 .sendToTarget();
324 }
325
326 @Override
327 public void onNotificationDirectReply(String key) {
328 SomeArgs args = SomeArgs.obtain();
329 args.arg1 = key;
330 mHandler.obtainMessage(MyHandler.MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT, args)
331 .sendToTarget();
332 }
Tony Mak29996702018-11-26 16:23:34 +0000333
334 @Override
335 public void onSuggestedReplySent(String key, CharSequence reply, int source) {
336 SomeArgs args = SomeArgs.obtain();
337 args.arg1 = key;
338 args.arg2 = reply;
339 args.argi2 = source;
340 mHandler.obtainMessage(MyHandler.MSG_ON_SUGGESTED_REPLY_SENT, args).sendToTarget();
341 }
Tony Mak7d4b3a52018-11-27 17:29:36 +0000342
343 @Override
344 public void onActionClicked(String key, Notification.Action action, int source) {
345 SomeArgs args = SomeArgs.obtain();
346 args.arg1 = key;
347 args.arg2 = action;
348 args.argi2 = source;
Gustav Senntonced1d002019-01-11 16:19:45 +0000349 mHandler.obtainMessage(MyHandler.MSG_ON_ACTION_INVOKED, args).sendToTarget();
Tony Mak7d4b3a52018-11-27 17:29:36 +0000350 }
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800351 }
352
353 private final class MyHandler extends Handler {
354 public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
Julia Reynolds79672302017-01-12 08:30:16 -0500355 public static final int MSG_ON_NOTIFICATION_SNOOZED = 2;
Julia Reynolds6a63d1b2018-08-14 16:59:33 -0400356 public static final int MSG_ON_NOTIFICATIONS_SEEN = 3;
Tony Makeda84a72018-11-19 17:01:32 +0000357 public static final int MSG_ON_NOTIFICATION_EXPANSION_CHANGED = 4;
358 public static final int MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT = 5;
Tony Mak29996702018-11-26 16:23:34 +0000359 public static final int MSG_ON_SUGGESTED_REPLY_SENT = 6;
Gustav Senntonced1d002019-01-11 16:19:45 +0000360 public static final int MSG_ON_ACTION_INVOKED = 7;
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800361
362 public MyHandler(Looper looper) {
363 super(looper, null, false);
364 }
365
366 @Override
367 public void handleMessage(Message msg) {
368 switch (msg.what) {
369 case MSG_ON_NOTIFICATION_ENQUEUED: {
370 SomeArgs args = (SomeArgs) msg.obj;
371 StatusBarNotification sbn = (StatusBarNotification) args.arg1;
Julia Reynolds901bf282018-08-14 10:09:36 -0400372 NotificationChannel channel = (NotificationChannel) args.arg2;
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800373 args.recycle();
Julia Reynolds901bf282018-08-14 10:09:36 -0400374 Adjustment adjustment = onNotificationEnqueued(sbn, channel);
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800375 if (adjustment != null) {
Tony Mak180a9c42019-03-08 13:33:08 +0000376 if (!isBound()) {
377 Log.w(TAG, "MSG_ON_NOTIFICATION_ENQUEUED: service not bound, skip.");
378 return;
379 }
Julia Reynolds4b82f6d2017-01-04 10:47:41 -0500380 try {
381 getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(
382 mWrapper, adjustment);
383 } catch (android.os.RemoteException ex) {
384 Log.v(TAG, "Unable to contact notification manager", ex);
385 throw ex.rethrowFromSystemServer();
Julia Reynoldsca8e5352018-09-18 13:39:26 -0400386 } catch (SecurityException e) {
387 // app cannot catch and recover from this, so do on their behalf
388 Log.w(TAG, "Enqueue adjustment failed; no longer connected", e);
Julia Reynolds4b82f6d2017-01-04 10:47:41 -0500389 }
Svet Ganovb8f53ee2016-02-18 08:38:56 -0800390 }
Julia Reynolds79672302017-01-12 08:30:16 -0500391 break;
392 }
393 case MSG_ON_NOTIFICATION_SNOOZED: {
394 SomeArgs args = (SomeArgs) msg.obj;
395 StatusBarNotification sbn = (StatusBarNotification) args.arg1;
396 String snoozeCriterionId = (String) args.arg2;
397 args.recycle();
398 onNotificationSnoozedUntilContext(sbn, snoozeCriterionId);
399 break;
400 }
Julia Reynolds6a63d1b2018-08-14 16:59:33 -0400401 case MSG_ON_NOTIFICATIONS_SEEN: {
402 SomeArgs args = (SomeArgs) msg.obj;
403 List<String> keys = (List<String>) args.arg1;
404 args.recycle();
405 onNotificationsSeen(keys);
406 break;
407 }
Tony Makeda84a72018-11-19 17:01:32 +0000408 case MSG_ON_NOTIFICATION_EXPANSION_CHANGED: {
409 SomeArgs args = (SomeArgs) msg.obj;
410 String key = (String) args.arg1;
411 boolean isUserAction = args.argi1 == 1;
412 boolean isExpanded = args.argi2 == 1;
413 args.recycle();
414 onNotificationExpansionChanged(key, isUserAction, isExpanded);
415 break;
416 }
417 case MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT: {
418 SomeArgs args = (SomeArgs) msg.obj;
419 String key = (String) args.arg1;
420 args.recycle();
Tony Mak836147e2019-01-08 14:48:31 +0000421 onNotificationDirectReplied(key);
Tony Makeda84a72018-11-19 17:01:32 +0000422 break;
423 }
Tony Mak29996702018-11-26 16:23:34 +0000424 case MSG_ON_SUGGESTED_REPLY_SENT: {
425 SomeArgs args = (SomeArgs) msg.obj;
426 String key = (String) args.arg1;
427 CharSequence reply = (CharSequence) args.arg2;
428 int source = args.argi2;
429 args.recycle();
430 onSuggestedReplySent(key, reply, source);
431 break;
432 }
Gustav Senntonced1d002019-01-11 16:19:45 +0000433 case MSG_ON_ACTION_INVOKED: {
Tony Mak7d4b3a52018-11-27 17:29:36 +0000434 SomeArgs args = (SomeArgs) msg.obj;
435 String key = (String) args.arg1;
436 Notification.Action action = (Notification.Action) args.arg2;
437 int source = args.argi2;
438 args.recycle();
Gustav Senntonced1d002019-01-11 16:19:45 +0000439 onActionInvoked(key, action, source);
Tony Mak7d4b3a52018-11-27 17:29:36 +0000440 break;
441 }
Chris Wren51017d02015-12-15 15:34:46 -0500442 }
443 }
444 }
Chris Wren9fa689f2015-11-20 16:44:53 -0500445}