VoiceDialerActivity.java revision ef5d3e8cd31873c7af4902986ae61b408d0343bb
1538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project/* 2538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * 4538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * you may not use this file except in compliance with the License. 6538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * You may obtain a copy of the License at 7538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * 8538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * 10538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * See the License for the specific language governing permissions and 14538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * limitations under the License. 15538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project */ 16538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 17538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectpackage com.android.voicedialer; 18538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 19538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.app.Activity; 20538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.app.AlertDialog; 214a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdonimport android.app.Dialog; 22538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.content.Intent; 23538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.content.DialogInterface; 24538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.media.ToneGenerator; 25538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.media.AudioManager; 26538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.os.Bundle; 27538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.os.Handler; 28538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.os.SystemProperties; 29538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.os.Vibrator; 30538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.util.Config; 31538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.util.Log; 32538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.view.View; 33538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.widget.TextView; 34538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport android.widget.Toast; 35538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectimport java.io.File; 361b715dc663bd7155d996576774e487d31bf331f7Martin Hibdonimport java.io.InputStream; 37d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdonimport java.io.IOException; 38538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 39538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project/** 407a55150b308ed03d41091e4c3ac693d6eb0ab145mah * TODO: get rid of the anonymous classes 415f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon * TODO: merge with BluetoothVoiceDialerActivity 427a55150b308ed03d41091e4c3ac693d6eb0ab145mah * 43538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * This class is the user interface of the VoiceDialer application. 44538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * Its life cycle is as follows: 45538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <ul> 46538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>The user presses the recognize key, and the VoiceDialerActivity starts. 47538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>A {@link RecognizerEngine} instance is created. 48538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>The RecognizerEngine signals the user to speak with the Vibrator. 49538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>The RecognizerEngine captures, processes, and recognizes speech 50538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * against the names in the contact list. 51538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>The RecognizerEngine calls onRecognizerSuccess with a list of 52538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * sentences and corresponding Intents. 53538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>If the list is one element long, the corresponding Intent is dispatched. 54538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>Else an {@link AlertDialog} containing the list of sentences is 55538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * displayed. 56538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>The user selects the desired sentence from the list, 57538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * and the corresponding Intent is dispatched. 58538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <ul> 59538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * Notes: 60538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <ul> 61538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * <li>The RecognizerEngine is kept and reused for the next recognition cycle. 62538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project * </ul> 63538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project */ 64538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Projectpublic class VoiceDialerActivity extends Activity { 65538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 66538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private static final String TAG = "VoiceDialerActivity"; 67538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 68538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private static final String MICROPHONE_EXTRA = "microphone"; 69538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private static final String CONTACTS_EXTRA = "contacts"; 705f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon private static final String SAMPLE_RATE_EXTRA = "samplerate"; 714a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon private static final String INTENTS_KEY = "intents"; 72632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 73538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private static final int FAIL_PAUSE_MSEC = 5000; 7464c64e7c25e6efe31fa53369ec49db442b68ff9amah private static final int SAMPLE_RATE = 11025; 75538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 764a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon private static final int DIALOG_ID = 1; 774a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 785f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon private final static CommandRecognizerEngine mCommandEngine = 795f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon new CommandRecognizerEngine(); 8064c64e7c25e6efe31fa53369ec49db442b68ff9amah private CommandRecognizerClient mCommandClient; 81538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private VoiceDialerTester mVoiceDialerTester; 82538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private Handler mHandler; 83538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private Thread mRecognizerThread = null; 84538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private AudioManager mAudioManager; 85538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private ToneGenerator mToneGenerator; 864a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon private AlertDialog mAlertDialog; 87538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 88538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project @Override 89538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project protected void onCreate(Bundle icicle) { 90ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon if (Config.LOGD) Log.d(TAG, "onCreate"); 91538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project super.onCreate(icicle); 92538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mHandler = new Handler(); 93538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE); 94ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon mToneGenerator = new ToneGenerator(AudioManager.STREAM_RING, 95ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon ToneGenerator.MAX_VOLUME); 96ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon } 97ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon 98ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon protected void onStart() { 99ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon if (Config.LOGD) Log.d(TAG, "onStart " + getIntent()); 100ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon super.onStart(); 1012abf40fd5f901da1b6168aa778cbf7e6713a1e9bMartin Hibdon mAudioManager.requestAudioFocus( 1022abf40fd5f901da1b6168aa778cbf7e6713a1e9bMartin Hibdon null, AudioManager.STREAM_MUSIC, 1032abf40fd5f901da1b6168aa778cbf7e6713a1e9bMartin Hibdon AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 104be1584eb7e59c391a45aa21fb5e65ada1aedae9aDave Sparks 10564c64e7c25e6efe31fa53369ec49db442b68ff9amah mCommandEngine.setContactsFile(newFile(getArg(CONTACTS_EXTRA))); 10664c64e7c25e6efe31fa53369ec49db442b68ff9amah mCommandClient = new CommandRecognizerClient(); 1075f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon mCommandEngine.setMinimizeResults(false); 1085f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon mCommandEngine.setAllowOpenEntries(true); 10964c64e7c25e6efe31fa53369ec49db442b68ff9amah 110538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // open main window 111538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project setTheme(android.R.style.Theme_Dialog); 112538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project setTitle(R.string.title); 113538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project setContentView(R.layout.voice_dialing); 114538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project findViewById(R.id.microphone_view).setVisibility(View.INVISIBLE); 115538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project findViewById(R.id.retry_view).setVisibility(View.INVISIBLE); 116538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project findViewById(R.id.microphone_loading_view).setVisibility(View.VISIBLE); 117538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (RecognizerLogger.isEnabled(this)) { 118538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project ((TextView)findViewById(R.id.substate)).setText(R.string.logging_enabled); 119538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 120632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 121538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // start the tester, if present 122538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mVoiceDialerTester = null; 123538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project File micDir = newFile(getArg(MICROPHONE_EXTRA)); 124538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (micDir != null && micDir.isDirectory()) { 125538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mVoiceDialerTester = new VoiceDialerTester(micDir); 126538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project startNextTest(); 127538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project return; 128538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 129538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 1305f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon startWork(); 131538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 132538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 133538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private void startWork() { 134cd84f92b28c4d6fc55b76bce50434dd858f0d7d2Dave Sparks // start the engine 135538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mRecognizerThread = new Thread() { 136538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project public void run() { 137538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (Config.LOGD) Log.d(TAG, "onCreate.Runnable.run"); 1385f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon String sampleRateStr = getArg(SAMPLE_RATE_EXTRA); 1395f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon int sampleRate = SAMPLE_RATE; 1405f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon if (sampleRateStr != null) { 1415f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon sampleRate = Integer.parseInt(sampleRateStr); 1425f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon } 14364c64e7c25e6efe31fa53369ec49db442b68ff9amah mCommandEngine.recognize(mCommandClient, VoiceDialerActivity.this, 144538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project newFile(getArg(MICROPHONE_EXTRA)), 1455f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon sampleRate); 146538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 147538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project }; 148538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mRecognizerThread.start(); 149538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 150632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 151538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private String getArg(String name) { 152538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (name == null) return null; 153538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project String arg = getIntent().getStringExtra(name); 154538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (arg != null) return arg; 155538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project arg = SystemProperties.get("app.voicedialer." + name); 156538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project return arg != null && arg.length() > 0 ? arg : null; 157538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 158632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 159538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private static File newFile(String name) { 160538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project return name != null ? new File(name) : null; 161538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 162632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 163538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private void startNextTest() { 164538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mHandler.postDelayed(new Runnable() { 165538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project public void run() { 166538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (mVoiceDialerTester == null) { 167538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project return; 168538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 169538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (!mVoiceDialerTester.stepToNextTest()) { 170538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mVoiceDialerTester.report(); 171538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project notifyText("Test completed!"); 172538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project finish(); 173538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project return; 174538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 175538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project File microphone = mVoiceDialerTester.getWavFile(); 176538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project File contacts = newFile(getArg(CONTACTS_EXTRA)); 1775f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon 178538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project notifyText("Testing\n" + microphone + "\n" + contacts); 17964c64e7c25e6efe31fa53369ec49db442b68ff9amah mCommandEngine.recognize(mCommandClient, VoiceDialerActivity.this, 18064c64e7c25e6efe31fa53369ec49db442b68ff9amah microphone, SAMPLE_RATE); 181538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 182538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project }, 2000); 183538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 184632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 185538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private int playSound(int toneType) { 186538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project int msecDelay = 1; 187632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 188538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // use the MediaPlayer to prompt the user 189538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (mToneGenerator != null) { 190538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mToneGenerator.startTone(toneType); 191538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project msecDelay = StrictMath.max(msecDelay, 300); 192538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 193538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 194538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // use the Vibrator to prompt the user 1951b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon if ((mAudioManager != null) && 1961b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon (mAudioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER))) { 197538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project final int VIBRATOR_TIME = 150; 198538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project final int VIBRATOR_GUARD_TIME = 150; 199538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project Vibrator vibrator = new Vibrator(); 200538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project vibrator.vibrate(VIBRATOR_TIME); 201538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project msecDelay = StrictMath.max(msecDelay, 202538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project VIBRATOR_TIME + VIBRATOR_GUARD_TIME); 203538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 204632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 205538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project return msecDelay; 206538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 207632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 208538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project @Override 2095f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon protected void onStop() { 2105f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon if (Config.LOGD) Log.d(TAG, "onStop"); 211632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 2122abf40fd5f901da1b6168aa778cbf7e6713a1e9bMartin Hibdon mAudioManager.abandonAudioFocus(null); 2132abf40fd5f901da1b6168aa778cbf7e6713a1e9bMartin Hibdon 214538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // no more tester 215538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mVoiceDialerTester = null; 216632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 217538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // shut down recognizer and wait for the thread to complete 218538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (mRecognizerThread != null) { 219538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mRecognizerThread.interrupt(); 220538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project try { 221538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mRecognizerThread.join(); 222538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } catch (InterruptedException e) { 2234a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (Config.LOGD) Log.d(TAG, "onStop mRecognizerThread.join exception " + e); 224538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 225538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mRecognizerThread = null; 226538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 227632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 228538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // clean up UI 229538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mHandler.removeCallbacks(mMicFlasher); 230538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mHandler.removeMessages(0); 231632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 232538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project // clean up ToneGenerator 233538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project if (mToneGenerator != null) { 234538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mToneGenerator.release(); 235538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mToneGenerator = null; 236538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 237632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 2385f25619fecb3fda9b34f90eb1e333a89ec431583Martin Hibdon super.onStop(); 239ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon 240ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon // It makes no sense to have this activity maintain state when in 241ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon // background. When it stops, it should just be destroyed. 242ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon finish(); 243538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 244632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 245538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private void notifyText(final CharSequence msg) { 246538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project Toast.makeText(VoiceDialerActivity.this, msg, Toast.LENGTH_SHORT).show(); 247538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 248538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 249538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project private Runnable mMicFlasher = new Runnable() { 250538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project int visible = View.VISIBLE; 251538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 252538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project public void run() { 253538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project findViewById(R.id.microphone_view).setVisibility(visible); 254538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project findViewById(R.id.state).setVisibility(visible); 255538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project visible = visible == View.VISIBLE ? View.INVISIBLE : View.VISIBLE; 256538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project mHandler.postDelayed(this, 750); 257538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 258538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project }; 259538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 2604a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2614a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon protected Dialog onCreateDialog(int id, Bundle args) { 2624a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon final Intent intents[] = (Intent[])args.getParcelableArray(INTENTS_KEY); 2634a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2644a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon DialogInterface.OnClickListener clickListener = 2654a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon new DialogInterface.OnClickListener() { 2664a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2674a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon public void onClick(DialogInterface dialog, int which) { 2684a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (Config.LOGD) Log.d(TAG, "clickListener.onClick " + which); 2694a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon startActivityHelp(intents[which]); 2704a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon dismissDialog(DIALOG_ID); 2714a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon mAlertDialog = null; 2724a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon finish(); 2734a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 2744a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2754a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon }; 2764a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2774a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon DialogInterface.OnCancelListener cancelListener = 2784a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon new DialogInterface.OnCancelListener() { 2794a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2804a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon public void onCancel(DialogInterface dialog) { 2814a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (Config.LOGD) Log.d(TAG, "cancelListener.onCancel"); 2824a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon dismissDialog(DIALOG_ID); 2834a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon mAlertDialog = null; 2844a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon finish(); 2854a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 2864a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2874a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon }; 2884a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2894a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon DialogInterface.OnClickListener positiveListener = 2904a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon new DialogInterface.OnClickListener() { 2914a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 2924a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon public void onClick(DialogInterface dialog, int which) { 2934a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (Config.LOGD) Log.d(TAG, "positiveListener.onClick " + which); 2944a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (intents.length == 1 && which == -1) which = 0; 2954a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon startActivityHelp(intents[which]); 2964a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon dismissDialog(DIALOG_ID); 2974a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon mAlertDialog = null; 2984a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon finish(); 2994a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 3004a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3014a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon }; 3024a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3034a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon DialogInterface.OnClickListener negativeListener = 3044a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon new DialogInterface.OnClickListener() { 3054a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3064a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon public void onClick(DialogInterface dialog, int which) { 3074a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (Config.LOGD) Log.d(TAG, "negativeListener.onClick " + which); 3084a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon dismissDialog(DIALOG_ID); 3094a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon mAlertDialog = null; 3104a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon finish(); 3114a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 3124a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3134a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon }; 3144a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3154a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon String[] sentences = new String[intents.length]; 3164a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon for (int i = 0; i < intents.length; i++) { 3174a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon sentences[i] = intents[i].getStringExtra( 3184a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon RecognizerEngine.SENTENCE_EXTRA); 3194a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 3204a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3214a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon mAlertDialog = intents.length > 1 ? 3224a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon new AlertDialog.Builder(VoiceDialerActivity.this) 3234a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setTitle(R.string.title) 3244a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setItems(sentences, clickListener) 3254a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setOnCancelListener(cancelListener) 3264a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setNegativeButton(android.R.string.cancel, negativeListener) 3274a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .show() 3284a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon : 3294a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon new AlertDialog.Builder(VoiceDialerActivity.this) 3304a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setTitle(R.string.title) 3314a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setItems(sentences, clickListener) 3324a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setOnCancelListener(cancelListener) 3334a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setPositiveButton(android.R.string.ok, positiveListener) 3344a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .setNegativeButton(android.R.string.cancel, negativeListener) 3354a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon .show(); 3364a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 3374a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon return mAlertDialog; 3384a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 3394a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 34064c64e7c25e6efe31fa53369ec49db442b68ff9amah private class CommandRecognizerClient implements RecognizerClient { 341d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon static final int MIN_VOLUME_TO_SKIP = 2; 34264c64e7c25e6efe31fa53369ec49db442b68ff9amah /** 34364c64e7c25e6efe31fa53369ec49db442b68ff9amah * Called by the {@link RecognizerEngine} when the microphone is started. 34464c64e7c25e6efe31fa53369ec49db442b68ff9amah */ 3451b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon public void onMicrophoneStart(InputStream mic) { 34664c64e7c25e6efe31fa53369ec49db442b68ff9amah if (Config.LOGD) Log.d(TAG, "onMicrophoneStart"); 3471b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon playSound(ToneGenerator.TONE_PROP_BEEP); 3481b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon 349d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int ringVolume = mAudioManager.getStreamVolume( 350d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon AudioManager.STREAM_RING); 351d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon Log.d(TAG, "ringVolume " + ringVolume); 352d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 353d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (ringVolume >= MIN_VOLUME_TO_SKIP) { 354d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // now we're playing a sound, and corrupting the input sample. 355d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // So we need to pull that junk off of the input stream so that the 356d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // recognizer won't see it. 357d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon try { 358d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon skipBeep(mic); 359d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } catch (java.io.IOException e) { 360d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon Log.e(TAG, "IOException " + e); 361d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 362d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } else { 363d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon Log.d(TAG, "no tone"); 3641b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon } 365632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 36664c64e7c25e6efe31fa53369ec49db442b68ff9amah if (mVoiceDialerTester != null) return; 367632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 36864c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.post(new Runnable() { 36964c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 37064c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.microphone_loading_view).setVisibility(View.INVISIBLE); 37164c64e7c25e6efe31fa53369ec49db442b68ff9amah ((TextView)findViewById(R.id.state)).setText(R.string.listening); 37264c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.post(mMicFlasher); 37364c64e7c25e6efe31fa53369ec49db442b68ff9amah } 37464c64e7c25e6efe31fa53369ec49db442b68ff9amah }); 37564c64e7c25e6efe31fa53369ec49db442b68ff9amah } 376538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 377d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon /** 378d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon * Beep detection 379d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon */ 380d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int START_WINDOW_MS = 500; // Beep detection window duration in ms 381d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int SINE_FREQ = 400; // base sine frequency on beep 382d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int NUM_PERIODS_BLOCK = 10; // number of sine periods in one energy averaging block 383d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int THRESHOLD = 8; // absolute pseudo energy threshold 384d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int START = 0; // beep detection start 385d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int RISING = 1; // beep rising edge start 386d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon private static final int TOP = 2; // beep constant energy detected 387d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 388d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon void skipBeep(InputStream is) throws IOException { 389d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int sampleCount = ((SAMPLE_RATE / SINE_FREQ) * NUM_PERIODS_BLOCK); 390d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int blockSize = 2 * sampleCount; // energy averaging block 391d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 392d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (is == null || blockSize == 0) { 393d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon return; 394d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 395d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 396d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon byte[] buf = new byte[blockSize]; 397d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int maxBytes = 2 * ((START_WINDOW_MS * SAMPLE_RATE) / 1000); 398d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon maxBytes = ((maxBytes-1) / blockSize + 1) * blockSize; 399d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 400d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int count = 0; 401d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int state = START; // detection state 402d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon long prevE = 0; // previous pseudo energy 403d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon long peak = 0; 404d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int threshold = THRESHOLD*sampleCount; // absolute energy threshold 405d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon Log.d(TAG, "blockSize " + blockSize); 406d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 407d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon while (count < maxBytes) { 408d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int cnt = 0; 409d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon while (cnt < blockSize) { 410d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon int n = is.read(buf, cnt, blockSize-cnt); 411d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (n < 0) { 412d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon throw new java.io.IOException(); 413d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 414d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon cnt += n; 415d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 416d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 417d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // compute pseudo energy 418d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon cnt = blockSize; 419d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon long sumx = 0; 420d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon long sumxx = 0; 421d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon while (cnt >= 2) { 422d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon short smp = (short)((buf[cnt - 1] << 8) + (buf[cnt - 2] & 0xFF)); 423d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon sumx += smp; 424d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon sumxx += smp*smp; 425d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon cnt -= 2; 4261b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon } 427d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon long energy = (sumxx*sampleCount - sumx*sumx)/(sampleCount*sampleCount); 428d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon Log.d(TAG, "sumx " + sumx + " sumxx " + sumxx + " ee " + energy); 429d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon 430d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon switch (state) { 431d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon case START: 432d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (energy > threshold && energy > (prevE * 2) && prevE != 0) { 433d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // rising edge if energy doubled and > abs threshold 434d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon state = RISING; 435d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (Config.LOGD) Log.d(TAG, "start RISING: " + count +" time: "+ (((1000*count)/2)/SAMPLE_RATE)); 436d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 437d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon break; 438d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon case RISING: 439d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (energy < threshold || energy < (prevE / 2)){ 440d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // energy fell back below half of previous, back to start 441d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (Config.LOGD) Log.d(TAG, "back to START: " + count +" time: "+ (((1000*count)/2)/SAMPLE_RATE)); 442d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon peak = 0; 443d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon state = START; 444d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } else if (energy > (prevE / 2) && energy < (prevE * 2)) { 445d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // Start of constant energy 446d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (Config.LOGD) Log.d(TAG, "start TOP: " + count +" time: "+ (((1000*count)/2)/SAMPLE_RATE)); 447d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (peak < energy) { 448d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon peak = energy; 449d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 450d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon state = TOP; 451d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 452d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon break; 453d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon case TOP: 454d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (energy < threshold || energy < (peak / 2)) { 455d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon // e went to less than half of the peak 456d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (Config.LOGD) Log.d(TAG, "end TOP: " + count +" time: "+ (((1000*count)/2)/SAMPLE_RATE)); 457d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon return; 458d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 459d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon break; 460d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon } 461d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon prevE = energy; 462d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon count += blockSize; 4631b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon } 464d23e5f670b10a582761421d8bc101d4a2d660ac0Martin Hibdon if (Config.LOGD) Log.d(TAG, "no beep detected, timed out"); 4651b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon } 4661b715dc663bd7155d996576774e487d31bf331f7Martin Hibdon 46764c64e7c25e6efe31fa53369ec49db442b68ff9amah /** 46864c64e7c25e6efe31fa53369ec49db442b68ff9amah * Called by the {@link RecognizerEngine} if the recognizer fails. 46964c64e7c25e6efe31fa53369ec49db442b68ff9amah */ 47064c64e7c25e6efe31fa53369ec49db442b68ff9amah public void onRecognitionFailure(final String msg) { 47164c64e7c25e6efe31fa53369ec49db442b68ff9amah if (Config.LOGD) Log.d(TAG, "onRecognitionFailure " + msg); 47264c64e7c25e6efe31fa53369ec49db442b68ff9amah 47364c64e7c25e6efe31fa53369ec49db442b68ff9amah // get work off UAPI thread 47464c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.post(new Runnable() { 47564c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 47664c64e7c25e6efe31fa53369ec49db442b68ff9amah // failure, so beep about it 47764c64e7c25e6efe31fa53369ec49db442b68ff9amah playSound(ToneGenerator.TONE_PROP_NACK); 47864c64e7c25e6efe31fa53369ec49db442b68ff9amah 47964c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.removeCallbacks(mMicFlasher); 48064c64e7c25e6efe31fa53369ec49db442b68ff9amah ((TextView)findViewById(R.id.state)).setText(R.string.please_try_again); 48164c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.state).setVisibility(View.VISIBLE); 48264c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.microphone_view).setVisibility(View.INVISIBLE); 48364c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.retry_view).setVisibility(View.VISIBLE); 48464c64e7c25e6efe31fa53369ec49db442b68ff9amah 48564c64e7c25e6efe31fa53369ec49db442b68ff9amah if (mVoiceDialerTester != null) { 48664c64e7c25e6efe31fa53369ec49db442b68ff9amah mVoiceDialerTester.onRecognitionFailure(msg); 48764c64e7c25e6efe31fa53369ec49db442b68ff9amah startNextTest(); 48864c64e7c25e6efe31fa53369ec49db442b68ff9amah return; 48964c64e7c25e6efe31fa53369ec49db442b68ff9amah } 490538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 49164c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.postDelayed(new Runnable() { 49264c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 49364c64e7c25e6efe31fa53369ec49db442b68ff9amah finish(); 49464c64e7c25e6efe31fa53369ec49db442b68ff9amah } 49564c64e7c25e6efe31fa53369ec49db442b68ff9amah }, FAIL_PAUSE_MSEC); 496538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 49764c64e7c25e6efe31fa53369ec49db442b68ff9amah }); 49864c64e7c25e6efe31fa53369ec49db442b68ff9amah } 499538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 50064c64e7c25e6efe31fa53369ec49db442b68ff9amah /** 50164c64e7c25e6efe31fa53369ec49db442b68ff9amah * Called by the {@link RecognizerEngine} on an internal error. 50264c64e7c25e6efe31fa53369ec49db442b68ff9amah */ 50364c64e7c25e6efe31fa53369ec49db442b68ff9amah public void onRecognitionError(final String msg) { 50464c64e7c25e6efe31fa53369ec49db442b68ff9amah if (Config.LOGD) Log.d(TAG, "onRecognitionError " + msg); 50564c64e7c25e6efe31fa53369ec49db442b68ff9amah 50664c64e7c25e6efe31fa53369ec49db442b68ff9amah // get work off UAPI thread 50764c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.post(new Runnable() { 50864c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 50964c64e7c25e6efe31fa53369ec49db442b68ff9amah // error, so beep about it 51064c64e7c25e6efe31fa53369ec49db442b68ff9amah playSound(ToneGenerator.TONE_PROP_NACK); 51164c64e7c25e6efe31fa53369ec49db442b68ff9amah 51264c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.removeCallbacks(mMicFlasher); 51364c64e7c25e6efe31fa53369ec49db442b68ff9amah ((TextView)findViewById(R.id.state)).setText(R.string.please_try_again); 51464c64e7c25e6efe31fa53369ec49db442b68ff9amah ((TextView)findViewById(R.id.substate)).setText(R.string.recognition_error); 51564c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.state).setVisibility(View.VISIBLE); 51664c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.microphone_view).setVisibility(View.INVISIBLE); 51764c64e7c25e6efe31fa53369ec49db442b68ff9amah findViewById(R.id.retry_view).setVisibility(View.VISIBLE); 51864c64e7c25e6efe31fa53369ec49db442b68ff9amah 51964c64e7c25e6efe31fa53369ec49db442b68ff9amah if (mVoiceDialerTester != null) { 52064c64e7c25e6efe31fa53369ec49db442b68ff9amah mVoiceDialerTester.onRecognitionError(msg); 52164c64e7c25e6efe31fa53369ec49db442b68ff9amah startNextTest(); 52264c64e7c25e6efe31fa53369ec49db442b68ff9amah return; 523538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 524632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 52564c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.postDelayed(new Runnable() { 52664c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 52764c64e7c25e6efe31fa53369ec49db442b68ff9amah finish(); 52864c64e7c25e6efe31fa53369ec49db442b68ff9amah } 52964c64e7c25e6efe31fa53369ec49db442b68ff9amah }, FAIL_PAUSE_MSEC); 530538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 53164c64e7c25e6efe31fa53369ec49db442b68ff9amah }); 53264c64e7c25e6efe31fa53369ec49db442b68ff9amah } 533538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project 53464c64e7c25e6efe31fa53369ec49db442b68ff9amah /** 53564c64e7c25e6efe31fa53369ec49db442b68ff9amah * Called by the {@link RecognizerEngine} when is succeeds. If there is 53664c64e7c25e6efe31fa53369ec49db442b68ff9amah * only one item, then the Intent is dispatched immediately. 53764c64e7c25e6efe31fa53369ec49db442b68ff9amah * If there are more, then an AlertDialog is displayed and the user is 53864c64e7c25e6efe31fa53369ec49db442b68ff9amah * prompted to select. 53964c64e7c25e6efe31fa53369ec49db442b68ff9amah * @param intents a list of Intents corresponding to the sentences. 54064c64e7c25e6efe31fa53369ec49db442b68ff9amah */ 54164c64e7c25e6efe31fa53369ec49db442b68ff9amah public void onRecognitionSuccess(final Intent[] intents) { 54264c64e7c25e6efe31fa53369ec49db442b68ff9amah if (Config.LOGD) Log.d(TAG, "onRecognitionSuccess " + intents.length); 5434a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon // repackage our intents as a bundle so that we can pass it into 5444a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon // showDialog. This in required so that we can handle it when 5454a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon // orientation changes and the activity is destroyed and recreated. 5464a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon final Bundle args = new Bundle(); 5474a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon args.putParcelableArray(INTENTS_KEY, intents); 54864c64e7c25e6efe31fa53369ec49db442b68ff9amah 54964c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.post(new Runnable() { 55064c64e7c25e6efe31fa53369ec49db442b68ff9amah 55164c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 55264c64e7c25e6efe31fa53369ec49db442b68ff9amah // success, so beep about it 55364c64e7c25e6efe31fa53369ec49db442b68ff9amah playSound(ToneGenerator.TONE_PROP_ACK); 55464c64e7c25e6efe31fa53369ec49db442b68ff9amah 55564c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.removeCallbacks(mMicFlasher); 55664c64e7c25e6efe31fa53369ec49db442b68ff9amah 5574a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon showDialog(DIALOG_ID, args); 55864c64e7c25e6efe31fa53369ec49db442b68ff9amah 55964c64e7c25e6efe31fa53369ec49db442b68ff9amah // start the next test 56064c64e7c25e6efe31fa53369ec49db442b68ff9amah if (mVoiceDialerTester != null) { 56164c64e7c25e6efe31fa53369ec49db442b68ff9amah mVoiceDialerTester.onRecognitionSuccess(intents); 56264c64e7c25e6efe31fa53369ec49db442b68ff9amah startNextTest(); 56364c64e7c25e6efe31fa53369ec49db442b68ff9amah mHandler.postDelayed(new Runnable() { 56464c64e7c25e6efe31fa53369ec49db442b68ff9amah public void run() { 5654a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon dismissDialog(DIALOG_ID); 5664a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon mAlertDialog = null; 56764c64e7c25e6efe31fa53369ec49db442b68ff9amah } 56864c64e7c25e6efe31fa53369ec49db442b68ff9amah }, 2000); 569538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 570538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 57164c64e7c25e6efe31fa53369ec49db442b68ff9amah }); 57264c64e7c25e6efe31fa53369ec49db442b68ff9amah } 573538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 574632bb9327078cbe2794ff24be8bb28e4f81309f1The Android Open Source Project 5754a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon // post a Toast if not real contacts or microphone 5764a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon private void startActivityHelp(Intent intent) { 5774a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon if (getArg(MICROPHONE_EXTRA) == null && 5784a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon getArg(CONTACTS_EXTRA) == null) { 5794a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon startActivity(intent); 5804a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } else { 5814a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon notifyText(intent. 5824a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon getStringExtra(RecognizerEngine.SENTENCE_EXTRA) + 5834a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon "\n" + intent.toString()); 5844a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 5854a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon 5864a330957ce5190ed86c57e0c65910359b866cba7Martin Hibdon } 587538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project @Override 588538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project protected void onDestroy() { 589ef5d3e8cd31873c7af4902986ae61b408d0343bbMartin Hibdon if (Config.LOGD) Log.d(TAG, "onDestroy"); 590538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project super.onDestroy(); 591538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project } 592538879a6f24ff7305e66d719e751b5d612029bf3The Android Open Source Project} 593