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