/*
 * 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.devicepolicy;

import android.Manifest.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DeviceAdminService;
import android.app.admin.DevicePolicyManager;
import android.app.admin.IDeviceAdminService;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.IBinder;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.am.PersistentConnection;
import com.android.server.appbinding.AppBindingUtils;

/**
 * Manages connections to persistent services in owner packages.
 */
public class DeviceAdminServiceController {
    static final String TAG = DevicePolicyManagerService.LOG_TAG;

    static final boolean DEBUG = false; // DO NOT MERGE WITH TRUE.

    final Object mLock = new Object();
    final Context mContext;

    private final DevicePolicyManagerService mService;
    private final DevicePolicyManagerService.Injector mInjector;
    private final DevicePolicyConstants mConstants;

    private final Handler mHandler; // needed?

    static void debug(String format, Object... args) {
        if (!DEBUG) {
            return;
        }
        Slog.d(TAG, String.format(format, args));
    }

    private class DevicePolicyServiceConnection
            extends PersistentConnection<IDeviceAdminService> {
        public DevicePolicyServiceConnection(int userId, @NonNull ComponentName componentName) {
            super(TAG, mContext, mHandler, userId, componentName,
                    mConstants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC,
                    mConstants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE,
                    mConstants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC,
                    mConstants.DAS_DIED_SERVICE_STABLE_CONNECTION_THRESHOLD_SEC);
        }

        @Override
        protected int getBindFlags() {
            return Context.BIND_FOREGROUND_SERVICE;
        }

        @Override
        protected IDeviceAdminService asInterface(IBinder binder) {
            return IDeviceAdminService.Stub.asInterface(binder);
        }
    }

    /**
     * User-ID -> {@link PersistentConnection}.
     */
    @GuardedBy("mLock")
    private final SparseArray<DevicePolicyServiceConnection> mConnections = new SparseArray<>();

    public DeviceAdminServiceController(DevicePolicyManagerService service,
            DevicePolicyConstants constants) {
        mService = service;
        mInjector = service.mInjector;
        mContext = mInjector.mContext;
        mHandler = new Handler(BackgroundThread.get().getLooper());
        mConstants = constants;
    }

    /**
     * Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
     * in a given package.
     */
    @Nullable
    private ServiceInfo findService(@NonNull String packageName, int userId) {
        return AppBindingUtils.findService(
                packageName,
                userId,
                DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE,
                permission.BIND_DEVICE_ADMIN,
                DeviceAdminService.class,
                mInjector.getIPackageManager(),
                new StringBuilder() /* ignore error message */);
    }

    /**
     * Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
     * in an owner package and connect to it.
     */
    public void startServiceForOwner(@NonNull String packageName, int userId,
            @NonNull String actionForLog) {
        final long token = mInjector.binderClearCallingIdentity();
        try {
            synchronized (mLock) {
                final ServiceInfo service = findService(packageName, userId);
                if (service == null) {
                    debug("Owner package %s on u%d has no service.",
                            packageName, userId);
                    disconnectServiceOnUserLocked(userId, actionForLog);
                    return;
                }
                // See if it's already running.
                final PersistentConnection<IDeviceAdminService> existing =
                        mConnections.get(userId);
                if (existing != null) {
                    // Note even when we're already connected to the same service, the binding
                    // would have died at this point due to a package update.  So we disconnect
                    // anyway and re-connect.
                    debug("Disconnecting from existing service connection.",
                            packageName, userId);
                    disconnectServiceOnUserLocked(userId, actionForLog);
                }

                debug("Owner package %s on u%d has service %s for %s",
                        packageName, userId,
                        service.getComponentName().flattenToShortString(), actionForLog);

                final DevicePolicyServiceConnection conn =
                        new DevicePolicyServiceConnection(
                                userId, service.getComponentName());
                mConnections.put(userId, conn);
                conn.bind();
            }
        } finally {
            mInjector.binderRestoreCallingIdentity(token);
        }
    }

    /**
     * Stop an owner service on a given user.
     */
    public void stopServiceForOwner(int userId, @NonNull String actionForLog) {
        final long token = mInjector.binderClearCallingIdentity();
        try {
            synchronized (mLock) {
                disconnectServiceOnUserLocked(userId, actionForLog);
            }
        } finally {
            mInjector.binderRestoreCallingIdentity(token);
        }
    }

    @GuardedBy("mLock")
    private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) {
        final DevicePolicyServiceConnection conn = mConnections.get(userId);
        if (conn != null) {
            debug("Stopping service for u%d if already running for %s.",
                    userId, actionForLog);
            conn.unbind();
            mConnections.remove(userId);
        }
    }

    /** dump content */
    public void dump(IndentingPrintWriter pw) {
        synchronized (mLock) {
            if (mConnections.size() == 0) {
                return;
            }
            pw.println("Owner Services:");
            pw.increaseIndent();
            for (int i = 0; i < mConnections.size(); i++) {
                final int userId = mConnections.keyAt(i);
                pw.print("User: "); pw.println(userId);

                final DevicePolicyServiceConnection con = mConnections.valueAt(i);
                pw.increaseIndent();
                con.dump("", pw);
                pw.decreaseIndent();
            }
            pw.decreaseIndent();
        }
    }
}
