Loading tests/SoundTriggerTestApp/res/layout/main.xml +10 −17 Original line number Diff line number Diff line Loading @@ -60,29 +60,22 @@ android:onClick="onUnEnrollButtonClicked" android:padding="20dp" /> <Button android:id="@+id/play_trigger_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/play_trigger" android:onClick="onPlayTriggerButtonClicked" android:padding="20dp" /> </LinearLayout> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/model_group_id" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="20dp" android:checkedButton="@+id/model_one" android:orientation="vertical"> <RadioButton android:id="@+id/model_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/model_one" android:onClick="onRadioButtonClicked"/> <RadioButton android:id="@+id/model_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/model_two" android:onClick="onRadioButtonClicked"/> <RadioButton android:id="@+id/model_three" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/model_three" android:onClick="onRadioButtonClicked"/> </RadioGroup> <ScrollView Loading tests/SoundTriggerTestApp/res/values/strings.xml +1 −3 Original line number Diff line number Diff line Loading @@ -21,8 +21,6 @@ <string name="unenroll">Un-load</string> <string name="start_recog">Start</string> <string name="stop_recog">Stop</string> <string name="model_one">Model One</string> <string name="model_two">Model Two</string> <string name="model_three">Model Three</string> <string name="play_trigger">Play Trigger Audio</string> <string name="none">Debug messages appear here:\n</string> </resources> tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java +155 −58 Original line number Diff line number Diff line Loading @@ -16,24 +16,36 @@ package com.android.test.soundtrigger; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Random; import java.util.UUID; import android.app.Activity; import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; import android.hardware.soundtrigger.SoundTrigger; import android.media.AudioFormat; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.soundtrigger.SoundTriggerDetector; import android.media.soundtrigger.SoundTriggerManager; import android.text.Editable; import android.text.method.ScrollingMovementMethod; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; import android.os.UserManager; import android.text.Editable; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.RadioButton; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; Loading @@ -44,20 +56,17 @@ public class TestSoundTriggerActivity extends Activity { private SoundTriggerUtil mSoundTriggerUtil; private Random mRandom; private UUID mModelUuid1 = UUID.randomUUID(); private UUID mModelUuid2 = UUID.randomUUID(); private UUID mModelUuid3 = UUID.randomUUID(); private UUID mVendorUuid = UUID.randomUUID(); private SoundTriggerDetector mDetector1 = null; private SoundTriggerDetector mDetector2 = null; private SoundTriggerDetector mDetector3 = null; private Map<Integer, ModelInfo> mModelInfoMap; private Map<View, Integer> mModelIdMap; private TextView mDebugView = null; private int mSelectedModelId = 1; private int mSelectedModelId = -1; private ScrollView mScrollView = null; private Button mPlayTriggerButton = null; private PowerManager.WakeLock mScreenWakelock; private Handler mHandler; private RadioGroup mRadioGroup; @Override protected void onCreate(Bundle savedInstanceState) { Loading @@ -66,11 +75,108 @@ public class TestSoundTriggerActivity extends Activity { setContentView(R.layout.main); mDebugView = (TextView) findViewById(R.id.console); mScrollView = (ScrollView) findViewById(R.id.scroller_id); mRadioGroup = (RadioGroup) findViewById(R.id.model_group_id); mPlayTriggerButton = (Button) findViewById(R.id.play_trigger_id); mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE); mDebugView.setMovementMethod(new ScrollingMovementMethod()); mSoundTriggerUtil = new SoundTriggerUtil(this); mRandom = new Random(); mHandler = new Handler(); mModelInfoMap = new HashMap(); mModelIdMap = new HashMap(); setVolumeControlStream(AudioManager.STREAM_MUSIC); // Load all the models in the data dir. for (File file : getFilesDir().listFiles()) { // Find meta-data in .properties files, ignore everything else. if (!file.getName().endsWith(".properties")) { continue; } try { Properties properties = new Properties(); properties.load(new FileInputStream(file)); createModelInfoAndWidget(properties); } catch (Exception e) { Log.e(TAG, "Failed to load properties file " + file.getName()); } } // Create a few dummy models if we didn't load anything. if (mModelIdMap.isEmpty()) { Properties dummyModelProperties = new Properties(); for (String name : new String[]{"One", "Two", "Three"}) { dummyModelProperties.setProperty("name", "Model " + name); createModelInfoAndWidget(dummyModelProperties); } } } private void createModelInfoAndWidget(Properties properties) { try { ModelInfo modelInfo = new ModelInfo(); if (!properties.containsKey("name")) { throw new RuntimeException("must have a 'name' property"); } modelInfo.name = properties.getProperty("name"); if (properties.containsKey("modelUuid")) { modelInfo.modelUuid = UUID.fromString(properties.getProperty("modelUuid")); } else { modelInfo.modelUuid = UUID.randomUUID(); } if (properties.containsKey("vendorUuid")) { modelInfo.vendorUuid = UUID.fromString(properties.getProperty("vendorUuid")); } else { modelInfo.vendorUuid = UUID.randomUUID(); } if (properties.containsKey("triggerAudio")) { modelInfo.triggerAudioPlayer = MediaPlayer.create(this, Uri.parse( getFilesDir().getPath() + "/" + properties.getProperty("triggerAudio"))); } if (properties.containsKey("dataFile")) { File modelDataFile = new File( getFilesDir().getPath() + "/" + properties.getProperty("dataFile")); modelInfo.modelData = new byte[(int) modelDataFile.length()]; FileInputStream input = new FileInputStream(modelDataFile); input.read(modelInfo.modelData, 0, modelInfo.modelData.length); } else { modelInfo.modelData = new byte[1024]; mRandom.nextBytes(modelInfo.modelData); } // TODO: Add property support for keyphrase models when they're exposed by the // service. Also things like how much audio they should record with the capture session // provided in the callback. // Add a widget into the radio group. RadioButton button = new RadioButton(this); mRadioGroup.addView(button); button.setText(modelInfo.name); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { onRadioButtonClicked(v); } }); // Update our maps containing the button -> id and id -> modelInfo. int newModelId = mModelIdMap.size() + 1; mModelIdMap.put(button, newModelId); mModelInfoMap.put(newModelId, modelInfo); // If we don't have something selected, select this first thing. if (mSelectedModelId < 0) { button.setChecked(true); onRadioButtonClicked(button); } } catch (IOException e) { Log.e(TAG, "Error parsing properties for " + properties.getProperty("name"), e); } } private void postMessage(String msg) { Loading @@ -91,27 +197,15 @@ public class TestSoundTriggerActivity extends Activity { } private synchronized UUID getSelectedUuid() { if (mSelectedModelId == 2) return mModelUuid2; if (mSelectedModelId == 3) return mModelUuid3; return mModelUuid1; // Default. return mModelInfoMap.get(mSelectedModelId).modelUuid; } private synchronized void setDetector(SoundTriggerDetector detector) { if (mSelectedModelId == 2) { mDetector2 = detector; return; } if (mSelectedModelId == 3) { mDetector3 = detector; return; } mDetector1 = detector; mModelInfoMap.get(mSelectedModelId).detector = detector; } private synchronized SoundTriggerDetector getDetector() { if (mSelectedModelId == 2) return mDetector2; if (mSelectedModelId == 3) return mDetector3; return mDetector1; return mModelInfoMap.get(mSelectedModelId).detector; } private void screenWakeup() { Loading @@ -127,25 +221,29 @@ public class TestSoundTriggerActivity extends Activity { mScreenWakelock.release(); } /** TODO: Should return the abstract sound model that can be then sent to the service. */ private GenericSoundModel createNewSoundModel() { ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId); return new GenericSoundModel(modelInfo.modelUuid, modelInfo.vendorUuid, modelInfo.modelData); } /** * Called when the user clicks the enroll button. * Performs a fresh enrollment. */ public void onEnrollButtonClicked(View v) { postMessage("Loading model: " + mSelectedModelId); // Generate a fake model to push. byte[] data = new byte[1024]; mRandom.nextBytes(data); UUID modelUuid = getSelectedUuid(); GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data); GenericSoundModel model = createNewSoundModel(); boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(model); if (status) { Toast.makeText( this, "Successfully created sound trigger model UUID=" + modelUuid, this, "Successfully created sound trigger model UUID=" + model.uuid, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "Failed to enroll!!!" + modelUuid, Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Failed to enroll!!!" + model.uuid, Toast.LENGTH_SHORT).show(); } // Test the SoundManager API. Loading Loading @@ -185,11 +283,7 @@ public class TestSoundTriggerActivity extends Activity { Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show(); return; } // Generate a fake model to push. byte[] data = new byte[2048]; mRandom.nextBytes(data); GenericSoundModel updated = new GenericSoundModel(soundModel.uuid, soundModel.vendorUuid, data); GenericSoundModel updated = createNewSoundModel(); boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated); if (status) { Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid, Loading Loading @@ -237,29 +331,32 @@ public class TestSoundTriggerActivity extends Activity { public synchronized void onRadioButtonClicked(View view) { // Is the button now checked? boolean checked = ((RadioButton) view).isChecked(); // Check which radio button was clicked switch(view.getId()) { case R.id.model_one: if (checked) { mSelectedModelId = 1; postMessage("Selected model one."); } break; case R.id.model_two: if (checked) { mSelectedModelId = 2; postMessage("Selected model two."); } break; case R.id.model_three: if (checked) { mSelectedModelId = 3; postMessage("Selected model three."); mSelectedModelId = mModelIdMap.get(view); ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId); postMessage("Selected " + modelInfo.name); // Set the play trigger button to be enabled only if we actually have some audio. mPlayTriggerButton.setEnabled(modelInfo.triggerAudioPlayer != null); } break; } public synchronized void onPlayTriggerButtonClicked(View v) { ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId); modelInfo.triggerAudioPlayer.start(); postMessage("Playing trigger audio for " + modelInfo.name); } // Helper struct for holding information about a model. private static class ModelInfo { public String name; public UUID modelUuid; public UUID vendorUuid; public MediaPlayer triggerAudioPlayer; public SoundTriggerDetector detector; public byte modelData[]; }; // Implementation of SoundTriggerDetector.Callback. public class DetectorCallback extends SoundTriggerDetector.Callback { public void onAvailabilityChanged(int status) { Loading Loading
tests/SoundTriggerTestApp/res/layout/main.xml +10 −17 Original line number Diff line number Diff line Loading @@ -60,29 +60,22 @@ android:onClick="onUnEnrollButtonClicked" android:padding="20dp" /> <Button android:id="@+id/play_trigger_id" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/play_trigger" android:onClick="onPlayTriggerButtonClicked" android:padding="20dp" /> </LinearLayout> <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/model_group_id" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="20dp" android:checkedButton="@+id/model_one" android:orientation="vertical"> <RadioButton android:id="@+id/model_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/model_one" android:onClick="onRadioButtonClicked"/> <RadioButton android:id="@+id/model_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/model_two" android:onClick="onRadioButtonClicked"/> <RadioButton android:id="@+id/model_three" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/model_three" android:onClick="onRadioButtonClicked"/> </RadioGroup> <ScrollView Loading
tests/SoundTriggerTestApp/res/values/strings.xml +1 −3 Original line number Diff line number Diff line Loading @@ -21,8 +21,6 @@ <string name="unenroll">Un-load</string> <string name="start_recog">Start</string> <string name="stop_recog">Stop</string> <string name="model_one">Model One</string> <string name="model_two">Model Two</string> <string name="model_three">Model Three</string> <string name="play_trigger">Play Trigger Audio</string> <string name="none">Debug messages appear here:\n</string> </resources>
tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java +155 −58 Original line number Diff line number Diff line Loading @@ -16,24 +16,36 @@ package com.android.test.soundtrigger; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Random; import java.util.UUID; import android.app.Activity; import android.hardware.soundtrigger.SoundTrigger; import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; import android.hardware.soundtrigger.SoundTrigger; import android.media.AudioFormat; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.soundtrigger.SoundTriggerDetector; import android.media.soundtrigger.SoundTriggerManager; import android.text.Editable; import android.text.method.ScrollingMovementMethod; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; import android.os.UserManager; import android.text.Editable; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.RadioButton; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; Loading @@ -44,20 +56,17 @@ public class TestSoundTriggerActivity extends Activity { private SoundTriggerUtil mSoundTriggerUtil; private Random mRandom; private UUID mModelUuid1 = UUID.randomUUID(); private UUID mModelUuid2 = UUID.randomUUID(); private UUID mModelUuid3 = UUID.randomUUID(); private UUID mVendorUuid = UUID.randomUUID(); private SoundTriggerDetector mDetector1 = null; private SoundTriggerDetector mDetector2 = null; private SoundTriggerDetector mDetector3 = null; private Map<Integer, ModelInfo> mModelInfoMap; private Map<View, Integer> mModelIdMap; private TextView mDebugView = null; private int mSelectedModelId = 1; private int mSelectedModelId = -1; private ScrollView mScrollView = null; private Button mPlayTriggerButton = null; private PowerManager.WakeLock mScreenWakelock; private Handler mHandler; private RadioGroup mRadioGroup; @Override protected void onCreate(Bundle savedInstanceState) { Loading @@ -66,11 +75,108 @@ public class TestSoundTriggerActivity extends Activity { setContentView(R.layout.main); mDebugView = (TextView) findViewById(R.id.console); mScrollView = (ScrollView) findViewById(R.id.scroller_id); mRadioGroup = (RadioGroup) findViewById(R.id.model_group_id); mPlayTriggerButton = (Button) findViewById(R.id.play_trigger_id); mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE); mDebugView.setMovementMethod(new ScrollingMovementMethod()); mSoundTriggerUtil = new SoundTriggerUtil(this); mRandom = new Random(); mHandler = new Handler(); mModelInfoMap = new HashMap(); mModelIdMap = new HashMap(); setVolumeControlStream(AudioManager.STREAM_MUSIC); // Load all the models in the data dir. for (File file : getFilesDir().listFiles()) { // Find meta-data in .properties files, ignore everything else. if (!file.getName().endsWith(".properties")) { continue; } try { Properties properties = new Properties(); properties.load(new FileInputStream(file)); createModelInfoAndWidget(properties); } catch (Exception e) { Log.e(TAG, "Failed to load properties file " + file.getName()); } } // Create a few dummy models if we didn't load anything. if (mModelIdMap.isEmpty()) { Properties dummyModelProperties = new Properties(); for (String name : new String[]{"One", "Two", "Three"}) { dummyModelProperties.setProperty("name", "Model " + name); createModelInfoAndWidget(dummyModelProperties); } } } private void createModelInfoAndWidget(Properties properties) { try { ModelInfo modelInfo = new ModelInfo(); if (!properties.containsKey("name")) { throw new RuntimeException("must have a 'name' property"); } modelInfo.name = properties.getProperty("name"); if (properties.containsKey("modelUuid")) { modelInfo.modelUuid = UUID.fromString(properties.getProperty("modelUuid")); } else { modelInfo.modelUuid = UUID.randomUUID(); } if (properties.containsKey("vendorUuid")) { modelInfo.vendorUuid = UUID.fromString(properties.getProperty("vendorUuid")); } else { modelInfo.vendorUuid = UUID.randomUUID(); } if (properties.containsKey("triggerAudio")) { modelInfo.triggerAudioPlayer = MediaPlayer.create(this, Uri.parse( getFilesDir().getPath() + "/" + properties.getProperty("triggerAudio"))); } if (properties.containsKey("dataFile")) { File modelDataFile = new File( getFilesDir().getPath() + "/" + properties.getProperty("dataFile")); modelInfo.modelData = new byte[(int) modelDataFile.length()]; FileInputStream input = new FileInputStream(modelDataFile); input.read(modelInfo.modelData, 0, modelInfo.modelData.length); } else { modelInfo.modelData = new byte[1024]; mRandom.nextBytes(modelInfo.modelData); } // TODO: Add property support for keyphrase models when they're exposed by the // service. Also things like how much audio they should record with the capture session // provided in the callback. // Add a widget into the radio group. RadioButton button = new RadioButton(this); mRadioGroup.addView(button); button.setText(modelInfo.name); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { onRadioButtonClicked(v); } }); // Update our maps containing the button -> id and id -> modelInfo. int newModelId = mModelIdMap.size() + 1; mModelIdMap.put(button, newModelId); mModelInfoMap.put(newModelId, modelInfo); // If we don't have something selected, select this first thing. if (mSelectedModelId < 0) { button.setChecked(true); onRadioButtonClicked(button); } } catch (IOException e) { Log.e(TAG, "Error parsing properties for " + properties.getProperty("name"), e); } } private void postMessage(String msg) { Loading @@ -91,27 +197,15 @@ public class TestSoundTriggerActivity extends Activity { } private synchronized UUID getSelectedUuid() { if (mSelectedModelId == 2) return mModelUuid2; if (mSelectedModelId == 3) return mModelUuid3; return mModelUuid1; // Default. return mModelInfoMap.get(mSelectedModelId).modelUuid; } private synchronized void setDetector(SoundTriggerDetector detector) { if (mSelectedModelId == 2) { mDetector2 = detector; return; } if (mSelectedModelId == 3) { mDetector3 = detector; return; } mDetector1 = detector; mModelInfoMap.get(mSelectedModelId).detector = detector; } private synchronized SoundTriggerDetector getDetector() { if (mSelectedModelId == 2) return mDetector2; if (mSelectedModelId == 3) return mDetector3; return mDetector1; return mModelInfoMap.get(mSelectedModelId).detector; } private void screenWakeup() { Loading @@ -127,25 +221,29 @@ public class TestSoundTriggerActivity extends Activity { mScreenWakelock.release(); } /** TODO: Should return the abstract sound model that can be then sent to the service. */ private GenericSoundModel createNewSoundModel() { ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId); return new GenericSoundModel(modelInfo.modelUuid, modelInfo.vendorUuid, modelInfo.modelData); } /** * Called when the user clicks the enroll button. * Performs a fresh enrollment. */ public void onEnrollButtonClicked(View v) { postMessage("Loading model: " + mSelectedModelId); // Generate a fake model to push. byte[] data = new byte[1024]; mRandom.nextBytes(data); UUID modelUuid = getSelectedUuid(); GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data); GenericSoundModel model = createNewSoundModel(); boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(model); if (status) { Toast.makeText( this, "Successfully created sound trigger model UUID=" + modelUuid, this, "Successfully created sound trigger model UUID=" + model.uuid, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "Failed to enroll!!!" + modelUuid, Toast.LENGTH_SHORT).show(); Toast.makeText(this, "Failed to enroll!!!" + model.uuid, Toast.LENGTH_SHORT).show(); } // Test the SoundManager API. Loading Loading @@ -185,11 +283,7 @@ public class TestSoundTriggerActivity extends Activity { Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show(); return; } // Generate a fake model to push. byte[] data = new byte[2048]; mRandom.nextBytes(data); GenericSoundModel updated = new GenericSoundModel(soundModel.uuid, soundModel.vendorUuid, data); GenericSoundModel updated = createNewSoundModel(); boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated); if (status) { Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid, Loading Loading @@ -237,29 +331,32 @@ public class TestSoundTriggerActivity extends Activity { public synchronized void onRadioButtonClicked(View view) { // Is the button now checked? boolean checked = ((RadioButton) view).isChecked(); // Check which radio button was clicked switch(view.getId()) { case R.id.model_one: if (checked) { mSelectedModelId = 1; postMessage("Selected model one."); } break; case R.id.model_two: if (checked) { mSelectedModelId = 2; postMessage("Selected model two."); } break; case R.id.model_three: if (checked) { mSelectedModelId = 3; postMessage("Selected model three."); mSelectedModelId = mModelIdMap.get(view); ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId); postMessage("Selected " + modelInfo.name); // Set the play trigger button to be enabled only if we actually have some audio. mPlayTriggerButton.setEnabled(modelInfo.triggerAudioPlayer != null); } break; } public synchronized void onPlayTriggerButtonClicked(View v) { ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId); modelInfo.triggerAudioPlayer.start(); postMessage("Playing trigger audio for " + modelInfo.name); } // Helper struct for holding information about a model. private static class ModelInfo { public String name; public UUID modelUuid; public UUID vendorUuid; public MediaPlayer triggerAudioPlayer; public SoundTriggerDetector detector; public byte modelData[]; }; // Implementation of SoundTriggerDetector.Callback. public class DetectorCallback extends SoundTriggerDetector.Callback { public void onAvailabilityChanged(int status) { Loading