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

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.InstantAppResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;

import com.android.internal.os.SomeArgs;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Base class for implementing the resolver service.
 * @hide
 */
@SystemApi
public abstract class InstantAppResolverService extends Service {
    private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
    private static final String TAG = "PackageManager";

    /** @hide */
    public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
    /** @hide */
    public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
    Handler mHandler;

    /**
     * Called to retrieve resolve info for instant applications immediately.
     *
     * @param digestPrefix The hash prefix of the instant app's domain.
     * @deprecated Should implement {@link #onGetInstantAppResolveInfo(Intent, int[], UserHandle,
     *             String, InstantAppResolutionCallback)}.
     */
    @Deprecated
    public void onGetInstantAppResolveInfo(@Nullable int[] digestPrefix, @NonNull String token,
            @NonNull InstantAppResolutionCallback callback) {
        throw new IllegalStateException("Must define onGetInstantAppResolveInfo");
    }

    /**
     * Called to retrieve intent filters for instant applications from potentially expensive
     * sources.
     *
     * @param digestPrefix The hash prefix of the instant app's domain.
     * @deprecated Should implement {@link #onGetInstantAppIntentFilter(Intent, int[], UserHandle,
     *             String, InstantAppResolutionCallback)}.
     */
    @Deprecated
    public void onGetInstantAppIntentFilter(@Nullable int[] digestPrefix, @NonNull String token,
            @NonNull InstantAppResolutionCallback callback) {
        throw new IllegalStateException("Must define onGetInstantAppIntentFilter");
    }

    /**
     * Called to retrieve resolve info for instant applications immediately. The response will be
     * ignored if not provided within a reasonable time. {@link InstantAppResolveInfo}s provided
     * in response to this method may be partial to request a second phase of resolution which will
     * result in a subsequent call to
     * {@link #onGetInstantAppIntentFilter(Intent, int[], String, InstantAppResolutionCallback)}
     *
     * @param sanitizedIntent The sanitized {@link Intent} used for resolution. A sanitized Intent
     *                        is an intent with potential PII removed from the original intent.
     *                        Fields removed include extras and the host + path of the data, if
     *                        defined.
     * @param hostDigestPrefix The hash prefix of the instant app's domain.
     * @param token A unique identifier that will be provided in calls to
     *              {@link #onGetInstantAppIntentFilter(Intent, int[], String,
     *              InstantAppResolutionCallback)}
     *              and provided to the installer via {@link Intent#EXTRA_INSTANT_APP_TOKEN} to
     *              tie a single launch together.
     * @param callback The {@link InstantAppResolutionCallback} to provide results to.
     *
     * @see InstantAppResolveInfo
     *
     * @deprecated Should implement {@link #onGetInstantAppResolveInfo(Intent, int[], UserHandle,
     *             String, InstantAppResolutionCallback)}.
     */
    @Deprecated
    public void onGetInstantAppResolveInfo(@NonNull Intent sanitizedIntent,
            @Nullable int[] hostDigestPrefix, @NonNull String token,
            @NonNull InstantAppResolutionCallback callback) {
        // if not overridden, forward to old methods and filter out non-web intents
        if (sanitizedIntent.isWebIntent()) {
            onGetInstantAppResolveInfo(hostDigestPrefix, token, callback);
        } else {
            callback.onInstantAppResolveInfo(Collections.emptyList());
        }
    }

