/*
 * Copyright 2019 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.media;

import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
import static android.media.MediaConstants.KEY_PACKAGE_NAME;
import static android.media.MediaConstants.KEY_PID;

import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.MediaSession2.ControllerInfo;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager.RemoteUserInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.ArrayMap;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * This API is not generally intended for third party application developers.
 * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
 * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
 * Library</a> for consistent behavior across all devices.
 * <p>
 * Service containing {@link MediaSession2}.
 */
public abstract class MediaSession2Service extends Service {
    /**
     * The {@link Intent} that must be declared as handled by the service.
     */
    public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";

    private static final String TAG = "MediaSession2Service";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final MediaSession2.ForegroundServiceEventCallback mForegroundServiceEventCallback =
            new MediaSession2.ForegroundServiceEventCallback() {
                @Override
                public void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {
                    MediaSession2Service.this.onPlaybackActiveChanged(session, playbackActive);
                }

                @Override
                public void onSessionClosed(MediaSession2 session) {
                    removeSession(session);
                }
            };

    private final Object mLock = new Object();
    //@GuardedBy("mLock")
    private NotificationManager mNotificationManager;
    //@GuardedBy("mLock")
    private MediaSessionManager mMediaSessionManager;
    //@GuardedBy("mLock")
    private Intent mStartSelfIntent;
    //@GuardedBy("mLock")
    private Map<String, MediaSession2> mSessions = new ArrayMap<>();
    //@GuardedBy("mLock")
    private Map<MediaSession2, MediaNotification> mNotifications = new ArrayMap<>();
    //@GuardedBy("mLock")
    private MediaSession2ServiceStub mStub;

    /**
     * Called by the system when the service is first created. Do not call this method directly.
     * <p>
     * Override this method if you need your own initialization. Derived classes MUST call through
     * to the super class's implementation of this method.
     */
    @CallSuper
    @Override
    public void onCreate() {
        super.onCreate();
        synchronized (mLock) {
            mStub = new MediaSession2ServiceStub(this);
            mStartSelfIntent = new Intent(this, this.getClass());
            mNotificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            mMediaSessionManager =
                    (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
        }
    }

    @CallSuper
    @Override
    @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        if (SERVICE_INTERFACE.equals(intent.getAction())) {
            synchronized (mLock) {
                return mStub;
            }
        }
        return null;
    }

    /**
     * Called by the system to notify that it is no longer used and is being removed. Do not call
     * this method directly.
     * <p>
     * Override this method if you need your own clean up. Derived classes MUST call through
     * to the super class's implementation of this method.
     */
    @CallSuper
    @Override
    public void onDestroy() {
        super.onDestroy();
        synchronized (mLock) {
            List<MediaSession2> sessions = getSessions();
            for (MediaSession2 session : sessions) {
                removeSession(session);
            }
            mSessions.clear();
            mNotifications.clear();
        }
        mStub.close();
    }

    /**
     * Called when a {@link MediaController2} is created with the this service's
     * {@link Session2Token}. Return the session for telling the controller which session to
     * connect. Return {@code null} to reject the connection from this controller.
     * <p>
     * Session returned here will be added to this service automatically. You don't need to call
     * {@link #addSession(MediaSession2)} for that.
     * <p>
     * This method is always called on the main thread.
     *
     * @param controllerInfo information of the controller which is trying to connect.
     * @return a {@link MediaSession2} instance for the controller to connect to, or {@code null}
     *         to reject connection
     * @see MediaSession2.Builder
     * @see #getSessions()
     */
    @Nullable
    public abstract MediaSession2 onGetSession(@NonNull ControllerInfo controllerInfo);

    /**
     * Called when notification UI needs update. Override this method to show or cancel your own
     * notification UI.
     * <p>
     * This would be called on {@link MediaSession2}'s callback executor when playback state is
     * changed.
     * <p>
     * With the notification returned here, the service becomes foreground service when the playback
     * is started. Apps must request the permission
     * {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to use this API. It becomes
     * background service after the playback is stopped.
     *
     * @param session a session that needs notification update.
     * @return a {@link MediaNotification}. Can be {@code null}.
     */
    @Nullable
    public abstract MediaNotification onUpdateNotification(@NonNull MediaSession2 session);

