/*
 * Copyright (C) 2017 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.backup.transport;

import static com.android.server.backup.transport.TransportUtils.formatMessage;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.EventLog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
import com.android.server.backup.TransportManager;
import com.android.server.backup.transport.TransportUtils.Priority;

import dalvik.system.CloseGuard;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * A {@link TransportClient} manages the connection to an {@link IBackupTransport} service, obtained
 * via the {@param bindIntent} parameter provided in the constructor. A {@link TransportClient} is
 * responsible for only one connection to the transport service, not more.
 *
 * <p>After retrieved using {@link TransportManager#getTransportClient(String, String)}, you can
 * call either {@link #connect(String)}, if you can block your thread, or {@link
 * #connectAsync(TransportConnectionListener, String)}, otherwise, to obtain a {@link
 * IBackupTransport} instance. It's meant to be passed around as a token to a connected transport.
 * When the connection is not needed anymore you should call {@link #unbind(String)} or indirectly
 * via {@link TransportManager#disposeOfTransportClient(TransportClient, String)}.
 *
 * <p>DO NOT forget to unbind otherwise there will be dangling connections floating around.
 *
 * <p>This class is thread-safe.
 *
 * @see TransportManager
 */
public class TransportClient {
    @VisibleForTesting static final String TAG = "TransportClient";
    private static final int LOG_BUFFER_SIZE = 5;

    private final @UserIdInt int mUserId;
    private final Context mContext;
    private final TransportStats mTransportStats;
    private final Intent mBindIntent;
    private final ServiceConnection mConnection;
    private final String mIdentifier;
    private final String mCreatorLogString;
    private final ComponentName mTransportComponent;
    private final Handler mListenerHandler;
    private final String mPrefixForLog;
    private final Object mStateLock = new Object();
    private final Object mLogBufferLock = new Object();
    private final CloseGuard mCloseGuard = CloseGuard.get();

    @GuardedBy("mLogBufferLock")
    private final List<String> mLogBuffer = new LinkedList<>();

    @GuardedBy("mStateLock")
    private final Map<TransportConnectionListener, String> mListeners = new ArrayMap<>();

    @GuardedBy("mStateLock")
    @State
    private int mState = State.IDLE;

    @GuardedBy("mStateLock")
    private volatile IBackupTransport mTransport;

    TransportClient(
            @UserIdInt int userId,
            Context context,
            TransportStats transportStats,
            Intent bindIntent,
            ComponentName transportComponent,
            String identifier,
            String caller) {
        this(
                userId,
                context,
                transportStats,
                bindIntent,
                transportComponent,
                identifier,
                caller,
                new Handler(Looper.getMainLooper()));
    }

    @VisibleForTesting
    TransportClient(
            @UserIdInt int userId,
            Context context,
            TransportStats transportStats,
            Intent bindIntent,
            ComponentName transportComponent,
            String identifier,
            String caller,
            Handler listenerHandler) {
        mUserId = userId;
        mContext = context;
        mTransportStats = transportStats;
        mTransportComponent = transportComponent;
        mBindIntent = bindIntent;
        mIdentifier = identifier;
        mCreatorLogString = caller;
        mListenerHandler = listenerHandler;
        mConnection = new TransportConnection(context, this);

        // For logging
        String classNameForLog = mTransportComponent.getShortClassName().replaceFirst(".*\\.", "");
        mPrefixForLog = classNameForLog + "#" + mIdentifier + ":";

        mCloseGuard.open("markAsDisposed");
    }

    public ComponentName getTransportComponent() {
        return mTransportComponent;
    }

