/*
 * 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 com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Base class for media route provider services.
 * <p>
 * Media route provider services are used to publish {@link MediaRoute2Info media routes} such as
 * speakers, TVs, etc. The routes are published by calling {@link #notifyRoutes(Collection)}.
 * Media apps which use {@link MediaRouter2} can request to play their media on the routes.
 * </p><p>
 * When {@link MediaRouter2 media router} wants to play media on a route,
 * {@link #onCreateSession(long, String, String, Bundle)} will be called to handle the request.
 * A session can be considered as a group of currently selected routes for each connection.
 * Create and manage the sessions by yourself, and notify the {@link RoutingSessionInfo
 * session infos} when there are any changes.
 * </p><p>
 * The system media router service will bind to media route provider services when a
 * {@link RouteDiscoveryPreference discovery preference} is registered via
 * a {@link MediaRouter2 media router} by an application. See
 * {@link #onDiscoveryPreferenceChanged(RouteDiscoveryPreference)} for the details.
 * </p>
 * Use {@link #notifyRequestFailed(long, int)} to notify the failure with previously received
 * request ID.
 */
public abstract class MediaRoute2ProviderService extends Service {
    private static final String TAG = "MR2ProviderService";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    /**
     * The {@link Intent} action that must be declared as handled by the service.
     * Put this in your manifest to provide media routes.
     */
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";

    /**
     * The request ID to pass {@link #notifySessionCreated(long, RoutingSessionInfo)}
     * when {@link MediaRoute2ProviderService} created a session although there was no creation
     * request.
     *
     * @see #notifySessionCreated(long, RoutingSessionInfo)
     */
    public static final long REQUEST_ID_NONE = 0;

    /**
     * The request has failed due to unknown reason.
     *
     * @see #notifyRequestFailed(long, int)
     */
    public static final int REASON_UNKNOWN_ERROR = 0;

    /**
     * The request has failed since this service rejected the request.
     *
     * @see #notifyRequestFailed(long, int)
     */
    public static final int REASON_REJECTED = 1;

    /**
     * The request has failed due to a network error.
     *
     * @see #notifyRequestFailed(long, int)
     */
    public static final int REASON_NETWORK_ERROR = 2;

    /**
     * The request has failed since the requested route is no longer available.
     *
     * @see #notifyRequestFailed(long, int)
     */
    public static final int REASON_ROUTE_NOT_AVAILABLE = 3;

    /**
     * The request has failed since the request is not valid. For example, selecting a route
     * which is not selectable.
     *
     * @see #notifyRequestFailed(long, int)
     */
    public static final int REASON_INVALID_COMMAND = 4;

