/*
 * Copyright (C) 2014 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.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.Log;

import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.IVoiceInteractorCallback;
import com.android.internal.app.IVoiceInteractorRequest;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.Executor;

/**
 * Interface for an {@link Activity} to interact with the user through voice.  Use
 * {@link android.app.Activity#getVoiceInteractor() Activity.getVoiceInteractor}
 * to retrieve the interface, if the activity is currently involved in a voice interaction.
 *
 * <p>The voice interactor revolves around submitting voice interaction requests to the
 * back-end voice interaction service that is working with the user.  These requests are
 * submitted with {@link #submitRequest}, providing a new instance of a
 * {@link Request} subclass describing the type of operation to perform -- currently the
 * possible requests are {@link ConfirmationRequest} and {@link CommandRequest}.
 *
 * <p>Once a request is submitted, the voice system will process it and eventually deliver
 * the result to the request object.  The application can cancel a pending request at any
 * time.
 *
 * <p>The VoiceInteractor is integrated with Activity's state saving mechanism, so that
 * if an activity is being restarted with retained state, it will retain the current
 * VoiceInteractor and any outstanding requests.  Because of this, you should always use
 * {@link Request#getActivity() Request.getActivity} to get back to the activity of a
 * request, rather than holding on to the activity instance yourself, either explicitly
 * or implicitly through a non-static inner class.
 */
public final class VoiceInteractor {
    static final String TAG = "VoiceInteractor";
    static final boolean DEBUG = false;

    static final Request[] NO_REQUESTS = new Request[0];

    /** @hide */
    public static final String KEY_CANCELLATION_SIGNAL = "key_cancellation_signal";
    /** @hide */
    public static final String KEY_KILL_SIGNAL = "key_kill_signal";

    @Nullable IVoiceInteractor mInteractor;

    @Nullable Context mContext;
    @Nullable Activity mActivity;
    boolean mRetaining;

