/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.test.voiceinteraction; import android.app.ActivityManager; import android.app.VoiceInteractor; import android.app.assist.AssistContent; import android.app.assist.AssistStructure; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.service.voice.VoiceInteractionSession; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; public class MainInteractionSession extends VoiceInteractionSession implements View.OnClickListener { static final String TAG = "MainInteractionSession"; Intent mStartIntent; View mContentView; AssistVisualizer mAssistVisualizer; View mTopContent; View mBottomContent; TextView mText; Button mTreeButton; Button mTextButton; Button mStartButton; CheckBox mOptionsCheck; View mOptionsContainer; CheckBox mDisallowAssist; CheckBox mDisallowScreenshot; TextView mOptionsText; ImageView mScreenshot; ImageView mFullScreenshot; Button mConfirmButton; Button mCompleteButton; Button mAbortButton; AssistStructure mAssistStructure; static final int STATE_IDLE = 0; static final int STATE_LAUNCHING = 1; static final int STATE_CONFIRM = 2; static final int STATE_PICK_OPTION = 3; static final int STATE_COMMAND = 4; static final int STATE_ABORT_VOICE = 5; static final int STATE_COMPLETE_VOICE = 6; static final int STATE_DONE = 7; int mState = STATE_IDLE; VoiceInteractor.PickOptionRequest.Option[] mPendingOptions; CharSequence mPendingPrompt; Request mPendingRequest; int mCurrentTask = -1; MainInteractionSession(Context context) { super(context); } @Override public void onCreate() { super.onCreate(); ActivityManager am = getContext().getSystemService(ActivityManager.class); am.setWatchHeapLimit(40 * 1024 * 1024); } @Override public void onShow(Bundle args, int showFlags) { super.onShow(args, showFlags); Log.i(TAG, "onShow: flags=0x" + Integer.toHexString(showFlags) + " args=" + args); mState = STATE_IDLE; mStartIntent = args != null ? (Intent)args.getParcelable("intent") : null; if (mStartIntent == null) { mStartIntent = new Intent(getContext(), TestInteractionActivity.class); } if (mAssistVisualizer != null) { mAssistVisualizer.clearAssistData(); } onHandleScreenshot(null); updateState(); refreshOptions(); } @Override public void onHide() { super.onHide(); if (mAssistVisualizer != null) { mAssistVisualizer.clearAssistData(); } mState = STATE_DONE; updateState(); } @Override public View onCreateContentView() { mContentView = getLayoutInflater().inflate(R.layout.voice_interaction_session, null); mAssistVisualizer = (AssistVisualizer)mContentView.findViewById(R.id.assist_visualizer); if (mAssistStructure != null) { mAssistVisualizer.setAssistStructure(mAssistStructure); } mTopContent = mContentView.findViewById(R.id.top_content); mBottomContent = mContentView.findViewById(R.id.bottom_content); mText = (TextView)mContentView.findViewById(R.id.text); mTreeButton = (Button)mContentView.findViewById(R.id.do_tree); mTreeButton.setOnClickListener(this); mTextButton = (Button)mContentView.findViewById(R.id.do_text); mTextButton.setOnClickListener(this); mStartButton = (Button)mContentView.findViewById(R.id.start); mStartButton.setOnClickListener(this); mScreenshot = (ImageView)mContentView.findViewById(R.id.screenshot); mScreenshot.setOnClickListener(this); mFullScreenshot = (ImageView)mContentView.findViewById(R.id.full_screenshot); mOptionsCheck = (CheckBox)mContentView.findViewById(R.id.show_options); mOptionsCheck.setOnClickListener(this); mOptionsContainer = mContentView.findViewById(R.id.options); mDisallowAssist = (CheckBox)mContentView.findViewById(R.id.disallow_structure); mDisallowAssist.setOnClickListener(this); mDisallowScreenshot = (CheckBox)mContentView.findViewById(R.id.disallow_screenshot); mDisallowScreenshot.setOnClickListener(this); mOptionsText = (TextView)mContentView.findViewById(R.id.options_text); mConfirmButton = (Button)mContentView.findViewById(R.id.confirm); mConfirmButton.setOnClickListener(this); mCompleteButton = (Button)mContentView.findViewById(R.id.complete); mCompleteButton.setOnClickListener(this); mAbortButton = (Button)mContentView.findViewById(R.id.abort); mAbortButton.setOnClickListener(this); refreshOptions(); return mContentView; } void refreshOptions() { if (mOptionsContainer != null) { if (mOptionsCheck.isChecked()) { mOptionsContainer.setVisibility(View.VISIBLE); int flags = getDisabledShowContext(); mDisallowAssist.setChecked((flags & SHOW_WITH_ASSIST) != 0); mDisallowScreenshot.setChecked((flags & SHOW_WITH_SCREENSHOT) != 0); int disabled = getUserDisabledShowContext(); mOptionsText.setText("Disabled: 0x" + Integer.toHexString(disabled)); } else { mOptionsContainer.setVisibility(View.GONE); } } } public void onHandleAssist(Bundle assistBundle) { } @Override public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) { mAssistStructure = structure; if (mAssistStructure != null) { if (mAssistVisualizer != null) { mAssistVisualizer.setAssistStructure(mAssistStructure); } } else { if (mAssistVisualizer != null) { mAssistVisualizer.clearAssistData(); } } if (content != null) { Log.i(TAG, "Assist intent: " + content.getIntent()); Log.i(TAG, "Assist clipdata: " + content.getClipData()); } if (data != null) { Uri referrer = data.getParcelable(Intent.EXTRA_REFERRER); if (referrer != null) { Log.i(TAG, "Referrer: " + referrer); } } } @Override public void onHandleScreenshot(Bitmap screenshot) { if (screenshot != null) { mScreenshot.setImageBitmap(screenshot); mScreenshot.setAdjustViewBounds(true); mScreenshot.setMaxWidth(screenshot.getWidth() / 3); mScreenshot.setMaxHeight(screenshot.getHeight() / 3); mFullScreenshot.setImageBitmap(screenshot); } else { mScreenshot.setImageDrawable(null); mFullScreenshot.setImageDrawable(null); } } void updateState() { if (mState == STATE_IDLE) { mTopContent.setVisibility(View.VISIBLE); mBottomContent.setVisibility(View.GONE); mAssistVisualizer.setVisibility(View.VISIBLE); } else if (mState == STATE_DONE) { mTopContent.setVisibility(View.GONE); mBottomContent.setVisibility(View.GONE); mAssistVisualizer.setVisibility(View.GONE); } else { mTopContent.setVisibility(View.GONE); mBottomContent.setVisibility(View.VISIBLE); mAssistVisualizer.setVisibility(View.GONE); } mStartButton.setEnabled(mState == STATE_IDLE); mConfirmButton.setEnabled(mState == STATE_CONFIRM || mState == STATE_PICK_OPTION || mState == STATE_COMMAND); mAbortButton.setEnabled(mState == STATE_ABORT_VOICE); mCompleteButton.setEnabled(mState == STATE_COMPLETE_VOICE); } public void onClick(View v) { if (v == mTreeButton) { if (mAssistVisualizer != null) { mAssistVisualizer.logTree(); } } else if (v == mTextButton) { if (mAssistVisualizer != null) { mAssistVisualizer.logText(); } } else if (v == mOptionsCheck) { refreshOptions(); } else if (v == mDisallowAssist) { int flags = getDisabledShowContext(); if (mDisallowAssist.isChecked()) { flags |= SHOW_WITH_ASSIST; } else { flags &= ~SHOW_WITH_ASSIST; } setDisabledShowContext(flags); } else if (v == mDisallowScreenshot) { int flags = getDisabledShowContext(); if (mDisallowScreenshot.isChecked()) { flags |= SHOW_WITH_SCREENSHOT; } else { flags &= ~SHOW_WITH_SCREENSHOT; } setDisabledShowContext(flags); } else if (v == mStartButton) { mState = STATE_LAUNCHING; updateState(); startVoiceActivity(mStartIntent); } else if (v == mConfirmButton) { if (mPendingRequest instanceof ConfirmationRequest) { ((ConfirmationRequest)mPendingRequest).sendConfirmationResult(true, null); mPendingRequest = null; mState = STATE_LAUNCHING; } else if (mPendingRequest instanceof PickOptionRequest) { PickOptionRequest pick = (PickOptionRequest)mPendingRequest; int numReturn = mPendingOptions.length/2; if (numReturn <= 0) { numReturn = 1; } VoiceInteractor.PickOptionRequest.Option[] picked = new VoiceInteractor.PickOptionRequest.Option[numReturn]; for (int i=0; i<picked.length; i++) { picked[i] = mPendingOptions[i*2]; } mPendingOptions = picked; if (picked.length <= 1) { pick.sendPickOptionResult(picked, null); mPendingRequest = null; mState = STATE_LAUNCHING; } else { pick.sendIntermediatePickOptionResult(picked, null); updatePickText(); } } else if (mPendingRequest instanceof CommandRequest) { Bundle result = new Bundle(); result.putString("key", "a result!"); ((CommandRequest)mPendingRequest).sendResult(result); mPendingRequest = null; mState = STATE_LAUNCHING; } } else if (v == mAbortButton && mPendingRequest instanceof AbortVoiceRequest) { ((AbortVoiceRequest)mPendingRequest).sendAbortResult(null); mPendingRequest = null; } else if (v == mCompleteButton && mPendingRequest instanceof CompleteVoiceRequest) { ((CompleteVoiceRequest)mPendingRequest).sendCompleteResult(null); mPendingRequest = null; } else if (v == mScreenshot) { if (mFullScreenshot.getVisibility() != View.VISIBLE) { mFullScreenshot.setVisibility(View.VISIBLE); } else { mFullScreenshot.setVisibility(View.INVISIBLE); } } updateState(); } @Override public void onComputeInsets(Insets outInsets) { super.onComputeInsets(outInsets); if (mState != STATE_IDLE) { outInsets.contentInsets.top = mBottomContent.getTop(); outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_CONTENT; } } @Override public void onTaskStarted(Intent intent, int taskId) { super.onTaskStarted(intent, taskId); mCurrentTask = taskId; } @Override public void onTaskFinished(Intent intent, int taskId) { super.onTaskFinished(intent, taskId); if (mCurrentTask == taskId) { mCurrentTask = -1; } } @Override public void onLockscreenShown() { if (mCurrentTask < 0) { hide(); } } @Override public boolean[] onGetSupportedCommands(String[] commands) { boolean[] res = new boolean[commands.length]; for (int i=0; i<commands.length; i++) { if ("com.android.test.voiceinteraction.COMMAND".equals(commands[i])) { res[i] = true; } } return res; } void setPrompt(VoiceInteractor.Prompt prompt) { if (prompt == null) { mText.setText("(null)"); mPendingPrompt = ""; } else { mText.setText(prompt.getVisualPrompt()); mPendingPrompt = prompt.getVisualPrompt(); } } @Override public void onRequestConfirmation(ConfirmationRequest request) { Log.i(TAG, "onConfirm: prompt=" + request.getVoicePrompt() + " extras=" + request.getExtras()); setPrompt(request.getVoicePrompt()); mConfirmButton.setText("Confirm"); mPendingRequest = request; mState = STATE_CONFIRM; updateState(); } @Override public void onRequestPickOption(PickOptionRequest request) { Log.i(TAG, "onPickOption: prompt=" + request.getVoicePrompt() + " options=" + request.getOptions() + " extras=" + request.getExtras()); mConfirmButton.setText("Pick Option"); mPendingRequest = request; setPrompt(request.getVoicePrompt()); mPendingOptions = request.getOptions(); mState = STATE_PICK_OPTION; updatePickText(); updateState(); } void updatePickText() { StringBuilder sb = new StringBuilder(); sb.append(mPendingPrompt); sb.append(": "); for (int i=0; i<mPendingOptions.length; i++) { if (i > 0) { sb.append(", "); } sb.append(mPendingOptions[i].getLabel()); } mText.setText(sb.toString()); } @Override public void onRequestCompleteVoice(CompleteVoiceRequest request) { Log.i(TAG, "onCompleteVoice: message=" + request.getVoicePrompt() + " extras=" + request.getExtras()); setPrompt(request.getVoicePrompt()); mPendingRequest = request; mState = STATE_COMPLETE_VOICE; updateState(); } @Override public void onRequestAbortVoice(AbortVoiceRequest request) { Log.i(TAG, "onAbortVoice: message=" + request.getVoicePrompt() + " extras=" + request.getExtras()); setPrompt(request.getVoicePrompt()); mPendingRequest = request; mState = STATE_ABORT_VOICE; updateState(); } @Override public void onRequestCommand(CommandRequest request) { Bundle extras = request.getExtras(); if (extras != null) { extras.getString("arg"); } Log.i(TAG, "onCommand: command=" + request.getCommand() + " extras=" + extras); mText.setText("Command: " + request.getCommand() + ", " + extras); mConfirmButton.setText("Finish Command"); mPendingRequest = request; mState = STATE_COMMAND; updateState(); } @Override public void onCancelRequest(Request request) { Log.i(TAG, "onCancel"); if (mPendingRequest == request) { mPendingRequest = null; mState = STATE_LAUNCHING; updateState(); } request.cancel(); } }