/*
 * Copyright (C) 2016 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.tv;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.tv.ITvRemoteProvider;
import android.media.tv.ITvRemoteServiceInput;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;

/**
 * Maintains a connection to a tv remote provider service.
 */
final class TvRemoteProviderProxy implements ServiceConnection {
    private static final String TAG = "TvRemoteProvProxy";  // max. 23 chars
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);
    private static final boolean DEBUG_KEY = false;


    // This should match TvRemoteProvider.ACTION_TV_REMOTE_PROVIDER
    protected static final String SERVICE_INTERFACE =
            "com.android.media.tv.remoteprovider.TvRemoteProvider";
    private final Context mContext;
    private final ComponentName mComponentName;
    private final int mUserId;
    private final int mUid;
    private final Handler mHandler;

    /**
     * State guarded by mLock.
     *  This is the first lock in sequence for an incoming call.
     *  The second lock is always {@link TvRemoteService#mLock}
     *
     *  There are currently no methods that break this sequence.
     */
    private final Object mLock = new Object();

    private ProviderMethods mProviderMethods;
    // Connection state
    private boolean mRunning;
    private boolean mBound;
    private Connection mActiveConnection;
    private boolean mConnectionReady;

    public TvRemoteProviderProxy(Context context, ComponentName componentName, int userId,
                                 int uid) {
        mContext = context;
        mComponentName = componentName;
        mUserId = userId;
        mUid = uid;
        mHandler = new Handler();
    }

    public void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + "Proxy");
        pw.println(prefix + "  mUserId=" + mUserId);
        pw.println(prefix + "  mRunning=" + mRunning);
        pw.println(prefix + "  mBound=" + mBound);
        pw.println(prefix + "  mActiveConnection=" + mActiveConnection);
        pw.println(prefix + "  mConnectionReady=" + mConnectionReady);
    }

    public void setProviderSink(ProviderMethods provider) {
        mProviderMethods = provider;
    }

    public boolean hasComponentName(String packageName, String className) {
        return mComponentName.getPackageName().equals(packageName)
                && mComponentName.getClassName().equals(className);
    }

    public void start() {
        if (!mRunning) {
            if (DEBUG) {
                Slog.d(TAG, this + ": Starting");
            }

            mRunning = true;
            updateBinding();
        }
    }

    public void stop() {
        if (mRunning) {
            if (DEBUG) {
                Slog.d(TAG, this + ": Stopping");
            }

            mRunning = false;
            updateBinding();
        }
    }

    public void rebindIfDisconnected() {
        synchronized (mLock) {
            if (mActiveConnection == null && shouldBind()) {
                unbind();
                bind();
            }
        }
    }

    private void updateBinding() {
        if (shouldBind()) {
            bind();
        } else {
            unbind();
        }
    }

    private boolean shouldBind() {
        return mRunning;
    }

    private void bind() {
        if (!mBound) {
            if (DEBUG) {
                Slog.d(TAG, this + ": Binding");
            }

            Intent service = new Intent(SERVICE_INTERFACE);
            service.setComponent(mComponentName);
            try {
                mBound = mContext.bindServiceAsUser(service, this,
                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                        new UserHandle(mUserId));
                if (!mBound && DEBUG) {
                    Slog.d(TAG, this + ": Bind failed");
                }
            } catch (SecurityException ex) {
                if (DEBUG) {
                    Slog.d(TAG, this + ": Bind failed", ex);
                }
            }
        }
    }

    private void unbind() {
        if (mBound) {
            if (DEBUG) {
                Slog.d(TAG, this + ": Unbinding");
            }

            mBound = false;
            disconnect();
            mContext.unbindService(this);
        }
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        if (DEBUG) {
            Slog.d(TAG, this + ": onServiceConnected()");
        }

        if (mBound) {
            disconnect();

            ITvRemoteProvider provider = ITvRemoteProvider.Stub.asInterface(service);
            if (provider != null) {
                Connection connection = new Connection(provider);
                if (connection.register()) {
                    synchronized (mLock) {
                        mActiveConnection = connection;
                    }
                    if (DEBUG) {
                        Slog.d(TAG, this + ": Connected successfully.");
                    }
                } else {
                    if (DEBUG) {
                        Slog.d(TAG, this + ": Registration failed");
                    }
                }
            } else {
                Slog.e(TAG, this + ": Service returned invalid remote-control provider binder");
            }
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        if (DEBUG) Slog.d(TAG, this + ": Service disconnected");
        disconnect();
    }


    private void onConnectionReady(Connection connection) {
        synchronized (mLock) {
            if (DEBUG) Slog.d(TAG, "onConnectionReady");
            if (mActiveConnection == connection) {
                if (DEBUG) Slog.d(TAG, "mConnectionReady = true");
                mConnectionReady = true;
            }
        }
    }

    private void onConnectionDied(Connection connection) {
        if (mActiveConnection == connection) {
            if (DEBUG) Slog.d(TAG, this + ": Service connection died");
            disconnect();
        }
    }

    private void disconnect() {
        synchronized (mLock) {
            if (mActiveConnection != null) {
                mConnectionReady = false;
                mActiveConnection.dispose();
                mActiveConnection = null;
            }
        }
    }

    // Provider helpers
    public void inputBridgeConnected(IBinder token) {
        synchronized (mLock) {
            if (DEBUG) Slog.d(TAG, this + ": inputBridgeConnected token: " + token);
            if (mConnectionReady) {
                mActiveConnection.onInputBridgeConnected(token);
            }
        }
    }

    public interface ProviderMethods {
        // InputBridge
        void openInputBridge(TvRemoteProviderProxy provider, IBinder token, String name,
                             int width, int height, int maxPointers);

        void closeInputBridge(TvRemoteProviderProxy provider, IBinder token);

        void clearInputBridge(TvRemoteProviderProxy provider, IBinder token);

        void sendTimeStamp(TvRemoteProviderProxy provider, IBinder token, long timestamp);

        void sendKeyDown(TvRemoteProviderProxy provider, IBinder token, int keyCode);

        void sendKeyUp(TvRemoteProviderProxy provider, IBinder token, int keyCode);

        void sendPointerDown(TvRemoteProviderProxy provider, IBinder token, int pointerId, int x,
                             int y);

        void sendPointerUp(TvRemoteProviderProxy provider, IBinder token, int pointerId);

        void sendPointerSync(TvRemoteProviderProxy provider, IBinder token);
    }

    private final class Connection implements IBinder.DeathRecipient {
        private final ITvRemoteProvider mTvRemoteProvider;
        private final RemoteServiceInputProvider mServiceInputProvider;

        public Connection(ITvRemoteProvider provider) {
            mTvRemoteProvider = provider;
            mServiceInputProvider = new RemoteServiceInputProvider(this);
        }

        public boolean register() {
            if (DEBUG) Slog.d(TAG, "Connection::register()");
            try {
                mTvRemoteProvider.asBinder().linkToDeath(this, 0);
                mTvRemoteProvider.setRemoteServiceInputSink(mServiceInputProvider);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        onConnectionReady(Connection.this);
                    }
                });
                return true;
            } catch (RemoteException ex) {
                binderDied();
            }
            return false;
        }

        public void dispose() {
            if (DEBUG) Slog.d(TAG, "Connection::dispose()");
            mTvRemoteProvider.asBinder().unlinkToDeath(this, 0);
            mServiceInputProvider.dispose();
        }


        public void onInputBridgeConnected(IBinder token) {
            if (DEBUG) Slog.d(TAG, this + ": onInputBridgeConnected");
            try {
                mTvRemoteProvider.onInputBridgeConnected(token);
            } catch (RemoteException ex) {
                Slog.e(TAG, "Failed to deliver onInputBridgeConnected. ", ex);
            }
        }

        @Override
        public void binderDied() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    onConnectionDied(Connection.this);
                }
            });
        }

        void openInputBridge(final IBinder token, final String name, final int width,
                             final int height, final int maxPointers) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG) {
                        Slog.d(TAG, this + ": openInputBridge," +
                                " token=" + token + ", name=" + name);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.openInputBridge(TvRemoteProviderProxy.this, token,
                                    name, width, height, maxPointers);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "openInputBridge, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }

        void closeInputBridge(final IBinder token) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG) {
                        Slog.d(TAG, this + ": closeInputBridge," +
                                " token=" + token);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.closeInputBridge(TvRemoteProviderProxy.this, token);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "closeInputBridge, Invalid connection or incorrect uid: " +
                                        Binder.getCallingUid());
                    }
                }
            }
        }

        void clearInputBridge(final IBinder token) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG) {
                        Slog.d(TAG, this + ": clearInputBridge," +
                                " token=" + token);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.clearInputBridge(TvRemoteProviderProxy.this, token);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "clearInputBridge, Invalid connection or incorrect uid: " +
                                        Binder.getCallingUid());
                    }
                }
            }
        }

        void sendTimestamp(final IBinder token, final long timestamp) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendTimeStamp(TvRemoteProviderProxy.this, token,
                                    timestamp);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "sendTimeStamp, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }

        void sendKeyDown(final IBinder token, final int keyCode) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG_KEY) {
                        Slog.d(TAG, this + ": sendKeyDown," +
                                " token=" + token + ", keyCode=" + keyCode);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendKeyDown(TvRemoteProviderProxy.this, token,
                                    keyCode);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "sendKeyDown, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }

        void sendKeyUp(final IBinder token, final int keyCode) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG_KEY) {
                        Slog.d(TAG, this + ": sendKeyUp," +
                                " token=" + token + ", keyCode=" + keyCode);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendKeyUp(TvRemoteProviderProxy.this, token, keyCode);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "sendKeyUp, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }

        void sendPointerDown(final IBinder token, final int pointerId, final int x, final int y) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG_KEY) {
                        Slog.d(TAG, this + ": sendPointerDown," +
                                " token=" + token + ", pointerId=" + pointerId);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendPointerDown(TvRemoteProviderProxy.this, token,
                                    pointerId, x, y);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "sendPointerDown, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }

        void sendPointerUp(final IBinder token, final int pointerId) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG_KEY) {
                        Slog.d(TAG, this + ": sendPointerUp," +
                                " token=" + token + ", pointerId=" + pointerId);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendPointerUp(TvRemoteProviderProxy.this, token,
                                    pointerId);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "sendPointerUp, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }

        void sendPointerSync(final IBinder token) {
            synchronized (mLock) {
                if (mActiveConnection == this && Binder.getCallingUid() == mUid) {
                    if (DEBUG_KEY) {
                        Slog.d(TAG, this + ": sendPointerSync," +
                                " token=" + token);
                    }
                    final long idToken = Binder.clearCallingIdentity();
                    try {
                        if (mProviderMethods != null) {
                            mProviderMethods.sendPointerSync(TvRemoteProviderProxy.this, token);
                        }
                    } finally {
                        Binder.restoreCallingIdentity(idToken);
                    }
                } else {
                    if (DEBUG) {
                        Slog.w(TAG,
                                "sendPointerSync, Invalid connection or incorrect uid: " + Binder
                                        .getCallingUid());
                    }
                }
            }
        }
    }

    /**
     * Receives events from the connected provider.
     * <p>
     * This inner class is static and only retains a weak reference to the connection
     * to prevent the client from being leaked in case the service is holding an
     * active reference to the client's callback.
     * </p>
     */
    private static final class RemoteServiceInputProvider extends ITvRemoteServiceInput.Stub {
        private final WeakReference<Connection> mConnectionRef;

        public RemoteServiceInputProvider(Connection connection) {
            mConnectionRef = new WeakReference<Connection>(connection);
        }

        public void dispose() {
            // Terminate the connection.
            mConnectionRef.clear();
        }

        @Override
        public void openInputBridge(IBinder token, String name, int width,
                                    int height, int maxPointers) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.openInputBridge(token, name, width, height, maxPointers);
            }
        }

        @Override
        public void closeInputBridge(IBinder token) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.closeInputBridge(token);
            }
        }

        @Override
        public void clearInputBridge(IBinder token) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.clearInputBridge(token);
            }
        }

        @Override
        public void sendTimestamp(IBinder token, long timestamp) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.sendTimestamp(token, timestamp);
            }
        }

        @Override
        public void sendKeyDown(IBinder token, int keyCode) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.sendKeyDown(token, keyCode);
            }
        }

        @Override
        public void sendKeyUp(IBinder token, int keyCode) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.sendKeyUp(token, keyCode);
            }
        }

        @Override
        public void sendPointerDown(IBinder token, int pointerId, int x, int y)
                throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.sendPointerDown(token, pointerId, x, y);
            }
        }

        @Override
        public void sendPointerUp(IBinder token, int pointerId) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.sendPointerUp(token, pointerId);
            }
        }

        @Override
        public void sendPointerSync(IBinder token) throws RemoteException {
            Connection connection = mConnectionRef.get();
            if (connection != null) {
                connection.sendPointerSync(token);
            }
        }
    }
}
