/*
 * Copyright (C) 2019 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 android.service.watchdog;

import static android.os.Parcelable.Creator;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * A service to provide packages supporting explicit health checks and route checks to these
 * packages on behalf of the package watchdog.
 *
 * <p>To extend this class, you must declare the service in your manifest file with the
 * {@link android.Manifest.permission#BIND_EXPLICIT_HEALTH_CHECK_SERVICE} permission,
 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. In adddition,
 * your implementation must live in
 * {@link PackageManager#getServicesSystemSharedLibraryPackageName()}.
 * For example:</p>
 * <pre>
 *     &lt;service android:name=".FooExplicitHealthCheckService"
 *             android:exported="true"
 *             android:priority="100"
 *             android:permission="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"&gt;
 *         &lt;intent-filter&gt;
 *             &lt;action android:name="android.service.watchdog.ExplicitHealthCheckService" /&gt;
 *         &lt;/intent-filter&gt;
 *     &lt;/service&gt;
 * </pre>
 * @hide
 */
@SystemApi
public abstract class ExplicitHealthCheckService extends Service {

    private static final String TAG = "ExplicitHealthCheckService";

    /**
     * {@link Bundle} key for a {@link List} of {@link PackageConfig} value.
     *
     * {@hide}
     */
    public static final String EXTRA_SUPPORTED_PACKAGES =
            "android.service.watchdog.extra.supported_packages";

    /**
     * {@link Bundle} key for a {@link List} of {@link String} value.
     *
     * {@hide}
     */
    public static final String EXTRA_REQUESTED_PACKAGES =
            "android.service.watchdog.extra.requested_packages";

    /**
     * {@link Bundle} key for a {@link String} value.
     *
     * {@hide}
     */
    public static final String EXTRA_HEALTH_CHECK_PASSED_PACKAGE =
            "android.service.watchdog.extra.health_check_passed_package";

    /**
     * The Intent action that a service must respond to. Add it to the intent filter of the service
     * in its manifest.
     */
    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
    public static final String SERVICE_INTERFACE =
            "android.service.watchdog.ExplicitHealthCheckService";

    /**
     * The permission that a service must require to ensure that only Android system can bind to it.
     * If this permission is not enforced in the AndroidManifest of the service, the system will
     * skip that service.
     */
    public static final String BIND_PERMISSION =
            "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";

    private final ExplicitHealthCheckServiceWrapper mWrapper =
            new ExplicitHealthCheckServiceWrapper();

    /**
     * Called when the system requests an explicit health check for {@code packageName}.
     *
     * <p> When {@code packageName} passes the check, implementors should call
     * {@link #notifyHealthCheckPassed} to inform the system.
     *
     * <p> It could take many hours before a {@code packageName} passes a check and implementors
     * should never drop requests unless {@link onCancel} is called or the service dies.
     *
     * <p> Requests should not be queued and additional calls while expecting a result for
     * {@code packageName} should have no effect.
     */
    public abstract void onRequestHealthCheck(@NonNull String packageName);

    /**
     * Called when the system cancels the explicit health check request for {@code packageName}.
     * Should do nothing if there are is no active request for {@code packageName}.
     */
    public abstract void onCancelHealthCheck(@NonNull String packageName);

    /**
     * Called when the system requests for all the packages supporting explicit health checks. The
     * system may request an explicit health check for any of these packages with
     * {@link #onRequestHealthCheck}.
     *
     * @return all packages supporting explicit health checks
     */
    @NonNull public abstract List<PackageConfig> onGetSupportedPackages();

    /**
     * Called when the system requests for all the packages that it has currently requested
     * an explicit health check for.
     *
     * @return all packages expecting an explicit health check result
     */
    @NonNull public abstract List<String> onGetRequestedPackages();

    private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
    @Nullable private RemoteCallback mCallback;

    @Override
    @NonNull
    public final IBinder onBind(@NonNull Intent intent) {
        return mWrapper;
    }

    /**
     * Sets {@link RemoteCallback}, for testing purpose.
     *
     * @hide
     */
    @TestApi
    public void setCallback(@Nullable RemoteCallback callback) {
        mCallback = callback;
    }
    /**
     * Implementors should call this to notify the system when explicit health check passes
     * for {@code packageName};
     */
    public final void notifyHealthCheckPassed(@NonNull String packageName) {
        mHandler.post(() -> {
            if (mCallback != null) {
                Objects.requireNonNull(packageName,
                        "Package passing explicit health check must be non-null");
                Bundle bundle = new Bundle();
                bundle.putString(EXTRA_HEALTH_CHECK_PASSED_PACKAGE, packageName);
                mCallback.sendResult(bundle);
            } else {
                Log.wtf(TAG, "System missed explicit health check result for " + packageName);
            }
        });
    }