    final HandlerCaller mHandlerCaller;
    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
        @Override
        public void executeMessage(Message msg) {
            SomeArgs args = (SomeArgs)msg.obj;
            Request request;
            boolean complete;
            switch (msg.what) {
                case MSG_CONFIRMATION_RESULT:
                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
                    if (DEBUG) Log.d(TAG, "onConfirmResult: req="
                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
                            + " confirmed=" + msg.arg1 + " result=" + args.arg2);
                    if (request != null) {
                        ((ConfirmationRequest)request).onConfirmationResult(msg.arg1 != 0,
                                (Bundle) args.arg2);
                        request.clear();
                    }
                    break;
                case MSG_PICK_OPTION_RESULT:
                    complete = msg.arg1 != 0;
                    request = pullRequest((IVoiceInteractorRequest)args.arg1, complete);
                    if (DEBUG) Log.d(TAG, "onPickOptionResult: req="
                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
                            + " finished=" + complete + " selection=" + args.arg2
                            + " result=" + args.arg3);
                    if (request != null) {
                        ((PickOptionRequest)request).onPickOptionResult(complete,
                                (PickOptionRequest.Option[]) args.arg2, (Bundle) args.arg3);
                        if (complete) {
                            request.clear();
                        }
                    }
                    break;
                case MSG_COMPLETE_VOICE_RESULT:
                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
                    if (DEBUG) Log.d(TAG, "onCompleteVoice: req="
                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
                            + " result=" + args.arg2);
                    if (request != null) {
                        ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg2);
                        request.clear();
                    }
                    break;
                case MSG_ABORT_VOICE_RESULT:
                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
                    if (DEBUG) Log.d(TAG, "onAbortVoice: req="
                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
                            + " result=" + args.arg2);
                    if (request != null) {
                        ((AbortVoiceRequest)request).onAbortResult((Bundle) args.arg2);
                        request.clear();
                    }
                    break;
                case MSG_COMMAND_RESULT:
                    complete = msg.arg1 != 0;
                    request = pullRequest((IVoiceInteractorRequest)args.arg1, complete);
                    if (DEBUG) Log.d(TAG, "onCommandResult: req="
                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
                            + " completed=" + msg.arg1 + " result=" + args.arg2);
                    if (request != null) {
                        ((CommandRequest)request).onCommandResult(msg.arg1 != 0,
                                (Bundle) args.arg2);
                        if (complete) {
                            request.clear();
                        }
                    }
                    break;
                case MSG_CANCEL_RESULT:
                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
                    if (DEBUG) Log.d(TAG, "onCancelResult: req="
                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request);
                    if (request != null) {
                        request.onCancel();
                        request.clear();
                    }
                    break;
            }
        }
    };

    final IVoiceInteractorCallback.Stub mCallback = new IVoiceInteractorCallback.Stub() {
        @Override
        public void deliverConfirmationResult(IVoiceInteractorRequest request, boolean finished,
                Bundle result) {
            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
                    MSG_CONFIRMATION_RESULT, finished ? 1 : 0, request, result));
        }

        @Override
        public void deliverPickOptionResult(IVoiceInteractorRequest request,
                boolean finished, PickOptionRequest.Option[] options, Bundle result) {
            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOOO(
                    MSG_PICK_OPTION_RESULT, finished ? 1 : 0, request, options, result));
        }

        @Override
        public void deliverCompleteVoiceResult(IVoiceInteractorRequest request, Bundle result) {
            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(
                    MSG_COMPLETE_VOICE_RESULT, request, result));
        }

        @Override
        public void deliverAbortVoiceResult(IVoiceInteractorRequest request, Bundle result) {
            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(
                    MSG_ABORT_VOICE_RESULT, request, result));
        }

        @Override
        public void deliverCommandResult(IVoiceInteractorRequest request, boolean complete,
                Bundle result) {
            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
                    MSG_COMMAND_RESULT, complete ? 1 : 0, request, result));
        }

        @Override
        public void deliverCancel(IVoiceInteractorRequest request) {
            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(
                    MSG_CANCEL_RESULT, request, null));
        }

        @Override
        public void destroy() {
            mHandlerCaller.getHandler().sendMessage(PooledLambda.obtainMessage(
                    VoiceInteractor::destroy, VoiceInteractor.this));
        }
    };

    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<>();
    final ArrayMap<Runnable, Executor> mOnDestroyCallbacks = new ArrayMap<>();

    static final int MSG_CONFIRMATION_RESULT = 1;
    static final int MSG_PICK_OPTION_RESULT = 2;
    static final int MSG_COMPLETE_VOICE_RESULT = 3;
    static final int MSG_ABORT_VOICE_RESULT = 4;
    static final int MSG_COMMAND_RESULT = 5;
    static final int MSG_CANCEL_RESULT = 6;

    /**
     * Base class for voice interaction requests that can be submitted to the interactor.
     * Do not instantiate this directly -- instead, use the appropriate subclass.
     */
    public static abstract class Request {
        IVoiceInteractorRequest mRequestInterface;
        Context mContext;
        Activity mActivity;
        String mName;

        Request() {
        }

        /**
         * Return the name this request was submitted through
         * {@link #submitRequest(android.app.VoiceInteractor.Request, String)}.
         */
        public String getName() {
            return mName;
        }

        /**
         * Cancel this active request.
         */
        public void cancel() {
            if (mRequestInterface == null) {
                throw new IllegalStateException("Request " + this + " is no longer active");
            }
            try {
                mRequestInterface.cancel();
            } catch (RemoteException e) {
                Log.w(TAG, "Voice interactor has died", e);
            }
        }

        /**
         * Return the current {@link Context} this request is associated with.  May change
         * if the activity hosting it goes through a configuration change.
         */
        public Context getContext() {
            return mContext;
        }

        /**
         * Return the current {@link Activity} this request is associated with.  Will change
         * if the activity is restarted such as through a configuration change.
         */
        public Activity getActivity() {
            return mActivity;
        }

        /**
         * Report from voice interaction service: this operation has been canceled, typically
         * as a completion of a previous call to {@link #cancel} or when the user explicitly
         * cancelled.
         */
        public void onCancel() {
        }

        /**
         * The request is now attached to an activity, or being re-attached to a new activity
         * after a configuration change.
         */
        public void onAttached(Activity activity) {
        }

        /**
         * The request is being detached from an activity.
         */
        public void onDetached() {
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(128);
            DebugUtils.buildShortClassTag(this, sb);
            sb.append(" ");
            sb.append(getRequestTypeName());
            sb.append(" name=");
            sb.append(mName);
            sb.append('}');
            return sb.toString();
        }

        void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
            writer.print(prefix); writer.print("mRequestInterface=");
            writer.println(mRequestInterface.asBinder());
            writer.print(prefix); writer.print("mActivity="); writer.println(mActivity);
            writer.print(prefix); writer.print("mName="); writer.println(mName);
        }

        String getRequestTypeName() {
            return "Request";
        }

        void clear() {
            mRequestInterface = null;
            mContext = null;
            mActivity = null;
            mName = null;
        }

        abstract IVoiceInteractorRequest submit(IVoiceInteractor interactor,
                String packageName, IVoiceInteractorCallback callback) throws RemoteException;
    }

    /**
     * Confirms an operation with the user via the trusted system
     * VoiceInteractionService.  This allows an Activity to complete an unsafe operation that
     * would require the user to touch the screen when voice interaction mode is not enabled.
     * The result of the confirmation will be returned through an asynchronous call to
     * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or
     * {@link #onCancel()} - these methods should be overridden to define the application specific
     *  behavior.
     *
     * <p>In some cases this may be a simple yes / no confirmation or the confirmation could
     * include context information about how the action will be completed
     * (e.g. booking a cab might include details about how long until the cab arrives)
     * so the user can give a confirmation.
     */
    public static class ConfirmationRequest extends Request {
        final Prompt mPrompt;
        final Bundle mExtras;

        /**
         * Create a new confirmation request.
         * @param prompt Optional confirmation to speak to the user or null if nothing
         *     should be spoken.
         * @param extras Additional optional information or null.
         */
        public ConfirmationRequest(@Nullable Prompt prompt, @Nullable Bundle extras) {
            mPrompt = prompt;
            mExtras = extras;
        }

        /**
         * Create a new confirmation request.
         * @param prompt Optional confirmation to speak to the user or null if nothing
         *     should be spoken.
         * @param extras Additional optional information or null.
         * @hide
         */
        public ConfirmationRequest(CharSequence prompt, Bundle extras) {
            mPrompt = (prompt != null ? new Prompt(prompt) : null);
            mExtras = extras;
        }

        /**
         * Handle the confirmation result. Override this method to define
         * the behavior when the user confirms or rejects the operation.
         * @param confirmed Whether the user confirmed or rejected the operation.
         * @param result Additional result information or null.
         */
        public void onConfirmationResult(boolean confirmed, Bundle result) {
        }

        void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
            super.dump(prefix, fd, writer, args);
            writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
            if (mExtras != null) {
                writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
            }
        }

        String getRequestTypeName() {
            return "Confirmation";
        }

        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
                IVoiceInteractorCallback callback) throws RemoteException {
            return interactor.startConfirmation(packageName, callback, mPrompt, mExtras);
        }
    }

    /**
     * Select a single option from multiple potential options with the user via the trusted system
     * VoiceInteractionService. Typically, the application would present this visually as
     * a list view to allow selecting the option by touch.
     * The result of the confirmation will be returned through an asynchronous call to
     * either {@link #onPickOptionResult} or {@link #onCancel()} - these methods should
     * be overridden to define the application specific behavior.
     */
    public static class PickOptionRequest extends Request {
        final Prompt mPrompt;
        final Option[] mOptions;
        final Bundle mExtras;

        /**
         * Represents a single option that the user may select using their voice. The 
         * {@link #getIndex()} method should be used as a unique ID to identify the option
         * when it is returned from the voice interactor.
         */
        public static final class Option implements Parcelable {
            final CharSequence mLabel;
            final int mIndex;
            ArrayList<CharSequence> mSynonyms;
            Bundle mExtras;

            /**
             * Creates an option that a user can select with their voice by matching the label
             * or one of several synonyms.
             * @param label The label that will both be matched against what the user speaks
             *     and displayed visually.
             * @hide
             */
            public Option(CharSequence label) {
                mLabel = label;
                mIndex = -1;
            }

            /**
             * Creates an option that a user can select with their voice by matching the label
             * or one of several synonyms.
             * @param label The label that will both be matched against what the user speaks
             *     and displayed visually.
             * @param index The location of this option within the overall set of options.
             *     Can be used to help identify the option when it is returned from the
             *     voice interactor.
             */
            public Option(CharSequence label, int index) {
                mLabel = label;
                mIndex = index;
            }

            /**
             * Add a synonym term to the option to indicate an alternative way the content
             * may be matched.
             * @param synonym The synonym that will be matched against what the user speaks,
             *     but not displayed.
             */
            public Option addSynonym(CharSequence synonym) {
                if (mSynonyms == null) {
                    mSynonyms = new ArrayList<>();
                }
                mSynonyms.add(synonym);
                return this;
            }

            public CharSequence getLabel() {
                return mLabel;
            }

            /**
             * Return the index that was supplied in the constructor.
             * If the option was constructed without an index, -1 is returned.
             */
            public int getIndex() {
                return mIndex;
            }

            public int countSynonyms() {
                return mSynonyms != null ? mSynonyms.size() : 0;
            }

            public CharSequence getSynonymAt(int index) {
                return mSynonyms != null ? mSynonyms.get(index) : null;
            }

            /**
             * Set optional extra information associated with this option.  Note that this
             * method takes ownership of the supplied extras Bundle.
             */
            public void setExtras(Bundle extras) {
                mExtras = extras;
            }

            /**
             * Return any optional extras information associated with this option, or null
             * if there is none.  Note that this method returns a reference to the actual
             * extras Bundle in the option, so modifications to it will directly modify the
             * extras in the option.
             */
            public Bundle getExtras() {
                return mExtras;
            }

            Option(Parcel in) {
                mLabel = in.readCharSequence();
                mIndex = in.readInt();
                mSynonyms = in.readCharSequenceList();
                mExtras = in.readBundle();
            }

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

            @Override
            public void writeToParcel(Parcel dest, int flags) {
                dest.writeCharSequence(mLabel);
                dest.writeInt(mIndex);
                dest.writeCharSequenceList(mSynonyms);
                dest.writeBundle(mExtras);
            }

            public static final @android.annotation.NonNull Parcelable.Creator<Option> CREATOR
                    = new Parcelable.Creator<Option>() {
                public Option createFromParcel(Parcel in) {
                    return new Option(in);
                }

                public Option[] newArray(int size) {
                    return new Option[size];
                }
            };
        };

        /**
         * Create a new pick option request.
         * @param prompt Optional question to be asked of the user when the options are
         *     presented or null if nothing should be asked.
         * @param options The set of {@link Option}s the user is selecting from.
         * @param extras Additional optional information or null.
         */
        public PickOptionRequest(@Nullable Prompt prompt, Option[] options,
                @Nullable Bundle extras) {
            mPrompt = prompt;
            mOptions = options;
            mExtras = extras;
        }

        /**
         * Create a new pick option request.
         * @param prompt Optional question to be asked of the user when the options are
         *     presented or null if nothing should be asked.
         * @param options The set of {@link Option}s the user is selecting from.
         * @param extras Additional optional information or null.
         * @hide
         */
        public PickOptionRequest(CharSequence prompt, Option[] options, Bundle extras) {
            mPrompt = (prompt != null ? new Prompt(prompt) : null);
            mOptions = options;
            mExtras = extras;
        }

        /**
         * Called when a single option is confirmed or narrowed to one of several options. Override
         * this method to define the behavior when the user selects an option or narrows down the
         * set of options.
         * @param finished True if the voice interaction has finished making a selection, in
         *     which case {@code selections} contains the final result.  If false, this request is
         *     still active and you will continue to get calls on it.
         * @param selections Either a single {@link Option} or one of several {@link Option}s the
         *     user has narrowed the choices down to.
         * @param result Additional optional information.
         */
        public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
        }

        void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
            super.dump(prefix, fd, writer, args);
            writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
            if (mOptions != null) {
                writer.print(prefix); writer.println("Options:");
                for (int i=0; i<mOptions.length; i++) {
                    Option op = mOptions[i];
                    writer.print(prefix); writer.print("  #"); writer.print(i); writer.println(":");
                    writer.print(prefix); writer.print("    mLabel="); writer.println(op.mLabel);
                    writer.print(prefix); writer.print("    mIndex="); writer.println(op.mIndex);
                    if (op.mSynonyms != null && op.mSynonyms.size() > 0) {
                        writer.print(prefix); writer.println("    Synonyms:");
                        for (int j=0; j<op.mSynonyms.size(); j++) {
                            writer.print(prefix); writer.print("      #"); writer.print(j);
                            writer.print(": "); writer.println(op.mSynonyms.get(j));
                        }
                    }
                    if (op.mExtras != null) {
                        writer.print(prefix); writer.print("    mExtras=");
                        writer.println(op.mExtras);
                    }
                }
            }
            if (mExtras != null) {
                writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
            }
        }

        String getRequestTypeName() {
            return "PickOption";
        }

        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
                IVoiceInteractorCallback callback) throws RemoteException {
            return interactor.startPickOption(packageName, callback, mPrompt, mOptions, mExtras);
        }
    }

    /**
     * Reports that the current interaction was successfully completed with voice, so the
     * application can report the final status to the user. When the response comes back, the
     * voice system has handled the request and is ready to switch; at that point the
     * application can start a new non-voice activity or finish.  Be sure when starting the new
     * activity to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
     * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
     * interaction task.
     */
    public static class CompleteVoiceRequest extends Request {
        final Prompt mPrompt;
        final Bundle mExtras;

        /**
         * Create a new completed voice interaction request.
         * @param prompt Optional message to speak to the user about the completion status of
         *     the task or null if nothing should be spoken.
         * @param extras Additional optional information or null.
         */
        public CompleteVoiceRequest(@Nullable Prompt prompt, @Nullable Bundle extras) {
            mPrompt = prompt;
            mExtras = extras;
        }

        /**
         * Create a new completed voice interaction request.
         * @param message Optional message to speak to the user about the completion status of
         *     the task or null if nothing should be spoken.
         * @param extras Additional optional information or null.
         * @hide
         */
        public CompleteVoiceRequest(CharSequence message, Bundle extras) {
            mPrompt = (message != null ? new Prompt(message) : null);
            mExtras = extras;
        }

        public void onCompleteResult(Bundle result) {
        }

        void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
            super.dump(prefix, fd, writer, args);
            writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
            if (mExtras != null) {
                writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
            }
        }

        String getRequestTypeName() {
            return "CompleteVoice";
        }

        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
                IVoiceInteractorCallback callback) throws RemoteException {
            return interactor.startCompleteVoice(packageName, callback, mPrompt, mExtras);
        }
    }

    /**
     * Reports that the current interaction can not be complete with voice, so the
     * application will need to switch to a traditional input UI.  Applications should
     * only use this when they need to completely bail out of the voice interaction
     * and switch to a traditional UI.  When the response comes back, the voice
     * system has handled the request and is ready to switch; at that point the application
     * can start a new non-voice activity.  Be sure when starting the new activity
     * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
     * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
     * interaction task.
     */
    public static class AbortVoiceRequest extends Request {
        final Prompt mPrompt;
        final Bundle mExtras;

        /**
         * Create a new voice abort request.
         * @param prompt Optional message to speak to the user indicating why the task could
         *     not be completed by voice or null if nothing should be spoken.
         * @param extras Additional optional information or null.
         */
        public AbortVoiceRequest(@Nullable Prompt prompt, @Nullable Bundle extras) {
            mPrompt = prompt;
            mExtras = extras;
        }

        /**
         * Create a new voice abort request.
         * @param message Optional message to speak to the user indicating why the task could
         *     not be completed by voice or null if nothing should be spoken.
         * @param extras Additional optional information or null.
         * @hide
         */
        public AbortVoiceRequest(CharSequence message, Bundle extras) {
            mPrompt = (message != null ? new Prompt(message) : null);
            mExtras = extras;
        }

        public void onAbortResult(Bundle result) {
        }

        void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
            super.dump(prefix, fd, writer, args);
            writer.print(prefix); writer.print("mPrompt="); writer.println(mPrompt);
            if (mExtras != null) {
                writer.print(prefix); writer.print("mExtras="); writer.println(mExtras);
            }
        }

        String getRequestTypeName() {
            return "AbortVoice";
        }

        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
                IVoiceInteractorCallback callback) throws RemoteException {
            return interactor.startAbortVoice(packageName, callback, mPrompt, mExtras);
        }
    }

    /**
     * Execute a vendor-specific command using the trusted system VoiceInteractionService.
     * This allows an Activity to request additional information from the user needed to
     * complete an action (e.g. booking a table might have several possible times that the
     * user could select from or an app might need the user to agree to a terms of service).
     * The result of the confirmation will be returned through an asynchronous call to
     * either {@link #onCommandResult(boolean, android.os.Bundle)} or
     * {@link #onCancel()}.
     *
     * <p>The command is a string that describes the generic operation to be performed.
     * The command will determine how the properties in extras are interpreted and the set of
     * available commands is expected to grow over time.  An example might be
     * "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number of bags as part of
     * airline check-in.  (This is not an actual working example.)
     */
    public static class CommandRequest extends Request {
        final String mCommand;
        final Bundle mArgs;

        /**
         * Create a new generic command request.
         * @param command The desired command to perform.
         * @param args Additional arguments to control execution of the command.
         */
        public CommandRequest(String command, Bundle args) {
            mCommand = command;
            mArgs = args;
        }

        /**
         * Results for CommandRequest can be returned in partial chunks.
         * The isCompleted is set to true iff all results have been returned, indicating the
         * CommandRequest has completed.
         */
        public void onCommandResult(boolean isCompleted, Bundle result) {
        }

        void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
            super.dump(prefix, fd, writer, args);
            writer.print(prefix); writer.print("mCommand="); writer.println(mCommand);
            if (mArgs != null) {
                writer.print(prefix); writer.print("mArgs="); writer.println(mArgs);
            }
        }

        String getRequestTypeName() {
            return "Command";
        }

        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
                IVoiceInteractorCallback callback) throws RemoteException {
            return interactor.startCommand(packageName, callback, mCommand, mArgs);
        }
    }

    /**
     * A set of voice prompts to use with the voice interaction system to confirm an action, select
     * an option, or do similar operations. Multiple voice prompts may be provided for variety. A
     * visual prompt must be provided, which might not match the spoken version. For example, the
     * confirmation "Are you sure you want to purchase this item?" might use a visual label like
     * "Purchase item".
     */
    public static class Prompt implements Parcelable {
        // Mandatory voice prompt. Must contain at least one item, which must not be null.
        private final CharSequence[] mVoicePrompts;

        // Mandatory visual prompt.
        private final CharSequence mVisualPrompt;

        /**
         * Constructs a prompt set.
         * @param voicePrompts An array of one or more voice prompts. Must not be empty or null.
         * @param visualPrompt A prompt to display on the screen. Must not be null.
         */
        public Prompt(@NonNull CharSequence[] voicePrompts, @NonNull CharSequence visualPrompt) {
            if (voicePrompts == null) {
                throw new NullPointerException("voicePrompts must not be null");
            }
            if (voicePrompts.length == 0) {
                throw new IllegalArgumentException("voicePrompts must not be empty");
            }
            if (visualPrompt == null) {
                throw new NullPointerException("visualPrompt must not be null");
            }
            this.mVoicePrompts = voicePrompts;
            this.mVisualPrompt = visualPrompt;
        }

        /**
         * Constructs a prompt set with single prompt used for all interactions. This is most useful
         * in test apps. Non-trivial apps should prefer the detailed constructor.
         */
        public Prompt(@NonNull CharSequence prompt) {
            this.mVoicePrompts = new CharSequence[] { prompt };
            this.mVisualPrompt = prompt;
        }

        /**
         * Returns a prompt to use for voice interactions.
         */
        @NonNull
        public CharSequence getVoicePromptAt(int index) {
            return mVoicePrompts[index];
        }

        /**
         * Returns the number of different voice prompts.
         */
        public int countVoicePrompts() {
            return mVoicePrompts.length;
        }

        /**
         * Returns the prompt to use for visual display.
         */
        @NonNull
        public CharSequence getVisualPrompt() {
            return mVisualPrompt;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(128);
            DebugUtils.buildShortClassTag(this, sb);
            if (mVisualPrompt != null && mVoicePrompts != null && mVoicePrompts.length == 1
                && mVisualPrompt.equals(mVoicePrompts[0])) {
                sb.append(" ");
                sb.append(mVisualPrompt);
            } else {
                if (mVisualPrompt != null) {
                    sb.append(" visual="); sb.append(mVisualPrompt);
                }
                if (mVoicePrompts != null) {
                    sb.append(", voice=");
                    for (int i=0; i<mVoicePrompts.length; i++) {
                        if (i > 0) sb.append(" | ");
                        sb.append(mVoicePrompts[i]);
                    }
                }
            }
            sb.append('}');
            return sb.toString();
        }

        /** Constructor to support Parcelable behavior. */
        Prompt(Parcel in) {
            mVoicePrompts = in.readCharSequenceArray();
            mVisualPrompt = in.readCharSequence();
        }

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

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeCharSequenceArray(mVoicePrompts);
            dest.writeCharSequence(mVisualPrompt);
        }

        public static final @android.annotation.NonNull Creator<Prompt> CREATOR
                = new Creator<Prompt>() {
            public Prompt createFromParcel(Parcel in) {
                return new Prompt(in);
            }

            public Prompt[] newArray(int size) {
                return new Prompt[size];
            }
        };
    }

    VoiceInteractor(IVoiceInteractor interactor, Context context, Activity activity,
            Looper looper) {
        mInteractor = interactor;
        mContext = context;
        mActivity = activity;
        mHandlerCaller = new HandlerCaller(context, looper, mHandlerCallerCallback, true);
        try {
            mInteractor.setKillCallback(new KillCallback(this));
        } catch (RemoteException e) {
            /* ignore */
        }
    }

    Request pullRequest(IVoiceInteractorRequest request, boolean complete) {
        synchronized (mActiveRequests) {
            Request req = mActiveRequests.get(request.asBinder());
            if (req != null && complete) {
                mActiveRequests.remove(request.asBinder());
            }
            return req;
        }
    }

    private ArrayList<Request> makeRequestList() {
        final int N = mActiveRequests.size();
        if (N < 1) {
            return null;
        }
        ArrayList<Request> list = new ArrayList<>(N);
        for (int i=0; i<N; i++) {
            list.add(mActiveRequests.valueAt(i));
        }
        return list;
    }

    void attachActivity(Activity activity) {
        mRetaining = false;
        if (mActivity == activity) {
            return;
        }
        mContext = activity;
        mActivity = activity;
        ArrayList<Request> reqs = makeRequestList();
        if (reqs != null) {
            for (int i=0; i<reqs.size(); i++) {
                Request req = reqs.get(i);
                req.mContext = activity;
                req.mActivity = activity;
                req.onAttached(activity);
            }
        }
    }

    void retainInstance() {
        mRetaining = true;
    }

    void detachActivity() {
        ArrayList<Request> reqs = makeRequestList();
        if (reqs != null) {
            for (int i=0; i<reqs.size(); i++) {
                Request req = reqs.get(i);
                req.onDetached();
                req.mActivity = null;
                req.mContext = null;
            }
        }
        if (!mRetaining) {
            reqs = makeRequestList();
            if (reqs != null) {
                for (int i=0; i<reqs.size(); i++) {
                    Request req = reqs.get(i);
                    req.cancel();
                }
            }
            mActiveRequests.clear();
        }
        mContext = null;
        mActivity = null;
    }

    void destroy() {
        final int requestCount = mActiveRequests.size();
        for (int i = requestCount - 1; i >= 0; i--) {
            final Request request = mActiveRequests.valueAt(i);
            mActiveRequests.removeAt(i);
            request.cancel();
        }

        final int callbackCount = mOnDestroyCallbacks.size();
        for (int i = callbackCount - 1; i >= 0; i--) {
            final Runnable callback = mOnDestroyCallbacks.keyAt(i);
            final Executor executor = mOnDestroyCallbacks.valueAt(i);
            executor.execute(callback);
            mOnDestroyCallbacks.removeAt(i);
        }

        // destroyed now
        mInteractor = null;
        if (mActivity != null) {
            mActivity.setVoiceInteractor(null);
        }
    }

    public boolean submitRequest(Request request) {
        return submitRequest(request, null);
    }

    /**
     * Submit a new {@link Request} to the voice interaction service.  The request must be
     * one of the available subclasses -- {@link ConfirmationRequest}, {@link PickOptionRequest},
     * {@link CompleteVoiceRequest}, {@link AbortVoiceRequest}, or {@link CommandRequest}.
     *
     * @param request The desired request to submit.
     * @param name An optional name for this request, or null. This can be used later with
     * {@link #getActiveRequests} and {@link #getActiveRequest} to find the request.
     *
     * @return Returns true of the request was successfully submitted, else false.
     */
    public boolean submitRequest(Request request, String name) {
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return false;
        }
        try {
            if (request.mRequestInterface != null) {
                throw new IllegalStateException("Given " + request + " is already active");
            }
            IVoiceInteractorRequest ireq = request.submit(mInteractor,
                    mContext.getOpPackageName(), mCallback);
            request.mRequestInterface = ireq;
            request.mContext = mContext;
            request.mActivity = mActivity;
            request.mName = name;
            synchronized (mActiveRequests) {
                mActiveRequests.put(ireq.asBinder(), request);
            }
            return true;
        } catch (RemoteException e) {
            Log.w(TAG, "Remove voice interactor service died", e);
            return false;
        }
    }

    /**
     * Return all currently active requests.
     */
    public Request[] getActiveRequests() {
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return null;
        }
        synchronized (mActiveRequests) {
            final int N = mActiveRequests.size();
            if (N <= 0) {
                return NO_REQUESTS;
            }
            Request[] requests = new Request[N];
            for (int i=0; i<N; i++) {
                requests[i] = mActiveRequests.valueAt(i);
            }
            return requests;
        }
    }

    /**
     * Return any currently active request that was submitted with the given name.
     *
     * @param name The name used to submit the request, as per
     * {@link #submitRequest(android.app.VoiceInteractor.Request, String)}.
     * @return Returns the active request with that name, or null if there was none.
     */
    public Request getActiveRequest(String name) {
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return null;
        }
        synchronized (mActiveRequests) {
            final int N = mActiveRequests.size();
            for (int i=0; i<N; i++) {
                Request req = mActiveRequests.valueAt(i);
                if (name == req.getName() || (name != null && name.equals(req.getName()))) {
                    return req;
                }
            }
        }
        return null;
    }

    /**
     * Queries the supported commands available from the VoiceInteractionService.
     * The command is a string that describes the generic operation to be performed.
     * An example might be "org.example.commands.PICK_DATE" to ask the user to pick
     * a date.  (Note: This is not an actual working example.)
     *
     * @param commands The array of commands to query for support.
     * @return Array of booleans indicating whether each command is supported or not.
     */
    public boolean[] supportsCommands(String[] commands) {
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return new boolean[commands.length];
        }
        try {
            boolean[] res = mInteractor.supportsCommands(mContext.getOpPackageName(), commands);
            if (DEBUG) Log.d(TAG, "supportsCommands: cmds=" + commands + " res=" + res);
            return res;
        } catch (RemoteException e) {
            throw new RuntimeException("Voice interactor has died", e);
        }
    }

    /**
     * @return whether the voice interactor is destroyed. You should not interact
     * with a destroyed voice interactor.
     */
    public boolean isDestroyed() {
        return mInteractor == null;
    }

    /**
     * Registers a callback to be called when the VoiceInteractor is destroyed.
     *
     * @param executor Executor on which to run the callback.
     * @param callback The callback to run.
     * @return whether the callback was registered.
     */
    public boolean registerOnDestroyedCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull Runnable callback) {
        Preconditions.checkNotNull(executor);
        Preconditions.checkNotNull(callback);
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return false;
        }
        mOnDestroyCallbacks.put(callback, executor);
        return true;
    }

    /**
     * Unregisters a previously registered onDestroy callback
     *
     * @param callback The callback to remove.
     * @return whether the callback was unregistered.
     */
    public boolean unregisterOnDestroyedCallback(@NonNull Runnable callback) {
        Preconditions.checkNotNull(callback);
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return false;
        }
        return mOnDestroyCallbacks.remove(callback) != null;
    }

    /**
     * Notifies the assist framework that the direct actions supported by the app changed.
     */
    public void notifyDirectActionsChanged() {
        if (isDestroyed()) {
            Log.w(TAG, "Cannot interact with a destroyed voice interactor");
            return;
        }
        try {
            mInteractor.notifyDirectActionsChanged(mActivity.getTaskId(),
                    mActivity.getAssistToken());
        } catch (RemoteException e) {
            Log.w(TAG, "Voice interactor has died", e);
        }
    }

    void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
        String innerPrefix = prefix + "    ";
        if (mActiveRequests.size() > 0) {
            writer.print(prefix); writer.println("Active voice requests:");
            for (int i=0; i<mActiveRequests.size(); i++) {
                Request req = mActiveRequests.valueAt(i);
                writer.print(prefix); writer.print("  #"); writer.print(i);
                writer.print(": ");
                writer.println(req);
                req.dump(innerPrefix, fd, writer, args);
            }
        }
        writer.print(prefix); writer.println("VoiceInteractor misc state:");
        writer.print(prefix); writer.print("  mInteractor=");
        writer.println(mInteractor.asBinder());
        writer.print(prefix); writer.print("  mActivity="); writer.println(mActivity);
    }

    private static final class KillCallback extends ICancellationSignal.Stub {
        private final WeakReference<VoiceInteractor> mInteractor;

        KillCallback(VoiceInteractor interactor) {
            mInteractor= new WeakReference<>(interactor);
        }

        @Override
        public void cancel() {
            final VoiceInteractor voiceInteractor = mInteractor.get();
            if (voiceInteractor != null) {
                voiceInteractor.mHandlerCaller.getHandler().sendMessage(PooledLambda
                        .obtainMessage(VoiceInteractor::destroy, voiceInteractor));
            }
        }
    }
}
