• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.test.voiceinteraction;
18 
19 import android.app.ActivityManager;
20 import android.app.VoiceInteractor;
21 import android.app.assist.AssistContent;
22 import android.app.assist.AssistStructure;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.graphics.Bitmap;
26 import android.net.Uri;
27 import android.os.Bundle;
28 import android.service.voice.VoiceInteractionSession;
29 import android.util.Log;
30 import android.view.View;
31 import android.widget.Button;
32 import android.widget.CheckBox;
33 import android.widget.ImageView;
34 import android.widget.TextView;
35 
36 public class MainInteractionSession extends VoiceInteractionSession
37         implements View.OnClickListener {
38     static final String TAG = "MainInteractionSession";
39 
40     Intent mStartIntent;
41     View mContentView;
42     AssistVisualizer mAssistVisualizer;
43     View mTopContent;
44     View mBottomContent;
45     TextView mText;
46     Button mTreeButton;
47     Button mTextButton;
48     Button mStartButton;
49     CheckBox mOptionsCheck;
50     View mOptionsContainer;
51     CheckBox mDisallowAssist;
52     CheckBox mDisallowScreenshot;
53     TextView mOptionsText;
54     ImageView mScreenshot;
55     ImageView mFullScreenshot;
56     Button mConfirmButton;
57     Button mCompleteButton;
58     Button mAbortButton;
59 
60     AssistStructure mAssistStructure;
61 
62     static final int STATE_IDLE = 0;
63     static final int STATE_LAUNCHING = 1;
64     static final int STATE_CONFIRM = 2;
65     static final int STATE_PICK_OPTION = 3;
66     static final int STATE_COMMAND = 4;
67     static final int STATE_ABORT_VOICE = 5;
68     static final int STATE_COMPLETE_VOICE = 6;
69     static final int STATE_DONE = 7;
70 
71     int mState = STATE_IDLE;
72     VoiceInteractor.PickOptionRequest.Option[] mPendingOptions;
73     CharSequence mPendingPrompt;
74     Request mPendingRequest;
75     int mCurrentTask = -1;
76 
MainInteractionSession(Context context)77     MainInteractionSession(Context context) {
78         super(context);
79     }
80 
81     @Override
onCreate()82     public void onCreate() {
83         super.onCreate();
84         ActivityManager am = getContext().getSystemService(ActivityManager.class);
85         am.setWatchHeapLimit(40 * 1024 * 1024);
86     }
87 
88     @Override
onShow(Bundle args, int showFlags)89     public void onShow(Bundle args, int showFlags) {
90         super.onShow(args, showFlags);
91         Log.i(TAG, "onShow: flags=0x" + Integer.toHexString(showFlags) + " args=" + args);
92         mState = STATE_IDLE;
93         mStartIntent = args != null ? (Intent)args.getParcelable("intent") : null;
94         if (mStartIntent == null) {
95             mStartIntent = new Intent(getContext(), TestInteractionActivity.class);
96         }
97         if (mAssistVisualizer != null) {
98             mAssistVisualizer.clearAssistData();
99         }
100         onHandleScreenshot(null);
101         updateState();
102         refreshOptions();
103     }
104 
105     @Override
onHide()106     public void onHide() {
107         super.onHide();
108         if (mAssistVisualizer != null) {
109             mAssistVisualizer.clearAssistData();
110         }
111         mState = STATE_DONE;
112         updateState();
113     }
114 
115     @Override
onCreateContentView()116     public View onCreateContentView() {
117         mContentView = getLayoutInflater().inflate(R.layout.voice_interaction_session, null);
118         mAssistVisualizer = (AssistVisualizer)mContentView.findViewById(R.id.assist_visualizer);
119         if (mAssistStructure != null) {
120             mAssistVisualizer.setAssistStructure(mAssistStructure);
121         }
122         mTopContent = mContentView.findViewById(R.id.top_content);
123         mBottomContent = mContentView.findViewById(R.id.bottom_content);
124         mText = (TextView)mContentView.findViewById(R.id.text);
125         mTreeButton = (Button)mContentView.findViewById(R.id.do_tree);
126         mTreeButton.setOnClickListener(this);
127         mTextButton = (Button)mContentView.findViewById(R.id.do_text);
128         mTextButton.setOnClickListener(this);
129         mStartButton = (Button)mContentView.findViewById(R.id.start);
130         mStartButton.setOnClickListener(this);
131         mScreenshot = (ImageView)mContentView.findViewById(R.id.screenshot);
132         mScreenshot.setOnClickListener(this);
133         mFullScreenshot = (ImageView)mContentView.findViewById(R.id.full_screenshot);
134         mOptionsCheck = (CheckBox)mContentView.findViewById(R.id.show_options);
135         mOptionsCheck.setOnClickListener(this);
136         mOptionsContainer = mContentView.findViewById(R.id.options);
137         mDisallowAssist = (CheckBox)mContentView.findViewById(R.id.disallow_structure);
138         mDisallowAssist.setOnClickListener(this);
139         mDisallowScreenshot = (CheckBox)mContentView.findViewById(R.id.disallow_screenshot);
140         mDisallowScreenshot.setOnClickListener(this);
141         mOptionsText = (TextView)mContentView.findViewById(R.id.options_text);
142         mConfirmButton = (Button)mContentView.findViewById(R.id.confirm);
143         mConfirmButton.setOnClickListener(this);
144         mCompleteButton = (Button)mContentView.findViewById(R.id.complete);
145         mCompleteButton.setOnClickListener(this);
146         mAbortButton = (Button)mContentView.findViewById(R.id.abort);
147         mAbortButton.setOnClickListener(this);
148         refreshOptions();
149         return mContentView;
150     }
151 
refreshOptions()152     void refreshOptions() {
153         if (mOptionsContainer != null) {
154             if (mOptionsCheck.isChecked()) {
155                 mOptionsContainer.setVisibility(View.VISIBLE);
156                 int flags = getDisabledShowContext();
157                 mDisallowAssist.setChecked((flags & SHOW_WITH_ASSIST) != 0);
158                 mDisallowScreenshot.setChecked((flags & SHOW_WITH_SCREENSHOT) != 0);
159                 int disabled = getUserDisabledShowContext();
160                 mOptionsText.setText("Disabled: 0x" + Integer.toHexString(disabled));
161             } else {
162                 mOptionsContainer.setVisibility(View.GONE);
163             }
164         }
165     }
166 
onHandleAssist(Bundle assistBundle)167     public void onHandleAssist(Bundle assistBundle) {
168     }
169 
170     @Override
onHandleAssist(Bundle data, AssistStructure structure, AssistContent content)171     public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) {
172         mAssistStructure = structure;
173         if (mAssistStructure != null) {
174             if (mAssistVisualizer != null) {
175                 mAssistVisualizer.setAssistStructure(mAssistStructure);
176             }
177         } else {
178             if (mAssistVisualizer != null) {
179                 mAssistVisualizer.clearAssistData();
180             }
181         }
182         if (content != null) {
183             Log.i(TAG, "Assist intent: " + content.getIntent());
184             Log.i(TAG, "Assist clipdata: " + content.getClipData());
185         }
186         if (data != null) {
187             Uri referrer = data.getParcelable(Intent.EXTRA_REFERRER);
188             if (referrer != null) {
189                 Log.i(TAG, "Referrer: " + referrer);
190             }
191         }
192     }
193 
194     @Override
onHandleScreenshot(Bitmap screenshot)195     public void onHandleScreenshot(Bitmap screenshot) {
196         if (screenshot != null) {
197             mScreenshot.setImageBitmap(screenshot);
198             mScreenshot.setAdjustViewBounds(true);
199             mScreenshot.setMaxWidth(screenshot.getWidth() / 3);
200             mScreenshot.setMaxHeight(screenshot.getHeight() / 3);
201             mFullScreenshot.setImageBitmap(screenshot);
202         } else {
203             mScreenshot.setImageDrawable(null);
204             mFullScreenshot.setImageDrawable(null);
205         }
206     }
207 
updateState()208     void updateState() {
209         if (mState == STATE_IDLE) {
210             mTopContent.setVisibility(View.VISIBLE);
211             mBottomContent.setVisibility(View.GONE);
212             mAssistVisualizer.setVisibility(View.VISIBLE);
213         } else if (mState == STATE_DONE) {
214             mTopContent.setVisibility(View.GONE);
215             mBottomContent.setVisibility(View.GONE);
216             mAssistVisualizer.setVisibility(View.GONE);
217         } else {
218             mTopContent.setVisibility(View.GONE);
219             mBottomContent.setVisibility(View.VISIBLE);
220             mAssistVisualizer.setVisibility(View.GONE);
221         }
222         mStartButton.setEnabled(mState == STATE_IDLE);
223         mConfirmButton.setEnabled(mState == STATE_CONFIRM || mState == STATE_PICK_OPTION
224                 || mState == STATE_COMMAND);
225         mAbortButton.setEnabled(mState == STATE_ABORT_VOICE);
226         mCompleteButton.setEnabled(mState == STATE_COMPLETE_VOICE);
227     }
228 
onClick(View v)229     public void onClick(View v) {
230         if (v == mTreeButton) {
231             if (mAssistVisualizer != null) {
232                 mAssistVisualizer.logTree();
233             }
234         } else if (v == mTextButton) {
235             if (mAssistVisualizer != null) {
236                 mAssistVisualizer.logText();
237             }
238         } else if (v == mOptionsCheck) {
239             refreshOptions();
240         } else if (v == mDisallowAssist) {
241             int flags = getDisabledShowContext();
242             if (mDisallowAssist.isChecked()) {
243                 flags |= SHOW_WITH_ASSIST;
244             } else {
245                 flags &= ~SHOW_WITH_ASSIST;
246             }
247             setDisabledShowContext(flags);
248         } else if (v == mDisallowScreenshot) {
249             int flags = getDisabledShowContext();
250             if (mDisallowScreenshot.isChecked()) {
251                 flags |= SHOW_WITH_SCREENSHOT;
252             } else {
253                 flags &= ~SHOW_WITH_SCREENSHOT;
254             }
255             setDisabledShowContext(flags);
256         } else if (v == mStartButton) {
257             mState = STATE_LAUNCHING;
258             updateState();
259             startVoiceActivity(mStartIntent);
260         } else if (v == mConfirmButton) {
261             if (mPendingRequest instanceof ConfirmationRequest) {
262                 ((ConfirmationRequest)mPendingRequest).sendConfirmationResult(true, null);
263                 mPendingRequest = null;
264                 mState = STATE_LAUNCHING;
265             } else if (mPendingRequest instanceof PickOptionRequest) {
266                 PickOptionRequest pick = (PickOptionRequest)mPendingRequest;
267                 int numReturn = mPendingOptions.length/2;
268                 if (numReturn <= 0) {
269                     numReturn = 1;
270                 }
271                 VoiceInteractor.PickOptionRequest.Option[] picked
272                         = new VoiceInteractor.PickOptionRequest.Option[numReturn];
273                 for (int i=0; i<picked.length; i++) {
274                     picked[i] = mPendingOptions[i*2];
275                 }
276                 mPendingOptions = picked;
277                 if (picked.length <= 1) {
278                     pick.sendPickOptionResult(picked, null);
279                     mPendingRequest = null;
280                     mState = STATE_LAUNCHING;
281                 } else {
282                     pick.sendIntermediatePickOptionResult(picked, null);
283                     updatePickText();
284                 }
285             } else if (mPendingRequest instanceof CommandRequest) {
286                 Bundle result = new Bundle();
287                 result.putString("key", "a result!");
288                 ((CommandRequest)mPendingRequest).sendResult(result);
289                 mPendingRequest = null;
290                 mState = STATE_LAUNCHING;
291             }
292         } else if (v == mAbortButton && mPendingRequest instanceof AbortVoiceRequest) {
293             ((AbortVoiceRequest)mPendingRequest).sendAbortResult(null);
294             mPendingRequest = null;
295         } else if (v == mCompleteButton && mPendingRequest instanceof CompleteVoiceRequest) {
296             ((CompleteVoiceRequest)mPendingRequest).sendCompleteResult(null);
297             mPendingRequest = null;
298         } else if (v == mScreenshot) {
299             if (mFullScreenshot.getVisibility() != View.VISIBLE) {
300                 mFullScreenshot.setVisibility(View.VISIBLE);
301             } else {
302                 mFullScreenshot.setVisibility(View.INVISIBLE);
303             }
304         }
305         updateState();
306     }
307 
308     @Override
onComputeInsets(Insets outInsets)309     public void onComputeInsets(Insets outInsets) {
310         super.onComputeInsets(outInsets);
311         if (mState != STATE_IDLE) {
312             outInsets.contentInsets.top = mBottomContent.getTop();
313             outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_CONTENT;
314         }
315     }
316 
317     @Override
onTaskStarted(Intent intent, int taskId)318     public void onTaskStarted(Intent intent, int taskId) {
319         super.onTaskStarted(intent, taskId);
320         mCurrentTask = taskId;
321     }
322 
323     @Override
onTaskFinished(Intent intent, int taskId)324     public void onTaskFinished(Intent intent, int taskId) {
325         super.onTaskFinished(intent, taskId);
326         if (mCurrentTask == taskId) {
327             mCurrentTask = -1;
328         }
329     }
330 
331     @Override
onLockscreenShown()332     public void onLockscreenShown() {
333         if (mCurrentTask < 0) {
334             hide();
335         }
336     }
337 
338     @Override
onGetSupportedCommands(String[] commands)339     public boolean[] onGetSupportedCommands(String[] commands) {
340         boolean[] res = new boolean[commands.length];
341         for (int i=0; i<commands.length; i++) {
342             if ("com.android.test.voiceinteraction.COMMAND".equals(commands[i])) {
343                 res[i] = true;
344             }
345         }
346         return res;
347     }
348 
setPrompt(VoiceInteractor.Prompt prompt)349     void setPrompt(VoiceInteractor.Prompt prompt) {
350         if (prompt == null) {
351             mText.setText("(null)");
352             mPendingPrompt = "";
353         } else {
354             mText.setText(prompt.getVisualPrompt());
355             mPendingPrompt = prompt.getVisualPrompt();
356         }
357     }
358 
359     @Override
onRequestConfirmation(ConfirmationRequest request)360     public void onRequestConfirmation(ConfirmationRequest request) {
361         Log.i(TAG, "onConfirm: prompt=" + request.getVoicePrompt() + " extras="
362                 + request.getExtras());
363         setPrompt(request.getVoicePrompt());
364         mConfirmButton.setText("Confirm");
365         mPendingRequest = request;
366         mState = STATE_CONFIRM;
367         updateState();
368     }
369 
370     @Override
onRequestPickOption(PickOptionRequest request)371     public void onRequestPickOption(PickOptionRequest request) {
372         Log.i(TAG, "onPickOption: prompt=" + request.getVoicePrompt() + " options="
373                 + request.getOptions() + " extras=" + request.getExtras());
374         mConfirmButton.setText("Pick Option");
375         mPendingRequest = request;
376         setPrompt(request.getVoicePrompt());
377         mPendingOptions = request.getOptions();
378         mState = STATE_PICK_OPTION;
379         updatePickText();
380         updateState();
381     }
382 
updatePickText()383     void updatePickText() {
384         StringBuilder sb = new StringBuilder();
385         sb.append(mPendingPrompt);
386         sb.append(": ");
387         for (int i=0; i<mPendingOptions.length; i++) {
388             if (i > 0) {
389                 sb.append(", ");
390             }
391             sb.append(mPendingOptions[i].getLabel());
392         }
393         mText.setText(sb.toString());
394     }
395 
396     @Override
onRequestCompleteVoice(CompleteVoiceRequest request)397     public void onRequestCompleteVoice(CompleteVoiceRequest request) {
398         Log.i(TAG, "onCompleteVoice: message=" + request.getVoicePrompt() + " extras="
399                 + request.getExtras());
400         setPrompt(request.getVoicePrompt());
401         mPendingRequest = request;
402         mState = STATE_COMPLETE_VOICE;
403         updateState();
404     }
405 
406     @Override
onRequestAbortVoice(AbortVoiceRequest request)407     public void onRequestAbortVoice(AbortVoiceRequest request) {
408         Log.i(TAG, "onAbortVoice: message=" + request.getVoicePrompt() + " extras="
409                 + request.getExtras());
410         setPrompt(request.getVoicePrompt());
411         mPendingRequest = request;
412         mState = STATE_ABORT_VOICE;
413         updateState();
414     }
415 
416     @Override
onRequestCommand(CommandRequest request)417     public void onRequestCommand(CommandRequest request) {
418         Bundle extras = request.getExtras();
419         if (extras != null) {
420             extras.getString("arg");
421         }
422         Log.i(TAG, "onCommand: command=" + request.getCommand() + " extras=" + extras);
423         mText.setText("Command: " + request.getCommand() + ", " + extras);
424         mConfirmButton.setText("Finish Command");
425         mPendingRequest = request;
426         mState = STATE_COMMAND;
427         updateState();
428     }
429 
430     @Override
onCancelRequest(Request request)431     public void onCancelRequest(Request request) {
432         Log.i(TAG, "onCancel");
433         if (mPendingRequest == request) {
434             mPendingRequest = null;
435             mState = STATE_LAUNCHING;
436             updateState();
437         }
438         request.cancel();
439     }
440 }
441