1 /* 2 * Copyright (C) 2015 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 17 package android.voiceinteraction.service; 18 19 import android.app.VoiceInteractor; 20 import android.app.VoiceInteractor.Prompt; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.AsyncTask; 24 import android.os.Bundle; 25 import android.service.voice.VoiceInteractionSession; 26 import android.service.voice.VoiceInteractionSession.ConfirmationRequest; 27 import android.service.voice.VoiceInteractionSession.PickOptionRequest; 28 import android.util.Log; 29 import android.voiceinteraction.common.Utils; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 35 public class MainInteractionSession extends VoiceInteractionSession { 36 static final String TAG = "MainInteractionSession"; 37 38 Intent mStartIntent; 39 List<MyTask> mUsedTasks = new ArrayList<MyTask>(); 40 MainInteractionSession(Context context)41 MainInteractionSession(Context context) { 42 super(context); 43 } 44 45 @Override onCreate()46 public void onCreate() { 47 super.onCreate(); 48 Intent sessionStarted = new Intent(); 49 sessionStarted.setClassName("android.voiceinteraction.cts", 50 "android.voiceinteraction.cts.VoiceInteractionTestReceiver"); 51 getContext().sendBroadcast(sessionStarted); 52 } 53 54 @Override onDestroy()55 public void onDestroy() { 56 Log.i(TAG, "Canceling the Asynctask in onDestroy()"); 57 for (MyTask t : mUsedTasks) { 58 t.cancel(true); 59 } 60 super.onDestroy(); 61 } 62 63 @Override onShow(Bundle args, int showFlags)64 public void onShow(Bundle args, int showFlags) { 65 super.onShow(args, showFlags); 66 mStartIntent = args.getParcelable("intent"); 67 if (mStartIntent != null) { 68 startVoiceActivity(mStartIntent); 69 } else if ((showFlags & SHOW_SOURCE_ACTIVITY) == SHOW_SOURCE_ACTIVITY) { 70 // Verify args 71 if (args == null 72 || !Utils.PRIVATE_OPTIONS_VALUE.equals( 73 args.getString(Utils.PRIVATE_OPTIONS_KEY))) { 74 throw new IllegalArgumentException("Incorrect arguments for SHOW_SOURCE_ACTIVITY"); 75 } 76 } 77 } 78 assertPromptFromTestApp(CharSequence prompt, Bundle extras)79 void assertPromptFromTestApp(CharSequence prompt, Bundle extras) { 80 String str = prompt.toString(); 81 if (str.equals(Utils.TEST_PROMPT)) { 82 Log.i(TAG, "prompt received ok from TestApp in Session"); 83 } else { 84 Utils.addErrorResult(extras, "Invalid prompt received: " + str); 85 } 86 } 87 newTask()88 synchronized MyTask newTask() { 89 MyTask t = new MyTask(); 90 mUsedTasks.add(t); 91 return t; 92 } 93 94 @Override onGetSupportedCommands(String[] commands)95 public boolean[] onGetSupportedCommands(String[] commands) { 96 boolean[] results = new boolean[commands.length]; 97 Log.i(TAG, "in onGetSupportedCommands"); 98 for (int idx = 0; idx < commands.length; idx++) { 99 results[idx] = Utils.TEST_COMMAND.equals(commands[idx]); 100 Log.i(TAG, "command " + commands[idx] + ", support = " + results[idx]); 101 } 102 return results; 103 } 104 105 @Override onRequestConfirmation(ConfirmationRequest request)106 public void onRequestConfirmation(ConfirmationRequest request) { 107 Bundle extras = request.getExtras(); 108 CharSequence prompt = request.getVoicePrompt().getVoicePromptAt(0); 109 Log.i(TAG, "in Session onRequestConfirmation recvd. prompt=" + prompt + 110 ", extras=" + Utils.toBundleString(extras)); 111 assertPromptFromTestApp(prompt, extras); 112 AsyncTaskArg asyncTaskArg = new AsyncTaskArg().setRequest(request).setExtras(extras); 113 if (isTestTypeCancel(extras)) { 114 Log.i(TAG, "Sending Cancel."); 115 newTask().execute( 116 asyncTaskArg.setTestType(Utils.TestCaseType.CONFIRMATION_REQUEST_CANCEL_TEST)); 117 } else { 118 Log.i(TAG, "in Session sending sendConfirmationResult. " + 119 Utils.toBundleString(extras)); 120 newTask().execute( 121 asyncTaskArg.setTestType(Utils.TestCaseType.CONFIRMATION_REQUEST_TEST)); 122 } 123 } 124 125 @Override onRequestCompleteVoice(CompleteVoiceRequest request)126 public void onRequestCompleteVoice(CompleteVoiceRequest request) { 127 Bundle extras = request.getExtras(); 128 CharSequence prompt = request.getVoicePrompt().getVoicePromptAt(0); 129 Log.i(TAG, "in Session onRequestCompleteVoice recvd. message=" + 130 prompt + ", extras=" + Utils.toBundleString(extras)); 131 assertPromptFromTestApp(prompt, extras); 132 AsyncTaskArg asyncTaskArg = new AsyncTaskArg().setRequest(request).setExtras(extras); 133 if (isTestTypeCancel(extras)) { 134 Log.i(TAG, "Sending Cancel."); 135 newTask().execute( 136 asyncTaskArg.setTestType(Utils.TestCaseType.COMPLETION_REQUEST_CANCEL_TEST)); 137 } else { 138 Log.i(TAG, "in Session sending sendConfirmationResult. " + 139 Utils.toBundleString(extras)); 140 newTask().execute( 141 asyncTaskArg.setTestType(Utils.TestCaseType.COMPLETION_REQUEST_TEST)); 142 } 143 } 144 145 @Override onRequestAbortVoice(AbortVoiceRequest request)146 public void onRequestAbortVoice(AbortVoiceRequest request) { 147 Bundle extras = request.getExtras(); 148 CharSequence prompt = request.getVoicePrompt().getVoicePromptAt(0); 149 Log.i(TAG, "in Session onRequestAbortVoice recvd. message=" + 150 prompt + ", extras=" + Utils.toBundleString(extras)); 151 assertPromptFromTestApp(prompt, extras); 152 AsyncTaskArg asyncTaskArg = new AsyncTaskArg().setRequest(request).setExtras(extras); 153 if (isTestTypeCancel(extras)) { 154 Log.i(TAG, "Sending Cancel."); 155 newTask().execute( 156 asyncTaskArg.setTestType(Utils.TestCaseType.ABORT_REQUEST_CANCEL_TEST)); 157 } else { 158 Log.i(TAG, "in Session sending sendAbortResult. " + 159 Utils.toBundleString(extras)); 160 newTask().execute(asyncTaskArg.setTestType(Utils.TestCaseType.ABORT_REQUEST_TEST)); 161 } 162 } 163 164 @Override onRequestCommand(CommandRequest request)165 public void onRequestCommand(CommandRequest request) { 166 Bundle extras = request.getExtras(); 167 Log.i(TAG, "in Session onRequestCommand recvd. Bundle = " + 168 Utils.toBundleString(extras)); 169 170 // Make sure that the input request has Utils.TEST_COMMAND sent by TestApp 171 String command = request.getCommand(); 172 if (command.equals(Utils.TEST_COMMAND)) { 173 Log.i(TAG, "command received ok from TestApp in Session"); 174 } else { 175 Utils.addErrorResult(extras, "Invalid TEST_COMMAND received: " + command); 176 } 177 // Add a field and value in the bundle to be sent to TestApp. 178 // TestApp will ensure that these are transmitted correctly. 179 extras.putString(Utils.TEST_ONCOMMAND_RESULT, Utils.TEST_ONCOMMAND_RESULT_VALUE); 180 AsyncTaskArg asyncTaskArg = new AsyncTaskArg().setRequest(request).setExtras(extras); 181 if (isTestTypeCancel(extras)) { 182 Log.i(TAG, "Sending Cancel."); 183 newTask().execute( 184 asyncTaskArg.setTestType(Utils.TestCaseType.COMMANDREQUEST_CANCEL_TEST)); 185 } else { 186 Log.i(TAG, "in Session sending sendResult. " + 187 Utils.toBundleString(extras) + ", string_in_bundle: " + 188 Utils.TEST_ONCOMMAND_RESULT + " = " + Utils.TEST_ONCOMMAND_RESULT_VALUE); 189 newTask().execute(asyncTaskArg.setTestType(Utils.TestCaseType.COMMANDREQUEST_TEST)); 190 } 191 } 192 assertPickOptionsFromTestApp(VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras)193 void assertPickOptionsFromTestApp(VoiceInteractor.PickOptionRequest.Option[] options, 194 Bundle extras) { 195 if ((options.length != 2) || 196 !options[0].getLabel().toString().equals(Utils.PICKOPTON_1) || 197 !options[1].getLabel().toString().equals(Utils.PICKOPTON_2)) { 198 Utils.addErrorResult(extras, "Pickoptions Not received correctly in Session."); 199 } else { 200 Log.i(TAG, "Pickoptions received ok from TestApp in Session"); 201 } 202 } 203 204 @Override onRequestPickOption(PickOptionRequest request)205 public void onRequestPickOption(PickOptionRequest request) { 206 Bundle extras = request.getExtras(); 207 CharSequence prompt = request.getVoicePrompt().getVoicePromptAt(0); 208 Log.i(TAG, "in Session onRequestPickOption recvd. message=" + 209 prompt + ", options = " + Utils.toOptionsString(request.getOptions()) + 210 ", extras=" + Utils.toBundleString(extras)); 211 VoiceInteractor.PickOptionRequest.Option[] picked 212 = new VoiceInteractor.PickOptionRequest.Option[1]; 213 assertPromptFromTestApp(prompt, extras); 214 assertPickOptionsFromTestApp(request.getOptions(), extras); 215 picked[0] = new VoiceInteractor.PickOptionRequest.Option(Utils.PICKOPTON_3, 0); 216 AsyncTaskArg asyncTaskArg = new AsyncTaskArg().setRequest(request) 217 .setExtras(extras) 218 .setPickedOptions(picked); 219 if (isTestTypeCancel(extras)) { 220 Log.i(TAG, "in MainInteractionSession, Sending Cancel."); 221 newTask().execute( 222 asyncTaskArg.setTestType(Utils.TestCaseType.PICKOPTION_REQUEST_CANCEL_TEST)); 223 } else { 224 Log.i(TAG, "in MainInteractionSession sending sendPickOptionResult. " + 225 Utils.toBundleString(extras)); 226 newTask().execute(asyncTaskArg.setTestType(Utils.TestCaseType.PICKOPTION_REQUEST_TEST)); 227 } 228 } 229 isTestTypeCancel(Bundle extras)230 public static final boolean isTestTypeCancel(Bundle extras) { 231 Utils.TestCaseType testCaseType; 232 try { 233 testCaseType = Utils.TestCaseType.valueOf(extras.getString(Utils.TESTCASE_TYPE)); 234 } catch (IllegalArgumentException | NullPointerException e) { 235 Log.wtf(TAG, "unexpected testCaseType value in Bundle received", e); 236 return true; 237 } 238 return testCaseType == Utils.TestCaseType.COMPLETION_REQUEST_CANCEL_TEST || 239 testCaseType == Utils.TestCaseType.COMMANDREQUEST_CANCEL_TEST || 240 testCaseType == Utils.TestCaseType.CONFIRMATION_REQUEST_CANCEL_TEST || 241 testCaseType == Utils.TestCaseType.PICKOPTION_REQUEST_CANCEL_TEST || 242 testCaseType == Utils.TestCaseType.ABORT_REQUEST_CANCEL_TEST; 243 } 244 245 private class AsyncTaskArg { 246 ConfirmationRequest confReq; 247 CommandRequest commandReq; 248 CompleteVoiceRequest compReq; 249 AbortVoiceRequest abortReq; 250 PickOptionRequest pickReq; 251 Bundle extras; 252 VoiceInteractor.PickOptionRequest.Option[] picked; 253 Utils.TestCaseType testType; 254 setTestType(Utils.TestCaseType t)255 AsyncTaskArg setTestType(Utils.TestCaseType t) {testType = t; return this;} setRequest(CommandRequest r)256 AsyncTaskArg setRequest(CommandRequest r) {commandReq = r; return this;} setRequest(ConfirmationRequest r)257 AsyncTaskArg setRequest(ConfirmationRequest r) {confReq = r; return this;} setRequest(CompleteVoiceRequest r)258 AsyncTaskArg setRequest(CompleteVoiceRequest r) {compReq = r; return this;} setRequest(AbortVoiceRequest r)259 AsyncTaskArg setRequest(AbortVoiceRequest r) {abortReq = r; return this;} setRequest(PickOptionRequest r)260 AsyncTaskArg setRequest(PickOptionRequest r) {pickReq = r; return this;} setExtras(Bundle e)261 AsyncTaskArg setExtras(Bundle e) {extras = e; return this;} setPickedOptions(VoiceInteractor.PickOptionRequest.Option[] p)262 AsyncTaskArg setPickedOptions(VoiceInteractor.PickOptionRequest.Option[] p) { 263 picked = p; 264 return this; 265 } 266 } 267 268 private class MyTask extends AsyncTask<AsyncTaskArg, Void, Void> { 269 @Override doInBackground(AsyncTaskArg... params)270 protected Void doInBackground(AsyncTaskArg... params) { 271 AsyncTaskArg arg = params[0]; 272 Log.i(TAG, "in MyTask - doInBackground: requestType = " + 273 arg.testType.toString()); 274 switch (arg.testType) { 275 case ABORT_REQUEST_CANCEL_TEST: 276 arg.abortReq.cancel(); 277 break; 278 case ABORT_REQUEST_TEST: 279 arg.abortReq.sendAbortResult(arg.extras); 280 break; 281 case COMMANDREQUEST_CANCEL_TEST: 282 arg.commandReq.cancel(); 283 break; 284 case COMMANDREQUEST_TEST: 285 Log.i(TAG, "in MyTask sendResult. " + 286 Utils.toBundleString(arg.extras) + ", string_in_bundle: " + 287 Utils.TEST_ONCOMMAND_RESULT + " = " + 288 Utils.TEST_ONCOMMAND_RESULT_VALUE); 289 arg.commandReq.sendResult(arg.extras); 290 break; 291 case COMPLETION_REQUEST_CANCEL_TEST: 292 arg.compReq.cancel(); 293 break; 294 case COMPLETION_REQUEST_TEST: 295 arg.compReq.sendCompleteResult(arg.extras); 296 break; 297 case CONFIRMATION_REQUEST_CANCEL_TEST: 298 arg.confReq.cancel(); 299 break; 300 case CONFIRMATION_REQUEST_TEST: 301 arg.confReq.sendConfirmationResult(true, arg.extras); 302 break; 303 case PICKOPTION_REQUEST_CANCEL_TEST: 304 arg.pickReq.cancel(); 305 break; 306 case PICKOPTION_REQUEST_TEST: 307 StringBuilder buf = new StringBuilder(); 308 for (VoiceInteractor.PickOptionRequest.Option s : arg.picked) { 309 buf.append("option: " + s.toString() + ", "); 310 } 311 Log.i(TAG, "******** Sending PickoptionResult: " + 312 "picked: size = " + arg.picked.length + 313 ", Options = " + buf.toString() + 314 ", Bundle: " + Utils.toBundleString(arg.extras)); 315 arg.pickReq.sendPickOptionResult(arg.picked, arg.extras); 316 break; 317 default: 318 Log.i(TAG, "Doing nothing for the testcase type: " + arg.testType); 319 break; 320 } 321 return null; 322 } 323 } 324 } 325