    /**
     * A PackageConfig contains a package supporting explicit health checks and the
     * timeout in {@link System#uptimeMillis} across reboots after which health
     * check requests from clients are failed.
     *
     * @hide
     */
    @SystemApi
    public static final class PackageConfig implements Parcelable {
        private static final long DEFAULT_HEALTH_CHECK_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(1);

        private final String mPackageName;
        private final long mHealthCheckTimeoutMillis;

        /**
         * Creates a new instance.
         *
         * @param packageName the package name
         * @param durationMillis the duration in milliseconds, must be greater than or
         * equal to 0. If it is 0, it will use a system default value.
         */
        public PackageConfig(@NonNull String packageName, long healthCheckTimeoutMillis) {
            mPackageName = Preconditions.checkNotNull(packageName);
            if (healthCheckTimeoutMillis == 0) {
                mHealthCheckTimeoutMillis = DEFAULT_HEALTH_CHECK_TIMEOUT_MILLIS;
            } else {
                mHealthCheckTimeoutMillis = Preconditions.checkArgumentNonnegative(
                        healthCheckTimeoutMillis);
            }
        }

        private PackageConfig(Parcel parcel) {
            mPackageName = parcel.readString();
            mHealthCheckTimeoutMillis = parcel.readLong();
        }

        /**
         * Gets the package name.
         *
         * @return the package name
         */
        public @NonNull String getPackageName() {
            return mPackageName;
        }

        /**
         * Gets the timeout in milliseconds to evaluate an explicit health check result after a
         * request.
         *
         * @return the duration in {@link System#uptimeMillis} across reboots
         */
        public long getHealthCheckTimeoutMillis() {
            return mHealthCheckTimeoutMillis;
        }

        @NonNull
        @Override
        public String toString() {
            return "PackageConfig{" + mPackageName + ", " + mHealthCheckTimeoutMillis + "}";
        }

        @Override
        public boolean equals(@Nullable Object other) {
            if (other == this) {
                return true;
            }
            if (!(other instanceof PackageConfig)) {
                return false;
            }

            PackageConfig otherInfo = (PackageConfig) other;
            return Objects.equals(otherInfo.getHealthCheckTimeoutMillis(),
                    mHealthCheckTimeoutMillis)
                    && Objects.equals(otherInfo.getPackageName(), mPackageName);
        }

        @Override
        public int hashCode() {
            return Objects.hash(mPackageName, mHealthCheckTimeoutMillis);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@SuppressLint({"MissingNullability"}) Parcel parcel, int flags) {
            parcel.writeString(mPackageName);
            parcel.writeLong(mHealthCheckTimeoutMillis);
        }

        public static final @NonNull Creator<PackageConfig> CREATOR = new Creator<PackageConfig>() {
                @Override
                public PackageConfig createFromParcel(Parcel source) {
                    return new PackageConfig(source);
                }

                @Override
                public PackageConfig[] newArray(int size) {
                    return new PackageConfig[size];
                }
            };
    }


    private class ExplicitHealthCheckServiceWrapper extends IExplicitHealthCheckService.Stub {
        @Override
        public void setCallback(RemoteCallback callback) throws RemoteException {
            mHandler.post(() -> {
                mCallback = callback;
            });
        }

        @Override
        public void request(String packageName) throws RemoteException {
            mHandler.post(() -> ExplicitHealthCheckService.this.onRequestHealthCheck(packageName));
        }

        @Override
        public void cancel(String packageName) throws RemoteException {
            mHandler.post(() -> ExplicitHealthCheckService.this.onCancelHealthCheck(packageName));
        }

        @Override
        public void getSupportedPackages(RemoteCallback callback) throws RemoteException {
            mHandler.post(() -> {
                List<PackageConfig> packages =
                        ExplicitHealthCheckService.this.onGetSupportedPackages();
                Objects.requireNonNull(packages, "Supported package list must be non-null");
                Bundle bundle = new Bundle();
                bundle.putParcelableArrayList(EXTRA_SUPPORTED_PACKAGES, new ArrayList<>(packages));
                callback.sendResult(bundle);
            });
        }

        @Override
        public void getRequestedPackages(RemoteCallback callback) throws RemoteException {
            mHandler.post(() -> {
                List<String> packages =
                        ExplicitHealthCheckService.this.onGetRequestedPackages();
                Objects.requireNonNull(packages, "Requested  package list must be non-null");
                Bundle bundle = new Bundle();
                bundle.putStringArrayList(EXTRA_REQUESTED_PACKAGES, new ArrayList<>(packages));
                callback.sendResult(bundle);
            });
        }
    }
}
