| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.mojo.notifications; |
| |
| import android.app.NotificationManager; |
| import android.content.Context; |
| import android.util.SparseArray; |
| |
| import org.chromium.mojo.application.ShellHelper; |
| import org.chromium.mojo.intent.IntentReceiverManager; |
| import org.chromium.mojo.system.Core; |
| import org.chromium.mojo.system.MojoException; |
| import org.chromium.mojom.mojo.Shell; |
| import org.chromium.mojom.notifications.Notification; |
| import org.chromium.mojom.notifications.NotificationClient; |
| import org.chromium.mojom.notifications.NotificationData; |
| import org.chromium.mojom.notifications.NotificationService; |
| |
| /** |
| * Android implementation of Notifications. |
| */ |
| class NotificationServiceImpl implements NotificationService, |
| NotificationBuilder.NotificationActionListener, |
| NotificationBuilder.NotificationReadyListener { |
| private final NotificationManager mNotificationManager; |
| private final SparseArray<NotificationImpl> mNotificationMap; |
| private final SparseArray<NotificationClient> mNotificationClientMap; |
| |
| /** |
| * This tag is used when notifying and cancelling notifications to ensure the notifications |
| * being notified and cancelled are unique to this notification service instance. |
| */ |
| private final String mNotificationManagerTag; |
| |
| private final NotificationBuilder mNotificationBuilder; |
| private int mNextNotificationId; |
| |
| NotificationServiceImpl( |
| Context context, Core core, Shell shell, int notificationIconResourceId) { |
| mNotificationManager = |
| (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); |
| mNotificationMap = new SparseArray<NotificationImpl>(); |
| mNotificationClientMap = new SparseArray<NotificationClient>(); |
| mNotificationManagerTag = toString(); |
| IntentReceiverManager intentReceiverManager = ShellHelper.connectToService( |
| core, shell, "mojo:android_handler", IntentReceiverManager.MANAGER); |
| mNotificationBuilder = new NotificationBuilder( |
| context, intentReceiverManager, notificationIconResourceId, this, this); |
| mNextNotificationId = 1; |
| } |
| |
| // NotificationService implementation. |
| @Override |
| public void close() {} |
| |
| @Override |
| public void onConnectionError(MojoException e) {} |
| |
| @Override |
| public void post(NotificationData notificationData, NotificationClient notificationClient, |
| org.chromium.mojo.bindings.InterfaceRequest<Notification> request) { |
| final int newNotificationId = getNewNotificationId(); |
| mNotificationClientMap.put(newNotificationId, notificationClient); |
| NotificationImpl notification = new NotificationImpl(this, newNotificationId); |
| mNotificationMap.put(newNotificationId, notification); |
| Notification.MANAGER.bind(notification, request); |
| postOrUpdateNotification(newNotificationId, notificationData); |
| } |
| |
| // NotificationBuilder.NotificationActionListener implementation. |
| @Override |
| public void onNotificationSelected(int notificationId) { |
| NotificationClient client = mNotificationClientMap.get(notificationId); |
| if (client != null) { |
| client.onSelected(); |
| } |
| // Since autoCancel is set to true (@see NotificationBuilder#build(int, NotificationData)), |
| // the notification no |
| // longer exists at this point. Clean |
| // it up. |
| cleanUpNotification(notificationId); |
| } |
| |
| @Override |
| public void onNotificationDismissed(int notificationId) { |
| NotificationClient client = mNotificationClientMap.get(notificationId); |
| if (client != null) { |
| client.onDismissed(); |
| } |
| // Since the notification was dismissed it can no longer be interacted with. Clean it up. |
| cleanUpNotification(notificationId); |
| } |
| |
| // NotificationBuilder.NotificationReadyListener implementation. |
| @Override |
| public void onNotificationReady(int notificationId, android.app.Notification notification) { |
| // Only allow notification of ids we know about. This will filter out situations where a |
| // cancel quickly follows a post or update before the notification is finished being |
| // created. |
| if (mNotificationMap.get(notificationId) != null) { |
| mNotificationManager.notify(mNotificationManagerTag, notificationId, notification); |
| } |
| } |
| |
| void cancel(int notificationId) { |
| mNotificationManager.cancel(mNotificationManagerTag, notificationId); |
| // Since we're cancelling the notification, the notification can no longer be interacted |
| // with. Clean it up. |
| cleanUpNotification(notificationId); |
| } |
| |
| /** |
| * Posts a notification to the notification manager once built, or updates that notification if |
| * it already exists. |
| */ |
| void postOrUpdateNotification(int notificationId, NotificationData notificationData) { |
| mNotificationBuilder.build(notificationId, notificationData); |
| } |
| |
| private int getNewNotificationId() { |
| return mNextNotificationId++; |
| } |
| |
| private void cleanUpNotification(int notificationId) { |
| NotificationClient client = mNotificationClientMap.get(notificationId); |
| if (client != null) { |
| client.close(); |
| } |
| |
| mNotificationClientMap.remove(notificationId); |
| |
| NotificationImpl notification = mNotificationMap.get(notificationId); |
| if (notification != null) { |
| notification.invalidate(); |
| } |
| mNotificationMap.remove(notificationId); |
| } |
| } |