/*
 * Copyright (C) 2015 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 com.android.server.telecom;

import android.Manifest;
import android.app.AppOpsManager;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telecom.Connection;
import android.telecom.InCallService;
import android.telecom.Log;
import android.telecom.VideoProfile;
import android.text.TextUtils;
import android.view.Surface;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telecom.IVideoCallback;
import com.android.internal.telecom.IVideoProvider;

import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Proxies video provider messages from {@link InCallService.VideoCall}
 * implementations to the underlying {@link Connection.VideoProvider} implementation.  Also proxies
 * callbacks from the {@link Connection.VideoProvider} to {@link InCallService.VideoCall}
 * implementations.
 *
 * Also provides a means for Telecom to send and receive these messages.
 */
public class VideoProviderProxy extends Connection.VideoProvider {

    /**
     * Listener for Telecom components interested in callbacks from the video provider.
     */
    public interface Listener {
        void onSessionModifyRequestReceived(Call call, VideoProfile videoProfile);
        void onSetCamera(Call call, String cameraId);
    }

    /**
     * Set of listeners on this VideoProviderProxy.
     *
     * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
     * load factor before resizing, 1 means we only expect a single thread to
     * access the map so make only a single shard
     */
    private final Set<Listener> mListeners = Collections.newSetFromMap(
            new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));

    /** The TelecomSystem SyncRoot used for synchronized operations. */
    private final TelecomSystem.SyncRoot mLock;

    /**
     * The {@link android.telecom.Connection.VideoProvider} implementation residing with the
     * {@link android.telecom.ConnectionService} which is being wrapped by this
     * {@link VideoProviderProxy}.
     */
    private final IVideoProvider mConectionServiceVideoProvider;

    /**
     * Binder used to bind to the {@link android.telecom.ConnectionService}'s
     * {@link com.android.internal.telecom.IVideoCallback}.
     */
    private final VideoCallListenerBinder mVideoCallListenerBinder;

    /**
     * The Telecom {@link Call} this {@link VideoProviderProxy} is associated with.
     */
    private Call mCall;

    /**
     * Interface providing access to the currently logged in user.
     */
    private CurrentUserProxy mCurrentUserProxy;

    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            mConectionServiceVideoProvider.asBinder().unlinkToDeath(this, 0);
        }
    };

    /**
     * Creates a new instance of the {@link VideoProviderProxy}, binding it to the passed in
     * {@code videoProvider} residing with the {@link android.telecom.ConnectionService}.
     *
     *
     * @param lock
     * @param videoProvider The {@link android.telecom.ConnectionService}'s video provider.
     * @param call The current call.
     * @throws RemoteException Remote exception.
     */
    public VideoProviderProxy(TelecomSystem.SyncRoot lock,
            IVideoProvider videoProvider, Call call, CurrentUserProxy currentUserProxy)
            throws RemoteException {

        super(Looper.getMainLooper());

        mLock = lock;

        mConectionServiceVideoProvider = videoProvider;
        mConectionServiceVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);

        mVideoCallListenerBinder = new VideoCallListenerBinder();
        mConectionServiceVideoProvider.addVideoCallback(mVideoCallListenerBinder);
        mCall = call;
        mCurrentUserProxy = currentUserProxy;
    }

    public void clearVideoCallback() {
        try {
            mConectionServiceVideoProvider.removeVideoCallback(mVideoCallListenerBinder);
        } catch (RemoteException e) {
        }
    }

    @VisibleForTesting
    public VideoCallListenerBinder getVideoCallListenerBinder() {
        return mVideoCallListenerBinder;
    }

    /**
     * IVideoCallback stub implementation.  An instance of this class receives callbacks from the
     * {@code ConnectionService}'s video provider.
     */
    public final class VideoCallListenerBinder extends IVideoCallback.Stub {
        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when a session modification request is received.
         *
         * @param videoProfile The requested video profile.
         */
        @Override
        public void receiveSessionModifyRequest(VideoProfile videoProfile) {
            try {
                Log.startSession("VPP.rSMR");
                synchronized (mLock) {
                    logFromVideoProvider("receiveSessionModifyRequest: " + videoProfile);
                    Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_REQUEST,
                            VideoProfile.videoStateToString(videoProfile.getVideoState()));

                    mCall.getAnalytics().addVideoEvent(
                            Analytics.RECEIVE_REMOTE_SESSION_MODIFY_REQUEST,
                            videoProfile.getVideoState());

                    if ((!mCall.isVideoCallingSupportedByPhoneAccount()
                            || !mCall.isLocallyVideoCapable())
                            && VideoProfile.isVideo(videoProfile.getVideoState())) {
                        // If video calling is not supported by the phone account, or is not
                        // locally video capable and we receive a request to upgrade to video,
                        // automatically reject it without informing the InCallService.
                        Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE,
                                "video not supported");
                        VideoProfile responseProfile = new VideoProfile(
                                VideoProfile.STATE_AUDIO_ONLY);
                        try {
                            mConectionServiceVideoProvider.sendSessionModifyResponse(
                                    responseProfile);
                        } catch (RemoteException e) {
                        }

                        // Don't want to inform listeners of the request as we've just rejected it.
                        return;
                    }

                    // Inform other Telecom components of the session modification request.
                    for (Listener listener : mListeners) {
                        listener.onSessionModifyRequestReceived(mCall, videoProfile);
                    }

                    VideoProviderProxy.this.receiveSessionModifyRequest(videoProfile);
                }
            } finally {
                Log.endSession();
            }
        }

        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when a session modification response is received.
         *
         * @param status The status of the response.
         * @param requestProfile The requested video profile.
         * @param responseProfile The response video profile.
         */
        @Override
        public void receiveSessionModifyResponse(int status, VideoProfile requestProfile,
                VideoProfile responseProfile) {
            logFromVideoProvider("receiveSessionModifyResponse: status=" + status +
                    " requestProfile=" + requestProfile + " responseProfile=" + responseProfile);
            String eventMessage = "Status Code : " + status + " Video State: " +
                    (responseProfile != null ? responseProfile.getVideoState() : "null");
            Log.addEvent(mCall, LogUtils.Events.RECEIVE_VIDEO_RESPONSE, eventMessage);
            synchronized (mLock) {
                if (status == Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS) {
                    mCall.getAnalytics().addVideoEvent(
                            Analytics.RECEIVE_REMOTE_SESSION_MODIFY_RESPONSE,
                            responseProfile == null ?
                                    VideoProfile.STATE_AUDIO_ONLY :
                                    responseProfile.getVideoState());
                }
                VideoProviderProxy.this.receiveSessionModifyResponse(status, requestProfile,
                        responseProfile);
            }
        }

        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when a call session event occurs.
         *
         * @param event The call session event.
         */
        @Override
        public void handleCallSessionEvent(int event) {
            synchronized (mLock) {
                logFromVideoProvider("handleCallSessionEvent: " +
                        Connection.VideoProvider.sessionEventToString(event));
                VideoProviderProxy.this.handleCallSessionEvent(event);
            }
        }

        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when the peer dimensions change.
         *
         * @param width The width of the peer's video.
         * @param height The height of the peer's video.
         */
        @Override
        public void changePeerDimensions(int width, int height) {
            synchronized (mLock) {
                logFromVideoProvider("changePeerDimensions: width=" + width + " height=" +
                        height);
                VideoProviderProxy.this.changePeerDimensions(width, height);
            }
        }

        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when the video quality changes.
         *
         * @param videoQuality The video quality.
         */
        @Override
        public void changeVideoQuality(int videoQuality) {
            synchronized (mLock) {
                logFromVideoProvider("changeVideoQuality: " + videoQuality);
                VideoProviderProxy.this.changeVideoQuality(videoQuality);
            }
        }

        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when the call data usage changes.
         *
         * Also tracks the current call data usage on the {@link Call} for use when writing to the
         * call log.
         *
         * @param dataUsage The data usage.
         */
        @Override
        public void changeCallDataUsage(long dataUsage) {
            synchronized (mLock) {
                logFromVideoProvider("changeCallDataUsage: " + dataUsage);
                VideoProviderProxy.this.setCallDataUsage(dataUsage);
                mCall.setCallDataUsage(dataUsage);
            }
        }

        /**
         * Proxies a request from the {@link #mConectionServiceVideoProvider} to the
         * {@link InCallService} when the camera capabilities change.
         *
         * @param cameraCapabilities The camera capabilities.
         */
        @Override
        public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
            synchronized (mLock) {
                logFromVideoProvider("changeCameraCapabilities: " + cameraCapabilities);
                VideoProviderProxy.this.changeCameraCapabilities(cameraCapabilities);
            }
        }
    }

    @Override
    public void onSetCamera(String cameraId) {
        // No-op.  We implement the other prototype of onSetCamera so that we can use the calling
        // package, uid and pid to verify permission.
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to change the camera.
     *
     * @param cameraId The id of the camera.
     * @param callingPackage The package calling in.
     * @param callingUid The UID of the caller.
     * @param callingPid The PID of the caller.
     * @param targetSdkVersion The target SDK version of the calling InCallService where the camera
     *      request originated.
     */
    @Override
    public void onSetCamera(String cameraId, String callingPackage, int callingUid,
            int callingPid, int targetSdkVersion) {
        synchronized (mLock) {
            logFromInCall("setCamera: " + cameraId + " callingPackage=" + callingPackage +
                    "; callingUid=" + callingUid);

            if (!TextUtils.isEmpty(cameraId)) {
                if (!canUseCamera(mCall.getContext(), callingPackage, callingUid, callingPid)) {
                    // Calling app is not permitted to use the camera.  Ignore the request and send
                    // back a call session event indicating the error.
                    Log.i(this, "onSetCamera: camera permission denied; package=%s, uid=%d, "
                            + "pid=%d, targetSdkVersion=%d",
                            callingPackage, callingUid, callingPid, targetSdkVersion);

                    // API 26 introduces a new camera permission error we can use here since the
                    // caller supports that API version.
                    if (targetSdkVersion > Build.VERSION_CODES.N_MR1) {
                        VideoProviderProxy.this.handleCallSessionEvent(
                                Connection.VideoProvider.SESSION_EVENT_CAMERA_PERMISSION_ERROR);
                    } else {
                        VideoProviderProxy.this.handleCallSessionEvent(
                                Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE);
                    }
                    return;
                }
            }

            // Inform other Telecom components of the change in camera status.
            for (Listener listener : mListeners) {
                listener.onSetCamera(mCall, cameraId);
            }

            try {
                mConectionServiceVideoProvider.setCamera(cameraId, callingPackage,
                        targetSdkVersion);
            } catch (RemoteException e) {
                VideoProviderProxy.this.handleCallSessionEvent(
                        Connection.VideoProvider.SESSION_EVENT_CAMERA_FAILURE);
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to set the preview surface.
     *
     * @param surface The surface.
     */
    @Override
    public void onSetPreviewSurface(Surface surface) {
        synchronized (mLock) {
            logFromInCall("setPreviewSurface");
            try {
                mConectionServiceVideoProvider.setPreviewSurface(surface);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to change the display surface.
     *
     * @param surface The surface.
     */
    @Override
    public void onSetDisplaySurface(Surface surface) {
        synchronized (mLock) {
            logFromInCall("setDisplaySurface");
            try {
                mConectionServiceVideoProvider.setDisplaySurface(surface);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to change the device orientation.
     *
     * @param rotation The device orientation, in degrees.
     */
    @Override
    public void onSetDeviceOrientation(int rotation) {
        synchronized (mLock) {
            logFromInCall("setDeviceOrientation: " + rotation);
            try {
                mConectionServiceVideoProvider.setDeviceOrientation(rotation);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to change the camera zoom ratio.
     *
     * @param value The camera zoom ratio.
     */
    @Override
    public void onSetZoom(float value) {
        synchronized (mLock) {
            logFromInCall("setZoom: " + value);
            try {
                mConectionServiceVideoProvider.setZoom(value);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to provide a response to a session modification
     * request.
     *
     * @param fromProfile The video properties prior to the request.
     * @param toProfile The video properties with the requested changes made.
     */
    @Override
    public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
        synchronized (mLock) {
            logFromInCall("sendSessionModifyRequest: from=" + fromProfile + " to=" + toProfile);
            Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_REQUEST,
                    VideoProfile.videoStateToString(toProfile.getVideoState()));
            if (!VideoProfile.isVideo(fromProfile.getVideoState())
                    && VideoProfile.isVideo(toProfile.getVideoState())) {
                // Upgrading to video; change to speaker potentially.
                mCall.maybeEnableSpeakerForVideoUpgrade(toProfile.getVideoState());
            }
            mCall.getAnalytics().addVideoEvent(
                    Analytics.SEND_LOCAL_SESSION_MODIFY_REQUEST,
                    toProfile.getVideoState());
            try {
                mConectionServiceVideoProvider.sendSessionModifyRequest(fromProfile, toProfile);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to send a session modification request.
     *
     * @param responseProfile The response connection video properties.
     */
    @Override
    public void onSendSessionModifyResponse(VideoProfile responseProfile) {
        synchronized (mLock) {
            logFromInCall("sendSessionModifyResponse: " + responseProfile);
            Log.addEvent(mCall, LogUtils.Events.SEND_VIDEO_RESPONSE,
                    VideoProfile.videoStateToString(responseProfile.getVideoState()));
            mCall.getAnalytics().addVideoEvent(
                    Analytics.SEND_LOCAL_SESSION_MODIFY_RESPONSE,
                    responseProfile.getVideoState());
            try {
                mConectionServiceVideoProvider.sendSessionModifyResponse(responseProfile);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to request the camera capabilities.
     */
    @Override
    public void onRequestCameraCapabilities() {
        synchronized (mLock) {
            logFromInCall("requestCameraCapabilities");
            try {
                mConectionServiceVideoProvider.requestCameraCapabilities();
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to request the connection data usage.
     */
    @Override
    public void onRequestConnectionDataUsage() {
        synchronized (mLock) {
            logFromInCall("requestCallDataUsage");
            try {
                mConectionServiceVideoProvider.requestCallDataUsage();
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Proxies a request from the {@link InCallService} to the
     * {@link #mConectionServiceVideoProvider} to set the pause image.
     *
     * @param uri URI of image to display.
     */
    @Override
    public void onSetPauseImage(Uri uri) {
        synchronized (mLock) {
            logFromInCall("setPauseImage: " + uri);
            try {
                mConectionServiceVideoProvider.setPauseImage(uri);
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Add a listener to this {@link VideoProviderProxy}.
     *
     * @param listener The listener.
     */
    public void addListener(Listener listener) {
        mListeners.add(listener);
    }

    /**
     * Remove a listener from this {@link VideoProviderProxy}.
     *
     * @param listener The listener.
     */
    public void removeListener(Listener listener) {
        if (listener != null) {
            mListeners.remove(listener);
        }
    }

    /**
     * Logs a message originating from the {@link InCallService}.
     *
     * @param toLog The message to log.
     */
    private void logFromInCall(String toLog) {
        Log.i(this, "IC->VP (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog);
    }

    /**
     * Logs a message originating from the {@link android.telecom.ConnectionService}'s
     * {@link Connection.VideoProvider}.
     *
     * @param toLog The message to log.
     */
    private void logFromVideoProvider(String toLog) {
        Log.i(this, "VP->IC (callId=" + (mCall == null ? "?" : mCall.getId()) + "): " + toLog);
    }

    /**
     * Determines if the caller has permission to use the camera.
     *
     * @param context The context.
     * @param callingPackage The package name of the caller (i.e. Dialer).
     * @param callingUid The UID of the caller.
     * @param callingPid The PID of the caller.
     * @return {@code true} if the calling uid and package can use the camera, {@code false}
     *      otherwise.
     */
    private boolean canUseCamera(Context context, String callingPackage, int callingUid,
            int callingPid) {

        UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
        UserHandle currentUserHandle = mCurrentUserProxy.getCurrentUserHandle();
        if (currentUserHandle != null && !currentUserHandle.equals(callingUser)) {
            Log.w(this, "canUseCamera attempt to user camera by background user.");
            return false;
        }

        try {
            context.enforcePermission(Manifest.permission.CAMERA, callingPid, callingUid,
                    "Camera permission required.");
        } catch (SecurityException se) {
            return false;
        }

        AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(
                Context.APP_OPS_SERVICE);

        try {
            // Some apps that have the permission can be restricted via app ops.
            return appOpsManager != null && appOpsManager.noteOp(AppOpsManager.OP_CAMERA,
                    callingUid, callingPackage) == AppOpsManager.MODE_ALLOWED;
        } catch (SecurityException se) {
            Log.w(this, "canUseCamera got appOpps Exception " + se.toString());
            return false;
        }
    }

}
