VoiceInteractionSession.java revision 18f0d357f9693fe787a3e3777d8fdf01357a6e3f
1/** 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.service.voice; 18 19import android.content.Context; 20import android.os.Binder; 21import android.os.Bundle; 22import android.os.Handler; 23import android.os.IBinder; 24import android.os.Message; 25import android.os.RemoteException; 26import android.util.ArrayMap; 27import android.util.Log; 28import com.android.internal.app.IVoiceInteractor; 29import com.android.internal.app.IVoiceInteractorCallback; 30import com.android.internal.app.IVoiceInteractorRequest; 31import com.android.internal.os.HandlerCaller; 32import com.android.internal.os.SomeArgs; 33 34public abstract class VoiceInteractionSession { 35 static final String TAG = "VoiceInteractionSession"; 36 static final boolean DEBUG = true; 37 38 final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() { 39 @Override 40 public IVoiceInteractorRequest startConfirmation(String callingPackage, 41 IVoiceInteractorCallback callback, String prompt, Bundle extras) { 42 Request request = findRequest(callback, true); 43 mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_START_CONFIRMATION, 44 new Caller(callingPackage, Binder.getCallingUid()), request, 45 prompt, extras)); 46 return request.mInterface; 47 } 48 49 @Override 50 public IVoiceInteractorRequest startCommand(String callingPackage, 51 IVoiceInteractorCallback callback, String command, Bundle extras) { 52 Request request = findRequest(callback, true); 53 mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_START_COMMAND, 54 new Caller(callingPackage, Binder.getCallingUid()), request, 55 command, extras)); 56 return request.mInterface; 57 } 58 59 @Override 60 public boolean[] supportsCommands(String callingPackage, String[] commands) { 61 Message msg = mHandlerCaller.obtainMessageIOO(MSG_SUPPORTS_COMMANDS, 62 0, new Caller(callingPackage, Binder.getCallingUid()), commands); 63 SomeArgs args = mHandlerCaller.sendMessageAndWait(msg); 64 if (args != null) { 65 boolean[] res = (boolean[])args.arg1; 66 args.recycle(); 67 return res; 68 } 69 return new boolean[commands.length]; 70 } 71 }; 72 73 final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() { 74 }; 75 76 public static class Request { 77 final IVoiceInteractorRequest mInterface = new IVoiceInteractorRequest.Stub() { 78 @Override 79 public void cancel() throws RemoteException { 80 mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_CANCEL, Request.this)); 81 } 82 }; 83 final IVoiceInteractorCallback mCallback; 84 final HandlerCaller mHandlerCaller; 85 Request(IVoiceInteractorCallback callback, HandlerCaller handlerCaller) { 86 mCallback = callback; 87 mHandlerCaller = handlerCaller; 88 } 89 90 public void sendConfirmResult(boolean confirmed, Bundle result) { 91 try { 92 if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface 93 + " confirmed=" + confirmed + " result=" + result); 94 mCallback.deliverConfirmationResult(mInterface, confirmed, result); 95 } catch (RemoteException e) { 96 } 97 } 98 99 public void sendCommandResult(boolean complete, Bundle result) { 100 try { 101 if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface 102 + " result=" + result); 103 mCallback.deliverCommandResult(mInterface, complete, result); 104 } catch (RemoteException e) { 105 } 106 } 107 108 public void sendCancelResult() { 109 try { 110 if (DEBUG) Log.d(TAG, "sendCancelResult: req=" + mInterface); 111 mCallback.deliverCancel(mInterface); 112 } catch (RemoteException e) { 113 } 114 } 115 } 116 117 public static class Caller { 118 final String packageName; 119 final int uid; 120 121 Caller(String _packageName, int _uid) { 122 packageName = _packageName; 123 uid = _uid; 124 } 125 } 126 127 static final int MSG_START_CONFIRMATION = 1; 128 static final int MSG_START_COMMAND = 2; 129 static final int MSG_SUPPORTS_COMMANDS = 3; 130 static final int MSG_CANCEL = 4; 131 132 final Context mContext; 133 final HandlerCaller mHandlerCaller; 134 final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() { 135 @Override 136 public void executeMessage(Message msg) { 137 SomeArgs args = (SomeArgs)msg.obj; 138 switch (msg.what) { 139 case MSG_START_CONFIRMATION: 140 if (DEBUG) Log.d(TAG, "onConfirm: req=" + ((Request) args.arg2).mInterface 141 + " prompt=" + args.arg3 + " extras=" + args.arg4); 142 onConfirm((Caller)args.arg1, (Request)args.arg2, (String)args.arg3, 143 (Bundle)args.arg4); 144 break; 145 case MSG_START_COMMAND: 146 if (DEBUG) Log.d(TAG, "onCommand: req=" + ((Request) args.arg2).mInterface 147 + " command=" + args.arg3 + " extras=" + args.arg4); 148 onCommand((Caller) args.arg1, (Request) args.arg2, (String) args.arg3, 149 (Bundle) args.arg4); 150 break; 151 case MSG_SUPPORTS_COMMANDS: 152 if (DEBUG) Log.d(TAG, "onGetSupportedCommands: cmds=" + args.arg2); 153 args.arg1 = onGetSupportedCommands((Caller) args.arg1, (String[]) args.arg2); 154 break; 155 case MSG_CANCEL: 156 if (DEBUG) Log.d(TAG, "onCancel: req=" + ((Request) args.arg1).mInterface); 157 onCancel((Request)args.arg1); 158 break; 159 } 160 } 161 }; 162 163 final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>(); 164 165 public VoiceInteractionSession(Context context) { 166 this(context, new Handler()); 167 } 168 169 public VoiceInteractionSession(Context context, Handler handler) { 170 mContext = context; 171 mHandlerCaller = new HandlerCaller(context, handler.getLooper(), 172 mHandlerCallerCallback, true); 173 } 174 175 Request findRequest(IVoiceInteractorCallback callback, boolean newRequest) { 176 synchronized (this) { 177 Request req = mActiveRequests.get(callback.asBinder()); 178 if (req != null) { 179 if (newRequest) { 180 throw new IllegalArgumentException("Given request callback " + callback 181 + " is already active"); 182 } 183 return req; 184 } 185 req = new Request(callback, mHandlerCaller); 186 mActiveRequests.put(callback.asBinder(), req); 187 return req; 188 } 189 } 190 191 public abstract boolean[] onGetSupportedCommands(Caller caller, String[] commands); 192 public abstract void onConfirm(Caller caller, Request request, String prompt, Bundle extras); 193 public abstract void onCommand(Caller caller, Request request, String command, Bundle extras); 194 public abstract void onCancel(Request request); 195} 196