    /**
     * Called to retrieve intent filters for potentially matching instant applications. Unlike
     * {@link #onGetInstantAppResolveInfo(Intent, int[], String, InstantAppResolutionCallback)},
     * the response may take as long as necessary to respond. All {@link InstantAppResolveInfo}s
     * provided in response to this method must be completely populated.
     *
     * @param sanitizedIntent The sanitized {@link Intent} used for resolution.
     * @param hostDigestPrefix The hash prefix of the instant app's domain or null if no host is
     *                         defined.
     * @param token A unique identifier that was provided in
     *              {@link #onGetInstantAppResolveInfo(Intent, int[], String,
     *              InstantAppResolutionCallback)}
     *              and provided to the currently visible installer via
     *              {@link Intent#EXTRA_INSTANT_APP_TOKEN}.
     * @param callback The {@link InstantAppResolutionCallback} to provide results to.
     *
     * @deprecated Should implement {@link #onGetInstantAppIntentFilter(Intent, int[], UserHandle,
     *             String, InstantAppResolutionCallback)}.
     */
    @Deprecated
    public void onGetInstantAppIntentFilter(@NonNull Intent sanitizedIntent,
            @Nullable int[] hostDigestPrefix,
            @NonNull String token, @NonNull InstantAppResolutionCallback callback) {
        Log.e(TAG, "New onGetInstantAppIntentFilter is not overridden");
        // if not overridden, forward to old methods and filter out non-web intents
        if (sanitizedIntent.isWebIntent()) {
            onGetInstantAppIntentFilter(hostDigestPrefix, token, callback);
        } else {
            callback.onInstantAppResolveInfo(Collections.emptyList());
        }
    }

    /**
     * Called to retrieve resolve info for instant applications immediately. The response will be
     * ignored if not provided within a reasonable time. {@link InstantAppResolveInfo}s provided
     * in response to this method may be partial to request a second phase of resolution which will
     * result in a subsequent call to {@link #onGetInstantAppIntentFilter(Intent, int[], UserHandle,
     * String, InstantAppResolutionCallback)}
     *
     * @param sanitizedIntent The sanitized {@link Intent} used for resolution. A sanitized Intent
     *                        is an intent with potential PII removed from the original intent.
     *                        Fields removed include extras and the host + path of the data, if
     *                        defined.
     * @param hostDigestPrefix The hash prefix of the instant app's domain.
     * @param userHandle The user for which to resolve the instant app.
     * @param token A unique identifier that will be provided in calls to {@link
     *              #onGetInstantAppIntentFilter(Intent, int[], UserHandle, String,
     *              InstantAppResolutionCallback)} and provided to the installer via {@link
     *              Intent#EXTRA_INSTANT_APP_TOKEN} to tie a single launch together.
     * @param callback The {@link InstantAppResolutionCallback} to provide results to.
     *
     * @see InstantAppResolveInfo
     */
    public void onGetInstantAppResolveInfo(@NonNull Intent sanitizedIntent,
            @Nullable int[] hostDigestPrefix, @NonNull UserHandle userHandle,
            @NonNull String token, @NonNull InstantAppResolutionCallback callback) {
        // If not overridden, forward to the old method.
        onGetInstantAppResolveInfo(sanitizedIntent, hostDigestPrefix, token, callback);
    }

    /**
     * Called to retrieve intent filters for potentially matching instant applications. Unlike
     * {@link #onGetInstantAppResolveInfo(Intent, int[], UserHandle, String,
     * InstantAppResolutionCallback)}, the response may take as long as necessary to respond. All
     * {@link InstantAppResolveInfo}s provided in response to this method must be completely
     * populated.
     *
     * @param sanitizedIntent The sanitized {@link Intent} used for resolution.
     * @param hostDigestPrefix The hash prefix of the instant app's domain or null if no host is
     *                         defined.
     * @param userHandle The user for which to resolve the instant app.
     * @param token A unique identifier that was provided in {@link #onGetInstantAppResolveInfo(
     *              Intent, int[], UserHandle, String, InstantAppResolutionCallback)} and provided
     *              to the currently visible installer via {@link Intent#EXTRA_INSTANT_APP_TOKEN}.
     * @param callback The {@link InstantAppResolutionCallback} to provide results to.
     */
    public void onGetInstantAppIntentFilter(@NonNull Intent sanitizedIntent,
            @Nullable int[] hostDigestPrefix, @NonNull UserHandle userHandle,
            @NonNull String token, @NonNull InstantAppResolutionCallback callback) {
        // If not overridden, forward to the old method.
        onGetInstantAppIntentFilter(sanitizedIntent, hostDigestPrefix, token, callback);
    }

    /**
     * Returns a {@link Looper} to perform service operations on.
     */
    Looper getLooper() {
        return getBaseContext().getMainLooper();
    }

