/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.pm;

import android.annotation.AnyThread;
import android.annotation.WorkerThread;
import android.app.IInstantAppResolver;
import android.app.InstantAppResolverService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.InstantAppResolveInfo;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Slog;
import android.util.TimedRemoteCaller;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeoutException;

/**
 * Represents a remote instant app resolver. It is responsible for binding to the remote
 * service and handling all interactions in a timely manner.
 * @hide
 */
final class InstantAppResolverConnection implements DeathRecipient {
    private static final String TAG = "PackageManager";
    // This is running in a critical section and the timeout must be sufficiently low
    private static final long BIND_SERVICE_TIMEOUT_MS =
            Build.IS_ENG ? 500 : 300;
    private static final long CALL_SERVICE_TIMEOUT_MS =
            Build.IS_ENG ? 200 : 100;
    private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;

    private final Object mLock = new Object();
    private final GetInstantAppResolveInfoCaller mGetInstantAppResolveInfoCaller =
            new GetInstantAppResolveInfoCaller();
    private final ServiceConnection mServiceConnection = new MyServiceConnection();
    private final Context mContext;
    /** Intent used to bind to the service */
    private final Intent mIntent;

    private static final int STATE_IDLE    = 0; // no bind operation is ongoing
    private static final int STATE_BINDING = 1; // someone is binding and waiting
    private static final int STATE_PENDING = 2; // a bind is pending, but the caller is not waiting
    private final Handler mBgHandler;

    @GuardedBy("mLock")
    private int mBindState = STATE_IDLE;
    @GuardedBy("mLock")
    private IInstantAppResolver mRemoteInstance;

    public InstantAppResolverConnection(
            Context context, ComponentName componentName, String action) {
        mContext = context;
        mIntent = new Intent(action).setComponent(componentName);
        mBgHandler = BackgroundThread.getHandler();
    }

