xref: /aosp_15_r20/cts/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioColdStartBaseActivity.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2021 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.audio;
18 
19 import android.os.Bundle;
20 import android.view.View;
21 import android.widget.Button;
22 import android.widget.RadioButton;
23 import android.widget.TextView;
24 
25 import com.android.compatibility.common.util.ResultType;
26 import com.android.compatibility.common.util.ResultUnit;
27 import com.android.cts.verifier.PassFailButtons;
28 import com.android.cts.verifier.R;
29 
30 import org.hyphonate.megaaudio.common.BuilderBase;
31 import org.hyphonate.megaaudio.common.StreamBase;
32 
33 public abstract class AudioColdStartBaseActivity
34         extends PassFailButtons.Activity
35         implements View.OnClickListener {
36     private static final String TAG = "AudioColdStartBaseActivity";
37 
38     // Test State
39     protected boolean mIsTestRunning;
40 
41     // Audio Attributes
42     protected static final int NUM_CHANNELS = 2;
43     protected int mSampleRate;
44     protected int mNumExchangeFrames;
45 
46     protected int mAudioApi = BuilderBase.TYPE_OBOE;
47 
48     // (all times in nanoseconds)
49     protected long mPreOpenTime;
50     protected long mPostOpenTime;
51     protected long mPreStartTime;
52     protected long mPostStartTime;
53 
54     protected double mColdStartlatencyMS;
55     private double mOpenTimeMS;
56     private double mStartTimeMS;
57 
58     // Widgets
59     Button mStartBtn;
60     Button mStopBtn;
61 
62     TextView mAttributesTxt;
63     TextView mOpenTimeTxt;
64     TextView mStartTimeTxt;
65     TextView mLatencyTxt;
66     TextView mResultsTxt;
67 
68     // ReportLog Schema
69     private static final String KEY_AUDIO_API = "audio_api";
70     private static final String KEY_LATENCY = "latency_ms";
71     private static final String KEY_OPEN = "open_ms";
72     private static final String KEY_START = "start_ms";
73 
74     // Time-base conversions
nanosToMs(double nanos)75     protected double nanosToMs(double nanos) {
76         return nanos / 1000000.0;
77     }
78 
msToNanos(double ms)79     protected long msToNanos(double ms) {
80         return (long) (ms * 1000000.0);
81     }
82 
83     //
84     // UI Helpers
85     //
86     private final String msFormat = "%.2f ms";
87 
makeMSString(double ms)88     protected String makeMSString(double ms) {
89         return String.format(msFormat, ms);
90     }
91 
92     //
93     // UI
94     //
showAttributes()95     void showAttributes() {
96         mAttributesTxt.setText("" + mSampleRate + " Hz " + mNumExchangeFrames + " Frames");
97     }
98 
showOpenTime()99     private void showOpenTime() {
100         mOpenTimeMS = nanosToMs(mPostOpenTime - mPreOpenTime);
101         mOpenTimeTxt.setText("Open: " + makeMSString(mOpenTimeMS));
102 
103         reportOpenTime();
104     }
105 
showStartTime()106     private void showStartTime() {
107         mStartTimeMS = nanosToMs(mPostStartTime - mPreStartTime);
108         mStartTimeTxt.setText("Start: " + makeMSString(mStartTimeMS));
109 
110         reportStartTime();
111     }
112 
showColdStartLatency()113     protected void showColdStartLatency() {
114         mLatencyTxt.setText("Latency: " + mColdStartlatencyMS);
115 
116         if (mColdStartlatencyMS < 0) {
117             mResultsTxt.setText("Invalid cold start latency.");
118         } else if (mColdStartlatencyMS <= getRecommendedTimeMS()) {
119             mResultsTxt.setText("PASS. Meets RECOMMENDED latency of "
120                     + getRecommendedTimeMS() + "ms");
121         } else if (mColdStartlatencyMS <= getRequiredTimeMS()) {
122             mResultsTxt.setText("PASS. Meets REQUIRED latency of " + getRequiredTimeMS() + "ms");
123         } else {
124             mResultsTxt.setText("FAIL. Did not meet REQUIRED latency of " + getRequiredTimeMS()
125                     + "ms");
126         }
127     }
128 
clearResults()129     protected void clearResults() {
130         mAttributesTxt.setText("");
131         mOpenTimeTxt.setText("");
132         mStartTimeTxt.setText("");
133         mLatencyTxt.setText("");
134         mResultsTxt.setText("");
135     }
136 
137     @Override
onCreate(Bundle savedInstanceState)138     protected void onCreate(Bundle savedInstanceState) {
139         super.onCreate(savedInstanceState);
140 
141         // MegaAudio Initialization
142         StreamBase.setup(this);
143         mSampleRate = StreamBase.getSystemSampleRate();
144         mNumExchangeFrames = StreamBase.getNumBurstFrames(mAudioApi);
145 
146         ((RadioButton) findViewById(R.id.audioJavaApiBtn)).setOnClickListener(this);
147         RadioButton nativeApiRB = findViewById(R.id.audioNativeApiBtn);
148         nativeApiRB.setChecked(true);
149         nativeApiRB.setOnClickListener(this);
150 
151         mStartBtn = (Button) findViewById(R.id.coldstart_run_btn);
152         mStartBtn.setOnClickListener(this);
153         mStopBtn = (Button) findViewById(R.id.coldstart_cancel_btn);
154         mStopBtn.setOnClickListener(this);
155         mStopBtn.setEnabled(false);
156 
157         mAttributesTxt = ((TextView) findViewById(R.id.coldstart_attributesTxt));
158         mOpenTimeTxt = ((TextView) findViewById(R.id.coldstart_openTimeTxt));
159         mStartTimeTxt = ((TextView) findViewById(R.id.coldstart_startTimeTxt));
160         mLatencyTxt = (TextView) findViewById(R.id.coldstart_coldLatencyTxt);
161         mResultsTxt = (TextView) findViewById(R.id.coldstart_coldResultsTxt);
162 
163         reportApi();
164     }
165 
getRequiredTimeMS()166     abstract int getRequiredTimeMS();
getRecommendedTimeMS()167     abstract int getRecommendedTimeMS();
168 
runAudioTest()169     abstract boolean runAudioTest();
stopAudio()170     abstract void stopAudio();
cancelTest()171     void cancelTest() {
172         stopAudio();
173         updateTestStateButtons();
174 
175         mOpenTimeTxt.setText("");
176         mStartTimeTxt.setText("");
177         mLatencyTxt.setText("");
178         mResultsTxt.setText("");
179 
180         getPassButton().setEnabled(false);
181     }
182 
updateTestStateButtons()183     protected void updateTestStateButtons() {
184         mStartBtn.setEnabled(!mIsTestRunning);
185         mStopBtn.setEnabled(mIsTestRunning);
186     }
187 
188     //
189     // PassFailButtons Overrides
190     //
191     @Override
requiresReportLog()192     public boolean requiresReportLog() {
193         return true;
194     }
195 
196     @Override
getReportFileName()197     public String getReportFileName() {
198         return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME;
199     }
200 
201     @Override
recordTestResults()202     public void recordTestResults() {
203         getReportLog().submit();
204     }
205 
reportApi()206     private void reportApi() {
207         getReportLog().addValue(
208                 KEY_AUDIO_API,
209                 mAudioApi,
210                 ResultType.NEUTRAL,
211                 ResultUnit.NONE);
212     }
213 
reportOpenTime()214     private void reportOpenTime() {
215         getReportLog().addValue(
216                 KEY_OPEN,
217                 mOpenTimeMS,
218                 ResultType.NEUTRAL,
219                 ResultUnit.MS);
220     }
221 
reportStartTime()222     private void reportStartTime() {
223         getReportLog().addValue(
224                 KEY_START,
225                 mStartTimeMS,
226                 ResultType.NEUTRAL,
227                 ResultUnit.MS);
228     }
229 
reportLatency()230     protected void reportLatency() {
231         getReportLog().addValue(
232                 KEY_LATENCY,
233                 mColdStartlatencyMS,
234                 ResultType.NEUTRAL,
235                 ResultUnit.NONE);
236     }
237 
238     //
239     // View.OnClickListener overrides
240     //
241     @Override
onClick(View v)242     public void onClick(View v) {
243         int id = v.getId();
244         if (id == R.id.audioJavaApiBtn) {
245             stopAudio();
246             clearResults();
247             updateTestStateButtons();
248             mAudioApi = BuilderBase.TYPE_JAVA;
249             mNumExchangeFrames = StreamBase.getNumBurstFrames(mAudioApi);
250         } else if (id == R.id.audioNativeApiBtn) {
251             stopAudio();
252             clearResults();
253             updateTestStateButtons();
254             mAudioApi = BuilderBase.TYPE_OBOE;
255             mNumExchangeFrames = StreamBase.getNumBurstFrames(mAudioApi);
256         } else if (id == R.id.coldstart_run_btn) {
257             runAudioTest();
258 
259             showAttributes();
260             showOpenTime();
261             showStartTime();
262 
263             updateTestStateButtons();
264         } else if (id == R.id.coldstart_cancel_btn) {
265             cancelTest();
266         }
267     }
268 }
269