1 /* 2 * Copyright (C) 2010 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.cts.verifier.audioquality; 18 19 import com.android.cts.verifier.R; 20 21 import android.app.Activity; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.graphics.Color; 27 import android.graphics.Typeface; 28 import android.media.AudioFormat; 29 import android.os.Bundle; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.AdapterView; 34 import android.widget.ArrayAdapter; 35 import android.widget.Button; 36 import android.widget.ListView; 37 import android.widget.ProgressBar; 38 import android.widget.TextView; 39 import android.widget.AdapterView.OnItemClickListener; 40 41 import java.util.ArrayList; 42 43 /** 44 * Main UI for the Android Audio Quality Verifier. 45 */ 46 public class AudioQualityVerifierActivity extends Activity implements View.OnClickListener, 47 OnItemClickListener { 48 public static final String TAG = "AudioQualityVerifier"; 49 50 public static final int SAMPLE_RATE = 16000; 51 public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; 52 public static final int BYTES_PER_SAMPLE = 2; 53 54 // Intent Extra definitions, which must match those in 55 // com.google.android.voicesearch.speechservice.RecognitionController 56 public static final String EXTRA_RAW_AUDIO = 57 "android.speech.extras.RAW_AUDIO"; 58 59 // Communication with ExperimentService 60 public static final String ACTION_EXP_STARTED = 61 "com.android.cts.verifier.audioquality.EXP_STARTED"; 62 public static final String ACTION_EXP_FINISHED = 63 "com.android.cts.verifier.audioquality.EXP_FINISHED"; 64 public static final String EXTRA_ABORTED = 65 "com.android.cts.verifier.audioquality.ABORTED"; 66 public static final String EXTRA_EXP_ID = 67 "com.android.cts.verifier.audioquality.EXP_ID"; 68 public static final String EXTRA_RUN_ALL = 69 "com.android.cts.verifier.audioquality.RUN_ALL"; 70 71 // Communication with ViewResultsActivity 72 public static final String EXTRA_RESULTS = 73 "com.android.cts.verifier.audioquality.RESULTS"; 74 75 private Button mCalibrateButton; 76 private Button mRunAllButton; 77 private Button mStopButton; 78 private Button mViewResultsButton; 79 private Button mClearButton; 80 81 private ListView mList; 82 private TwoColumnAdapter mAdapter; 83 84 private ProgressBar mProgress; 85 86 private ArrayList<Experiment> mExperiments; 87 88 private boolean mRunningExperiment; 89 90 @Override 91 public void onCreate(Bundle savedInstanceState) { 92 super.onCreate(savedInstanceState); 93 setContentView(R.layout.aq_verifier_activity); 94 95 mCalibrateButton = (Button) findViewById(R.id.calibrateButton); 96 mRunAllButton = (Button) findViewById(R.id.runAllButton); 97 mStopButton = (Button) findViewById(R.id.stopButton); 98 mViewResultsButton = (Button) findViewById(R.id.viewResultsButton); 99 mClearButton = (Button) findViewById(R.id.clearButton); 100 101 mCalibrateButton.setOnClickListener(this); 102 mRunAllButton.setOnClickListener(this); 103 mStopButton.setOnClickListener(this); 104 mViewResultsButton.setOnClickListener(this); 105 mClearButton.setOnClickListener(this); 106 107 mStopButton.setEnabled(false); 108 109 mProgress = (ProgressBar) findViewById(R.id.progress); 110 111 mList = (ListView) findViewById(R.id.list); 112 mAdapter = new TwoColumnAdapter(this); 113 114 mExperiments = VerifierExperiments.getExperiments(this); 115 116 BroadcastReceiver receiver = new BroadcastReceiver() { 117 @Override 118 public void onReceive(Context context, Intent intent) { 119 experimentReplied(intent); 120 } 121 }; 122 IntentFilter filter = new IntentFilter(); 123 filter.addAction(ACTION_EXP_STARTED); 124 filter.addAction(ACTION_EXP_FINISHED); 125 registerReceiver(receiver, filter); 126 127 fillAdapter(); 128 mList.setAdapter(mAdapter); 129 mList.setOnItemClickListener(this); 130 } 131 132 @Override 133 public void onResume() { 134 super.onResume(); 135 mAdapter.notifyDataSetChanged(); // Update List UI 136 } 137 138 // Called when an experiment has completed 139 private void experimentReplied(Intent intent) { 140 String action = intent.getAction(); 141 if (ACTION_EXP_STARTED.equals(action)) { 142 mStopButton.setEnabled(true); 143 mRunAllButton.setEnabled(false); 144 } else if (ACTION_EXP_FINISHED.equals(action)) { 145 boolean mRunAll = intent.getBooleanExtra(EXTRA_RUN_ALL, false); 146 boolean aborted = intent.getBooleanExtra(EXTRA_ABORTED, true); 147 int expID = intent.getIntExtra(EXTRA_EXP_ID, -1); 148 if (mRunAll && !aborted) { 149 while (expID < mExperiments.size() - 1) { 150 if (runExperiment(++expID, true)) { 151 // OK, experiment is running 152 mAdapter.notifyDataSetChanged(); 153 return; 154 } 155 // Otherwise, loop back and try the next experiment 156 } 157 } 158 mStopButton.setEnabled(false); 159 mRunAllButton.setEnabled(true); 160 mRunningExperiment = false; 161 mProgress.setVisibility(ProgressBar.INVISIBLE); 162 } 163 mAdapter.notifyDataSetChanged(); 164 } 165 166 // Implements AdapterView.OnItemClickListener 167 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 168 if (mRunningExperiment) return; 169 runExperiment(position, false); 170 } 171 172 // Begin an experiment. Returns false if the experiment is not enabled. 173 private boolean runExperiment(int which, boolean all) { 174 Experiment exp = mExperiments.get(which); 175 if (!exp.isEnabled()) return false; 176 Intent intent = new Intent(this, ExperimentService.class); 177 intent.putExtra(EXTRA_EXP_ID, which); 178 intent.putExtra(EXTRA_RUN_ALL, all); 179 startService(intent); 180 mRunningExperiment = true; 181 mAdapter.notifyDataSetChanged(); 182 mProgress.setVisibility(ProgressBar.VISIBLE); 183 return true; 184 } 185 186 // Implements View.OnClickListener: 187 public void onClick(View v) { 188 if (v == mCalibrateButton) { 189 Intent intent = new Intent(this, CalibrateVolumeActivity.class); 190 startActivity(intent); 191 } else if (v == mRunAllButton) { 192 if (mRunningExperiment) return; 193 int expID = -1; 194 while (expID < mExperiments.size() - 1) { 195 if (runExperiment(++expID, true)) break; 196 } 197 } else if (v == mStopButton) { 198 Intent intent = new Intent(this, ExperimentService.class); 199 stopService(intent); 200 } else if (v == mViewResultsButton) { 201 Intent intent = new Intent(this, ViewResultsActivity.class); 202 intent.putExtra(EXTRA_RESULTS, genReport()); 203 startActivity(intent); 204 } else if (v == mClearButton) { 205 clear(); 206 } 207 } 208 209 private void fillAdapter() { 210 mAdapter.clear(); 211 for (Experiment exp : mExperiments) { 212 mAdapter.add(exp.getName()); 213 } 214 } 215 216 class TwoColumnAdapter extends ArrayAdapter<String> { 217 TwoColumnAdapter(Context context) { 218 super(context, R.layout.aq_row); 219 } 220 221 @Override 222 public View getView(int position, View convertView, ViewGroup parent) { 223 LayoutInflater inflater = getLayoutInflater(); 224 View row = inflater.inflate(R.layout.aq_row, parent, false); 225 TextView nameField = (TextView) row.findViewById(R.id.testName); 226 TextView scoreField = (TextView) row.findViewById(R.id.testScore); 227 Experiment exp = mExperiments.get(position); 228 nameField.setText(exp.getName()); 229 scoreField.setText(exp.getScore()); 230 if (exp.isRunning()) { 231 Typeface tf = nameField.getTypeface(); 232 nameField.setTypeface(tf, 1); 233 } 234 if (!exp.isEnabled()) { 235 nameField.setTextColor(Color.GRAY); 236 } 237 return row; 238 } 239 } 240 241 private String genReport() { 242 StringBuilder sb = new StringBuilder(); 243 for (Experiment exp : mExperiments) { 244 exp.getReport(sb); 245 } 246 return sb.toString(); 247 } 248 249 private void clear() { 250 if (mRunningExperiment) { 251 Intent intent = new Intent(this, ExperimentService.class); 252 stopService(intent); 253 } 254 for (Experiment exp : mExperiments) { 255 exp.reset(); 256 } 257 mAdapter.notifyDataSetChanged(); 258 } 259 } 260