xref: /aosp_15_r20/cts/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java (revision b7c941bb3fa97aba169d73cee0bed2de8ac964bf)
1 /*
2  * Copyright (C) 2017 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.app.AlertDialog;
20 import android.media.AudioDeviceCallback;
21 import android.media.AudioDeviceInfo;
22 import android.media.AudioManager;
23 import android.os.Bundle;
24 import android.util.Log;
25 import android.view.View;
26 import android.view.View.OnClickListener;
27 import android.widget.TextView;
28 
29 import com.android.compatibility.common.util.ResultType;
30 import com.android.compatibility.common.util.ResultUnit;
31 import com.android.cts.verifier.PassFailButtons;
32 import com.android.cts.verifier.R;
33 import com.android.cts.verifier.audio.peripheralprofile.PeripheralProfile;
34 import com.android.cts.verifier.audio.peripheralprofile.ProfileManager;
35 
36 public abstract class USBAudioPeripheralActivity extends PassFailButtons.Activity {
37     private static final String TAG = "USBAudioPeripheralActivity";
38     private static final boolean DEBUG = false;
39 
40     // Host Mode Support
41     protected boolean mHasHostMode;
42 
43     // Record if pass the test
44     protected boolean mHasPassedTest;
45 
46     // Profile
47     protected ProfileManager mProfileManager = new ProfileManager();
48     protected PeripheralProfile mSelectedProfile;
49 
50     // Peripheral
51     private AudioManager mAudioManager;
52     private ConnectListener mConnectionListener;
53 
54     protected boolean mIsPeripheralAttached;
55     protected AudioDeviceInfo mOutputDevInfo;
56     protected AudioDeviceInfo mInputDevInfo;
57 
58     protected final boolean mIsMandatedRequired;
59 
60     // Widgets
61     private TextView mProfileNameTx;
62     private TextView mProfileDescriptionTx;
63 
64     private TextView mPeripheralNameTx;
65 
66     private OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
67 
68     // ReportLog Schema
69     private static final String KEY_CLAIMS_HOST = "claims_host_mode";
70 
71     //
72     // Common UI Handling
73     //
connectUSBPeripheralUI()74     protected void connectUSBPeripheralUI() {
75         findViewById(R.id.uap_tests_yes_btn).setOnClickListener(mBtnClickListener);
76         findViewById(R.id.uap_tests_no_btn).setOnClickListener(mBtnClickListener);
77         findViewById(R.id.uap_test_info_btn).setOnClickListener(mBtnClickListener);
78 
79         // Leave the default state in tact
80         // enableTestUI(false);
81     }
82 
showUAPInfoDialog()83     private void showUAPInfoDialog() {
84         new AlertDialog.Builder(this)
85                 .setTitle(R.string.uap_test_hostmode_info_caption)
86                 .setMessage(R.string.uap_test_hostmode_info_text)
87                 .setPositiveButton(R.string.audio_general_ok, null)
88                 .show();
89     }
90 
91     private class OnBtnClickListener implements OnClickListener {
92         @Override
onClick(View v)93         public void onClick(View v) {
94             int id = v.getId();
95             if (id == R.id.uap_tests_yes_btn) {
96                 mHasHostMode = true;
97                 setUsbAudioStatus(mHasHostMode);
98             } else if (id == R.id.uap_tests_no_btn) {
99                 mHasHostMode = false;
100                 // If the device doesn't support USB host mode, no test need to run.
101                 // In that case, the test should always be passed.
102                 mHasPassedTest = true;
103                 setUsbAudioStatus(mHasHostMode);
104             } else if (id == R.id.uap_test_info_btn) {
105                 showUAPInfoDialog();
106             }
107         }
108     }
109 
110     @Override
requiresReportLog()111     public boolean requiresReportLog() {
112         return true;
113     }
114 
115     @Override
getReportFileName()116     public String getReportFileName() {
117         return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME;
118     }
119 
recordUSBAudioStatus(boolean has)120     private void recordUSBAudioStatus(boolean has) {
121         getReportLog().addValue(
122                 KEY_CLAIMS_HOST,
123                 has,
124                 ResultType.NEUTRAL,
125                 ResultUnit.NONE);
126     }
127 
setUsbAudioStatus(boolean has)128     protected void setUsbAudioStatus(boolean has) {
129         // ReportLog
130         recordUSBAudioStatus(has);
131 
132         // UI & Pass/Fail status
133         getPassButton().setEnabled(!mHasHostMode || mHasPassedTest);
134         findViewById(R.id.uap_tests_yes_btn).setEnabled(mHasHostMode);
135         findViewById(R.id.uap_tests_no_btn).setEnabled(!mHasHostMode);
136     }
137 
USBAudioPeripheralActivity(boolean mandatedRequired)138     public USBAudioPeripheralActivity(boolean mandatedRequired) {
139         // determine if to show "UNSUPPORTED" if the mandated peripheral is required.
140         mIsMandatedRequired = mandatedRequired;
141 
142         mProfileManager.loadProfiles();
143     }
144 
145     @Override
onCreate(Bundle savedInstanceState)146     protected void onCreate(Bundle savedInstanceState) {
147         super.onCreate(savedInstanceState);
148 
149         mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
150         mConnectionListener = new ConnectListener();
151     }
152 
153     @Override
onStart()154     public void onStart() {
155         super.onStart();
156         mAudioManager.registerAudioDeviceCallback(mConnectionListener, null);
157     }
158 
159     @Override
onStop()160     public void onStop() {
161         mAudioManager.unregisterAudioDeviceCallback(mConnectionListener);
162         super.onStop();
163     }
164 
connectPeripheralStatusWidgets()165     protected void connectPeripheralStatusWidgets() {
166         mProfileNameTx = (TextView)findViewById(R.id.uap_profileNameTx);
167         mProfileDescriptionTx =
168             (TextView)findViewById(R.id.uap_profileDescriptionTx);
169         mPeripheralNameTx = (TextView)findViewById(R.id.uap_peripheralNameTx);
170     }
171 
showProfileStatus()172     private void showProfileStatus() {
173         if (DEBUG) {
174             Log.d(TAG, "showProfileStatus()" + (mSelectedProfile != null));
175         }
176         if (mSelectedProfile != null) {
177             mProfileNameTx.setText(mSelectedProfile.getName());
178             mProfileDescriptionTx.setText(mSelectedProfile.getDescription());
179         } else {
180             mProfileNameTx.setText("");
181             mProfileDescriptionTx.setText("");
182         }
183     }
184 
showPeripheralStatus()185     private void showPeripheralStatus() {
186         if (mIsPeripheralAttached) {
187             String productName = "";
188             if (mOutputDevInfo != null) {
189                 productName = mOutputDevInfo.getProductName().toString();
190             } else if (mInputDevInfo != null) {
191                 productName = mInputDevInfo.getProductName().toString();
192             }
193             String ctrlText;
194             if (mSelectedProfile == null && mIsMandatedRequired) {
195                 ctrlText = productName + " - UNSUPPORTED";
196             } else {
197                 ctrlText = productName;
198             }
199             mPeripheralNameTx.setText(ctrlText);
200         } else {
201             mPeripheralNameTx.setText("Disconnected");
202         }
203     }
204 
scanPeripheralList(AudioDeviceInfo[] devices)205     private void scanPeripheralList(AudioDeviceInfo[] devices) {
206         // Can't just use the first record because then we will only get
207         // Source OR sink, not both even on devices that are both.
208         mOutputDevInfo = null;
209         mInputDevInfo = null;
210 
211         // Any valid peripherals
212         for(AudioDeviceInfo devInfo : devices) {
213             if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE ||
214                 devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
215                 if (devInfo.isSink()) {
216                     mOutputDevInfo = devInfo;
217                 }
218                 if (devInfo.isSource()) {
219                     mInputDevInfo = devInfo;
220                 }
221             }
222         }
223         mIsPeripheralAttached = mOutputDevInfo != null || mInputDevInfo != null;
224         if (DEBUG) {
225             Log.d(TAG, "mIsPeripheralAttached: " + mIsPeripheralAttached);
226         }
227 
228         // any associated profiles?
229         if (mIsPeripheralAttached) {
230             if (mOutputDevInfo != null) {
231                 mSelectedProfile =
232                     mProfileManager.getProfile(mOutputDevInfo.getProductName().toString());
233             } else if (mInputDevInfo != null) {
234                 mSelectedProfile =
235                     mProfileManager.getProfile(mInputDevInfo.getProductName().toString());
236             }
237         } else {
238             mSelectedProfile = null;
239         }
240     }
241 
242     private class ConnectListener extends AudioDeviceCallback {
ConnectListener()243         /*package*/ ConnectListener() {}
244 
245         //
246         // AudioDevicesManager.OnDeviceConnectionListener
247         //
248         @Override
onAudioDevicesAdded(AudioDeviceInfo[] addedDevices)249         public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
250             // Log.i(TAG, "onAudioDevicesAdded() num:" + addedDevices.length);
251 
252             scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
253 
254             showProfileStatus();
255             showPeripheralStatus();
256             updateConnectStatus();
257         }
258 
259         @Override
onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices)260         public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
261             // Log.i(TAG, "onAudioDevicesRemoved() num:" + removedDevices.length);
262 
263             scanPeripheralList(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
264 
265             showProfileStatus();
266             showPeripheralStatus();
267             updateConnectStatus();
268         }
269     }
270 
updateConnectStatus()271     abstract public void updateConnectStatus();
272 }
273 
274