/*
 * 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
 */
@TestApi
@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
     */
    @TestApi
    @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);
            });
        }
    }
}
