chromium/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationManagerProxyImpl.java

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.components.browser_ui.notifications;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.content.Context;
import android.os.Build;
import android.service.notification.StatusBarNotification;

import androidx.core.app.NotificationManagerCompat;

import org.chromium.base.Callback;
import org.chromium.base.Log;
import org.chromium.base.TraceEvent;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Default implementation of the NotificationManagerProxy, which passes through all calls to the
 * normal Android Notification Manager.
 */
public class NotificationManagerProxyImpl implements NotificationManagerProxy {
    private static final String TAG = "NotifManagerProxy";
    private final Context mContext;
    private final NotificationManagerCompat mNotificationManager;

    public NotificationManagerProxyImpl(Context context) {
        mContext = context;
        mNotificationManager = NotificationManagerCompat.from(mContext);
    }

    @Override
    public boolean areNotificationsEnabled() {
        return mNotificationManager.areNotificationsEnabled();
    }

    @Override
    public void cancel(int id) {
        try (TraceEvent e = TraceEvent.scoped("NotificationManagerProxyImpl.cancel(id)")) {
            mNotificationManager.cancel(id);
        }
    }

    @Override
    public void cancel(String tag, int id) {
        try (TraceEvent e = TraceEvent.scoped("NotificationManagerProxyImpl.cancel(tag, id)")) {
            mNotificationManager.cancel(tag, id);
        }
    }

    @Override
    public void cancelAll() {
        try (TraceEvent e = TraceEvent.scoped("NotificationManagerProxyImpl.cancelAll")) {
            mNotificationManager.cancelAll();
        }
    }

    @Override
    public void createNotificationChannel(NotificationChannel channel) {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.createNotificationChannel")) {
            mNotificationManager.createNotificationChannel(channel);
        }
    }

    @Override
    public void createNotificationChannelGroup(NotificationChannelGroup channelGroup) {
        assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.createNotificationChannelGroup")) {
            mNotificationManager.createNotificationChannelGroup(channelGroup);
        }
    }

    @Override
    public List<NotificationChannel> getNotificationChannels() {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.getNotificationChannels")) {
            return mNotificationManager.getNotificationChannels();
        }
    }

    @Override
    public void getNotificationChannels(Callback<List<NotificationChannel>> callback) {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.getNotificationChannels")) {
            List<NotificationChannel> channels = mNotificationManager.getNotificationChannels();
            PostTask.postTask(TaskTraits.UI_DEFAULT, () -> callback.onResult(channels));
        }
    }

    @Override
    public void getNotificationChannelGroups(Callback<List<NotificationChannelGroup>> callback) {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.getNotificationChannelGroups")) {
            List<NotificationChannelGroup> groups =
                    mNotificationManager.getNotificationChannelGroups();
            PostTask.postTask(TaskTraits.UI_DEFAULT, () -> callback.onResult(groups));
        }
    }

    @Override
    public void deleteNotificationChannel(String id) {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.deleteNotificationChannel")) {
            mNotificationManager.deleteNotificationChannel(id);
        }
    }

    @Override
    public void deleteAllNotificationChannels(Function<String, Boolean> func) {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.deleteAllNotificationChannels")) {
            for (NotificationChannel channel : mNotificationManager.getNotificationChannels()) {
                if (func.apply(channel.getId())) {
                    mNotificationManager.deleteNotificationChannel(channel.getId());
                }
            }
        }
    }

    @Override
    public void notify(int id, Notification notification) {
        if (notification == null) {
            Log.e(TAG, "Failed to create notification.");
            return;
        }

        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.notify(id, notification)")) {
            mNotificationManager.notify(id, notification);
        }
    }

    @Override
    public void notify(String tag, int id, Notification notification) {
        if (notification == null) {
            Log.e(TAG, "Failed to create notification.");
            return;
        }

        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.notify(tag, id, notification)")) {
            mNotificationManager.notify(tag, id, notification);
        }
    }

    @Override
    public void notify(NotificationWrapper notification) {
        if (notification == null || notification.getNotification() == null) {
            Log.e(TAG, "Failed to create notification.");
            return;
        }

        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.notify(notification)")) {
            assert notification.getMetadata() != null;
            mNotificationManager.notify(
                    notification.getMetadata().tag,
                    notification.getMetadata().id,
                    notification.getNotification());
        }
    }

    @Override
    public NotificationChannel getNotificationChannel(String channelId) {
        assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.getNotificationChannel")) {
            return mNotificationManager.getNotificationChannel(channelId);
        }
    }

    @Override
    public void deleteNotificationChannelGroup(String groupId) {
        assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.deleteNotificationChannelGroup")) {
            mNotificationManager.deleteNotificationChannelGroup(groupId);
        }
    }

    private static class StatusBarNotificationAdaptor implements StatusBarNotificationProxy {
        private final StatusBarNotification mStatusBarNotification;

        public StatusBarNotificationAdaptor(StatusBarNotification sbNotification) {
            this.mStatusBarNotification = sbNotification;
        }

        @Override
        public int getId() {
            return mStatusBarNotification.getId();
        }

        @Override
        public String getTag() {
            return mStatusBarNotification.getTag();
        }

        @Override
        public Notification getNotification() {
            return mStatusBarNotification.getNotification();
        }
    }

    @Override
    public void getActiveNotifications(
            Callback<List<? extends StatusBarNotificationProxy>> callback) {
        try (TraceEvent e =
                TraceEvent.scoped("NotificationManagerProxyImpl.getActiveNotifications")) {
            List<StatusBarNotificationAdaptor> notifications =
                    mNotificationManager.getActiveNotifications().stream()
                            .map((sbn) -> new StatusBarNotificationAdaptor(sbn))
                            .collect(Collectors.toList());
            PostTask.postTask(TaskTraits.UI_DEFAULT, () -> callback.onResult(notifications));
        }
    }
}