    @Override
    public final void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        mHandler = new ServiceHandler(getLooper());
    }

    @Override
    public final IBinder onBind(Intent intent) {
        return new IInstantAppResolver.Stub() {
            @Override
            public void getInstantAppResolveInfoList(Intent sanitizedIntent, int[] digestPrefix,
                    int userId, String token, int sequence, IRemoteCallback callback) {
                if (DEBUG_INSTANT) {
                    Slog.v(TAG, "[" + token + "] Phase1 called; posting");
                }
                final SomeArgs args = SomeArgs.obtain();
                args.arg1 = callback;
                args.arg2 = digestPrefix;
                args.arg3 = userId;
                args.arg4 = token;
                args.arg5 = sanitizedIntent;
                mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO,
                        sequence, 0, args).sendToTarget();
            }

            @Override
            public void getInstantAppIntentFilterList(Intent sanitizedIntent,
                    int[] digestPrefix, int userId, String token, IRemoteCallback callback) {
                if (DEBUG_INSTANT) {
                    Slog.v(TAG, "[" + token + "] Phase2 called; posting");
                }
                final SomeArgs args = SomeArgs.obtain();
                args.arg1 = callback;
                args.arg2 = digestPrefix;
                args.arg3 = userId;
                args.arg4 = token;
                args.arg5 = sanitizedIntent;
                mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER,
                        args).sendToTarget();
            }
        };
    }

    /**
     * Callback to post results from instant app resolution.
     */
    public static final class InstantAppResolutionCallback {
        private final IRemoteCallback mCallback;
        private final int mSequence;
        InstantAppResolutionCallback(int sequence, IRemoteCallback callback) {
            mCallback = callback;
            mSequence = sequence;
        }

        public void onInstantAppResolveInfo(List<InstantAppResolveInfo> resolveInfo) {
            final Bundle data = new Bundle();
            data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
            data.putInt(EXTRA_SEQUENCE, mSequence);
            try {
                mCallback.sendResult(data);
            } catch (RemoteException e) {
            }
        }
    }

    private final class ServiceHandler extends Handler {
        public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1;
        public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2;
        public ServiceHandler(Looper looper) {
            super(looper, null /*callback*/, true /*async*/);
        }

        @Override
        @SuppressWarnings("unchecked")
        public void handleMessage(Message message) {
            final int action = message.what;
            switch (action) {
                case MSG_GET_INSTANT_APP_RESOLVE_INFO: {
                    final SomeArgs args = (SomeArgs) message.obj;
                    final IRemoteCallback callback = (IRemoteCallback) args.arg1;
                    final int[] digestPrefix = (int[]) args.arg2;
                    final int userId = (int) args.arg3;
                    final String token = (String) args.arg4;
                    final Intent intent = (Intent) args.arg5;
                    final int sequence = message.arg1;
                    if (DEBUG_INSTANT) {
                        Slog.d(TAG, "[" + token + "] Phase1 request;"
                                + " prefix: " + Arrays.toString(digestPrefix)
                                + ", userId: " + userId);
                    }
                    onGetInstantAppResolveInfo(intent, digestPrefix, UserHandle.of(userId), token,
                            new InstantAppResolutionCallback(sequence, callback));
                } break;

                case MSG_GET_INSTANT_APP_INTENT_FILTER: {
                    final SomeArgs args = (SomeArgs) message.obj;
                    final IRemoteCallback callback = (IRemoteCallback) args.arg1;
                    final int[] digestPrefix = (int[]) args.arg2;
                    final int userId = (int) args.arg3;
                    final String token = (String) args.arg4;
                    final Intent intent = (Intent) args.arg5;
                    if (DEBUG_INSTANT) {
                        Slog.d(TAG, "[" + token + "] Phase2 request;"
                                + " prefix: " + Arrays.toString(digestPrefix)
                                + ", userId: " + userId);
                    }
                    onGetInstantAppIntentFilter(intent, digestPrefix, UserHandle.of(userId), token,
                            new InstantAppResolutionCallback(-1 /*sequence*/, callback));
                } break;

                default: {
                    throw new IllegalArgumentException("Unknown message: " + action);
                }
            }
        }
    }
}
