blob: c1714cc197356ee6d56afe3108efd2f26734a76f [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.verifier.audio;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
import com.android.cts.verifier.R; // needed to access resource in CTSVerifier project namespace.
public class ProAudioActivity
extends AudioLoopbackBaseActivity
implements View.OnClickListener {
private static final String TAG = ProAudioActivity.class.getName();
private static final boolean DEBUG = false;
// Flags
private boolean mClaimsProAudio;
private boolean mClaimsLowLatencyAudio; // CDD ProAudio section C-1-1
private boolean mClaimsMIDI; // CDD ProAudio section C-1-4
private boolean mClaimsUSBHostMode; // CDD ProAudio section C-1-3
private boolean mClaimsUSBPeripheralMode; // CDD ProAudio section C-1-3
private boolean mClaimsHDMI; // CDD ProAudio section C-1-3
AudioDeviceInfo mHDMIDeviceInfo;
// Widgets
TextView mHDMISupportLbl;
CheckBox mClaimsHDMICheckBox;
Button mRoundTripTestButton;
// Borrowed from PassFailButtons.java
private static final int INFO_DIALOG_ID = 1337;
private static final String INFO_DIALOG_TITLE_ID = "infoDialogTitleId";
private static final String INFO_DIALOG_MESSAGE_ID = "infoDialogMessageId";
public ProAudioActivity() {
super();
}
private boolean claimsProAudio() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);
}
private boolean claimsLowLatencyAudio() {
// CDD Section C-1-1: android.hardware.audio.low_latency
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
}
private boolean claimsMIDI() {
// CDD Section C-1-4: android.software.midi
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
}
private boolean claimsUSBHostMode() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
}
private boolean claimsUSBPeripheralMode() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
}
// HDMI Stuff
private boolean isHDMIValid() {
if (mHDMIDeviceInfo == null) {
return false;
}
// MUST support output in stereo and eight channels...
boolean has2Chans = false;
boolean has8Chans = false;
int[] channelCounts = mHDMIDeviceInfo.getChannelCounts();
for (int count : channelCounts) {
if (count == 2) {
has2Chans = true;
} else if (count == 8) {
has8Chans = true;
}
}
if (!has2Chans || !has8Chans) {
return false;
}
// at 20-bit or 24-bit depth
boolean hasFloatEncoding = false;
int[] encodings = mHDMIDeviceInfo.getEncodings();
for (int encoding : encodings) {
if (encoding == AudioFormat.ENCODING_PCM_FLOAT) {
hasFloatEncoding = true;
break;
}
}
if (!hasFloatEncoding) {
return false;
}
// and 192 kHz
boolean has192K = false;
int[] sampleRates = mHDMIDeviceInfo.getSampleRates();
for (int rate : sampleRates) {
if (rate >= 192000) {
has192K = true;
}
}
if (!has192K) {
return false;
}
// without bit-depth loss or resampling (hmmmmm....).
return true;
}
protected void handleDeviceConnection(AudioDeviceInfo devInfo) {
if (devInfo.isSink() && devInfo.getType() == AudioDeviceInfo.TYPE_HDMI) {
mHDMIDeviceInfo = devInfo;
}
if (mHDMIDeviceInfo != null) {
mClaimsHDMICheckBox.setChecked(true);
mHDMISupportLbl.setText(getResources().getString(
isHDMIValid() ? R.string.pass_button_text : R.string.fail_button_text));
}
mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_NA));
calculatePass();
}
private void calculatePass() {
boolean hasPassed = !mClaimsProAudio ||
(mClaimsLowLatencyAudio && mClaimsMIDI &&
mClaimsUSBHostMode && mClaimsUSBPeripheralMode &&
(!mClaimsHDMI || isHDMIValid()) &&
mOutputDevInfo != null && mInputDevInfo != null &&
mConfidence >= CONFIDENCE_THRESHOLD && mLatencyMillis <= PROAUDIO_LATENCY_MS_LIMIT);
getPassButton().setEnabled(hasPassed);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.pro_audio);
super.onCreate(savedInstanceState);
setPassFailButtonClickListeners();
setInfoResources(R.string.proaudio_test, R.string.proaudio_info, -1);
mClaimsProAudio = claimsProAudio();
((TextView)findViewById(R.id.proAudioHasProAudioLbl)).setText("" + mClaimsProAudio);
if (!mClaimsProAudio) {
Bundle args = new Bundle();
args.putInt(INFO_DIALOG_TITLE_ID, R.string.pro_audio_latency_test);
args.putInt(INFO_DIALOG_MESSAGE_ID, R.string.audio_proaudio_nopa_message);
showDialog(INFO_DIALOG_ID, args);
}
mClaimsLowLatencyAudio = claimsLowLatencyAudio();
((TextView)findViewById(R.id.proAudioHasLLALbl)).setText("" + mClaimsLowLatencyAudio);
mClaimsMIDI = claimsMIDI();
((TextView)findViewById(R.id.proAudioHasMIDILbl)).setText("" + mClaimsMIDI);
mClaimsUSBHostMode = claimsUSBHostMode();
((TextView)findViewById(R.id.proAudioMidiHasUSBHostLbl)).setText("" + mClaimsUSBHostMode);
mClaimsUSBPeripheralMode = claimsUSBPeripheralMode();
((TextView)findViewById(
R.id.proAudioMidiHasUSBPeripheralLbl)).setText("" + mClaimsUSBPeripheralMode);
mRoundTripTestButton = (Button)findViewById(R.id.proAudio_runRoundtripBtn);
mRoundTripTestButton.setOnClickListener(this);
// HDMI
mHDMISupportLbl = (TextView)findViewById(R.id.proAudioHDMISupportLbl);
mClaimsHDMICheckBox = (CheckBox)findViewById(R.id.proAudioHasHDMICheckBox);
mClaimsHDMICheckBox.setOnClickListener(this);
calculatePass();
}
protected void startAudioTest() {
mRoundTripTestButton.setEnabled(false);
super.startAudioTest(mMessageHandler);
}
protected void handleTestCompletion() {
super.handleTestCompletion();
calculatePass();
recordTestResults();
showWait(false);
mRoundTripTestButton.setEnabled(true);
}
/**
* Store test results in log
*/
protected void recordTestResults() {
super.recordTestResults();
ReportLog reportLog = getReportLog();
reportLog.addValue(
"Claims Pro Audio",
mClaimsProAudio,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
"Claims Low-Latency Audio",
mClaimsLowLatencyAudio,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
"Claims MIDI",
mClaimsMIDI,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
"Claims USB Host Mode",
mClaimsUSBHostMode,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
"Claims USB Peripheral Mode",
mClaimsUSBPeripheralMode,
ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(
"Claims HDMI",
mClaimsHDMI,
ResultType.NEUTRAL,
ResultUnit.NONE);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.proAudio_runRoundtripBtn:
startAudioTest();
break;
case R.id.proAudioHasHDMICheckBox:
if (mClaimsHDMICheckBox.isChecked()) {
AlertDialog.Builder builder =
new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert);
builder.setTitle(getResources().getString(R.string.proaudio_hdmi_infotitle));
builder.setMessage(getResources().getString(R.string.proaudio_hdmi_message));
builder.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {}
});
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.show();
mClaimsHDMI = true;
mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_pending));
} else {
mClaimsHDMI = false;
mHDMISupportLbl.setText(getResources().getString(R.string.audio_proaudio_NA));
}
break;
}
}
}