    /**
     * Attempts to connect to the transport (if needed).
     *
     * <p>Note that being bound is not the same as connected. To be connected you also need to be
     * bound. You go from nothing to bound, then to bound and connected. To have a usable transport
     * binder instance you need to be connected. This method will attempt to connect and return an
     * usable transport binder regardless of the state of the object, it may already be connected,
     * or bound but not connected, not bound at all or even unusable.
     *
     * <p>So, a {@link Context#bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)} (or
     * one of its variants) can be called or not depending on the inner state. However, it won't be
     * called again if we're already bound. For example, if one was already requested but the
     * framework has not yet returned (meaning we're bound but still trying to connect) it won't
     * trigger another one, just piggyback on the original request.
     *
     * <p>It's guaranteed that you are going to get a call back to {@param listener} after this
     * call. However, the {@param IBackupTransport} parameter, the transport binder, is not
     * guaranteed to be non-null, or if it's non-null it's not guaranteed to be usable - i.e. it can
     * throw {@link DeadObjectException}s on method calls. You should check for both in your code.
     * The reasons for a null transport binder are:
     *
     * <ul>
     *   <li>Some code called {@link #unbind(String)} before you got a callback.
     *   <li>The framework had already called {@link
     *       ServiceConnection#onServiceDisconnected(ComponentName)} or {@link
     *       ServiceConnection#onBindingDied(ComponentName)} on this object's connection before.
     *       Check the documentation of those methods for when that happens.
     *   <li>The framework returns false for {@link Context#bindServiceAsUser(Intent,
     *       ServiceConnection, int, UserHandle)} (or one of its variants). Check documentation for
     *       when this happens.
     * </ul>
     *
     * For unusable transport binders check {@link DeadObjectException}.
     *
     * @param listener The listener that will be called with the (possibly null or unusable) {@link
     *     IBackupTransport} instance and this {@link TransportClient} object.
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. This
     *     should be a human-readable short string that is easily identifiable in the logs. Ideally
     *     TAG.methodName(), where TAG is the one used in logcat. In cases where this is is not very
     *     descriptive like MyHandler.handleMessage() you should put something that someone reading
     *     the code would understand, like MyHandler/MSG_FOO.
     * @see #connect(String)
     * @see DeadObjectException
     * @see ServiceConnection#onServiceConnected(ComponentName, IBinder)
     * @see ServiceConnection#onServiceDisconnected(ComponentName)
     * @see Context#bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)
     */
    public void connectAsync(TransportConnectionListener listener, String caller) {
        synchronized (mStateLock) {
            checkStateIntegrityLocked();

            switch (mState) {
                case State.UNUSABLE:
                    log(Priority.WARN, caller, "Async connect: UNUSABLE client");
                    notifyListener(listener, null, caller);
                    break;
                case State.IDLE:
                    boolean hasBound =
                            mContext.bindServiceAsUser(
                                    mBindIntent,
                                    mConnection,
                                    Context.BIND_AUTO_CREATE,
                                    UserHandle.of(mUserId));
                    if (hasBound) {
                        // We don't need to set a time-out because we are guaranteed to get a call
                        // back in ServiceConnection, either an onServiceConnected() or
                        // onBindingDied().
                        log(Priority.DEBUG, caller, "Async connect: service bound, connecting");
                        setStateLocked(State.BOUND_AND_CONNECTING, null);
                        mListeners.put(listener, caller);
                    } else {
                        log(Priority.ERROR, "Async connect: bindService returned false");
                        // mState remains State.IDLE
                        mContext.unbindService(mConnection);
                        notifyListener(listener, null, caller);
                    }
                    break;
                case State.BOUND_AND_CONNECTING:
                    log(
                            Priority.DEBUG,
                            caller,
                            "Async connect: already connecting, adding listener");
                    mListeners.put(listener, caller);
                    break;
                case State.CONNECTED:
                    log(Priority.DEBUG, caller, "Async connect: reusing transport");
                    notifyListener(listener, mTransport, caller);
                    break;
            }
        }
    }

    /**
     * Removes the transport binding.
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     */
    public void unbind(String caller) {
        synchronized (mStateLock) {
            checkStateIntegrityLocked();

            log(Priority.DEBUG, caller, "Unbind requested (was " + stateToString(mState) + ")");
            switch (mState) {
                case State.UNUSABLE:
                case State.IDLE:
                    break;
                case State.BOUND_AND_CONNECTING:
                    setStateLocked(State.IDLE, null);
                    // After unbindService() no calls back to mConnection
                    mContext.unbindService(mConnection);
                    notifyListenersAndClearLocked(null);
                    break;
                case State.CONNECTED:
                    setStateLocked(State.IDLE, null);
                    mContext.unbindService(mConnection);
                    break;
            }
        }
    }

    /** Marks this TransportClient as disposed, allowing it to be GC'ed without warnings. */
    public void markAsDisposed() {
        synchronized (mStateLock) {
            Preconditions.checkState(
                    mState < State.BOUND_AND_CONNECTING, "Can't mark as disposed if still bound");
            mCloseGuard.close();
        }
    }

