/*
 * Copyright (C) 2014 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.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telecom.Log;
import android.text.TextUtils;
import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

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

/**
 * Abstract class to perform the work of binding and unbinding to the specified service interface.
 * Subclasses supply the service intent and component name and this class will invoke protected
 * methods when the class is bound, unbound, or upon failure.
 */
public abstract class ServiceBinder {

    /**
     * Callback to notify after a binding succeeds or fails.
     */
    interface BindCallback {
        void onSuccess();
        void onFailure();
    }

    /**
     * Listener for bind events on ServiceBinder.
     */
    interface Listener<ServiceBinderClass extends ServiceBinder> {
        void onUnbind(ServiceBinderClass serviceBinder);
    }

    /**
     * Helper class to perform on-demand binding.
     */
    final class Binder2 {
        /**
         * Performs an asynchronous bind to the service (only if not already bound) and executes the
         * specified callback.
         *
         * @param callback The callback to notify of the binding's success or failure.
         * @param call The call for which we are being bound.
         */
        void bind(BindCallback callback, Call call) {
            Log.d(ServiceBinder.this, "bind()");

            // Reset any abort request if we're asked to bind again.
            clearAbort();

            synchronized (mCallbacks) {
                if (!mCallbacks.isEmpty()) {
                    // Binding already in progress, append to the list of callbacks and bail out.
                    mCallbacks.add(callback);
                    return;
                }
                mCallbacks.add(callback);
            }

            if (mServiceConnection == null) {
                Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
                ServiceConnection connection = new ServiceBinderConnection(call);

                Log.addEvent(call, LogUtils.Events.BIND_CS, mComponentName);
                final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS;
                final boolean isBound;
                if (mUserHandle != null) {
                    isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags,
                            mUserHandle);
                } else {
                    isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
                }
                if (!isBound) {
                    handleFailedConnection();
                    return;
                }
            } else {
                Log.d(ServiceBinder.this, "Service is already bound.");
                Preconditions.checkNotNull(mBinder);
                handleSuccessfulConnection();
            }
        }
    }

    private class ServiceDeathRecipient implements IBinder.DeathRecipient {

        private ComponentName mComponentName;

        ServiceDeathRecipient(ComponentName name) {
            mComponentName = name;
        }

        @Override
        public void binderDied() {
            try {
                synchronized (mLock) {
                    Log.startSession("SDR.bD",
                            Log.getPackageAbbreviation(mComponentName));
                    Log.i(this, "binderDied: ConnectionService %s died.", mComponentName);
                    logServiceDisconnected("binderDied");
                    handleDisconnect();
                }
            } finally {
                Log.endSession();
            }
        }
    }

    private final class ServiceBinderConnection implements ServiceConnection {
        /**
         * The initial call for which the service was bound.
         */
        private Call mCall;

        ServiceBinderConnection(Call call) {
            mCall = call;
        }

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder binder) {
            try {
                Log.startSession("SBC.oSC", Log.getPackageAbbreviation(componentName));
                synchronized (mLock) {
                    Log.i(this, "Service bound %s", componentName);

                    Log.addEvent(mCall, LogUtils.Events.CS_BOUND, componentName);

                    // Unbind request was queued so unbind immediately.
                    if (mIsBindingAborted) {
                        clearAbort();
                        logServiceDisconnected("onServiceConnected");
                        mContext.unbindService(this);
                        handleFailedConnection();
                        return;
                    }
                    if (binder != null) {
                        mServiceDeathRecipient = new ServiceDeathRecipient(componentName);
                        try {
                            binder.linkToDeath(mServiceDeathRecipient, 0);
                            mServiceConnection = this;
                            setBinder(binder);
                            handleSuccessfulConnection();
                        } catch (RemoteException e) {
                            Log.w(this, "onServiceConnected: %s died.");
                            if (mServiceDeathRecipient != null) {
                                mServiceDeathRecipient.binderDied();
                            }
                        }
                    }
                }
            } finally {
                Log.endSession();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            try {
                Log.startSession("SBC.oSD", Log.getPackageAbbreviation(componentName));
                synchronized (mLock) {
                    logServiceDisconnected("onServiceDisconnected");
                    handleDisconnect();
                }
            } finally {
                Log.endSession();
            }
        }

        /**
         * Handles the case where the {@link ConnectionService} we bound to returned a null binding.
         * We want to unbind from the service and cleanup and call resources at this time.
         * @param componentName The component of the {@link ConnectionService}.
         */
        @Override
        public void onNullBinding(ComponentName componentName) {
            try {
                Log.startSession("SBC.oNB");
                synchronized (mLock) {
                    Log.w(this, "Null binding %s", componentName);
                    Log.addEvent(mCall, "NULL_BINDING", componentName);
                    String componentStr = componentName == null ? "null" : componentName.toString();
                    android.util.EventLog.writeEvent(0x534e4554, "211114016", -1, componentStr);
                    logServiceDisconnected("onNullBinding");
                    mContext.unbindService(this);
                    clearAbort();
                    handleFailedConnection();
                }
            } finally {
                Log.endSession();
            }
        }
    }

    private void handleDisconnect() {
        mServiceConnection = null;
        clearAbort();

        handleServiceDisconnected();
    }

    /** The application context. */
    private final Context mContext;

    /** The Telecom lock object. */
    protected final TelecomSystem.SyncRoot mLock;

    /** The intent action to use when binding through {@link Context#bindService}. */
    private final String mServiceAction;

    /** The component name of the service to bind to. */
    protected final ComponentName mComponentName;

    /**
     * Abbreviated form of the package name from {@link #mComponentName}; used for session logging.
     */
    protected final String mPackageAbbreviation;

    /** The set of callbacks waiting for notification of the binding's success or failure. */
    private final Set<BindCallback> mCallbacks = new ArraySet<>();

    /** Used to bind and unbind from the service. */
    private ServiceConnection mServiceConnection;

    /** Used to handle death of the service. */
    private ServiceDeathRecipient mServiceDeathRecipient;

    /** {@link UserHandle} to use for binding, to support work profiles and multi-user. */
    private UserHandle mUserHandle;

    /** The binder provided by {@link ServiceConnection#onServiceConnected} */
    private IBinder mBinder;

    private int mAssociatedCallCount = 0;

    /**
     * Indicates that an unbind request was made when the service was not yet bound. If the service
     * successfully connects when this is true, it should be unbound immediately.
     */
    private boolean mIsBindingAborted;

    /**
     * Set of currently registered listeners.
     * 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));

    /**
     * Persists the specified parameters and initializes the new instance.
     *
     * @param serviceAction The intent-action used with {@link Context#bindService}.
     * @param componentName The component name of the service with which to bind.
     * @param context The context.
     * @param userHandle The {@link UserHandle} to use for binding.
     */
    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context,
            TelecomSystem.SyncRoot lock, UserHandle userHandle) {
        Preconditions.checkState(!TextUtils.isEmpty(serviceAction));
        Preconditions.checkNotNull(componentName);

        mContext = context;
        mLock = lock;
        mServiceAction = serviceAction;
        mComponentName = componentName;
        mPackageAbbreviation = Log.getPackageAbbreviation(componentName);
        mUserHandle = userHandle;
    }

    final UserHandle getUserHandle() {
        return mUserHandle;
    }

    final void incrementAssociatedCallCount() {
        mAssociatedCallCount++;
        Log.v(this, "Call count increment %d, %s", mAssociatedCallCount,
                mComponentName.flattenToShortString());
    }

    final void decrementAssociatedCallCount() {
        decrementAssociatedCallCount(false /*isSuppressingUnbind*/);
    }

    final void decrementAssociatedCallCount(boolean isSuppressingUnbind) {
        if (mAssociatedCallCount > 0) {
            mAssociatedCallCount--;
            Log.v(this, "Call count decrement %d, %s", mAssociatedCallCount,
                    mComponentName.flattenToShortString());

            if (!isSuppressingUnbind && mAssociatedCallCount == 0) {
                unbind();
            }
        } else {
            Log.wtf(this, "%s: ignoring a request to decrement mAssociatedCallCount below zero",
                    mComponentName.getClassName());
        }
    }

    final int getAssociatedCallCount() {
        return mAssociatedCallCount;
    }

    /**
     * Unbinds from the service if already bound, no-op otherwise.
     */
    final void unbind() {
        if (mServiceConnection == null) {
            // We're not yet bound, so queue up an abort request.
            mIsBindingAborted = true;
        } else {
            logServiceDisconnected("unbind");
            unlinkDeathRecipient();
            mContext.unbindService(mServiceConnection);
            mServiceConnection = null;
            setBinder(null);
        }
    }

    public final ComponentName getComponentName() {
        return mComponentName;
    }

    @VisibleForTesting
    public boolean isServiceValid(String actionName) {
        if (mBinder == null) {
            Log.w(this, "%s invoked while service is unbound", actionName);
            return false;
        }

        return true;
    }

    final void addListener(Listener listener) {
        mListeners.add(listener);
    }

    final void removeListener(Listener listener) {
        if (listener != null) {
            mListeners.remove(listener);
        }
    }

    /**
     * Logs a standard message upon service disconnection. This method exists because there is no
     * single method called whenever the service unbinds and we want to log the same string in all
     * instances where that occurs.  (Context.unbindService() does not cause onServiceDisconnected
     * to execute).
     *
     * @param sourceTag Tag to disambiguate
     */
    private void logServiceDisconnected(String sourceTag) {
        Log.i(this, "Service unbound %s, from %s.", mComponentName, sourceTag);
    }

    /**
     * Notifies all the outstanding callbacks that the service is successfully bound. The list of
     * outstanding callbacks is cleared afterwards.
     */
    private void handleSuccessfulConnection() {
        // Make a copy so that we don't have a deadlock inside one of the callbacks.
        Set<BindCallback> callbacksCopy = new ArraySet<>();
        synchronized (mCallbacks) {
            callbacksCopy.addAll(mCallbacks);
            mCallbacks.clear();
        }

        for (BindCallback callback : callbacksCopy) {
            callback.onSuccess();
        }
    }

    /**
     * Notifies all the outstanding callbacks that the service failed to bind. The list of
     * outstanding callbacks is cleared afterwards.
     */
    private void handleFailedConnection() {
        // Make a copy so that we don't have a deadlock inside one of the callbacks.
        Set<BindCallback> callbacksCopy = new ArraySet<>();
        synchronized (mCallbacks) {
            callbacksCopy.addAll(mCallbacks);
            mCallbacks.clear();
        }

        for (BindCallback callback : callbacksCopy) {
            callback.onFailure();
        }
    }

    /**
     * Handles a service disconnection.
     */
    private void handleServiceDisconnected() {
        unlinkDeathRecipient();
        setBinder(null);
    }

    /**
     * Handles un-linking the death recipient from the service's binder.
     */
    private void unlinkDeathRecipient() {
        if (mServiceDeathRecipient != null && mBinder != null) {
            boolean unlinked = mBinder.unlinkToDeath(mServiceDeathRecipient, 0);
            if (!unlinked) {
                Log.i(this, "unlinkDeathRecipient: failed to unlink %s", mComponentName);
            }
            mServiceDeathRecipient = null;
        } else {
            Log.w(this, "unlinkDeathRecipient: death recipient is null.");
        }
    }

    private void clearAbort() {
        mIsBindingAborted = false;
    }

    /**
     * Sets the (private) binder and updates the child class.
     *
     * @param binder The new binder value.
     */
    private void setBinder(IBinder binder) {
        if (mBinder != binder) {
            if (binder == null) {
                removeServiceInterface();
                mBinder = null;
                for (Listener l : mListeners) {
                    l.onUnbind(this);
                }
            } else {
                mBinder = binder;
                setServiceInterface(binder);
            }
        }
    }

    /**
     * Sets the service interface after the service is bound.
     *
     * @param binder The new binder interface that is being set.
     */
    protected abstract void setServiceInterface(IBinder binder);

    /**
     * Removes the service interface before the service is unbound.
     */
    protected abstract void removeServiceInterface();
}
