VoiceInteractionSession.java revision 91097de49b0f683b00e26a75dbc0ac6082344137
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.service.voice;
1891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
1991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.content.Context;
2091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Binder;
2191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Bundle;
2291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Handler;
2391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.IBinder;
2491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.Message;
2591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornimport android.os.RemoteException;
2691097de49b0f683b00e26a75dbc0ac6082344137Dianne 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
3491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackbornpublic abstract class VoiceInteractionSession {
3591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final String TAG = "VoiceInteractionSession";
3691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final boolean DEBUG = true;
3791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
3891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() {
3991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
4091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public IVoiceInteractorRequest startConfirmation(String callingPackage,
4191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                IVoiceInteractorCallback callback, String prompt, Bundle extras) {
4291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            Request request = findRequest(callback, true);
4391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_START_CONFIRMATION,
4491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    new Caller(callingPackage, Binder.getCallingUid()), request,
4591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    prompt, extras));
4691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            return request.mInterface;
4791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
4891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
4991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
5091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public IVoiceInteractorRequest startCommand(String callingPackage,
5191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                IVoiceInteractorCallback callback, String command, Bundle extras) {
5291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            Request request = findRequest(callback, true);
5391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_START_COMMAND,
5491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    new Caller(callingPackage, Binder.getCallingUid()), request,
5591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    command, extras));
5691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            return request.mInterface;
5791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
5891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
5991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
6091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public boolean[] supportsCommands(String callingPackage, String[] commands) {
6191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            Message msg = mHandlerCaller.obtainMessageIOO(MSG_SUPPORTS_COMMANDS,
6291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    0, new Caller(callingPackage, Binder.getCallingUid()), commands);
6391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            SomeArgs args = mHandlerCaller.sendMessageAndWait(msg);
6491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            if (args != null) {
6591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                boolean[] res = (boolean[])args.arg1;
6691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                args.recycle();
6791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                return res;
6891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
6991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            return new boolean[commands.length];
7091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
7191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    };
7291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
7391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
7491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    };
7591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
7691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public static class Request {
7791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        final IVoiceInteractorRequest mInterface = new IVoiceInteractorRequest.Stub() {
7891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            @Override
7991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            public void cancel() throws RemoteException {
8091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_CANCEL, Request.this));
8191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
8291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        };
8391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        final IVoiceInteractorCallback mCallback;
8491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        final HandlerCaller mHandlerCaller;
8591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        Request(IVoiceInteractorCallback callback, HandlerCaller handlerCaller) {
8691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mCallback = callback;
8791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mHandlerCaller = handlerCaller;
8891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
8991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
9091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void sendConfirmResult(boolean confirmed, Bundle result) {
9191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            try {
9291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface
9391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        + " confirmed=" + confirmed + " result=" + result);
9491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mCallback.deliverConfirmationResult(mInterface, confirmed, result);
9591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            } catch (RemoteException e) {
9691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
9791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
9891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
9991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void sendCommandResult(Bundle result) {
10091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            try {
10191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface
10291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                        + " result=" + result);
10391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mCallback.deliverCommandResult(mInterface, result);
10491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            } catch (RemoteException e) {
10591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
10691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
10791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
10891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void sendCancelResult() {
10991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            try {
11091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                if (DEBUG) Log.d(TAG, "sendCancelResult: req=" + mInterface);
11191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mCallback.deliverCancel(mInterface);
11291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            } catch (RemoteException e) {
11391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
11491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
11591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
11691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
11791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public static class Caller {
11891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        final String packageName;
11991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        final int uid;
12091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
12191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        Caller(String _packageName, int _uid) {
12291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            packageName = _packageName;
12391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            uid = _uid;
12491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
12591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
12691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
12791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final int MSG_START_CONFIRMATION = 1;
12891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final int MSG_START_COMMAND = 2;
12991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final int MSG_SUPPORTS_COMMANDS = 3;
13091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    static final int MSG_CANCEL = 4;
13191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
13291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final Context mContext;
13391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final HandlerCaller mHandlerCaller;
13491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
13591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        @Override
13691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        public void executeMessage(Message msg) {
13791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            SomeArgs args = (SomeArgs)msg.obj;
13891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            switch (msg.what) {
13991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_START_CONFIRMATION:
14091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onConfirm: req=" + ((Request) args.arg2).mInterface
14191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            + " prompt=" + args.arg3 + " extras=" + args.arg4);
14291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    onConfirm((Caller)args.arg1, (Request)args.arg2, (String)args.arg3,
14391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            (Bundle)args.arg4);
14491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
14591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_START_COMMAND:
14691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onCommand: req=" + ((Request) args.arg2).mInterface
14791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            + " command=" + args.arg3 + " extras=" + args.arg4);
14891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    onCommand((Caller) args.arg1, (Request) args.arg2, (String) args.arg3,
14991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            (Bundle) args.arg4);
15091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
15191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_SUPPORTS_COMMANDS:
15291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onGetSupportedCommands: cmds=" + args.arg2);
15391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    args.arg1 = onGetSupportedCommands((Caller) args.arg1, (String[]) args.arg2);
15491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
15591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                case MSG_CANCEL:
15691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    if (DEBUG) Log.d(TAG, "onCancel: req=" + ((Request) args.arg1).mInterface);
15791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    onCancel((Request)args.arg1);
15891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    break;
15991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
16091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
16191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    };
16291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
16391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
16491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
16591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public VoiceInteractionSession(Context context) {
16691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        this(context, new Handler());
16791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
16891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
16991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public VoiceInteractionSession(Context context, Handler handler) {
17091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mContext = context;
17191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        mHandlerCaller = new HandlerCaller(context, handler.getLooper(),
17291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                mHandlerCallerCallback, true);
17391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
17491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
17591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    Request findRequest(IVoiceInteractorCallback callback, boolean newRequest) {
17691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        synchronized (this) {
17791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            Request req = mActiveRequests.get(callback.asBinder());
17891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            if (req != null) {
17991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                if (newRequest) {
18091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                    throw new IllegalArgumentException("Given request callback " + callback
18191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                            + " is already active");
18291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                }
18391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn                return req;
18491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            }
18591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            req = new Request(callback, mHandlerCaller);
18691097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            mActiveRequests.put(callback.asBinder(), req);
18791097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn            return req;
18891097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn        }
18991097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    }
19091097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn
19191097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public abstract boolean[] onGetSupportedCommands(Caller caller, String[] commands);
19291097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public abstract void onConfirm(Caller caller, Request request, String prompt, Bundle extras);
19391097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public abstract void onCommand(Caller caller, Request request, String command, Bundle extras);
19491097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn    public abstract void onCancel(Request request);
19591097de49b0f683b00e26a75dbc0ac6082344137Dianne Hackborn}
196