    public List<InstantAppResolveInfo> getInstantAppResolveInfoList(Intent sanitizedIntent,
            int[] hashPrefix, int userId, String token) throws ConnectionException {
        throwIfCalledOnMainThread();
        IInstantAppResolver target = null;
        try {
            try {
                target = getRemoteInstanceLazy(token);
            } catch (TimeoutException e) {
                throw new ConnectionException(ConnectionException.FAILURE_BIND);
            } catch (InterruptedException e) {
                throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED);
            }
            try {
                return mGetInstantAppResolveInfoCaller
                        .getInstantAppResolveInfoList(target, sanitizedIntent, hashPrefix, userId,
                                token);
            } catch (TimeoutException e) {
                throw new ConnectionException(ConnectionException.FAILURE_CALL);
            } catch (RemoteException ignore) {
            }
        } finally {
            synchronized (mLock) {
                mLock.notifyAll();
            }
        }
        return null;
    }

    public void getInstantAppIntentFilterList(Intent sanitizedIntent, int[] hashPrefix, int userId,
            String token, PhaseTwoCallback callback, Handler callbackHandler, final long startTime)
            throws ConnectionException {
        final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() {
            @Override
            public void sendResult(Bundle data) throws RemoteException {
                final ArrayList<InstantAppResolveInfo> resolveList =
                        data.getParcelableArrayList(
                                InstantAppResolverService.EXTRA_RESOLVE_INFO);
                callbackHandler.post(() -> callback.onPhaseTwoResolved(resolveList, startTime));
            }
        };
        try {
            getRemoteInstanceLazy(token)
                    .getInstantAppIntentFilterList(sanitizedIntent, hashPrefix, userId, token,
                            remoteCallback);
        } catch (TimeoutException e) {
            throw new ConnectionException(ConnectionException.FAILURE_BIND);
        } catch (InterruptedException e) {
            throw new ConnectionException(ConnectionException.FAILURE_INTERRUPTED);
        } catch (RemoteException ignore) {
        }
    }

    @WorkerThread
    private IInstantAppResolver getRemoteInstanceLazy(String token)
            throws ConnectionException, TimeoutException, InterruptedException {
        long binderToken = Binder.clearCallingIdentity();
        try {
            return bind(token);
        } finally {
            Binder.restoreCallingIdentity(binderToken);
        }
    }

    @GuardedBy("mLock")
    private void waitForBindLocked(String token) throws TimeoutException, InterruptedException {
        final long startMillis = SystemClock.uptimeMillis();
        while (mBindState != STATE_IDLE) {
            if (mRemoteInstance != null) {
                break;
            }
            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
            final long remainingMillis = BIND_SERVICE_TIMEOUT_MS - elapsedMillis;
            if (remainingMillis <= 0) {
                throw new TimeoutException("[" + token + "] Didn't bind to resolver in time!");
            }
            mLock.wait(remainingMillis);
        }
    }

    @WorkerThread
    private IInstantAppResolver bind(String token)
            throws ConnectionException, TimeoutException, InterruptedException {
        boolean doUnbind = false;
        synchronized (mLock) {
            if (mRemoteInstance != null) {
                return mRemoteInstance;
            }

            if (mBindState == STATE_PENDING) {
                // there is a pending bind, let's see if we can use it.
                if (DEBUG_INSTANT) {
                    Slog.i(TAG, "[" + token + "] Previous bind timed out; waiting for connection");
                }
                try {
                    waitForBindLocked(token);
                    if (mRemoteInstance != null) {
                        return mRemoteInstance;
                    }
                } catch (TimeoutException e) {
                    // nope, we might have to try a rebind.
                    doUnbind = true;
                }
            }

            if (mBindState == STATE_BINDING) {
                // someone was binding when we called bind(), or they raced ahead while we were
                // waiting in the PENDING case; wait for their result instead. Last chance!
                if (DEBUG_INSTANT) {
                    Slog.i(TAG, "[" + token + "] Another thread is binding; waiting for connection");
                }
                waitForBindLocked(token);
                // if the other thread's bindService() returned false, we could still have null.
                if (mRemoteInstance != null) {
                    return mRemoteInstance;
                }
                throw new ConnectionException(ConnectionException.FAILURE_BIND);
            }
            mBindState = STATE_BINDING; // our time to shine! :)
        }

        // only one thread can be here at a time (the one that set STATE_BINDING)
        boolean wasBound = false;
        IInstantAppResolver instance = null;
        try {
            if (doUnbind) {
                if (DEBUG_INSTANT) {
                    Slog.i(TAG, "[" + token + "] Previous connection never established; rebinding");
                }
                mContext.unbindService(mServiceConnection);
            }
            if (DEBUG_INSTANT) {
                Slog.v(TAG, "[" + token + "] Binding to instant app resolver");
            }
            final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
            wasBound = mContext
                    .bindServiceAsUser(mIntent, mServiceConnection, flags, UserHandle.SYSTEM);
            if (wasBound) {
                synchronized (mLock) {
                    waitForBindLocked(token);
                    instance = mRemoteInstance;
                    return instance;
                }
            } else {
                Slog.w(TAG, "[" + token + "] Failed to bind to: " + mIntent);
                throw new ConnectionException(ConnectionException.FAILURE_BIND);
            }
        } finally {
            synchronized (mLock) {
                if (wasBound && instance == null) {
                    mBindState = STATE_PENDING;
                } else {
                    mBindState = STATE_IDLE;
                }
                mLock.notifyAll();
            }
        }
    }

    private void throwIfCalledOnMainThread() {
        if (Thread.currentThread() == mContext.getMainLooper().getThread()) {
            throw new RuntimeException("Cannot invoke on the main thread");
        }
    }

    @AnyThread
    void optimisticBind() {
        mBgHandler.post(() -> {
            try {
                if (bind("Optimistic Bind") != null && DEBUG_INSTANT) {
                    Slog.i(TAG, "Optimistic bind succeeded.");
                }
            } catch (ConnectionException | TimeoutException | InterruptedException e) {
                Slog.e(TAG, "Optimistic bind failed.", e);
            }
        });
    }

    @Override
    public void binderDied() {
        if (DEBUG_INSTANT) {
            Slog.d(TAG, "Binder to instant app resolver died");
        }
        synchronized (mLock) {
            handleBinderDiedLocked();
        }
        optimisticBind();
    }

    @GuardedBy("mLock")
    private void handleBinderDiedLocked() {
        if (mRemoteInstance != null) {
            try {
                mRemoteInstance.asBinder().unlinkToDeath(this, 0 /*flags*/);
            } catch (NoSuchElementException ignore) { }
        }
        mRemoteInstance = null;
    }

    /**
     * Asynchronous callback when results come back from ephemeral resolution phase two.
     */
    public abstract static class PhaseTwoCallback {
        abstract void onPhaseTwoResolved(
                List<InstantAppResolveInfo> instantAppResolveInfoList, long startTime);
    }

    public static class ConnectionException extends Exception {
        public static final int FAILURE_BIND = 1;
        public static final int FAILURE_CALL = 2;
        public static final int FAILURE_INTERRUPTED = 3;

        public final int failure;
        public ConnectionException(int _failure) {
            failure = _failure;
        }
    }

    private final class MyServiceConnection implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DEBUG_INSTANT) {
                Slog.d(TAG, "Connected to instant app resolver");
            }
            synchronized (mLock) {
                mRemoteInstance = IInstantAppResolver.Stub.asInterface(service);
                if (mBindState == STATE_PENDING) {
                    mBindState = STATE_IDLE;
                }
                try {
                    service.linkToDeath(InstantAppResolverConnection.this, 0 /*flags*/);
                } catch (RemoteException e) {
                    handleBinderDiedLocked();
                }
                mLock.notifyAll();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG_INSTANT) {
                Slog.d(TAG, "Disconnected from instant app resolver");
            }
            synchronized (mLock) {
                handleBinderDiedLocked();
            }
        }
    }

    private static final class GetInstantAppResolveInfoCaller
            extends TimedRemoteCaller<List<InstantAppResolveInfo>> {
        private final IRemoteCallback mCallback;

        public GetInstantAppResolveInfoCaller() {
            super(CALL_SERVICE_TIMEOUT_MS);
            mCallback = new IRemoteCallback.Stub() {
                    @Override
                    public void sendResult(Bundle data) throws RemoteException {
                        final ArrayList<InstantAppResolveInfo> resolveList =
                                data.getParcelableArrayList(
                                        InstantAppResolverService.EXTRA_RESOLVE_INFO);
                        int sequence =
                                data.getInt(InstantAppResolverService.EXTRA_SEQUENCE, -1);
                        onRemoteMethodResult(resolveList, sequence);
                    }
            };
        }

        public List<InstantAppResolveInfo> getInstantAppResolveInfoList(
                IInstantAppResolver target, Intent sanitizedIntent, int[] hashPrefix, int userId,
                String token) throws RemoteException, TimeoutException {
            final int sequence = onBeforeRemoteCall();
            target.getInstantAppResolveInfoList(sanitizedIntent, hashPrefix, userId, token,
                    sequence, mCallback);
            return getResultTimed(sequence);
        }
    }
}