    /**
     * Adds a session to this service.
     * <p>
     * Added session will be removed automatically when it's closed, or removed when
     * {@link #removeSession} is called.
     *
     * @param session a session to be added.
     * @see #removeSession(MediaSession2)
     */
    public final void addSession(@NonNull MediaSession2 session) {
        if (session == null) {
            throw new IllegalArgumentException("session shouldn't be null");
        }
        if (session.isClosed()) {
            throw new IllegalArgumentException("session is already closed");
        }
        synchronized (mLock) {
            MediaSession2 previousSession = mSessions.get(session.getId());
            if (previousSession != null) {
                if (previousSession != session) {
                    Log.w(TAG, "Session ID should be unique, ID=" + session.getId()
                            + ", previous=" + previousSession + ", session=" + session);
                }
                return;
            }
            mSessions.put(session.getId(), session);
            session.setForegroundServiceEventCallback(mForegroundServiceEventCallback);
        }
    }

    /**
     * Removes a session from this service.
     *
     * @param session a session to be removed.
     * @see #addSession(MediaSession2)
     */
    public final void removeSession(@NonNull MediaSession2 session) {
        if (session == null) {
            throw new IllegalArgumentException("session shouldn't be null");
        }
        MediaNotification notification;
        synchronized (mLock) {
            if (mSessions.get(session.getId()) != session) {
                // Session isn't added or removed already.
                return;
            }
            mSessions.remove(session.getId());
            notification = mNotifications.remove(session);
        }
        session.setForegroundServiceEventCallback(null);
        if (notification != null) {
            mNotificationManager.cancel(notification.getNotificationId());
        }
        if (getSessions().isEmpty()) {
            stopForeground(false);
        }
    }

    /**
     * Gets the list of {@link MediaSession2}s that you've added to this service.
     *
     * @return sessions
     */
    public final @NonNull List<MediaSession2> getSessions() {
        List<MediaSession2> list = new ArrayList<>();
        synchronized (mLock) {
            list.addAll(mSessions.values());
        }
        return list;
    }

    /**
     * Returns the {@link MediaSessionManager}.
     */
    @NonNull
    MediaSessionManager getMediaSessionManager() {
        synchronized (mLock) {
            return mMediaSessionManager;
        }
    }

    /**
     * Called by registered {@link MediaSession2.ForegroundServiceEventCallback}
     *
     * @param session session with change
     * @param playbackActive {@code true} if playback is active.
     */
    void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {
        MediaNotification mediaNotification = onUpdateNotification(session);
        if (mediaNotification == null) {
            // The service implementation doesn't want to use the automatic start/stopForeground
            // feature.
            return;
        }
        synchronized (mLock) {
            mNotifications.put(session, mediaNotification);
        }
        int id = mediaNotification.getNotificationId();
        Notification notification = mediaNotification.getNotification();
        if (!playbackActive) {
            mNotificationManager.notify(id, notification);
            return;
        }
        // playbackActive == true
        startForegroundService(mStartSelfIntent);
        startForeground(id, notification);
    }

    /**
     * This API is not generally intended for third party application developers.
     * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
     * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
     * Library</a> for consistent behavior across all devices.
     * <p>
     * Returned by {@link #onUpdateNotification(MediaSession2)} for making session service
     * foreground service to keep playback running in the background. It's highly recommended to
     * show media style notification here.
     */
    public static class MediaNotification {
        private final int mNotificationId;
        private final Notification mNotification;

        /**
         * Default constructor
         *
         * @param notificationId notification id to be used for
         *        {@link NotificationManager#notify(int, Notification)}.
         * @param notification a notification to make session service run in the foreground. Media
         *        style notification is recommended here.
         */
        public MediaNotification(int notificationId, @NonNull Notification notification) {
            if (notification == null) {
                throw new IllegalArgumentException("notification shouldn't be null");
            }
            mNotificationId = notificationId;
            mNotification = notification;
        }