    /**
     * Attempts to connect to the transport (if needed) and returns it.
     *
     * <p>Synchronous version of {@link #connectAsync(TransportConnectionListener, String)}. The
     * same observations about state are valid here. Also, what was said about the {@link
     * IBackupTransport} parameter of {@link TransportConnectionListener} now apply to the return
     * value of this method.
     *
     * <p>This is a potentially blocking operation, so be sure to call this carefully on the correct
     * threads. You can't call this from the process main-thread (it throws an exception if you do
     * so).
     *
     * <p>In most cases only the first call to this method will block, the following calls should
     * return instantly. However, this is not guaranteed.
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     * @return A {@link IBackupTransport} transport binder instance or null. If it's non-null it can
     *     still be unusable - throws {@link DeadObjectException} on method calls
     */
    @WorkerThread
    @Nullable
    public IBackupTransport connect(String caller) {
        // If called on the main-thread this could deadlock waiting because calls to
        // ServiceConnection are on the main-thread as well
        Preconditions.checkState(
                !Looper.getMainLooper().isCurrentThread(), "Can't call connect() on main thread");

        IBackupTransport transport = mTransport;
        if (transport != null) {
            log(Priority.DEBUG, caller, "Sync connect: reusing transport");
            return transport;
        }

        // If it's already UNUSABLE we return straight away, no need to go to main-thread
        synchronized (mStateLock) {
            if (mState == State.UNUSABLE) {
                log(Priority.WARN, caller, "Sync connect: UNUSABLE client");
                return null;
            }
        }

        CompletableFuture<IBackupTransport> transportFuture = new CompletableFuture<>();
        TransportConnectionListener requestListener =
                (requestedTransport, transportClient) ->
                        transportFuture.complete(requestedTransport);

        long requestTime = SystemClock.elapsedRealtime();
        log(Priority.DEBUG, caller, "Sync connect: calling async");
        connectAsync(requestListener, caller);

        try {
            transport = transportFuture.get();
            long time = SystemClock.elapsedRealtime() - requestTime;
            mTransportStats.registerConnectionTime(mTransportComponent, time);
            log(Priority.DEBUG, caller, String.format(Locale.US, "Connect took %d ms", time));
            return transport;
        } catch (InterruptedException | ExecutionException e) {
            String error = e.getClass().getSimpleName();
            log(Priority.ERROR, caller, error + " while waiting for transport: " + e.getMessage());
            return null;
        }
    }

    /**
     * Tries to connect to the transport, if it fails throws {@link TransportNotAvailableException}.
     *
     * <p>Same as {@link #connect(String)} except it throws instead of returning null.
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     * @return A {@link IBackupTransport} transport binder instance.
     * @see #connect(String)
     * @throws TransportNotAvailableException if connection attempt fails.
     */
    @WorkerThread
    public IBackupTransport connectOrThrow(String caller) throws TransportNotAvailableException {
        IBackupTransport transport = connect(caller);
        if (transport == null) {
            log(Priority.ERROR, caller, "Transport connection failed");
            throw new TransportNotAvailableException();
        }
        return transport;
    }

    /**
     * If the {@link TransportClient} is already connected to the transport, returns the transport,
     * otherwise throws {@link TransportNotAvailableException}.
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     * @return A {@link IBackupTransport} transport binder instance.
     * @throws TransportNotAvailableException if not connected.
     */
    public IBackupTransport getConnectedTransport(String caller)
            throws TransportNotAvailableException {
        IBackupTransport transport = mTransport;
        if (transport == null) {
            log(Priority.ERROR, caller, "Transport not connected");
            throw new TransportNotAvailableException();
        }
        return transport;
    }

    @Override
    public String toString() {
        return "TransportClient{"
                + mTransportComponent.flattenToShortString()
                + "#"
                + mIdentifier
                + "}";
    }

    @Override
    protected void finalize() throws Throwable {
        synchronized (mStateLock) {
            mCloseGuard.warnIfOpen();
            if (mState >= State.BOUND_AND_CONNECTING) {
                String callerLogString = "TransportClient.finalize()";
                log(
                        Priority.ERROR,
                        callerLogString,
                        "Dangling TransportClient created in [" + mCreatorLogString + "] being "
                                + "GC'ed. Left bound, unbinding...");
                try {
                    unbind(callerLogString);
                } catch (IllegalStateException e) {
                    // May throw because there may be a race between this method being called and
                    // the framework calling any method on the connection with the weak reference
                    // there already cleared. In this case the connection will unbind before this
                    // is called. This is fine.
                }
            }
        }
    }

    private void onServiceConnected(IBinder binder) {
        IBackupTransport transport = IBackupTransport.Stub.asInterface(binder);
        synchronized (mStateLock) {
            checkStateIntegrityLocked();

            if (mState != State.UNUSABLE) {
                log(Priority.DEBUG, "Transport connected");
                setStateLocked(State.CONNECTED, transport);
                notifyListenersAndClearLocked(transport);
            }
        }
    }

