191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn/*
291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Copyright (C) 2014 The Android Open Source Project
391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *
491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * you may not use this file except in compliance with the License.
691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * You may obtain a copy of the License at
791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *
891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn *
1091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * See the License for the specific language governing permissions and
1491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn * limitations under the License.
1591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */
1691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
1791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpackage android.app;
1891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
19d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackbornimport android.annotation.SystemApi;
2091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.Context;
2191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Bundle;
2291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.IBinder;
2391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Looper;
2491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Message;
2591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.RemoteException;
2618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackbornimport android.util.ArrayMap;
2791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.util.Log;
2891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.app.IVoiceInteractor;
2991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.app.IVoiceInteractorCallback;
3091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.app.IVoiceInteractorRequest;
3191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.os.HandlerCaller;
3291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport com.android.internal.os.SomeArgs;
3391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
3420d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackbornimport java.util.ArrayList;
3591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
3691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn/**
37d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackborn * @hide
38a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * Interface for an {@link Activity} to interact with the user through voice.  Use
39a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * {@link android.app.Activity#getVoiceInteractor() Activity.getVoiceInteractor}
40a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * to retrieve the interface, if the activity is currently involved in a voice interaction.
41a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn *
42a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * <p>The voice interactor revolves around submitting voice interaction requests to the
43a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * back-end voice interaction service that is working with the user.  These requests are
44a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * submitted with {@link #submitRequest}, providing a new instance of a
45a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * {@link Request} subclass describing the type of operation to perform -- currently the
46a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * possible requests are {@link ConfirmationRequest} and {@link CommandRequest}.
47a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn *
48ca376027943a06e5237fd6a7df8ecf004c222d8eFabrice Di Meglio * <p>Once a request is submitted, the voice system will process it and eventually deliver
49a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * the result to the request object.  The application can cancel a pending request at any
50a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * time.
51a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn *
52a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * <p>The VoiceInteractor is integrated with Activity's state saving mechanism, so that
53a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * if an activity is being restarted with retained state, it will retain the current
54a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * VoiceInteractor and any outstanding requests.  Because of this, you should always use
55a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * {@link Request#getActivity() Request.getActivity} to get back to the activity of a
56ca376027943a06e5237fd6a7df8ecf004c222d8eFabrice Di Meglio * request, rather than holding on to the activity instance yourself, either explicitly
57a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn * or implicitly through a non-static inner class.
5891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn */
59d7c0395d26694c594c3e64b16ab647c971aeb422Dianne Hackborn@SystemApi
6091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpublic class VoiceInteractor {
6191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final String TAG = "VoiceInteractor";
6291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final boolean DEBUG = true;
6391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
6491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final IVoiceInteractor mInteractor;
6520d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
6620d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    Context mContext;
6720d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    Activity mActivity;
6820d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
6991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final HandlerCaller mHandlerCaller;
7091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
7191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
7291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void executeMessage(Message msg) {
7391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            SomeArgs args = (SomeArgs)msg.obj;
7418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            Request request;
7591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            switch (msg.what) {
7691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_CONFIRMATION_RESULT:
7718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
7891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onConfirmResult: req="
7918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
8018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                            + " confirmed=" + msg.arg1 + " result=" + args.arg2);
8118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    if (request != null) {
8218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        ((ConfirmationRequest)request).onConfirmationResult(msg.arg1 != 0,
8318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                                (Bundle) args.arg2);
8418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        request.clear();
8518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    }
8691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
87d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                case MSG_COMPLETE_VOICE_RESULT:
88d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
89d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                    if (DEBUG) Log.d(TAG, "onCompleteVoice: req="
90d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
91d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                            + " result=" + args.arg1);
92d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                    if (request != null) {
93d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                        ((CompleteVoiceRequest)request).onCompleteResult((Bundle) args.arg2);
94d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                        request.clear();
95d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                    }
96d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                    break;
97a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                case MSG_ABORT_VOICE_RESULT:
98a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
99a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onAbortVoice: req="
100a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
101a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                            + " result=" + args.arg1);
102a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                    if (request != null) {
103a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                        ((AbortVoiceRequest)request).onAbortResult((Bundle) args.arg2);
104a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                        request.clear();
105a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                    }
106a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                    break;
10791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_COMMAND_RESULT:
10818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    request = pullRequest((IVoiceInteractorRequest)args.arg1, msg.arg1 != 0);
10991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onCommandResult: req="
11018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
11191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            + " result=" + args.arg2);
11218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    if (request != null) {
11318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        ((CommandRequest)request).onCommandResult((Bundle) args.arg2);
11418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        if (msg.arg1 != 0) {
11518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                            request.clear();
11618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        }
11718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    }
11891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
11991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_CANCEL_RESULT:
12018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
12191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onCancelResult: req="
12218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request);
12318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    if (request != null) {
12418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        request.onCancel();
12518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                        request.clear();
12618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    }
12791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
12891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
12991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
13091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    };
13191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
13218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    final IVoiceInteractorCallback.Stub mCallback = new IVoiceInteractorCallback.Stub() {
13318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        @Override
13418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public void deliverConfirmationResult(IVoiceInteractorRequest request, boolean confirmed,
13518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                Bundle result) {
13618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
13718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    MSG_CONFIRMATION_RESULT, confirmed ? 1 : 0, request, result));
13818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
13918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
14018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        @Override
141d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        public void deliverCompleteVoiceResult(IVoiceInteractorRequest request, Bundle result) {
142d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(
143d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                    MSG_COMPLETE_VOICE_RESULT, request, result));
144d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        }
145d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James
146d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        @Override
147a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        public void deliverAbortVoiceResult(IVoiceInteractorRequest request, Bundle result) {
148a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(
149a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                    MSG_ABORT_VOICE_RESULT, request, result));
150a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        }
151a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn
152a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        @Override
15318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public void deliverCommandResult(IVoiceInteractorRequest request, boolean complete,
15418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                Bundle result) {
15518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
15618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    MSG_COMMAND_RESULT, complete ? 1 : 0, request, result));
15718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
15818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
15918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        @Override
16018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public void deliverCancel(IVoiceInteractorRequest request) throws RemoteException {
16118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(
16218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    MSG_CANCEL_RESULT, request));
16318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
16418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    };
16518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
16618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
16791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
16891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final int MSG_CONFIRMATION_RESULT = 1;
169d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James    static final int MSG_COMPLETE_VOICE_RESULT = 2;
170d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James    static final int MSG_ABORT_VOICE_RESULT = 3;
171d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James    static final int MSG_COMMAND_RESULT = 4;
172d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James    static final int MSG_CANCEL_RESULT = 5;
17391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
17418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    public static abstract class Request {
17518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        IVoiceInteractorRequest mRequestInterface;
17618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        Context mContext;
17718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        Activity mActivity;
17891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
17918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public Request() {
18091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
18191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
18291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void cancel() {
18391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            try {
18491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mRequestInterface.cancel();
18591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            } catch (RemoteException e) {
18691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                Log.w(TAG, "Voice interactor has died", e);
18791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
18891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
18918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
19018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public Context getContext() {
19118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            return mContext;
19218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
19318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
19418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public Activity getActivity() {
19518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            return mActivity;
19618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
19718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
19818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public void onCancel() {
19918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
20018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
20120d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        public void onAttached(Activity activity) {
20220d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
20320d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
20420d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        public void onDetached() {
20520d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
20620d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
20718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        void clear() {
20818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mRequestInterface = null;
20918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mContext = null;
21018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mActivity = null;
21118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
21218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
21318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        abstract IVoiceInteractorRequest submit(IVoiceInteractor interactor,
21418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                String packageName, IVoiceInteractorCallback callback) throws RemoteException;
21591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
21691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
21718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    public static class ConfirmationRequest extends Request {
21818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        final CharSequence mPrompt;
21918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        final Bundle mExtras;
22091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
22118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        /**
22218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * Confirms an operation with the user via the trusted system
22318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * VoiceInteractionService.  This allows an Activity to complete an unsafe operation that
22418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * would require the user to touch the screen when voice interaction mode is not enabled.
22518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * The result of the confirmation will be returned through an asynchronous call to
22618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or
22718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * {@link #onCancel()}.
22818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         *
22918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * <p>In some cases this may be a simple yes / no confirmation or the confirmation could
23018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * include context information about how the action will be completed
23118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * (e.g. booking a cab might include details about how long until the cab arrives)
23218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * so the user can give a confirmation.
23318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * @param prompt Optional confirmation text to read to the user as the action being
23418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * confirmed.
23518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * @param extras Additional optional information.
23618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         */
23718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public ConfirmationRequest(CharSequence prompt, Bundle extras) {
23818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mPrompt = prompt;
23918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mExtras = extras;
24018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
24191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
24218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public void onConfirmationResult(boolean confirmed, Bundle result) {
24318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
24491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
24518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
24618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                IVoiceInteractorCallback callback) throws RemoteException {
247a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn            return interactor.startConfirmation(packageName, callback, mPrompt, mExtras);
24818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        }
249a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn    }
250a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn
251d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James    public static class CompleteVoiceRequest extends Request {
252d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        final CharSequence mMessage;
253d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        final Bundle mExtras;
254d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James
255d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        /**
256d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * Reports that the current interaction was successfully completed with voice, so the
257d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * application can report the final status to the user. When the response comes back, the
258d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * voice system has handled the request and is ready to switch; at that point the
259d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * application can start a new non-voice activity or finish.  Be sure when starting the new
260d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * activity to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
261d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
262d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * interaction task.
263d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         *
264d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * @param message Optional message to tell user about the completion status of the task.
265d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         * @param extras Additional optional information.
266d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James         */
267d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        public CompleteVoiceRequest(CharSequence message, Bundle extras) {
268d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James            mMessage = message;
269d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James            mExtras = extras;
270d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        }
271d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James
272d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        public void onCompleteResult(Bundle result) {
273d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        }
274d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James
275d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
276d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James                IVoiceInteractorCallback callback) throws RemoteException {
277d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James            return interactor.startCompleteVoice(packageName, callback, mMessage, mExtras);
278d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James        }
279d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James    }
280d3fdb8bed8e836786253f9cd5ab640c7c5ed8501Barnaby James
281a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn    public static class AbortVoiceRequest extends Request {
282a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        final CharSequence mMessage;
283a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        final Bundle mExtras;
284a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn
285a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        /**
286a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * Reports that the current interaction can not be complete with voice, so the
287a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * application will need to switch to a traditional input UI.  Applications should
288a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * only use this when they need to completely bail out of the voice interaction
289ca376027943a06e5237fd6a7df8ecf004c222d8eFabrice Di Meglio         * and switch to a traditional UI.  When the response comes back, the voice
290a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * system has handled the request and is ready to switch; at that point the application
291a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * can start a new non-voice activity.  Be sure when starting the new activity
292a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
293a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * Intent.FLAG_ACTIVITY_NEW_TASK} to keep the new activity out of the current voice
294a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * interaction task.
295a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         *
296a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * @param message Optional message to tell user about not being able to complete
297a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * the interaction with voice.
298a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         * @param extras Additional optional information.
299a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn         */
300a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        public AbortVoiceRequest(CharSequence message, Bundle extras) {
301a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn            mMessage = message;
302a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn            mExtras = extras;
303a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        }
304a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn
305a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        public void onAbortResult(Bundle result) {
306a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        }
307a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn
308a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
309a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn                IVoiceInteractorCallback callback) throws RemoteException {
310a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn            return interactor.startAbortVoice(packageName, callback, mMessage, mExtras);
311a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn        }
312a2c076d54048258cf88ab14551ce5fdf5a09c6e8Dianne Hackborn    }
31391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
31418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    public static class CommandRequest extends Request {
31518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        final String mCommand;
31618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        final Bundle mArgs;
31718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn
31818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        /**
31918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * Execute a command using the trusted system VoiceInteractionService.
32018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * This allows an Activity to request additional information from the user needed to
32118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * complete an action (e.g. booking a table might have several possible times that the
32218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * user could select from or an app might need the user to agree to a terms of service).
32318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * The result of the confirmation will be returned through an asynchronous call to
32418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * either {@link #onCommandResult(android.os.Bundle)} or
32518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * {@link #onCancel()}.
32618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         *
32718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * <p>The command is a string that describes the generic operation to be performed.
32818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * The command will determine how the properties in extras are interpreted and the set of
32918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * available commands is expected to grow over time.  An example might be
33018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number of bags as part of
33118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * airline check-in.  (This is not an actual working example.)
33218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         *
33318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * @param command The desired command to perform.
33418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         * @param args Additional arguments to control execution of the command.
33518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn         */
33618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public CommandRequest(String command, Bundle args) {
33718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mCommand = command;
33818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            mArgs = args;
33991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
34091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
34118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        public void onCommandResult(Bundle result) {
34291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
34391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
34418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
34518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                IVoiceInteractorCallback callback) throws RemoteException {
34694d937014272bc482680234ce83438eacff21e8bDianne Hackborn            return interactor.startCommand(packageName, callback, mCommand, mArgs);
34791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
34818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn   }
34991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
35020d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    VoiceInteractor(IVoiceInteractor interactor, Context context, Activity activity,
35118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            Looper looper) {
35220d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        mInteractor = interactor;
35391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mContext = context;
35418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn        mActivity = activity;
35591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mHandlerCaller = new HandlerCaller(context, looper, mHandlerCallerCallback, true);
35691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
35791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
35818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    Request pullRequest(IVoiceInteractorRequest request, boolean complete) {
35991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        synchronized (mActiveRequests) {
36091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            Request req = mActiveRequests.get(request.asBinder());
36118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            if (req != null && complete) {
36218f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                mActiveRequests.remove(request.asBinder());
36391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
36491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            return req;
36591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
36691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
36791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
36820d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    private ArrayList<Request> makeRequestList() {
36920d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        final int N = mActiveRequests.size();
37020d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        if (N < 1) {
37120d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            return null;
37220d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
37320d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        ArrayList<Request> list = new ArrayList<Request>(N);
37420d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        for (int i=0; i<N; i++) {
37520d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            list.add(mActiveRequests.valueAt(i));
37620d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
37720d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        return list;
37820d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    }
37920d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
38020d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    void attachActivity(Activity activity) {
38120d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        if (mActivity == activity) {
38220d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            return;
38320d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
38420d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        mContext = activity;
38520d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        mActivity = activity;
38620d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        ArrayList<Request> reqs = makeRequestList();
38720d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        if (reqs != null) {
38820d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            for (int i=0; i<reqs.size(); i++) {
38920d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                Request req = reqs.get(i);
39020d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                req.mContext = activity;
39120d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                req.mActivity = activity;
39220d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                req.onAttached(activity);
39320d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            }
39420d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
39520d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    }
39620d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
39720d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    void detachActivity() {
39820d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        ArrayList<Request> reqs = makeRequestList();
39920d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        if (reqs != null) {
40020d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            for (int i=0; i<reqs.size(); i++) {
40120d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                Request req = reqs.get(i);
40220d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                req.onDetached();
40320d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                req.mActivity = null;
40420d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn                req.mContext = null;
40520d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn            }
40620d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        }
40720d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        mContext = null;
40820d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn        mActivity = null;
40920d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn    }
41020d94749043d0851f1da10c7749fd7eb13a35081Dianne Hackborn
41118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn    public boolean submitRequest(Request request) {
41291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        try {
41318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            IVoiceInteractorRequest ireq = request.submit(mInteractor,
41418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                    mContext.getOpPackageName(), mCallback);
41518f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            request.mRequestInterface = ireq;
41618f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            request.mContext = mContext;
41718f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            request.mActivity = mActivity;
41818f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            synchronized (mActiveRequests) {
41918f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn                mActiveRequests.put(ireq.asBinder(), request);
42018f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            }
42118f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            return true;
42291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        } catch (RemoteException e) {
42318f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            Log.w(TAG, "Remove voice interactor service died", e);
42418f0d357f9693fe787a3e3777d8fdf01357a6e3fDianne Hackborn            return false;
42591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
42691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
42791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
42891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    /**
42991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     * Queries the supported commands available from the VoiceinteractionService.
43091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     * The command is a string that describes the generic operation to be performed.
43191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     * An example might be "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number
43291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     * of bags as part of airline check-in.  (This is not an actual working example.)
43391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     *
43491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     * @param commands
43591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn     */
43691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public boolean[] supportsCommands(String[] commands) {
43791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        try {
43891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            boolean[] res = mInteractor.supportsCommands(mContext.getOpPackageName(), commands);
43991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            if (DEBUG) Log.d(TAG, "supportsCommands: cmds=" + commands + " res=" + res);
44091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            return res;
44191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        } catch (RemoteException e) {
44291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            throw new RuntimeException("Voice interactor has died", e);
44391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
44491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
44591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn}
446