        /**
         * Gets the id of the notification.
         *
         * @return the notification id
         */
        public int getNotificationId() {
            return mNotificationId;
        }

        /**
         * Gets the notification.
         *
         * @return the notification
         */
        @NonNull
        public Notification getNotification() {
            return mNotification;
        }
    }

    private static final class MediaSession2ServiceStub extends IMediaSession2Service.Stub
            implements AutoCloseable {
        final WeakReference<MediaSession2Service> mService;
        final Handler mHandler;

        MediaSession2ServiceStub(MediaSession2Service service) {
            mService = new WeakReference<>(service);
            mHandler = new Handler(service.getMainLooper());
        }

        @Override
        public void connect(Controller2Link caller, int seq, Bundle connectionRequest) {
            if (mService.get() == null) {
                if (DEBUG) {
                    Log.d(TAG, "Service is already destroyed");
                }
                return;
            }
            if (caller == null || connectionRequest == null) {
                if (DEBUG) {
                    Log.d(TAG, "Ignoring calls with illegal arguments, caller=" + caller
                            + ", connectionRequest=" + connectionRequest);
                }
                return;
            }
            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final long token = Binder.clearCallingIdentity();
            try {
                mHandler.post(() -> {
                    boolean shouldNotifyDisconnected = true;
                    try {
                        final MediaSession2Service service = mService.get();
                        if (service == null) {
                            if (DEBUG) {
                                Log.d(TAG, "Service isn't available");
                            }
                            return;
                        }

                        String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME);
                        // The Binder.getCallingPid() can be 0 for an oneway call from the
                        // remote process. If it's the case, use PID from the connectionRequest.
                        RemoteUserInfo remoteUserInfo = new RemoteUserInfo(
                                callingPkg,
                                pid == 0 ? connectionRequest.getInt(KEY_PID) : pid,
                                uid);

                        Bundle connectionHints = connectionRequest.getBundle(KEY_CONNECTION_HINTS);
                        if (connectionHints == null) {
                            Log.w(TAG, "connectionHints shouldn't be null.");
                            connectionHints = Bundle.EMPTY;
                        } else if (MediaSession2.hasCustomParcelable(connectionHints)) {
                            Log.w(TAG, "connectionHints contain custom parcelable. Ignoring.");
                            connectionHints = Bundle.EMPTY;
                        }

                        final ControllerInfo controllerInfo = new ControllerInfo(
                                remoteUserInfo,
                                service.getMediaSessionManager()
                                        .isTrustedForMediaControl(remoteUserInfo),
                                caller,
                                connectionHints);

                        if (DEBUG) {
                            Log.d(TAG, "Handling incoming connection request from the"
                                    + " controller=" + controllerInfo);
                        }

                        final MediaSession2 session;
                        session = service.onGetSession(controllerInfo);

                        if (session == null) {
                            if (DEBUG) {
                                Log.d(TAG, "Rejecting incoming connection request from the"
                                        + " controller=" + controllerInfo);
                            }
                            // Note: Trusted controllers also can be rejected according to the
                            // service implementation.
                            return;
                        }
                        service.addSession(session);
                        shouldNotifyDisconnected = false;
                        session.onConnect(caller, pid, uid, seq, connectionRequest);
                    } catch (Exception e) {
                        // Don't propagate exception in service to the controller.
                        Log.w(TAG, "Failed to add a session to session service", e);
                    } finally {
                        // Trick to call onDisconnected() in one place.
                        if (shouldNotifyDisconnected) {
                            if (DEBUG) {
                                Log.d(TAG, "Notifying the controller of its disconnection");
                            }
                            try {
                                caller.notifyDisconnected(0);
                            } catch (RuntimeException e) {
                                // Controller may be died prematurely.
                                // Not an issue because we'll ignore it anyway.
                            }
                        }
                    }
                });
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void close() {
            mHandler.removeCallbacksAndMessages(null);
            mService.clear();
        }
    }
}
