/*
 * Copyright (C) 2018 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.internal.infra;

import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.IInterface;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Slog;
import android.util.TimeUtils;

import com.android.internal.annotations.GuardedBy;

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

/**
 * Base class representing a remote service.
 *
 * <p>It abstracts away the binding and unbinding from the remote implementation, so clients can
 * call its methods without worrying about when and how to bind/unbind/timeout.
 *
 * <p>All state of this class is modified on a handler thread.
 *
 * <p><b>NOTE: </b>this class should not be extended directly, you should extend either
 * {@link AbstractSinglePendingRequestRemoteService} or
 * {@link AbstractMultiplePendingRequestsRemoteService}.
 *
 * <p>See {@code com.android.server.autofill.RemoteFillService} for a concrete
 * (no pun intended) example of how to use it.
 *
 * @param <S> the concrete remote service class
 * @param <I> the interface of the binder service
 *
 * @deprecated Use {@link ServiceConnector} to manage remote service connections
 *
 * @hide
 */
//TODO(b/117779333): improve javadoc above instead of using Autofill as an example
@Deprecated
public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I>,
        I extends IInterface> implements DeathRecipient {
    private static final int MSG_BIND = 1;
    private static final int MSG_UNBIND = 2;

    public static final long PERMANENT_BOUND_TIMEOUT_MS = 0;

    protected static final int LAST_PRIVATE_MSG = MSG_UNBIND;

    // TODO(b/117779333): convert all booleans into an integer / flags
    public final boolean mVerbose;

    protected final String mTag = getClass().getSimpleName();
    protected final Handler mHandler;
    protected final ComponentName mComponentName;

    private final Context mContext;
    private final Intent mIntent;
    private final VultureCallback<S> mVultureCallback;
    private final int mUserId;
    private final ServiceConnection mServiceConnection = new RemoteServiceConnection();
    private final int mBindingFlags;
    protected I mService;

    private boolean mConnecting;
    private boolean mDestroyed;
    private boolean mServiceDied;
    private boolean mCompleted;

    // Used just for debugging purposes (on dump)
    private long mNextUnbind;

    /** Requests that have been scheduled, but that are not finished yet */
    private final ArrayList<BasePendingRequest<S, I>> mUnfinishedRequests = new ArrayList<>();

    /**
     * Callback called when the service dies.
     *
     * @param <T> service class
     */
    public interface VultureCallback<T> {
        /**
         * Called when the service dies.
         *
         * @param service service that died!
         */
        void onServiceDied(T service);
    }

    // NOTE: must be package-protected so this class is not extended outside
    AbstractRemoteService(@NonNull Context context, @NonNull String serviceInterface,
            @NonNull ComponentName componentName, int userId, @NonNull VultureCallback<S> callback,
            @NonNull Handler handler, int bindingFlags, boolean verbose) {
        mContext = context;
        mVultureCallback = callback;
        mVerbose = verbose;
        mComponentName = componentName;
        mIntent = new Intent(serviceInterface).setComponent(mComponentName);
        mUserId = userId;
        mHandler = new Handler(handler.getLooper());
        mBindingFlags = bindingFlags;
    }

    /**
     * Destroys this service.
     */
    public final void destroy() {
        mHandler.sendMessage(obtainMessage(AbstractRemoteService::handleDestroy, this));
    }

    /**
     * Checks whether this service is destroyed.
     */
    public final boolean isDestroyed() {
        return mDestroyed;
    }

    /**
     * Gets the name of the service.
     */
    @NonNull
    public final ComponentName getComponentName() {
        return mComponentName;
    }

    private void handleOnConnectedStateChangedInternal(boolean connected) {
        handleOnConnectedStateChanged(connected);
        if (connected) {
            handlePendingRequests();
        }
    }

    /**
     * Handles the pending requests when the connection it bounds to the remote service.
     */
    abstract void handlePendingRequests();

    /**
     * Callback called when the system connected / disconnected to the service and the pending
     * requests have been handled.
     *
     * @param state {@code true} when connected, {@code false} when disconnected.
     */
    protected void handleOnConnectedStateChanged(boolean state) {
    }

    /**
     * Gets the base Binder interface from the service.
     */
    @NonNull
    protected abstract I getServiceInterface(@NonNull IBinder service);

    /**
     * Defines how long after the last interaction with the service we would unbind.
     *
     * @return time to unbind (in millis), or {@link #PERMANENT_BOUND_TIMEOUT_MS} to not unbind.
     */
    protected abstract long getTimeoutIdleBindMillis();

    /**
     * Defines how long after we make a remote request to a fill service we timeout.
     *
     * <p>Just need to be overridden by subclasses that uses sync {@link PendingRequest}s.
     *
     * @throws UnsupportedOperationException if called when not overridden.
     *
     */
    protected long getRemoteRequestMillis() {
        throw new UnsupportedOperationException("not implemented by " + getClass());
    }

    /**
     * Gets the currently registered service interface or {@code null} if the service is not
     * connected.
     */
    @Nullable
    public final I getServiceInterface() {
        return mService;
    }

    private void handleDestroy() {
        if (checkIfDestroyed()) return;
        handleOnDestroy();
        handleEnsureUnbound();
        mDestroyed = true;
    }

    /**
     * Clears the state when this object is destroyed.
     *
     * <p>Typically used to cancel the pending requests.
     */
    protected abstract void handleOnDestroy();

    @Override // from DeathRecipient
    public void binderDied() {
        mHandler.sendMessage(obtainMessage(AbstractRemoteService::handleBinderDied, this));
    }

    private void handleBinderDied() {
        if (checkIfDestroyed()) return;
        if (mService != null) {
            mService.asBinder().unlinkToDeath(this, 0);
        }
        mConnecting = true;
        mService = null;
        mServiceDied = true;
        cancelScheduledUnbind();
        @SuppressWarnings("unchecked") // TODO(b/117779333): fix this warning
        final S castService = (S) this;
        mVultureCallback.onServiceDied(castService);
        handleBindFailure();
    }

    // Note: we are dumping without a lock held so this is a bit racy but
    // adding a lock to a class that offloads to a handler thread would
    // mean adding a lock adding overhead to normal runtime operation.
    /**
     * Dump it!
     */
    public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
        String tab = "  ";
        pw.append(prefix).append("service:").println();
        pw.append(prefix).append(tab).append("userId=")
                .append(String.valueOf(mUserId)).println();
        pw.append(prefix).append(tab).append("componentName=")
                .append(mComponentName.flattenToString()).println();
        pw.append(prefix).append(tab).append("destroyed=")
                .append(String.valueOf(mDestroyed)).println();
        pw.append(prefix).append(tab).append("numUnfinishedRequests=")
                .append(String.valueOf(mUnfinishedRequests.size())).println();
        final boolean bound = handleIsBound();
        pw.append(prefix).append(tab).append("bound=")
                .append(String.valueOf(bound));
        final long idleTimeout = getTimeoutIdleBindMillis();
        if (bound) {
            if (idleTimeout > 0) {
                pw.append(" (unbind in : ");
                TimeUtils.formatDuration(mNextUnbind - SystemClock.elapsedRealtime(), pw);
                pw.append(")");
            } else {
                pw.append(" (permanently bound)");
            }
        }
        pw.println();
        pw.append(prefix).append("mBindingFlags=").println(mBindingFlags);
        pw.append(prefix).append("idleTimeout=")
            .append(Long.toString(idleTimeout / 1000)).append("s\n");
        pw.append(prefix).append("requestTimeout=");
        try {
            pw.append(Long.toString(getRemoteRequestMillis() / 1000)).append("s\n");
        } catch (UnsupportedOperationException e) {
            pw.append("not supported\n");
        }
        pw.println();
    }

    /**
     * Schedules a "sync" request.
     *
     * <p>This request must be responded by the service somehow (typically using a callback),
     * othewise it will trigger a {@link PendingRequest#onTimeout(AbstractRemoteService)} if the
     * service doesn't respond.
     */
    protected void scheduleRequest(@NonNull BasePendingRequest<S, I> pendingRequest) {
        mHandler.sendMessage(obtainMessage(
                AbstractRemoteService::handlePendingRequest, this, pendingRequest));
    }

    /**
     * Marks a pendingRequest as finished.
     *
     * @param finshedRequest The request that is finished
     */
    void finishRequest(@NonNull BasePendingRequest<S, I> finshedRequest) {
        mHandler.sendMessage(
                obtainMessage(AbstractRemoteService::handleFinishRequest, this, finshedRequest));
    }

    private void handleFinishRequest(@NonNull BasePendingRequest<S, I> finshedRequest) {
        mUnfinishedRequests.remove(finshedRequest);

        if (mUnfinishedRequests.isEmpty()) {
            scheduleUnbind();
        }
    }

    /**
     * Schedules an async request.
     *
     * <p>This request is not expecting a callback from the service, hence it's represented by
     * a simple {@link Runnable}.
     */
    protected void scheduleAsyncRequest(@NonNull AsyncRequest<I> request) {
        // TODO(b/117779333): fix generics below
        @SuppressWarnings({"unchecked", "rawtypes"})
        final MyAsyncPendingRequest<S, I> asyncRequest = new MyAsyncPendingRequest(this, request);
        mHandler.sendMessage(
                obtainMessage(AbstractRemoteService::handlePendingRequest, this, asyncRequest));
    }

    /**
     * Executes an async request immediately instead of sending it to Handler queue as what
     * {@link scheduleAsyncRequest} does.
     *
     * <p>This request is not expecting a callback from the service, hence it's represented by
     * a simple {@link Runnable}.
     */
    protected void executeAsyncRequest(@NonNull AsyncRequest<I> request) {
        // TODO(b/117779333): fix generics below
        @SuppressWarnings({"unchecked", "rawtypes"})
        final MyAsyncPendingRequest<S, I> asyncRequest = new MyAsyncPendingRequest(this, request);
        handlePendingRequest(asyncRequest);
    }

    private void cancelScheduledUnbind() {
        mHandler.removeMessages(MSG_UNBIND);
    }

    /**
     * Schedules a request to bind to the remote service.
     *
     * <p>Typically used on constructor for implementations that need a permanent connection to
     * the remote service.
     */
    protected void scheduleBind() {
        if (mHandler.hasMessages(MSG_BIND)) {
            if (mVerbose) Slog.v(mTag, "scheduleBind(): already scheduled");
            return;
        }
        mHandler.sendMessage(obtainMessage(AbstractRemoteService::handleEnsureBound, this)
                .setWhat(MSG_BIND));
    }

    /**
     * Schedules a request to automatically unbind from the service after the
     * {@link #getTimeoutIdleBindMillis() idle timeout} expires.
     */
    protected void scheduleUnbind() {
        scheduleUnbind(true);
    }

    private void scheduleUnbind(boolean delay) {
        long unbindDelay = getTimeoutIdleBindMillis();

        if (unbindDelay <= PERMANENT_BOUND_TIMEOUT_MS) {
            if (mVerbose) Slog.v(mTag, "not scheduling unbind when value is " + unbindDelay);
            return;
        }

        if (!delay) {
            unbindDelay = 0;
        }

        cancelScheduledUnbind();
        // TODO(b/117779333): make sure it's unbound if the service settings changing (right now
        // it's not)

        mNextUnbind = SystemClock.elapsedRealtime() + unbindDelay;
        if (mVerbose) Slog.v(mTag, "unbinding in " + unbindDelay + "ms: " + mNextUnbind);
        mHandler.sendMessageDelayed(obtainMessage(AbstractRemoteService::handleUnbind, this)
                .setWhat(MSG_UNBIND), unbindDelay);
    }

    private void handleUnbind() {
        if (checkIfDestroyed()) return;

        handleEnsureUnbound();
    }

    /**
     * Handles a request, either processing it right now when bound, or saving it to be handled when
     * bound.
     */
    protected final void handlePendingRequest(@NonNull BasePendingRequest<S, I> pendingRequest) {
        if (checkIfDestroyed() || mCompleted) return;

        if (!handleIsBound()) {
            if (mVerbose) Slog.v(mTag, "handlePendingRequest(): queuing " + pendingRequest);
            handlePendingRequestWhileUnBound(pendingRequest);
            handleEnsureBound();
        } else {
            if (mVerbose) Slog.v(mTag, "handlePendingRequest(): " + pendingRequest);

            mUnfinishedRequests.add(pendingRequest);
            cancelScheduledUnbind();

            pendingRequest.run();
            if (pendingRequest.isFinal()) {
                mCompleted = true;
            }
        }
    }

    /**
     * Defines what to do with a request that arrives while not bound to the service.
     */
    abstract void handlePendingRequestWhileUnBound(
            @NonNull BasePendingRequest<S, I> pendingRequest);

    /**
     * Called if {@link Context#bindServiceAsUser} returns {@code false}, or
     * if {@link DeathRecipient#binderDied()} is called.
     */
    abstract void handleBindFailure();

    private boolean handleIsBound() {
        return mService != null;
    }

    private void handleEnsureBound() {
        if (handleIsBound() || mConnecting) return;

        if (mVerbose) Slog.v(mTag, "ensureBound()");
        mConnecting = true;

        final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                | Context.BIND_INCLUDE_CAPABILITIES | mBindingFlags;

        final boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags,
                mHandler, new UserHandle(mUserId));

        if (!willBind) {
            Slog.w(mTag, "could not bind to " + mIntent + " using flags " + flags);
            mConnecting = false;

            if (!mServiceDied) {
                handleBinderDied();
            }
        }
    }

    private void handleEnsureUnbound() {
        if (!handleIsBound() && !mConnecting) return;

        if (mVerbose) Slog.v(mTag, "ensureUnbound()");
        mConnecting = false;
        if (handleIsBound()) {
            handleOnConnectedStateChangedInternal(false);
            if (mService != null) {
                mService.asBinder().unlinkToDeath(this, 0);
                mService = null;
            }
        }
        mNextUnbind = 0;
        mContext.unbindService(mServiceConnection);
    }

    private class RemoteServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (mVerbose) Slog.v(mTag, "onServiceConnected()");
            if (mDestroyed || !mConnecting) {
                // This is abnormal. Unbinding the connection has been requested already.
                Slog.wtf(mTag, "onServiceConnected() was dispatched after unbindService.");
                return;
            }
            mConnecting = false;
            try {
                service.linkToDeath(AbstractRemoteService.this, 0);
            } catch (RemoteException re) {
                handleBinderDied();
                return;
            }
            mService = getServiceInterface(service);
            handleOnConnectedStateChangedInternal(true);
            mServiceDied = false;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (mVerbose) Slog.v(mTag, "onServiceDisconnected()");
            mConnecting = true;
            mService = null;
        }

        @Override
        public void onBindingDied(ComponentName name) {
            if (mVerbose) Slog.v(mTag, "onBindingDied()");
            scheduleUnbind(false);
        }
    }

    private boolean checkIfDestroyed() {
        if (mDestroyed) {
            if (mVerbose) {
                Slog.v(mTag, "Not handling operation as service for " + mComponentName
                        + " is already destroyed");
            }
        }
        return mDestroyed;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "[" + mComponentName
                + " " + System.identityHashCode(this)
                + (mService != null ? " (bound)" : " (unbound)")
                + (mDestroyed ? " (destroyed)" : "")
                + "]";
    }

    /**
     * Base class for the requests serviced by the remote service.
     *
     * <p><b>NOTE: </b> this class is not used directly, you should either override
     * {@link com.android.internal.infra.AbstractRemoteService.PendingRequest} for sync requests, or
     * use {@link AbstractRemoteService#scheduleAsyncRequest(AsyncRequest)} for async requests.
     *
     * @param <S> the remote service class
     * @param <I> the interface of the binder service
     */
    public abstract static class BasePendingRequest<S extends AbstractRemoteService<S, I>,
            I extends IInterface> implements Runnable {
        protected final String mTag = getClass().getSimpleName();
        protected final Object mLock = new Object();

        final WeakReference<S> mWeakService;

        @GuardedBy("mLock")
        boolean mCancelled;

        @GuardedBy("mLock")
        boolean mCompleted;

        BasePendingRequest(@NonNull S service) {
            mWeakService = new WeakReference<>(service);
        }

        /**
         * Gets a reference to the remote service.
         */
        protected final S getService() {
            return mWeakService.get();
        }

        /**
         * Subclasses must call this method when the remote service finishes, i.e., when the service
         * finishes processing a request.
         *
         * @return {@code false} in the service is already finished, {@code true} otherwise.
         */
        protected final boolean finish() {
            synchronized (mLock) {
                if (mCompleted || mCancelled) {
                    return false;
                }
                mCompleted = true;
            }

            S service = mWeakService.get();
            if (service != null) {
                service.finishRequest(this);
            }

            onFinished();

            return true;
        }

        void onFinished() { }

        /**
         * Called when request fails due to reasons internal to {@link AbstractRemoteService},
         * e.g. failure to bind to service.
         */
        protected void onFailed() { }

        /**
         * Checks whether this request was cancelled.
         */
        @GuardedBy("mLock")
        protected final boolean isCancelledLocked() {
            return mCancelled;
        }

        /**
         * Cancels the service.
         *
         * @return {@code false} if service is already canceled, {@code true} otherwise.
         */
        public boolean cancel() {
            synchronized (mLock) {
                if (mCancelled || mCompleted) {
                    return false;
                }
                mCancelled = true;
            }

            onCancel();
            return true;
        }

        void onCancel() {}

        /**
         * Checks whether this request leads to a final state where no other requests can be made.
         */
        protected boolean isFinal() {
            return false;
        }

        protected boolean isRequestCompleted() {
            synchronized (mLock) {
                return mCompleted;
            }
        }
    }

    /**
     * Base class for the requests serviced by the remote service.
     *
     * <p><b>NOTE: </b> this class is typically used when the service needs to use a callback to
     * communicate back with the system server. For cases where that's not needed, you should use
     * {@link AbstractRemoteService#scheduleAsyncRequest(AsyncRequest)} instead.
     *
     * <p><b>NOTE: </b> you must override {@link AbstractRemoteService#getRemoteRequestMillis()},
     * otherwise the constructor will throw an {@link UnsupportedOperationException}.
     *
     * @param <S> the remote service class
     * @param <I> the interface of the binder service
     */
    public abstract static class PendingRequest<S extends AbstractRemoteService<S, I>,
            I extends IInterface> extends BasePendingRequest<S, I> {

        private final Runnable mTimeoutTrigger;
        private final Handler mServiceHandler;

        protected PendingRequest(S service) {
            super(service);
            mServiceHandler = service.mHandler;

            mTimeoutTrigger = () -> {
                synchronized (mLock) {
                    if (mCancelled) {
                        return;
                    }
                    mCompleted = true;
                }

                final S remoteService = mWeakService.get();
                if (remoteService != null) {
                    // TODO(b/117779333): we should probably ignore it if service is destroyed.
                    Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
                    remoteService.finishRequest(this);
                    onTimeout(remoteService);
                } else {
                    Slog.w(mTag, "timed out (no service)");
                }
            };
            mServiceHandler.postAtTime(mTimeoutTrigger,
                    SystemClock.uptimeMillis() + service.getRemoteRequestMillis());
        }

        @Override
        final void onFinished() {
            mServiceHandler.removeCallbacks(mTimeoutTrigger);
        }

        @Override
        final void onCancel() {
            mServiceHandler.removeCallbacks(mTimeoutTrigger);
        }

        /**
         * Called by the self-destruct timeout when the remote service didn't reply to the
         * request on time.
         */
        protected abstract void onTimeout(S remoteService);
    }

    /**
     * Represents a request that does not expect a callback from the remote service.
     *
     * @param <I> the interface of the binder service
     */
    public interface AsyncRequest<I extends IInterface> {

        /**
         * Run Forrest, run!
         */
        void run(@NonNull I binder) throws RemoteException;
    }

    private static final class MyAsyncPendingRequest<S extends AbstractRemoteService<S, I>,
            I extends IInterface> extends BasePendingRequest<S, I> {
        private static final String TAG = MyAsyncPendingRequest.class.getSimpleName();

        private final AsyncRequest<I> mRequest;

        protected MyAsyncPendingRequest(@NonNull S service, @NonNull AsyncRequest<I> request) {
            super(service);

            mRequest = request;
        }

        @Override
        public void run() {
            final S remoteService = getService();
            if (remoteService == null) return;
            try {
                mRequest.run(remoteService.mService);
            } catch (RemoteException e) {
                Slog.w(TAG, "exception handling async request (" + this + "): " + e);
            } finally {
                finish();
            }
        }
    }
}
