/*
 * Copyright (C) 2012 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;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;

import com.android.internal.content.PackageMonitor;
import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * Find the best Service, and bind to it.
 * Handles run-time package changes.
 */
public class ServiceWatcher implements ServiceConnection {

    private static final String TAG = "ServiceWatcher";
    private static final boolean D = false;

    public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
    public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";


    /** Function to run on binder interface. */
    public interface BinderRunner {
        /** Called to run client code with the binder. */
        void run(IBinder binder) throws RemoteException;
    }

    /**
     * Function to run on binder interface.
     * @param <T> Type to return.
     */
    public interface BlockingBinderRunner<T> {
        /** Called to run client code with the binder. */
        T run(IBinder binder) throws RemoteException;
    }

    public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
            String... packageNames) {
        PackageManager pm = context.getPackageManager();

        ArrayList<HashSet<Signature>> signatureSets = new ArrayList<>(packageNames.length);
        for (String packageName : packageNames) {
            try {
                Signature[] signatures = pm.getPackageInfo(packageName,
                        PackageManager.MATCH_SYSTEM_ONLY
                                | PackageManager.GET_SIGNATURES).signatures;

                HashSet<Signature> set = new HashSet<>();
                Collections.addAll(set, signatures);
                signatureSets.add(set);
            } catch (NameNotFoundException e) {
                Log.w(TAG, packageName + " not found");
            }
        }
        return signatureSets;
    }

    /** Checks if signatures match. */
    public static boolean isSignatureMatch(Signature[] signatures,
            List<HashSet<Signature>> sigSets) {
        if (signatures == null) return false;

        // build hashset of input to test against
        HashSet<Signature> inputSet = new HashSet<>();
        Collections.addAll(inputSet, signatures);

        // test input against each of the signature sets
        for (HashSet<Signature> referenceSet : sigSets) {
            if (referenceSet.equals(inputSet)) {
                return true;
            }
        }
        return false;
    }

    private final Context mContext;
    private final String mTag;
    private final String mAction;
    private final String mServicePackageName;
    private final List<HashSet<Signature>> mSignatureSets;

    private final Handler mHandler;

    // read/write from handler thread
    private IBinder mBestService;
    private int mCurrentUserId;

    // read from any thread, write from handler thread
    private volatile ComponentName mBestComponent;
    private volatile int mBestVersion;
    private volatile int mBestUserId;

    public ServiceWatcher(Context context, String logTag, String action,
            int overlaySwitchResId, int defaultServicePackageNameResId,
            int initialPackageNamesResId, Handler handler) {
        Resources resources = context.getResources();

        mContext = context;
        mTag = logTag;
        mAction = action;

        boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
        if (enableOverlay) {
            String[] pkgs = resources.getStringArray(initialPackageNamesResId);
            mServicePackageName = null;
            mSignatureSets = getSignatureSets(context, pkgs);
            if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
        } else {
            mServicePackageName = resources.getString(defaultServicePackageNameResId);
            mSignatureSets = getSignatureSets(context, mServicePackageName);
            if (D) Log.d(mTag, "Overlay disabled, default package=" + mServicePackageName);
        }

        mHandler = handler;

        mBestComponent = null;
        mBestVersion = Integer.MIN_VALUE;
        mBestUserId = UserHandle.USER_NULL;

        mBestService = null;
    }

    protected void onBind() {}

    protected void onUnbind() {}

    /**
     * Start this watcher, including binding to the current best match and
     * re-binding to any better matches down the road.
     * <p>
     * Note that if there are no matching encryption-aware services, we may not
     * bind to a real service until after the current user is unlocked.
     *
     * @return {@code true} if a potential service implementation was found.
     */
    public final boolean start() {
        // if we have to return false, do it before registering anything
        if (isServiceMissing()) return false;

        // listen for relevant package changes if service overlay is enabled on handler
        if (mServicePackageName == null) {
            new PackageMonitor() {
                @Override
                public void onPackageUpdateFinished(String packageName, int uid) {
                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
                }

                @Override
                public void onPackageAdded(String packageName, int uid) {
                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
                }

                @Override
                public void onPackageRemoved(String packageName, int uid) {
                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
                }

                @Override
                public boolean onPackageChanged(String packageName, int uid, String[] components) {
                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
                    return super.onPackageChanged(packageName, uid, components);
                }
            }.register(mContext, UserHandle.ALL, true, mHandler);
        }

        // listen for user change on handler
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
        intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
        mContext.registerReceiverAsUser(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                        UserHandle.USER_NULL);
                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                    mCurrentUserId = userId;
                    bindBestPackage(false);
                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                    if (userId == mCurrentUserId) {
                        bindBestPackage(false);
                    }
                }
            }
        }, UserHandle.ALL, intentFilter, null, mHandler);

        mCurrentUserId = ActivityManager.getCurrentUser();

        mHandler.post(() -> bindBestPackage(false));
        return true;
    }

    /** Returns the name of the currently connected package or null. */
    @Nullable
    public String getCurrentPackageName() {
        ComponentName bestComponent = mBestComponent;
        return bestComponent == null ? null : bestComponent.getPackageName();
    }

    private boolean isServiceMissing() {
        return mContext.getPackageManager().queryIntentServicesAsUser(new Intent(mAction),
                PackageManager.MATCH_DIRECT_BOOT_AWARE
                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                UserHandle.USER_SYSTEM).isEmpty();
    }

    private void bindBestPackage(boolean forceRebind) {
        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());

        Intent intent = new Intent(mAction);
        if (mServicePackageName != null) {
            intent.setPackage(mServicePackageName);
        }

        List<ResolveInfo> rInfos = mContext.getPackageManager().queryIntentServicesAsUser(intent,
                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AUTO,
                mCurrentUserId);
        if (rInfos == null) {
            rInfos = Collections.emptyList();
        }

        ComponentName bestComponent = null;
        int bestVersion = Integer.MIN_VALUE;
        boolean bestIsMultiuser = false;

        for (ResolveInfo rInfo : rInfos) {
            ComponentName component = rInfo.serviceInfo.getComponentName();
            String packageName = component.getPackageName();

            // check signature
            try {
                PackageInfo pInfo = mContext.getPackageManager().getPackageInfo(packageName,
                        PackageManager.GET_SIGNATURES
                                | PackageManager.MATCH_DIRECT_BOOT_AUTO);
                if (!isSignatureMatch(pInfo.signatures, mSignatureSets)) {
                    Log.w(mTag, packageName + " resolves service " + mAction
                            + ", but has wrong signature, ignoring");
                    continue;
                }
            } catch (NameNotFoundException e) {
                Log.wtf(mTag, e);
                continue;
            }

            // check metadata
            Bundle metadata = rInfo.serviceInfo.metaData;
            int version = Integer.MIN_VALUE;
            boolean isMultiuser = false;
            if (metadata != null) {
                version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
                isMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
            }

            if (version > bestVersion) {
                bestComponent = component;
                bestVersion = version;
                bestIsMultiuser = isMultiuser;
            }
        }

        if (D) {
            Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
                    (mServicePackageName == null ? ""
                            : "(" + mServicePackageName + ") "), rInfos.size(),
                    (bestComponent == null ? "no new best component"
                            : "new best component: " + bestComponent)));
        }

        if (bestComponent == null) {
            Slog.w(mTag, "Odd, no component found for service " + mAction);
            unbind();
            return;
        }

        int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
        boolean alreadyBound = Objects.equals(bestComponent, mBestComponent)
                && bestVersion == mBestVersion && userId == mBestUserId;
        if (forceRebind || !alreadyBound) {
            unbind();
            bind(bestComponent, bestVersion, userId);
        }
    }

    private void bind(ComponentName component, int version, int userId) {
        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());

        Intent intent = new Intent(mAction);
        intent.setComponent(component);

        mBestComponent = component;
        mBestVersion = version;
        mBestUserId = userId;

        if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
        mContext.bindServiceAsUser(intent, this,
                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
                UserHandle.of(userId));
    }

    private void unbind() {
        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());

        if (mBestComponent != null) {
            if (D) Log.d(mTag, "unbinding " + mBestComponent);
            mContext.unbindService(this);
        }

        mBestComponent = null;
        mBestVersion = Integer.MIN_VALUE;
        mBestUserId = UserHandle.USER_NULL;
    }

    /**
     * Runs the given function asynchronously if currently connected. Suppresses any RemoteException
     * thrown during execution.
     */
    public final void runOnBinder(BinderRunner runner) {
        runOnHandler(() -> {
            if (mBestService == null) {
                return;
            }

            try {
                runner.run(mBestService);
            } catch (RuntimeException e) {
                // the code being run is privileged, but may be outside the system server, and thus
                // we cannot allow runtime exceptions to crash the system server
                Log.e(TAG, "exception while while running " + runner + " on " + mBestService
                        + " from " + this, e);
            } catch (RemoteException e) {
                // do nothing
            }
        });
    }

    /**
     * Runs the given function synchronously if currently connected, and returns the default value
     * if not currently connected or if any exception is thrown.
     *
     * @deprecated Using this function is an indication that your AIDL API is broken. Calls from
     * system server to outside MUST be one-way, and so cannot return any result, and this
     * method should not be needed or used. Use a separate callback interface to allow outside
     * components to return results back to the system server.
     */
    @Deprecated
    public final <T> T runOnBinderBlocking(BlockingBinderRunner<T> runner, T defaultValue) {
        try {
            return runOnHandlerBlocking(() -> {
                if (mBestService == null) {
                    return defaultValue;
                }

                try {
                    return runner.run(mBestService);
                } catch (RemoteException e) {
                    return defaultValue;
                }
            });
        } catch (InterruptedException e) {
            return defaultValue;
        }
    }

    @Override
    public final void onServiceConnected(ComponentName component, IBinder binder) {
        runOnHandler(() -> {
            if (D) Log.d(mTag, component + " connected");
            mBestService = binder;
            onBind();
        });
    }

    @Override
    public final void onServiceDisconnected(ComponentName component) {
        runOnHandler(() -> {
            if (D) Log.d(mTag, component + " disconnected");
            mBestService = null;
            onUnbind();
        });
    }

    @Override
    public String toString() {
        ComponentName bestComponent = mBestComponent;
        return bestComponent == null ? "null" : bestComponent.toShortString() + "@" + mBestVersion;
    }

    private void runOnHandler(Runnable r) {
        if (Looper.myLooper() == mHandler.getLooper()) {
            r.run();
        } else {
            mHandler.post(r);
        }
    }

    private <T> T runOnHandlerBlocking(Callable<T> c) throws InterruptedException {
        if (Looper.myLooper() == mHandler.getLooper()) {
            try {
                return c.call();
            } catch (Exception e) {
                // Function cannot throw exception, this should never happen
                throw new IllegalStateException(e);
            }
        } else {
            FutureTask<T> task = new FutureTask<>(c);
            mHandler.post(task);
            try {
                return task.get();
            } catch (ExecutionException e) {
                // Function cannot throw exception, this should never happen
                throw new IllegalStateException(e);
            }
        }
    }
}
