• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
20 import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
21 
22 import android.app.AlertDialog;
23 import android.content.DialogInterface;
24 import android.content.res.Resources;
25 import android.media.AudioDeviceCallback;
26 import android.media.AudioDeviceInfo;
27 import android.media.AudioFormat;
28 import android.media.AudioManager;
29 import android.os.Bundle;
30 import android.util.Log;
31 import android.view.View;
32 import android.widget.CheckBox;
33 import android.widget.TextView;
34 
35 import com.android.compatibility.common.util.CddTest;
36 import com.android.compatibility.common.util.ResultType;
37 import com.android.compatibility.common.util.ResultUnit;
38 import com.android.cts.verifier.CtsVerifierReportLog;
39 import com.android.cts.verifier.PassFailButtons;
40 import com.android.cts.verifier.R;
41 import com.android.cts.verifier.audio.audiolib.AudioSystemFlags;
42 
43 @CddTest(requirement = "5.10/C-1-1,C-1-3,C-1-4")
44 public class ProAudioActivity
45         extends PassFailButtons.Activity
46         implements View.OnClickListener {
47     private static final String TAG = ProAudioActivity.class.getSimpleName();
48     private static final boolean DEBUG = false;
49 
50     // Flags
51     private boolean mClaimsProAudio;
52     private boolean mClaimsLowLatencyAudio;    // CDD ProAudio section C-1-1
53     private boolean mClaimsMIDI;               // CDD ProAudio section C-1-4
54     private boolean mClaimsUSBHostMode;        // CDD ProAudio section C-1-3
55     private boolean mClaimsUSBPeripheralMode;  // CDD ProAudio section C-1-3
56     private boolean mClaimsHDMI;               // CDD ProAudio section C-1-3
57 
58     AudioDeviceInfo mHDMIDeviceInfo;
59 
60     // Widgets
61     TextView mHDMISupportLbl;
62 
63     CheckBox mClaimsHDMICheckBox;
64 
65     TextView mTestStatusLbl;
66 
67     // Borrowed from PassFailButtons.java
68     private static final int INFO_DIALOG_ID = 1337;
69     private static final String INFO_DIALOG_TITLE_ID = "infoDialogTitleId";
70     private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId";
71 
72     // ReportLog Schema
73     private static final String SECTION_PRO_AUDIO_ACTIVITY = "pro_audio_activity";
74     private static final String KEY_CLAIMS_PRO = "claims_pro_audio";
75     private static final String KEY_CLAIMS_LOW_LATENCY = "claims_low_latency_audio";
76     private static final String KEY_CLAIMS_MIDI = "claims_midi";
77     private static final String KEY_CLAIMS_USB_HOST = "claims_usb_host";
78     private static final String KEY_CLAIMS_USB_PERIPHERAL = "claims_usb_peripheral";
79     private static final String KEY_CLAIMS_HDMI = "claims_hdmi";
80 
ProAudioActivity()81     public ProAudioActivity() {
82     }
83 
84     // HDMI Stuff
isHDMIConnected()85     private boolean isHDMIConnected() {
86         return mHDMIDeviceInfo != null;
87     }
88 
isHDMIValid()89     private boolean isHDMIValid() {
90         if (mHDMIDeviceInfo == null) {
91             return false;
92         }
93 
94         // MUST support output in stereo and eight channels...
95         boolean has2Chans = false;
96         boolean has8Chans = false;
97         int[] channelCounts = mHDMIDeviceInfo.getChannelCounts();
98         for (int count : channelCounts) {
99             if (count == 2) {
100                 has2Chans = true;
101             } else if (count == 8) {
102                 has8Chans = true;
103             }
104         }
105         if (!has2Chans || !has8Chans) {
106             return false;
107         }
108 
109         // at 20-bit or 24-bit depth
110         boolean hasFloatEncoding = false;
111         int[] encodings = mHDMIDeviceInfo.getEncodings();
112         for (int encoding : encodings) {
113             if (encoding == AudioFormat.ENCODING_PCM_FLOAT) {
114                 hasFloatEncoding = true;
115                 break;
116             }
117         }
118         if (!hasFloatEncoding) {
119             return false;
120         }
121 
122          // and 192 kHz
123         boolean has192K = false;
124         int[] sampleRates = mHDMIDeviceInfo.getSampleRates();
125         for (int rate : sampleRates) {
126             if (rate >= 192000) {
127                 has192K = true;
128             }
129         }
130         if (!has192K) {
131             return false;
132         }
133 
134         // without bit-depth loss or resampling (hmmmmm....).
135 
136         return true;
137     }
138 
handleDeviceConnection(AudioDeviceInfo[] addedDevices)139     protected void handleDeviceConnection(AudioDeviceInfo[] addedDevices) {
140         mHDMIDeviceInfo = null;
141         for (AudioDeviceInfo deviceInfo : addedDevices) {
142             Log.i(TAG, "  " + deviceInfo.getProductName() + " type:" + deviceInfo.getType());
143             if (deviceInfo.isSink() && deviceInfo.getType() == AudioDeviceInfo.TYPE_HDMI) {
144                 mHDMIDeviceInfo = deviceInfo;
145                 break;
146             }
147         }
148 
149         if (mHDMIDeviceInfo != null) {
150             mClaimsHDMICheckBox.setChecked(true);
151         }
152 
153         displayTestResults();
154     }
155 
calculatePass()156     private boolean calculatePass() {
157         boolean usbOK = mClaimsUSBHostMode && mClaimsUSBPeripheralMode;
158         boolean hdmiOK = !mClaimsHDMI || isHDMIValid();
159 
160         boolean hasPassed = isReportLogOkToPass()
161                 && !mClaimsProAudio
162                 || (mClaimsLowLatencyAudio && mClaimsMIDI && usbOK && hdmiOK);
163 
164         getPassButton().setEnabled(hasPassed);
165         return hasPassed;
166     }
167 
displayTestResults()168     private void displayTestResults() {
169         boolean hasPassed = calculatePass();
170 
171         Resources strings = getResources();
172         if (!isReportLogOkToPass()) {
173             mTestStatusLbl.setText(getResources().getString(R.string.audio_general_reportlogtest));
174         } else  if (hasPassed) {
175             mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_pass));
176         } else if (!mClaimsMIDI) {
177             mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_midinotreported));
178         } else if (!mClaimsUSBHostMode) {
179             mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_usbhostnotreported));
180         } else if (!mClaimsUSBPeripheralMode) {
181             mTestStatusLbl.setText(strings.getString(
182                     R.string.audio_proaudio_usbperipheralnotreported));
183         } else if (mClaimsHDMI) {
184             if (!isHDMIConnected()) {
185                 mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_hdmiNotFound));
186             } else if (!isHDMIValid()) {
187                 mTestStatusLbl.setText(strings.getString(R.string.hdmi_insufficient));
188             }
189         }
190     }
191 
192     @Override
onCreate(Bundle savedInstanceState)193     protected void onCreate(Bundle savedInstanceState) {
194         setContentView(R.layout.pro_audio);
195 
196         super.onCreate(savedInstanceState);
197 
198         setPassFailButtonClickListeners();
199         setInfoResources(R.string.proaudio_test, R.string.proaudio_info, -1);
200 
201         mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
202         ((TextView)findViewById(R.id.proAudioHasProAudioLbl)).setText("" + mClaimsProAudio);
203 
204         if (!mClaimsProAudio) {
205             Bundle args = new Bundle();
206             args.putInt(INFO_DIALOG_TITLE_ID, R.string.pro_audio_latency_test);
207             args.putInt(INFO_DIALOG_MESSAGE_ID, R.string.audio_proaudio_nopa_message);
208             showDialog(INFO_DIALOG_ID, args);
209         }
210 
211         mClaimsLowLatencyAudio = AudioSystemFlags.claimsLowLatencyAudio(this);
212         ((TextView)findViewById(R.id.proAudioHasLLALbl)).setText("" + mClaimsLowLatencyAudio);
213 
214         mClaimsMIDI = AudioSystemFlags.claimsMIDI(this);
215         ((TextView)findViewById(R.id.proAudioHasMIDILbl)).setText("" + mClaimsMIDI);
216 
217         mClaimsUSBHostMode = AudioSystemFlags.claimsUSBHostMode(this);
218         ((TextView)findViewById(R.id.proAudioMidiHasUSBHostLbl)).setText("" + mClaimsUSBHostMode);
219 
220         mClaimsUSBPeripheralMode = AudioSystemFlags.claimsUSBPeripheralMode(this);
221         ((TextView)findViewById(
222                 R.id.proAudioMidiHasUSBPeripheralLbl)).setText("" + mClaimsUSBPeripheralMode);
223 
224         // HDMI
225         mHDMISupportLbl = (TextView)findViewById(R.id.proAudioHDMISupportLbl);
226         mClaimsHDMICheckBox = (CheckBox)findViewById(R.id.proAudioHasHDMICheckBox);
227         mClaimsHDMICheckBox.setOnClickListener(this);
228 
229         mTestStatusLbl = (TextView)findViewById(R.id.proAudioTestStatusLbl);
230 
231         AudioManager audioManager = getSystemService(AudioManager.class);
232         audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null);
233 
234         displayTestResults();
235     }
236 
237     /**
238      * Store test results in log
239      */
240     @Override
getTestId()241     public String getTestId() {
242         return setTestNameSuffix(sCurrentDisplayMode, getClass().getName());
243     }
244 
245     //
246     // PassFailButtons Overrides
247     //
248     @Override
requiresReportLog()249     public boolean requiresReportLog() {
250         return true;
251     }
252 
253     @Override
getReportFileName()254     public String getReportFileName() { return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME; }
255 
256     @Override
getReportSectionName()257     public final String getReportSectionName() {
258         return setTestNameSuffix(sCurrentDisplayMode, SECTION_PRO_AUDIO_ACTIVITY);
259     }
260 
261     @Override
recordTestResults()262     public void recordTestResults() {
263 
264         CtsVerifierReportLog reportLog = getReportLog();
265         reportLog.addValue(
266                 KEY_CLAIMS_PRO,
267                 mClaimsProAudio,
268                 ResultType.NEUTRAL,
269                 ResultUnit.NONE);
270 
271         reportLog.addValue(
272                 KEY_CLAIMS_LOW_LATENCY,
273                 mClaimsLowLatencyAudio,
274                 ResultType.NEUTRAL,
275                 ResultUnit.NONE);
276 
277         reportLog.addValue(
278                 KEY_CLAIMS_MIDI,
279                 mClaimsMIDI,
280                 ResultType.NEUTRAL,
281                 ResultUnit.NONE);
282 
283         reportLog.addValue(
284                 KEY_CLAIMS_USB_HOST,
285                 mClaimsUSBHostMode,
286                 ResultType.NEUTRAL,
287                 ResultUnit.NONE);
288 
289         reportLog.addValue(
290                 KEY_CLAIMS_USB_PERIPHERAL,
291                 mClaimsUSBPeripheralMode,
292                 ResultType.NEUTRAL,
293                 ResultUnit.NONE);
294 
295         reportLog.addValue(
296                 KEY_CLAIMS_HDMI,
297                 mClaimsHDMI,
298                 ResultType.NEUTRAL,
299                 ResultUnit.NONE);
300 
301         reportLog.submit();
302     }
303 
304     @Override
onClick(View view)305     public void onClick(View view) {
306         if (view.getId() == R.id.proAudioHasHDMICheckBox) {
307             if (mClaimsHDMICheckBox.isChecked()) {
308                 AlertDialog.Builder builder = new AlertDialog.Builder(
309                         this, android.R.style.Theme_Material_Dialog_Alert);
310                 builder.setTitle(getResources().getString(R.string.proaudio_hdmi_infotitle));
311                 builder.setMessage(getResources().getString(R.string.proaudio_hdmi_message));
312                 builder.setPositiveButton(android.R.string.yes,
313                         new DialogInterface.OnClickListener() {
314                             public void onClick(DialogInterface dialog, int which) {
315                             }
316                         });
317                 builder.setIcon(android.R.drawable.ic_dialog_alert);
318                 builder.show();
319 
320                 mClaimsHDMI = true;
321                 mHDMISupportLbl.setText(
322                         getResources().getString(R.string.audio_proaudio_hdmiPending));
323             } else {
324                 mClaimsHDMI = false;
325                 mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_NA));
326             }
327             displayTestResults();
328         }
329     }
330 
331     private class TestAudioDeviceCallback extends AudioDeviceCallback {
onAudioDevicesAdded(AudioDeviceInfo[] addedDevices)332         public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
333             handleDeviceConnection(addedDevices);
334         }
335 
onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices)336         public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
337             // NOP
338         }
339     }
340 }
341