• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.media.AudioDeviceCallback;
24 import android.media.AudioDeviceInfo;
25 import android.media.AudioManager;
26 import android.os.Bundle;
27 import android.os.Handler;
28 import android.util.Log;
29 import android.widget.TextView;
30 
31 import com.android.compatibility.common.util.CddTest;
32 import com.android.compatibility.common.util.ResultType;
33 import com.android.compatibility.common.util.ResultUnit;
34 import com.android.cts.verifier.PassFailButtons;
35 import com.android.cts.verifier.R;  // needed to access resource in CTSVerifier project namespace.
36 
37 @CddTest(requirement = "7.8.2.2/H-2-1,H-3-1,H-4-2,H-4-3,H-4-4,H-4-5")
38 public class USBAudioPeripheralNotificationsTest extends PassFailButtons.Activity {
39     private static final String
40             TAG = USBAudioPeripheralNotificationsTest.class.getSimpleName();
41 
42     private AudioManager    mAudioManager;
43 
44     private TextView mHeadsetInName;
45     private TextView mHeadsetOutName;
46     private TextView mUsbDeviceInName;
47     private TextView mUsbDeviceOutName;
48 
49     // private TextView mHeadsetPlugText;
50     private TextView mHeadsetPlugMessage;
51 
52     // Intents
53     private HeadsetPlugReceiver mHeadsetPlugReceiver;
54     private boolean mPlugIntentReceived;
55 
56     // Device
57     private AudioDeviceInfo mUsbHeadsetInInfo;
58     private AudioDeviceInfo mUsbHeadsetOutInfo;
59     private AudioDeviceInfo mUsbDeviceInInfo;
60     private AudioDeviceInfo mUsbDeviceOutInfo;
61 
62     private boolean mUsbHeadsetInReceived;
63     private boolean mUsbHeadsetOutReceived;
64     private boolean mUsbDeviceInReceived;
65     private boolean mUsbDeviceOutReceived;
66 
67     @Override
onCreate(Bundle savedInstanceState)68     protected void onCreate(Bundle savedInstanceState) {
69         super.onCreate(savedInstanceState);
70         setContentView(R.layout.uap_notifications_layout);
71 
72         mHeadsetInName = (TextView)findViewById(R.id.uap_messages_headset_in_name);
73         mHeadsetOutName = (TextView)findViewById(R.id.uap_messages_headset_out_name);
74 
75         mUsbDeviceInName = (TextView)findViewById(R.id.uap_messages_usb_device_in_name);
76         mUsbDeviceOutName = (TextView)findViewById(R.id.uap_messages_usb_device__out_name);
77 
78         mHeadsetPlugMessage = (TextView)findViewById(R.id.uap_messages_plug_message);
79 
80         mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
81         mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
82 
83         mHeadsetPlugReceiver = new HeadsetPlugReceiver();
84         IntentFilter filter = new IntentFilter();
85         filter.addAction(Intent.ACTION_HEADSET_PLUG);
86         registerReceiver(mHeadsetPlugReceiver, filter);
87 
88         setInfoResources(R.string.audio_uap_notifications_test, R.string.uapNotificationsTestInfo,
89                 -1);
90 
91         setPassFailButtonClickListeners();
92         getPassButton().setEnabled(false);
93     }
94 
95     //
96     // UI
97     //
showConnectedDevices()98     private void showConnectedDevices() {
99         if (mUsbHeadsetInInfo != null) {
100             mHeadsetInName.setText(
101                     "Headset INPUT Connected " + mUsbHeadsetInInfo.getProductName());
102         } else {
103             mHeadsetInName.setText("");
104         }
105 
106         if (mUsbHeadsetOutInfo != null) {
107             mHeadsetOutName.setText(
108                     "Headset OUTPUT Connected " + mUsbHeadsetOutInfo.getProductName());
109         } else {
110             mHeadsetOutName.setText("");
111         }
112 
113         if (mUsbDeviceInInfo != null) {
114             mUsbDeviceInName.setText(
115                     "USB DEVICE INPUT Connected " + mUsbDeviceInInfo.getProductName());
116         } else {
117             mUsbDeviceInName.setText("");
118         }
119 
120         if (mUsbDeviceOutInfo != null) {
121             mUsbDeviceOutName.setText(
122                     "USB DEVICE OUTPUT Connected " + mUsbDeviceOutInfo.getProductName());
123         } else {
124             mUsbDeviceOutName.setText("");
125         }
126     }
127 
128     @Override
requiresReportLog()129     public boolean requiresReportLog() {
130         return true;
131     }
132 
133     @Override
getReportFileName()134     public String getReportFileName() {
135         return PassFailButtons.AUDIO_TESTS_REPORT_LOG_NAME;
136     }
137 
reportPlugIntent(Intent intent)138     private void reportPlugIntent(Intent intent) {
139         // [ 7.8 .2.2/H-2-1] MUST broadcast Intent ACTION_HEADSET_PLUG with "microphone" extra
140         // set to 0 when the USB audio terminal types 0x0302 is detected.
141         // [ 7.8 .2.2/H-3-1] MUST broadcast Intent ACTION_HEADSET_PLUG with "microphone" extra
142         // set to 1 when the USB audio terminal types 0x0402 is detected, they:
143         mPlugIntentReceived = true;
144 
145         // state - 0 for unplugged, 1 for plugged.
146         // name - Headset type, human readable string
147         // microphone - 1 if headset has a microphone, 0 otherwise
148         int state = intent.getIntExtra("state", -1);
149         if (state != -1) {
150 
151             StringBuilder sb = new StringBuilder();
152             sb.append("ACTION_HEADSET_PLUG received - " + (state == 0 ? "Unplugged" : "Plugged"));
153 
154             String name = intent.getStringExtra("name");
155             if (name != null) {
156                 sb.append(" - " + name);
157             }
158 
159             int hasMic = intent.getIntExtra("microphone", 0);
160             if (hasMic == 1) {
161                 sb.append(" [mic]");
162             }
163 
164             mHeadsetPlugMessage.setText(sb.toString());
165         }
166 
167         getReportLog().addValue(
168                 "ACTION_HEADSET_PLUG Intent Received. State: ",
169                 state,
170                 ResultType.NEUTRAL,
171                 ResultUnit.NONE);
172 
173         getPassButton().setEnabled(calculatePass());
174     }
175 
176     //
177     // Test Status
178     //
calculatePass()179     private boolean calculatePass() {
180         return isReportLogOkToPass()
181                 && mUsbHeadsetInReceived && mUsbHeadsetOutReceived
182                 && mUsbDeviceInReceived && mUsbDeviceOutReceived
183                 && mPlugIntentReceived;
184     }
185 
186     //
187     // Devices
188     //
scanDevices(AudioDeviceInfo[] devices)189     private void scanDevices(AudioDeviceInfo[] devices) {
190         mUsbHeadsetInInfo = mUsbHeadsetOutInfo =
191                 mUsbDeviceInInfo = mUsbDeviceOutInfo = null;
192 
193         for (AudioDeviceInfo devInfo : devices) {
194             if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_HEADSET) {
195                 if (devInfo.isSource()) {
196                     // [ 7.8 .2.2/H-4-3] MUST list a device of type AudioDeviceInfo.TYPE_USB_HEADSET
197                     // and role isSource() if the USB audio terminal type field is 0x0402.
198                     mUsbHeadsetInReceived = true;
199                     mUsbHeadsetInInfo = devInfo;
200                     getReportLog().addValue(
201                             "USB Headset connected - INPUT",
202                             0,
203                             ResultType.NEUTRAL,
204                             ResultUnit.NONE);
205                 } else if (devInfo.isSink()) {
206                     // [ 7.8 .2.2/H-4-2] MUST list a device of type AudioDeviceInfo.TYPE_USB_HEADSET
207                     // and role isSink() if the USB audio terminal type field is 0x0402.
208                     mUsbHeadsetOutReceived = true;
209                     mUsbHeadsetOutInfo = devInfo;
210                     getReportLog().addValue(
211                             "USB Headset connected - OUTPUT",
212                             0,
213                             ResultType.NEUTRAL,
214                             ResultUnit.NONE);
215                 }
216             } else if (devInfo.getType() == AudioDeviceInfo.TYPE_USB_DEVICE) {
217                 if (devInfo.isSource()) {
218                     // [ 7.8 .2.2/H-4-5] MUST list a device of type AudioDeviceInfo.TYPE_USB_DEVICE
219                     // and role isSource() if the USB audio terminal type field is 0x604.
220                     mUsbDeviceInReceived = true;
221                     mUsbDeviceInInfo = devInfo;
222                     getReportLog().addValue(
223                             "USB Device connected - INPUT",
224                             0,
225                             ResultType.NEUTRAL,
226                             ResultUnit.NONE);
227                 } else if (devInfo.isSink()) {
228                     // [ 7.8 .2.2/H-4-4] MUST list a device of type AudioDeviceInfo.TYPE_USB_DEVICE
229                     // and role isSink() if the USB audio terminal type field is 0x603.
230                     mUsbDeviceOutReceived = true;
231                     mUsbDeviceOutInfo = devInfo;
232                     getReportLog().addValue(
233                             "USB Headset connected - OUTPUT",
234                             0,
235                             ResultType.NEUTRAL,
236                             ResultUnit.NONE);
237                 }
238             }
239 
240             if (mUsbHeadsetInInfo != null &&
241                     mUsbHeadsetOutInfo != null &&
242                     mUsbDeviceInInfo != null &&
243                     mUsbDeviceOutInfo != null) {
244                 break;
245             }
246         }
247 
248 
249         showConnectedDevices();
250         getPassButton().setEnabled(calculatePass());
251     }
252 
253     private class ConnectListener extends AudioDeviceCallback {
ConnectListener()254         /*package*/ ConnectListener() {}
255 
256         //
257         // AudioDevicesManager.OnDeviceConnectionListener
258         //
259         @Override
onAudioDevicesAdded(AudioDeviceInfo[] addedDevices)260         public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
261             Log.i(TAG, "onAudioDevicesAdded() num:" + addedDevices.length);
262 
263             scanDevices(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
264         }
265 
266         @Override
onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices)267         public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
268             Log.i(TAG, "onAudioDevicesRemoved() num:" + removedDevices.length);
269 
270             scanDevices(mAudioManager.getDevices(AudioManager.GET_DEVICES_ALL));
271         }
272     }
273 
274     // Intents
275     private class HeadsetPlugReceiver extends BroadcastReceiver {
276         @Override
onReceive(Context context, Intent intent)277         public void onReceive(Context context, Intent intent) {
278             reportPlugIntent(intent);
279         }
280     }
281 
282 }
283