    /**
     * @hide
     */
    @IntDef(prefix = "REASON_", value = {
            REASON_UNKNOWN_ERROR, REASON_REJECTED, REASON_NETWORK_ERROR, REASON_ROUTE_NOT_AVAILABLE,
            REASON_INVALID_COMMAND
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Reason {}

    private static final int MAX_REQUEST_IDS_SIZE = 500;

    private final Handler mHandler;
    private final Object mSessionLock = new Object();
    private final Object mRequestIdsLock = new Object();
    private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
    private final AtomicBoolean mSessionUpdateScheduled = new AtomicBoolean(false);
    private MediaRoute2ProviderServiceStub mStub;
    private IMediaRoute2ProviderServiceCallback mRemoteCallback;
    private volatile MediaRoute2ProviderInfo mProviderInfo;

    @GuardedBy("mRequestIdsLock")
    private final Deque<Long> mRequestIds = new ArrayDeque<>(MAX_REQUEST_IDS_SIZE);

    @GuardedBy("mSessionLock")
    private final ArrayMap<String, RoutingSessionInfo> mSessionInfos = new ArrayMap<>();

    public MediaRoute2ProviderService() {
        mHandler = new Handler(Looper.getMainLooper());
    }

    /**
     * If overriding this method, call through to the super method for any unknown actions.
     * <p>
     * {@inheritDoc}
     */
    @CallSuper
    @Override
    @Nullable
    public IBinder onBind(@NonNull Intent intent) {
        if (SERVICE_INTERFACE.equals(intent.getAction())) {
            if (mStub == null) {
                mStub = new MediaRoute2ProviderServiceStub();
            }
            return mStub;
        }
        return null;
    }

    /**
     * Called when a volume setting is requested on a route of the provider
     *
     * @param requestId the ID of this request
     * @param routeId the ID of the route
     * @param volume the target volume
     * @see MediaRoute2Info.Builder#setVolume(int)
     */
    public abstract void onSetRouteVolume(long requestId, @NonNull String routeId, int volume);

    /**
     * Called when {@link MediaRouter2.RoutingController#setVolume(int)} is called on
     * a routing session of the provider
     *
     * @param requestId the ID of this request
     * @param sessionId the ID of the routing session
     * @param volume the target volume
     * @see RoutingSessionInfo.Builder#setVolume(int)
     */
    public abstract void onSetSessionVolume(long requestId, @NonNull String sessionId, int volume);

    /**
     * Gets information of the session with the given id.
     *
     * @param sessionId the ID of the session
     * @return information of the session with the given id.
     *         null if the session is released or ID is not valid.
     */
    @Nullable
    public final RoutingSessionInfo getSessionInfo(@NonNull String sessionId) {
        if (TextUtils.isEmpty(sessionId)) {
            throw new IllegalArgumentException("sessionId must not be empty");
        }
        synchronized (mSessionLock) {
            return mSessionInfos.get(sessionId);
        }
    }

    /**
     * Gets the list of {@link RoutingSessionInfo session info} that the provider service maintains.
     */
    @NonNull
    public final List<RoutingSessionInfo> getAllSessionInfo() {
        synchronized (mSessionLock) {
            return new ArrayList<>(mSessionInfos.values());
        }
    }

    /**
     * Notifies clients of that the session is created and ready for use.
     * <p>
     * If this session is created without any creation request, use {@link #REQUEST_ID_NONE}
     * as the request ID.
     *
     * @param requestId the ID of the previous request to create this session provided in
     *                  {@link #onCreateSession(long, String, String, Bundle)}. Can be
     *                  {@link #REQUEST_ID_NONE} if this session is created without any request.
     * @param sessionInfo information of the new session.
     *                    The {@link RoutingSessionInfo#getId() id} of the session must be unique.
     * @see #onCreateSession(long, String, String, Bundle)
     * @see #getSessionInfo(String)
     */
    public final void notifySessionCreated(long requestId,
            @NonNull RoutingSessionInfo sessionInfo) {
        Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");

        if (DEBUG) {
            Log.d(TAG, "notifySessionCreated: Creating a session. requestId=" + requestId
                    + ", sessionInfo=" + sessionInfo);
        }

        if (requestId != REQUEST_ID_NONE && !removeRequestId(requestId)) {
            Log.w(TAG, "notifySessionCreated: The requestId doesn't exist. requestId=" + requestId);
            return;
        }

        String sessionId = sessionInfo.getId();
        synchronized (mSessionLock) {
            if (mSessionInfos.containsKey(sessionId)) {
                Log.w(TAG, "notifySessionCreated: Ignoring duplicate session id.");
                return;
            }
            mSessionInfos.put(sessionInfo.getId(), sessionInfo);

            if (mRemoteCallback == null) {
                return;
            }
            try {
                mRemoteCallback.notifySessionCreated(requestId, sessionInfo);
            } catch (RemoteException ex) {
                Log.w(TAG, "Failed to notify session created.");
            }
        }
    }

    /**
     * Notifies the existing session is updated. For example, when
     * {@link RoutingSessionInfo#getSelectedRoutes() selected routes} are changed.
     */
    public final void notifySessionUpdated(@NonNull RoutingSessionInfo sessionInfo) {
        Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");

        if (DEBUG) {
            Log.d(TAG, "notifySessionUpdated: Updating session id=" + sessionInfo);
        }

        String sessionId = sessionInfo.getId();
        synchronized (mSessionLock) {
            if (mSessionInfos.containsKey(sessionId)) {
                mSessionInfos.put(sessionId, sessionInfo);
            } else {
                Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info.");
                return;
            }
        }
        scheduleUpdateSessions();
    }

    /**
     * Notifies that the session is released.
     *
     * @param sessionId the ID of the released session.
     * @see #onReleaseSession(long, String)
     */
    public final void notifySessionReleased(@NonNull String sessionId) {
        if (TextUtils.isEmpty(sessionId)) {
            throw new IllegalArgumentException("sessionId must not be empty");
        }
        if (DEBUG) {
            Log.d(TAG, "notifySessionReleased: Releasing session id=" + sessionId);
        }

        RoutingSessionInfo sessionInfo;
        synchronized (mSessionLock) {
            sessionInfo = mSessionInfos.remove(sessionId);

            if (sessionInfo == null) {
                Log.w(TAG, "notifySessionReleased: Ignoring unknown session info.");
                return;
            }

            if (mRemoteCallback == null) {
                return;
            }
            try {
                mRemoteCallback.notifySessionReleased(sessionInfo);
            } catch (RemoteException ex) {
                Log.w(TAG, "Failed to notify session released.", ex);
            }
        }
    }

    /**
     * Notifies to the client that the request has failed.
     *
     * @param requestId the ID of the previous request
     * @param reason the reason why the request has failed
     *
     * @see #REASON_UNKNOWN_ERROR
     * @see #REASON_REJECTED
     * @see #REASON_NETWORK_ERROR
     * @see #REASON_ROUTE_NOT_AVAILABLE
     * @see #REASON_INVALID_COMMAND
     */
    public final void notifyRequestFailed(long requestId, @Reason int reason) {
        if (mRemoteCallback == null) {
            return;
        }

        if (!removeRequestId(requestId)) {
            Log.w(TAG, "notifyRequestFailed: The requestId doesn't exist. requestId="
                    + requestId);
            return;
        }

        try {
            mRemoteCallback.notifyRequestFailed(requestId, reason);
        } catch (RemoteException ex) {
            Log.w(TAG, "Failed to notify that the request has failed.");
        }
    }

    /**
     * Called when the service receives a request to create a session.
     * <p>
     * You should create and maintain your own session and notifies the client of
     * session info. Call {@link #notifySessionCreated(long, RoutingSessionInfo)}
     * with the given {@code requestId} to notify the information of a new session.
     * The created session must have the same route feature and must include the given route
     * specified by {@code routeId}.
     * <p>
     * If the session can be controlled, you can optionally pass the control hints to
     * {@link RoutingSessionInfo.Builder#setControlHints(Bundle)}. Control hints is a
     * {@link Bundle} which contains how to control the session.
     * <p>
     * If you can't create the session or want to reject the request, call
     * {@link #notifyRequestFailed(long, int)} with the given {@code requestId}.
     *
     * @param requestId the ID of this request
     * @param packageName the package name of the application that selected the route
     * @param routeId the ID of the route initially being connected
     * @param sessionHints an optional bundle of app-specific arguments sent by
     *                     {@link MediaRouter2}, or null if none. The contents of this bundle
     *                     may affect the result of session creation.
     *
     * @see RoutingSessionInfo.Builder#Builder(String, String)
     * @see RoutingSessionInfo.Builder#addSelectedRoute(String)
     * @see RoutingSessionInfo.Builder#setControlHints(Bundle)
     */
    public abstract void onCreateSession(long requestId, @NonNull String packageName,
            @NonNull String routeId, @Nullable Bundle sessionHints);

    /**
     * Called when the session should be released. A client of the session or system can request
     * a session to be released.
     * <p>
     * After releasing the session, call {@link #notifySessionReleased(String)}
     * with the ID of the released session.
     *
     * Note: Calling {@link #notifySessionReleased(String)} will <em>NOT</em> trigger
     * this method to be called.
     *
     * @param requestId the ID of this request
     * @param sessionId the ID of the session being released.
     * @see #notifySessionReleased(String)
     * @see #getSessionInfo(String)
     */
    public abstract void onReleaseSession(long requestId, @NonNull String sessionId);

    /**
     * Called when a client requests selecting a route for the session.
     * After the route is selected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
     * to update session info.
     *
     * @param requestId the ID of this request
     * @param sessionId the ID of the session
     * @param routeId the ID of the route
     */
    public abstract void onSelectRoute(long requestId, @NonNull String sessionId,
            @NonNull String routeId);

    /**
     * Called when a client requests deselecting a route from the session.
     * After the route is deselected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
     * to update session info.
     *
     * @param requestId the ID of this request
     * @param sessionId the ID of the session
     * @param routeId the ID of the route
     */
    public abstract void onDeselectRoute(long requestId, @NonNull String sessionId,
            @NonNull String routeId);

    /**
     * Called when a client requests transferring a session to a route.
     * After the transfer is finished, call {@link #notifySessionUpdated(RoutingSessionInfo)}
     * to update session info.
     *
     * @param requestId the ID of this request
     * @param sessionId the ID of the session
     * @param routeId the ID of the route
     */
    public abstract void onTransferToRoute(long requestId, @NonNull String sessionId,
            @NonNull String routeId);

    /**
     * Called when the {@link RouteDiscoveryPreference discovery preference} has changed.
     * <p>
     * Whenever an application registers a {@link MediaRouter2.RouteCallback callback},
     * it also provides a discovery preference to specify features of routes that it is interested
     * in. The media router combines all of these discovery request into a single discovery
     * preference and notifies each provider.
     * </p><p>
     * The provider should examine {@link RouteDiscoveryPreference#getPreferredFeatures()
     * preferred features} in the discovery preference to determine what kind of routes it should
     * try to discover and whether it should perform active or passive scans. In many cases,
     * the provider may be able to save power by not performing any scans when the request doesn't
     * have any matching route features.
     * </p>
     *
     * @param preference the new discovery preference
     */
    public void onDiscoveryPreferenceChanged(@NonNull RouteDiscoveryPreference preference) {}

    /**
     * Updates routes of the provider and notifies the system media router service.
     */
    public final void notifyRoutes(@NonNull Collection<MediaRoute2Info> routes) {
        Objects.requireNonNull(routes, "routes must not be null");
        mProviderInfo = new MediaRoute2ProviderInfo.Builder()
                .addRoutes(routes)
                .build();
        schedulePublishState();
    }

    void setCallback(IMediaRoute2ProviderServiceCallback callback) {
        mRemoteCallback = callback;
        schedulePublishState();
        scheduleUpdateSessions();
    }

    void schedulePublishState() {
        if (mStatePublishScheduled.compareAndSet(false, true)) {
            mHandler.post(this::publishState);
        }
    }

    private void publishState() {
        if (!mStatePublishScheduled.compareAndSet(true, false)) {
            return;
        }

        if (mRemoteCallback == null) {
            return;
        }

        try {
            mRemoteCallback.notifyProviderUpdated(mProviderInfo);
        } catch (RemoteException ex) {
            Log.w(TAG, "Failed to publish provider state.", ex);
        }
    }

    void scheduleUpdateSessions() {
        if (mSessionUpdateScheduled.compareAndSet(false, true)) {
            mHandler.post(this::updateSessions);
        }
    }

    private void updateSessions() {
        if (!mSessionUpdateScheduled.compareAndSet(true, false)) {
            return;
        }

        if (mRemoteCallback == null) {
            return;
        }

        List<RoutingSessionInfo> sessions;
        synchronized (mSessionLock) {
            sessions = new ArrayList<>(mSessionInfos.values());
        }

        try {
            mRemoteCallback.notifySessionsUpdated(sessions);
        } catch (RemoteException ex) {
            Log.w(TAG, "Failed to notify session info changed.");
        }

    }

    /**
     * Adds a requestId in the request ID list whose max size is {@link #MAX_REQUEST_IDS_SIZE}.
     * When the max size is reached, the first element is removed (FIFO).
     */
    private void addRequestId(long requestId) {
        synchronized (mRequestIdsLock) {
            if (mRequestIds.size() >= MAX_REQUEST_IDS_SIZE) {
                mRequestIds.removeFirst();
            }
            mRequestIds.addLast(requestId);
        }
    }

    /**
     * Removes the given {@code requestId} from received request ID list.
     * <p>
     * Returns whether the list contains the {@code requestId}. These are the cases when the list
     * doesn't contain the given {@code requestId}:
     * <ul>
     *     <li>This service has never received a request with the requestId. </li>
     *     <li>{@link #notifyRequestFailed} or {@link #notifySessionCreated} already has been called
     *         for the requestId. </li>
     * </ul>
     */
    private boolean removeRequestId(long requestId) {
        synchronized (mRequestIdsLock) {
            return mRequestIds.removeFirstOccurrence(requestId);
        }
    }

    final class MediaRoute2ProviderServiceStub extends IMediaRoute2ProviderService.Stub {
        MediaRoute2ProviderServiceStub() { }

        private boolean checkCallerIsSystem() {
            return Binder.getCallingUid() == Process.SYSTEM_UID;
        }

        private boolean checkSessionIdIsValid(String sessionId, String description) {
            if (TextUtils.isEmpty(sessionId)) {
                Log.w(TAG, description + ": Ignoring empty sessionId from system service.");
                return false;
            }
            if (getSessionInfo(sessionId) == null) {
                Log.w(TAG, description + ": Ignoring unknown session from system service. "
                        + "sessionId=" + sessionId);
                return false;
            }
            return true;
        }

        private boolean checkRouteIdIsValid(String routeId, String description) {
            if (TextUtils.isEmpty(routeId)) {
                Log.w(TAG, description + ": Ignoring empty routeId from system service.");
                return false;
            }
            if (mProviderInfo == null || mProviderInfo.getRoute(routeId) == null) {
                Log.w(TAG, description + ": Ignoring unknown route from system service. "
                        + "routeId=" + routeId);
                return false;
            }
            return true;
        }

        @Override
        public void setCallback(IMediaRoute2ProviderServiceCallback callback) {
            if (!checkCallerIsSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setCallback,
                    MediaRoute2ProviderService.this, callback));
        }

        @Override
        public void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference) {
            if (!checkCallerIsSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(
                    MediaRoute2ProviderService::onDiscoveryPreferenceChanged,
                    MediaRoute2ProviderService.this, discoveryPreference));
        }

        @Override
        public void setRouteVolume(long requestId, String routeId, int volume) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkRouteIdIsValid(routeId, "setRouteVolume")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetRouteVolume,
                    MediaRoute2ProviderService.this, requestId, routeId, volume));
        }

        @Override
        public void requestCreateSession(long requestId, String packageName, String routeId,
                @Nullable Bundle requestCreateSession) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkRouteIdIsValid(routeId, "requestCreateSession")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
                    MediaRoute2ProviderService.this, requestId, packageName, routeId,
                    requestCreateSession));
        }

        @Override
        public void selectRoute(long requestId, String sessionId, String routeId) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkSessionIdIsValid(sessionId, "selectRoute")
                    || !checkRouteIdIsValid(routeId, "selectRoute")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
                    MediaRoute2ProviderService.this, requestId, sessionId, routeId));
        }

        @Override
        public void deselectRoute(long requestId, String sessionId, String routeId) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkSessionIdIsValid(sessionId, "deselectRoute")
                    || !checkRouteIdIsValid(routeId, "deselectRoute")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onDeselectRoute,
                    MediaRoute2ProviderService.this, requestId, sessionId, routeId));
        }

        @Override
        public void transferToRoute(long requestId, String sessionId, String routeId) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkSessionIdIsValid(sessionId, "transferToRoute")
                    || !checkRouteIdIsValid(routeId, "transferToRoute")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onTransferToRoute,
                    MediaRoute2ProviderService.this, requestId, sessionId, routeId));
        }

        @Override
        public void setSessionVolume(long requestId, String sessionId, int volume) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkSessionIdIsValid(sessionId, "setSessionVolume")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetSessionVolume,
                    MediaRoute2ProviderService.this, requestId, sessionId, volume));
        }

        @Override
        public void releaseSession(long requestId, String sessionId) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkSessionIdIsValid(sessionId, "releaseSession")) {
                return;
            }
            addRequestId(requestId);
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession,
                    MediaRoute2ProviderService.this, requestId, sessionId));
        }
    }
}
