1 /* 2 * Copyright 2019 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.mobileer.oboetester; 18 19 import android.annotation.TargetApi; 20 import android.app.Activity; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.hardware.usb.UsbDevice; 24 import android.hardware.usb.UsbManager; 25 import android.media.AudioDeviceCallback; 26 import android.media.AudioDeviceInfo; 27 import android.media.AudioManager; 28 import android.media.MicrophoneInfo; 29 import android.media.midi.MidiDeviceInfo; 30 import android.media.midi.MidiManager; 31 import android.os.Build; 32 import android.os.Bundle; 33 import android.util.Log; 34 import android.view.Menu; 35 import android.view.MenuItem; 36 import android.widget.TextView; 37 import android.widget.Toast; 38 39 import com.mobileer.audio_device.AudioDeviceInfoConverter; 40 41 import java.io.IOException; 42 import java.util.Collection; 43 import java.util.HashMap; 44 import java.util.List; 45 import java.util.Set; 46 47 /** 48 * Print a report of all the available audio devices. 49 */ 50 public class DeviceReportActivity extends Activity { 51 52 class MyAudioDeviceCallback extends AudioDeviceCallback { 53 private HashMap<Integer, AudioDeviceInfo> mDevices 54 = new HashMap<Integer, AudioDeviceInfo>(); 55 56 @Override onAudioDevicesAdded(AudioDeviceInfo[] addedDevices)57 public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) { 58 for (AudioDeviceInfo info : addedDevices) { 59 mDevices.put(info.getId(), info); 60 } 61 reportDeviceInfo(mDevices.values()); 62 } 63 onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices)64 public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { 65 for (AudioDeviceInfo info : removedDevices) { 66 mDevices.remove(info.getId()); 67 } 68 reportDeviceInfo(mDevices.values()); 69 } 70 } 71 72 MyAudioDeviceCallback mDeviceCallback = new MyAudioDeviceCallback(); 73 private TextView mAutoTextView; 74 private AudioManager mAudioManager; 75 private UsbManager mUsbManager; 76 private MidiManager mMidiManager; 77 78 @Override onCreate(Bundle savedInstanceState)79 protected void onCreate(Bundle savedInstanceState) { 80 super.onCreate(savedInstanceState); 81 setContentView(R.layout.activity_device_report); 82 mAutoTextView = (TextView) findViewById(R.id.text_log_device_report); 83 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 84 mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); 85 mMidiManager = (MidiManager) getSystemService(Context.MIDI_SERVICE); 86 } 87 88 @Override onCreateOptionsMenu(Menu menu)89 public boolean onCreateOptionsMenu(Menu menu) { 90 getMenuInflater().inflate(R.menu.menu_main, menu); 91 MenuItem settings = menu.findItem(R.id.action_share); 92 settings.setOnMenuItemClickListener(item -> { 93 if(mAutoTextView !=null) { 94 Intent sendIntent = new Intent(); 95 sendIntent.setAction(Intent.ACTION_SEND); 96 sendIntent.putExtra(Intent.EXTRA_TEXT, mAutoTextView.getText().toString()); 97 sendIntent.setType("text/plain"); 98 Intent shareIntent = Intent.createChooser(sendIntent, null); 99 startActivity(shareIntent); 100 } 101 return false; 102 }); 103 return true; 104 } 105 106 @Override onStart()107 protected void onStart() { 108 super.onStart(); 109 addAudioDeviceCallback(); 110 } 111 112 @Override onStop()113 protected void onStop() { 114 removeAudioDeviceCallback(); 115 super.onStop(); 116 } 117 118 @TargetApi(23) addAudioDeviceCallback()119 private void addAudioDeviceCallback(){ 120 // Note that we will immediately receive a call to onDevicesAdded with the list of 121 // devices which are currently connected. 122 mAudioManager.registerAudioDeviceCallback(mDeviceCallback, null); 123 } 124 125 @TargetApi(23) removeAudioDeviceCallback()126 private void removeAudioDeviceCallback(){ 127 mAudioManager.unregisterAudioDeviceCallback(mDeviceCallback); 128 } 129 reportDeviceInfo(Collection<AudioDeviceInfo> devices)130 private void reportDeviceInfo(Collection<AudioDeviceInfo> devices) { 131 logClear(); 132 StringBuffer report = new StringBuffer(); 133 report.append("Device Report:\n"); 134 report.append("App: ").append(MainActivity.getVersionText()).append("\n"); 135 report.append("Device: ").append(Build.MANUFACTURER).append(", ").append(Build.MODEL) 136 .append(", ").append(Build.PRODUCT).append("\n"); 137 138 report.append(reportExtraDeviceInfo()); 139 140 for (AudioDeviceInfo deviceInfo : devices) { 141 report.append("\n==== Device =================== " + deviceInfo.getId() + "\n"); 142 String item = AudioDeviceInfoConverter.toString(deviceInfo); 143 report.append(item); 144 } 145 report.append(reportAllMicrophones()); 146 report.append(reportUsbDevices()); 147 report.append(reportMidiDevices()); 148 log(report.toString()); 149 } 150 reportUsbDevices()151 public String reportUsbDevices() { 152 StringBuffer report = new StringBuffer(); 153 report.append("\n############################"); 154 report.append("\nUsb Device Report:\n"); 155 try { 156 HashMap<String, UsbDevice> usbDeviceList = mUsbManager.getDeviceList(); 157 for (UsbDevice usbDevice : usbDeviceList.values()) { 158 report.append("\n==== USB Device ========= " + usbDevice.getDeviceId()); 159 report.append("\nProduct Name : " + usbDevice.getProductName()); 160 report.append("\nProduct ID : 0x" + Integer.toHexString(usbDevice.getProductId())); 161 report.append("\nManufacturer Name : " + usbDevice.getManufacturerName()); 162 report.append("\nVendor ID : 0x" + Integer.toHexString(usbDevice.getVendorId())); 163 report.append("\nDevice Name : " + usbDevice.getDeviceName()); 164 report.append("\nDevice Protocol : " + usbDevice.getDeviceProtocol()); 165 report.append("\nDevice Class : " + usbDevice.getDeviceClass()); 166 report.append("\nDevice Subclass : " + usbDevice.getDeviceSubclass()); 167 report.append("\nVersion : " + usbDevice.getVersion()); 168 report.append("\n" + usbDevice); 169 report.append("\n"); 170 } 171 } catch (Exception e) { 172 Log.e(TestAudioActivity.TAG, "Caught ", e); 173 showErrorToast(e.getMessage()); 174 report.append("\nERROR: " + e.getMessage() + "\n"); 175 } 176 return report.toString(); 177 } 178 reportMidiDevices()179 public String reportMidiDevices() { 180 StringBuffer report = new StringBuffer(); 181 report.append("\n############################"); 182 report.append("\nMidi Device Report:\n"); 183 try { 184 MidiDeviceInfo[] midiDeviceInfos = mMidiManager.getDevices(); 185 for (MidiDeviceInfo midiDeviceInfo : midiDeviceInfos) { 186 report.append("\n==== MIDI Device ========= " + midiDeviceInfo.getId()); 187 addMidiDeviceInfoToDeviceReport(midiDeviceInfo, report); 188 } 189 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 190 Set<MidiDeviceInfo> umpDeviceInfos = 191 mMidiManager.getDevicesForTransport(MidiManager.TRANSPORT_UNIVERSAL_MIDI_PACKETS); 192 for (MidiDeviceInfo midiDeviceInfo : umpDeviceInfos) { 193 report.append("\n==== UMP Device ========= " + midiDeviceInfo.getId()); 194 addMidiDeviceInfoToDeviceReport(midiDeviceInfo, report); 195 } 196 } 197 } catch (Exception e) { 198 Log.e(TestAudioActivity.TAG, "Caught ", e); 199 showErrorToast(e.getMessage()); 200 report.append("\nERROR: " + e.getMessage() + "\n"); 201 } 202 return report.toString(); 203 } 204 addMidiDeviceInfoToDeviceReport(MidiDeviceInfo midiDeviceInfo, StringBuffer report)205 private void addMidiDeviceInfoToDeviceReport(MidiDeviceInfo midiDeviceInfo, 206 StringBuffer report){ 207 report.append("\nInput Count : " + midiDeviceInfo.getInputPortCount()); 208 report.append("\nOutput Count : " + midiDeviceInfo.getOutputPortCount()); 209 report.append("\nType : " + midiDeviceInfo.getType()); 210 report.append("\nIs Private : " + midiDeviceInfo.isPrivate()); 211 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { 212 report.append("\nDefault Protocol : " + midiDeviceInfo.getDefaultProtocol()); 213 } 214 report.append("\n" + midiDeviceInfo); 215 report.append("\n"); 216 } 217 reportAllMicrophones()218 public String reportAllMicrophones() { 219 StringBuffer report = new StringBuffer(); 220 report.append("\n############################"); 221 report.append("\nMicrophone Report:\n"); 222 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { 223 try { 224 List<MicrophoneInfo> micList = mAudioManager.getMicrophones(); 225 for (MicrophoneInfo micInfo : micList) { 226 String micItem = MicrophoneInfoConverter.reportMicrophoneInfo(micInfo); 227 report.append(micItem); 228 } 229 } catch (IOException e) { 230 Log.e(TestAudioActivity.TAG, "Caught ", e); 231 return e.getMessage(); 232 } catch (Exception e) { 233 Log.e(TestAudioActivity.TAG, "Caught ", e); 234 showErrorToast(e.getMessage()); 235 report.append("\nERROR: " + e.getMessage() + "\n"); 236 } 237 } else { 238 report.append("\nMicrophoneInfo not available on V" + android.os.Build.VERSION.SDK_INT); 239 } 240 return report.toString(); 241 } 242 reportExtraDeviceInfo()243 private String reportExtraDeviceInfo() { 244 StringBuffer report = new StringBuffer(); 245 report.append("\n\n############################"); 246 report.append("\nAudioManager:"); 247 report.append(AudioQueryTools.getAudioManagerReport(mAudioManager)); 248 report.append("\n\nFeatures:"); 249 report.append(AudioQueryTools.getAudioFeatureReport(getPackageManager())); 250 report.append(AudioQueryTools.getMediaPerformanceClass()); 251 report.append("\n\nProperties:"); 252 report.append(AudioQueryTools.getAudioPropertyReport()); 253 return report.toString(); 254 } 255 256 // Write to scrollable TextView log(final String text)257 private void log(final String text) { 258 runOnUiThread(new Runnable() { 259 @Override 260 public void run() { 261 mAutoTextView.append(text); 262 mAutoTextView.append("\n"); 263 } 264 }); 265 } 266 logClear()267 private void logClear() { 268 runOnUiThread(new Runnable() { 269 @Override 270 public void run() { 271 mAutoTextView.setText(""); 272 } 273 }); 274 } 275 showErrorToast(String message)276 protected void showErrorToast(String message) { 277 String text = "Error: " + message; 278 Log.e(TestAudioActivity.TAG, text); 279 showToast(text); 280 } 281 showToast(final String message)282 protected void showToast(final String message) { 283 runOnUiThread(new Runnable() { 284 @Override 285 public void run() { 286 Toast.makeText(DeviceReportActivity.this, 287 message, 288 Toast.LENGTH_SHORT).show(); 289 } 290 }); 291 } 292 } 293