    /**
     * If we are called here the TransportClient becomes UNUSABLE. After one of these calls, if a
     * binding happen again the new service can be a different instance. Since transports are
     * stateful, we don't want a new instance responding for an old instance's state.
     */
    private void onServiceDisconnected() {
        synchronized (mStateLock) {
            log(Priority.ERROR, "Service disconnected: client UNUSABLE");
            setStateLocked(State.UNUSABLE, null);
            try {
                // After unbindService() no calls back to mConnection
                mContext.unbindService(mConnection);
            } catch (IllegalArgumentException e) {
                // TODO: Investigate why this is happening
                // We're UNUSABLE, so any calls to mConnection will be no-op, so it's safe to
                // swallow this one
                log(
                        Priority.WARN,
                        "Exception trying to unbind onServiceDisconnected(): " + e.getMessage());
            }
        }
    }

    /**
     * If we are called here the TransportClient becomes UNUSABLE for the same reason as in {@link
     * #onServiceDisconnected()}.
     */
    private void onBindingDied() {
        synchronized (mStateLock) {
            checkStateIntegrityLocked();

            log(Priority.ERROR, "Binding died: client UNUSABLE");
            // After unbindService() no calls back to mConnection
            switch (mState) {
                case State.UNUSABLE:
                    break;
                case State.IDLE:
                    log(Priority.ERROR, "Unexpected state transition IDLE => UNUSABLE");
                    setStateLocked(State.UNUSABLE, null);
                    break;
                case State.BOUND_AND_CONNECTING:
                    setStateLocked(State.UNUSABLE, null);
                    mContext.unbindService(mConnection);
                    notifyListenersAndClearLocked(null);
                    break;
                case State.CONNECTED:
                    setStateLocked(State.UNUSABLE, null);
                    mContext.unbindService(mConnection);
                    break;
            }
        }
    }

    private void notifyListener(
            TransportConnectionListener listener,
            @Nullable IBackupTransport transport,
            String caller) {
        String transportString = (transport != null) ? "IBackupTransport" : "null";
        log(Priority.INFO, "Notifying [" + caller + "] transport = " + transportString);
        mListenerHandler.post(() -> listener.onTransportConnectionResult(transport, this));
    }

    @GuardedBy("mStateLock")
    private void notifyListenersAndClearLocked(@Nullable IBackupTransport transport) {
        for (Map.Entry<TransportConnectionListener, String> entry : mListeners.entrySet()) {
            TransportConnectionListener listener = entry.getKey();
            String caller = entry.getValue();
            notifyListener(listener, transport, caller);
        }
        mListeners.clear();
    }

    @GuardedBy("mStateLock")
    private void setStateLocked(@State int state, @Nullable IBackupTransport transport) {
        log(Priority.VERBOSE, "State: " + stateToString(mState) + " => " + stateToString(state));
        onStateTransition(mState, state);
        mState = state;
        mTransport = transport;
    }

    private void onStateTransition(int oldState, int newState) {
        String transport = mTransportComponent.flattenToShortString();
        int bound = transitionThroughState(oldState, newState, State.BOUND_AND_CONNECTING);
        int connected = transitionThroughState(oldState, newState, State.CONNECTED);
        if (bound != Transition.NO_TRANSITION) {
            int value = (bound == Transition.UP) ? 1 : 0; // 1 is bound, 0 is not bound
            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, transport, value);
        }
        if (connected != Transition.NO_TRANSITION) {
            int value = (connected == Transition.UP) ? 1 : 0; // 1 is connected, 0 is not connected
            EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_CONNECTION, transport, value);
        }
    }

    /**
     * Returns:
     *
     * <ul>
     *   <li>{@link Transition#UP}, if oldState < stateReference <= newState
     *   <li>{@link Transition#DOWN}, if oldState >= stateReference > newState
     *   <li>{@link Transition#NO_TRANSITION}, otherwise
     */
    @Transition
    private int transitionThroughState(
            @State int oldState, @State int newState, @State int stateReference) {
        if (oldState < stateReference && stateReference <= newState) {
            return Transition.UP;
        }
        if (oldState >= stateReference && stateReference > newState) {
            return Transition.DOWN;
        }
        return Transition.NO_TRANSITION;
    }

    @GuardedBy("mStateLock")
    private void checkStateIntegrityLocked() {
        switch (mState) {
            case State.UNUSABLE:
                checkState(mListeners.isEmpty(), "Unexpected listeners when state = UNUSABLE");
                checkState(
                        mTransport == null, "Transport expected to be null when state = UNUSABLE");
            case State.IDLE:
                checkState(mListeners.isEmpty(), "Unexpected listeners when state = IDLE");
                checkState(mTransport == null, "Transport expected to be null when state = IDLE");
                break;
            case State.BOUND_AND_CONNECTING:
                checkState(
                        mTransport == null,
                        "Transport expected to be null when state = BOUND_AND_CONNECTING");
                break;
            case State.CONNECTED:
                checkState(mListeners.isEmpty(), "Unexpected listeners when state = CONNECTED");
                checkState(
                        mTransport != null,
                        "Transport expected to be non-null when state = CONNECTED");
                break;
            default:
                checkState(false, "Unexpected state = " + stateToString(mState));
        }
    }

    private void checkState(boolean assertion, String message) {
        if (!assertion) {
            log(Priority.ERROR, message);
        }
    }

    private String stateToString(@State int state) {
        switch (state) {
            case State.UNUSABLE:
                return "UNUSABLE";
            case State.IDLE:
                return "IDLE";
            case State.BOUND_AND_CONNECTING:
                return "BOUND_AND_CONNECTING";
            case State.CONNECTED:
                return "CONNECTED";
            default:
                return "<UNKNOWN = " + state + ">";
        }
    }

    private void log(int priority, String message) {
        TransportUtils.log(priority, TAG, formatMessage(mPrefixForLog, null, message));
        saveLogEntry(formatMessage(null, null, message));
    }

    private void log(int priority, String caller, String message) {
        TransportUtils.log(priority, TAG, formatMessage(mPrefixForLog, caller, message));
        saveLogEntry(formatMessage(null, caller, message));
    }

    private void saveLogEntry(String message) {
        CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
        message = time + " " + message;
        synchronized (mLogBufferLock) {
            if (mLogBuffer.size() == LOG_BUFFER_SIZE) {
                mLogBuffer.remove(mLogBuffer.size() - 1);
            }
            mLogBuffer.add(0, message);
        }
    }

    List<String> getLogBuffer() {
        synchronized (mLogBufferLock) {
            return Collections.unmodifiableList(mLogBuffer);
        }
    }

    @IntDef({Transition.DOWN, Transition.NO_TRANSITION, Transition.UP})
    @Retention(RetentionPolicy.SOURCE)
    private @interface Transition {
        int DOWN = -1;
        int NO_TRANSITION = 0;
        int UP = 1;
    }

    @IntDef({State.UNUSABLE, State.IDLE, State.BOUND_AND_CONNECTING, State.CONNECTED})
    @Retention(RetentionPolicy.SOURCE)
    private @interface State {
        // Constant values MUST be in order
        int UNUSABLE = 0;
        int IDLE = 1;
        int BOUND_AND_CONNECTING = 2;
        int CONNECTED = 3;
    }

    /**
     * This class is a proxy to TransportClient methods that doesn't hold a strong reference to the
     * TransportClient, allowing it to be GC'ed. If the reference was lost it logs a message.
     */
    private static class TransportConnection implements ServiceConnection {
        private final Context mContext;
        private final WeakReference<TransportClient> mTransportClientRef;

        private TransportConnection(Context context, TransportClient transportClient) {
            mContext = context;
            mTransportClientRef = new WeakReference<>(transportClient);
        }

        @Override
        public void onServiceConnected(ComponentName transportComponent, IBinder binder) {
            TransportClient transportClient = mTransportClientRef.get();
            if (transportClient == null) {
                referenceLost("TransportConnection.onServiceConnected()");
                return;
            }
            // TODO (b/147705255): Remove when binder calls to IBackupTransport are not blocking
            // In short-term, blocking calls are OK as the transports come from the whitelist at
            // {@link SystemConfig#getBackupTransportWhitelist()}
            Binder.allowBlocking(binder);
            transportClient.onServiceConnected(binder);
        }

        @Override
        public void onServiceDisconnected(ComponentName transportComponent) {
            TransportClient transportClient = mTransportClientRef.get();
            if (transportClient == null) {
                referenceLost("TransportConnection.onServiceDisconnected()");
                return;
            }
            transportClient.onServiceDisconnected();
        }

        @Override
        public void onBindingDied(ComponentName transportComponent) {
            TransportClient transportClient = mTransportClientRef.get();
            if (transportClient == null) {
                referenceLost("TransportConnection.onBindingDied()");
                return;
            }
            transportClient.onBindingDied();
        }

        /** @see TransportClient#finalize() */
        private void referenceLost(String caller) {
            mContext.unbindService(this);
            TransportUtils.log(
                    Priority.INFO,
                    TAG,
                    caller + " called but TransportClient reference has been GC'ed");
        }
    }
}
