当前位置:   article > 正文

Android11上实现独立切换MIC和扬声器_android mic

android mic

最近处理了一个需求,就是控制系统选择的麦克风和扬声器。原生的逻辑当插上一个既是麦克风又是扬声器的设备时,会去同时切换,与我们的需求不符。

原生逻辑看以下的代码

frameworks\base\services\usb\java\com\android\server\usb\UsbAlsaDevice.java

 核心的代码如下:

  1. /** Updates AudioService with the connection state of the alsaDevice.
  2. * Checks ALSA Jack state for inputs and outputs before reporting.
  3. */
  4. public synchronized void updateWiredDeviceConnectionState(boolean enable) {
  5. if (!mSelected) {
  6. Slog.e(TAG, "updateWiredDeviceConnectionState on unselected AlsaDevice!");
  7. return;
  8. }
  9. String alsaCardDeviceString = getAlsaCardDeviceString();
  10. if (alsaCardDeviceString == null) {
  11. return;
  12. }
  13. try {
  14. // Output Device
  15. if (mHasOutput) {
  16. int device = mIsOutputHeadset
  17. ? AudioSystem.DEVICE_OUT_USB_HEADSET
  18. : AudioSystem.DEVICE_OUT_USB_DEVICE;
  19. if (DEBUG) {
  20. Slog.d(TAG, "pre-call device:0x" + Integer.toHexString(device)
  21. + " addr:" + alsaCardDeviceString
  22. + " name:" + mDeviceName);
  23. }
  24. boolean connected = isOutputJackConnected();
  25. Slog.i(TAG, "OUTPUT JACK connected: " + connected);
  26. int outputState = (enable && connected) ? 1 : 0;
  27. if (outputState != mOutputState) {
  28. mOutputState = outputState;
  29. mAudioService.setWiredDeviceConnectionState(device, outputState,
  30. alsaCardDeviceString,
  31. mDeviceName, TAG);
  32. }
  33. }
  34. // Input Device
  35. if (mHasInput) {
  36. int device = mIsInputHeadset ? AudioSystem.DEVICE_IN_USB_HEADSET
  37. : AudioSystem.DEVICE_IN_USB_DEVICE;
  38. boolean connected = isInputJackConnected();
  39. Slog.i(TAG, "INPUT JACK connected: " + connected);
  40. int inputState = (enable && connected) ? 1 : 0;
  41. if (inputState != mInputState) {
  42. mInputState = inputState;
  43. mAudioService.setWiredDeviceConnectionState(
  44. device, inputState, alsaCardDeviceString,
  45. mDeviceName, TAG);
  46. }
  47. }
  48. } catch (RemoteException e) {
  49. Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
  50. }
  51. }

可以看到原生的代码其实是有对输入设备和输出设备有分开切换的,只不过系统合并成了一个方法。这样我们的思路就出来了,我们单独摘出来做处理就行了,还是这个文件。

  1. private boolean mSelectedInput = false;
  2. private boolean mSelectedOutput = false;
  3. public synchronized void startInput() {
  4. mSelectedInput = true;
  5. mInputState = 0;
  6. startJackDetect();
  7. updateWiredDeviceConnectionStateInput(true);
  8. }
  9. public synchronized void startOutput() {
  10. mSelectedOutput = true;
  11. mOutputState = 0;
  12. startJackDetect();
  13. updateWiredDeviceConnectionStateOutput(true);
  14. }
  15. public synchronized void stopInput() {
  16. if (!mSelectedOutput) {
  17. stopJackDetect();
  18. }
  19. updateWiredDeviceConnectionStateInput(false);
  20. mSelectedInput = false;
  21. }
  22. public synchronized void stopOutput() {
  23. if (!mSelectedInput) {
  24. stopJackDetect();
  25. }
  26. updateWiredDeviceConnectionStateOutput(false);
  27. mSelectedOutput = false;
  28. }
  29. public synchronized void updateWiredDeviceConnectionStateOutput(boolean enable) {
  30. if (!mSelectedOutput) {
  31. Slog.e(TAG, "updateWiredDeviceConnectionStateOutput on unselected AlsaDevice!");
  32. return;
  33. }
  34. String alsaCardDeviceString = getAlsaCardDeviceString();
  35. if (alsaCardDeviceString == null) {
  36. return;
  37. }
  38. try {
  39. // Output Device
  40. if (mHasOutput) {
  41. int device = mIsOutputHeadset
  42. ? AudioSystem.DEVICE_OUT_USB_HEADSET
  43. : AudioSystem.DEVICE_OUT_USB_DEVICE;
  44. if (DEBUG) {
  45. Slog.d(TAG, "pre-call device:0x" + Integer.toHexString(device)
  46. + " addr:" + alsaCardDeviceString
  47. + " name:" + mDeviceName);
  48. }
  49. boolean connected = isOutputJackConnected();
  50. Slog.i(TAG, "OUTPUT JACK connected: " + connected);
  51. int outputState = (enable && connected) ? 1 : 0;
  52. if (outputState != mOutputState) {
  53. mOutputState = outputState;
  54. mAudioService.setWiredDeviceConnectionState(device, outputState,
  55. alsaCardDeviceString,
  56. mDeviceName, TAG);
  57. }
  58. }
  59. } catch (RemoteException e) {
  60. Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
  61. }
  62. }
  63. public synchronized void updateWiredDeviceConnectionStateInput(boolean enable) {
  64. if (!mSelectedInput) {
  65. Slog.e(TAG, "updateWiredDeviceConnectionStateInput on unselected AlsaDevice!");
  66. return;
  67. }
  68. String alsaCardDeviceString = getAlsaCardDeviceString();
  69. if (alsaCardDeviceString == null) {
  70. return;
  71. }
  72. try {
  73. // Input Device
  74. if (mHasInput) {
  75. int device = mIsInputHeadset ? AudioSystem.DEVICE_IN_USB_HEADSET
  76. : AudioSystem.DEVICE_IN_USB_DEVICE;
  77. boolean connected = isInputJackConnected();
  78. Slog.i(TAG, "INPUT JACK connected: " + connected);
  79. int inputState = (enable && connected) ? 1 : 0;
  80. if (inputState != mInputState) {
  81. mInputState = inputState;
  82. mAudioService.setWiredDeviceConnectionState(
  83. device, inputState, alsaCardDeviceString,
  84. mDeviceName, TAG);
  85. }
  86. }
  87. } catch (RemoteException e) {
  88. Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
  89. }
  90. }

这里其实可以看到,我们并没有写一行代码,都是参照原生的代码,将输出和输入逻辑代码分隔开。接下来来到管理类

/frameworks/base/services/usb/java/com/android/server/usb/UsbAlsaManager.java
  1. /*
  2. * Copyright (C) 2014 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. package com.android.server.usb;
  17. import android.content.Context;
  18. import android.content.pm.PackageManager;
  19. import android.content.res.Resources;
  20. import android.hardware.usb.UsbDevice;
  21. import android.media.IAudioService;
  22. import android.media.midi.MidiDeviceInfo;
  23. import android.os.Bundle;
  24. import android.os.ServiceManager;
  25. import android.provider.Settings;
  26. import android.service.usb.UsbAlsaManagerProto;
  27. import android.util.Slog;
  28. import com.android.internal.alsa.AlsaCardsParser;
  29. import com.android.internal.util.dump.DualDumpOutputStream;
  30. import com.android.server.usb.descriptors.UsbDescriptorParser;
  31. import libcore.io.IoUtils;
  32. import java.util.ArrayList;
  33. import java.util.Arrays;
  34. import java.util.List;
  35. import android.os.SystemProperties;
  36. import android.os.UserHandle;
  37. import android.hardware.usb.UsbManager;
  38. import android.content.Intent;
  39. /**
  40. * UsbAlsaManager manages USB audio and MIDI devices.
  41. */
  42. public final class UsbAlsaManager {
  43. private static final String TAG = UsbAlsaManager.class.getSimpleName();
  44. private static final boolean DEBUG = false;
  45. // Flag to turn on/off multi-peripheral select mode
  46. // Set to true to have single-device-only mode
  47. private static final boolean mIsSingleMode = true;
  48. private static final String ALSA_DIRECTORY = "/dev/snd/";
  49. private final Context mContext;
  50. private IAudioService mAudioService;
  51. private final boolean mHasMidiFeature;
  52. private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
  53. // this is needed to map USB devices to ALSA Audio Devices, especially to remove an
  54. // ALSA device when we are notified that its associated USB device has been removed.
  55. private final ArrayList<UsbAlsaDevice> mAlsaDevices = new ArrayList<UsbAlsaDevice>();
  56. private UsbAlsaDevice mSelectedInputDevice;
  57. private UsbAlsaDevice mSelectedOutputDevice;
  58. //
  59. // Device Denylist
  60. //
  61. // This exists due to problems with Sony game controllers which present as an audio device
  62. // even if no headset is connected and have no way to set the volume on the unit.
  63. // Handle this by simply declining to use them as an audio device.
  64. private static final int USB_VENDORID_SONY = 0x054C;
  65. private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4;
  66. private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC;
  67. private static final int USB_DENYLIST_OUTPUT = 0x0001;
  68. private static final int USB_DENYLIST_INPUT = 0x0002;
  69. private static class DenyListEntry {
  70. final int mVendorId;
  71. final int mProductId;
  72. final int mFlags;
  73. DenyListEntry(int vendorId, int productId, int flags) {
  74. mVendorId = vendorId;
  75. mProductId = productId;
  76. mFlags = flags;
  77. }
  78. }
  79. static final List<DenyListEntry> sDeviceDenylist = Arrays.asList(
  80. new DenyListEntry(USB_VENDORID_SONY,
  81. USB_PRODUCTID_PS4CONTROLLER_ZCT1,
  82. USB_DENYLIST_OUTPUT),
  83. new DenyListEntry(USB_VENDORID_SONY,
  84. USB_PRODUCTID_PS4CONTROLLER_ZCT2,
  85. USB_DENYLIST_OUTPUT));
  86. private static boolean isDeviceDenylisted(int vendorId, int productId, int flags) {
  87. for (DenyListEntry entry : sDeviceDenylist) {
  88. if (entry.mVendorId == vendorId && entry.mProductId == productId) {
  89. // see if the type flag is set
  90. return (entry.mFlags & flags) != 0;
  91. }
  92. }
  93. return false;
  94. }
  95. // UsbMidiDevice for USB peripheral mode (gadget) device
  96. private UsbMidiDevice mPeripheralMidiDevice = null;
  97. /* package */ UsbAlsaManager(Context context) {
  98. mContext = context;
  99. mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
  100. }
  101. public void systemReady() {
  102. mAudioService = IAudioService.Stub.asInterface(
  103. ServiceManager.getService(Context.AUDIO_SERVICE));
  104. }
  105. public synchronized void selectAlsaInputDeviceByUsbDevice(UsbDevice usbDevice) {
  106. if (mAlsaDevices == null || mAlsaDevices.size() == 0) {
  107. return ;
  108. }
  109. List<UsbAlsaDevice> data = new ArrayList<UsbAlsaDevice>(mAlsaDevices);
  110. for (UsbAlsaDevice usbAlsaDevice : data) {
  111. if (usbDevice.getDeviceName().equals(usbAlsaDevice.getDeviceAddress())) {
  112. selectAlsaInputDevice(usbAlsaDevice);
  113. }
  114. }
  115. }
  116. public synchronized void selectAlsaOutputDeviceByUsbDevice(UsbDevice usbDevice) {
  117. if (mAlsaDevices == null || mAlsaDevices.size() == 0) {
  118. return ;
  119. }
  120. List<UsbAlsaDevice> data = new ArrayList<UsbAlsaDevice>(mAlsaDevices);
  121. for (UsbAlsaDevice usbAlsaDevice : data) {
  122. if (usbDevice.getDeviceName().equals(usbAlsaDevice.getDeviceAddress())) {
  123. selectAlsaOutputDevice(usbAlsaDevice);
  124. }
  125. }
  126. }
  127. public synchronized void deselectAlsaInputDeviceByNothing() {
  128. deselectAlsaInputDevice();
  129. }
  130. public synchronized void deselectAlsaOutputDeviceByNothing() {
  131. deselectAlsaOutputDevice();
  132. }
  133. /**
  134. * Select the AlsaDevice to be used for AudioService.
  135. * AlsaDevice.start() notifies AudioService of it's connected state.
  136. *
  137. * @param alsaDevice The selected UsbAlsaDevice for system USB audio.
  138. */
  139. private synchronized void selectAlsaInputDevice(UsbAlsaDevice alsaDevice) {
  140. if (DEBUG) {
  141. Slog.d(TAG, "selectAlsaInputDevice() " + alsaDevice);
  142. }
  143. // This must be where an existing USB audio device is deselected.... (I think)
  144. if (mIsSingleMode && mSelectedInputDevice != null) {
  145. deselectAlsaInputDevice();
  146. }
  147. // FIXME Does not yet handle the case where the setting is changed
  148. // after device connection. Ideally we should handle the settings change
  149. // in SettingsObserver. Here we should log that a USB device is connected
  150. // and disconnected with its address (card , device) and force the
  151. // connection or disconnection when the setting changes.
  152. int isDisabled = Settings.Secure.getInt(mContext.getContentResolver(),
  153. Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
  154. if (isDisabled != 0) {
  155. return;
  156. }
  157. mSelectedInputDevice = alsaDevice;
  158. SystemProperties.set("sys.hardware.mic.selected", alsaDevice.getDeviceAddress());
  159. alsaDevice.startInput();
  160. if (DEBUG) {
  161. Slog.d(TAG, "selectAlsaDevice() - done.");
  162. }
  163. }
  164. private synchronized void selectAlsaOutputDevice(UsbAlsaDevice alsaDevice) {
  165. if (DEBUG) {
  166. Slog.d(TAG, "selectAlsaOutputDevice() " + alsaDevice);
  167. }
  168. // This must be where an existing USB audio device is deselected.... (I think)
  169. if (mIsSingleMode && mSelectedOutputDevice != null) {
  170. deselectAlsaOutputDevice();
  171. }
  172. // FIXME Does not yet handle the case where the setting is changed
  173. // after device connection. Ideally we should handle the settings change
  174. // in SettingsObserver. Here we should log that a USB device is connected
  175. // and disconnected with its address (card , device) and force the
  176. // connection or disconnection when the setting changes.
  177. int isDisabled = Settings.Secure.getInt(mContext.getContentResolver(),
  178. Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
  179. if (isDisabled != 0) {
  180. return;
  181. }
  182. mSelectedOutputDevice = alsaDevice;
  183. SystemProperties.set("sys.hardware.usbspeaker.selected", alsaDevice.getDeviceAddress());
  184. alsaDevice.startOutput();
  185. if (DEBUG) {
  186. Slog.d(TAG, "selectAlsaDevice() - done.");
  187. }
  188. }
  189. private synchronized void deselectAlsaInputDevice() {
  190. if (DEBUG) {
  191. Slog.d(TAG, "deselectAlsaInputDevice() mSelectedDevice " + mSelectedInputDevice);
  192. }
  193. if (mSelectedInputDevice != null) {
  194. mSelectedInputDevice.stopInput();
  195. mSelectedInputDevice = null;
  196. SystemProperties.set("sys.hardware.mic.selected", "");
  197. }
  198. }
  199. private synchronized void deselectAlsaOutputDevice() {
  200. if (DEBUG) {
  201. Slog.d(TAG, "deselectAlsaOutputDevice() mSelectedDevice " + mSelectedOutputDevice);
  202. }
  203. if (mSelectedOutputDevice != null) {
  204. mSelectedOutputDevice.stopOutput();
  205. mSelectedOutputDevice = null;
  206. SystemProperties.set("sys.hardware.usbspeaker.selected", "");
  207. }
  208. }
  209. private int getAlsaDeviceListIndexFor(String deviceAddress) {
  210. for (int index = 0; index < mAlsaDevices.size(); index++) {
  211. if (mAlsaDevices.get(index).getDeviceAddress().equals(deviceAddress)) {
  212. return index;
  213. }
  214. }
  215. return -1;
  216. }
  217. private UsbAlsaDevice removeAlsaDeviceFromList(String deviceAddress) {
  218. int index = getAlsaDeviceListIndexFor(deviceAddress);
  219. if (index > -1) {
  220. UsbAlsaDevice ret = mAlsaDevices.remove(index);
  221. persistCurrentState();
  222. return ret;
  223. } else {
  224. return null;
  225. }
  226. }
  227. /* package */ UsbAlsaDevice selectDefaultOutputDevice() {
  228. if (DEBUG) {
  229. Slog.d(TAG, "selectDefaultDevice()");
  230. }
  231. /**
  232. if (mAlsaDevices.size() > 0) {
  233. for (UsbAlsaDevice dev : mAlsaDevices) {
  234. if (dev.hasOutput()) {
  235. selectAlsaOutputDevice(dev);
  236. break;
  237. }
  238. }
  239. }
  240. if (mAlsaDevices.size() > 0) {
  241. UsbAlsaDevice alsaDevice = mAlsaDevices.get(0);
  242. if (DEBUG) {
  243. Slog.d(TAG, " alsaDevice:" + alsaDevice);
  244. }
  245. if (alsaDevice != null) {
  246. selectAlsaDevice(alsaDevice);
  247. }
  248. return alsaDevice;
  249. } else {
  250. return null;
  251. }
  252. **/
  253. return null;
  254. }
  255. /* package */ void usbDeviceAdded(String deviceAddress, UsbDevice usbDevice,
  256. UsbDescriptorParser parser) {
  257. if (DEBUG) {
  258. Slog.d(TAG, "usbDeviceAdded(): " + usbDevice.getManufacturerName()
  259. + " nm:" + usbDevice.getProductName());
  260. }
  261. // Scan the Alsa File Space
  262. mCardsParser.scan();
  263. // Find the ALSA spec for this device address
  264. AlsaCardsParser.AlsaCardRecord cardRec =
  265. mCardsParser.findCardNumFor(deviceAddress);
  266. if (cardRec == null) {
  267. return;
  268. }
  269. // Add it to the devices list
  270. boolean hasInput = parser.hasInput()
  271. && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(),
  272. USB_DENYLIST_INPUT);
  273. boolean hasOutput = parser.hasOutput()
  274. && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(),
  275. USB_DENYLIST_OUTPUT);
  276. if (DEBUG) {
  277. Slog.d(TAG, "hasInput: " + hasInput + " hasOutput:" + hasOutput);
  278. }
  279. if (hasInput || hasOutput) {
  280. boolean isInputHeadset = parser.isInputHeadset();
  281. boolean isOutputHeadset = parser.isOutputHeadset();
  282. boolean isDock = parser.isDock();
  283. if (mAudioService == null) {
  284. Slog.e(TAG, "no AudioService");
  285. return;
  286. }
  287. UsbAlsaDevice alsaDevice =
  288. new UsbAlsaDevice(mAudioService, cardRec.getCardNum(), 0 /*device*/,
  289. deviceAddress, hasOutput, hasInput,
  290. isInputHeadset, isOutputHeadset, isDock);
  291. if (alsaDevice != null) {
  292. alsaDevice.setDeviceNameAndDescription(
  293. cardRec.getCardName(), cardRec.getCardDescription());
  294. mAlsaDevices.add(0, alsaDevice);
  295. persistCurrentState();
  296. if(mContext!=null){
  297. Intent i = new Intent("skg.hardware.alsa.device_attached");
  298. i.putExtra(UsbManager.EXTRA_DEVICE,usbDevice);
  299. mContext.sendBroadcastAsUser(i,UserHandle.SYSTEM);
  300. }
  301. //selectAlsaDevice(alsaDevice);
  302. /**
  303. if (alsaDevice.hasOutput()) {
  304. selectAlsaOutputDevice(alsaDevice);
  305. }
  306. **/
  307. }
  308. }
  309. logDevices("deviceAdded()");
  310. if (DEBUG) {
  311. Slog.d(TAG, "deviceAdded() - done");
  312. }
  313. }
  314. private void persistCurrentState() {
  315. if (mContext != null) {
  316. if (mAlsaDevices == null || mAlsaDevices.size() == 0) {
  317. return ;
  318. }
  319. List<UsbAlsaDevice> data = new ArrayList<UsbAlsaDevice>(mAlsaDevices);
  320. int idx = 0;
  321. for (UsbAlsaDevice usbAlsaDevice : data) {
  322. String value = String.format("%s#%s#%s", usbAlsaDevice.getDeviceAddress(), usbAlsaDevice.hasInput(), usbAlsaDevice.hasOutput());
  323. Settings.Global.putString(mContext.getContentResolver(), "usb_alsa_device_" + idx, value);
  324. idx++;
  325. }
  326. // what if we had more than 6 devices, crash
  327. while (idx < 6) {
  328. Settings.Global.putString(mContext.getContentResolver(), "usb_alsa_device_" + idx, "");
  329. idx++;
  330. }
  331. }
  332. }
  333. /* package */ synchronized void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
  334. if (DEBUG) {
  335. Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")");
  336. }
  337. // Audio
  338. UsbAlsaDevice alsaDevice = removeAlsaDeviceFromList(deviceAddress);
  339. Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice);
  340. if (alsaDevice != null && alsaDevice == mSelectedOutputDevice) {
  341. // deselectAlsaDevice();
  342. // selectDefaultDevice(); // if there any external devices left, select one of them
  343. // deselectAlsaOutputDevice();
  344. // selectDefaultOutputDevice();
  345. }
  346. logDevices("usbDeviceRemoved()");
  347. }
  348. /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
  349. if (!mHasMidiFeature) {
  350. return;
  351. }
  352. if (enabled && mPeripheralMidiDevice == null) {
  353. Bundle properties = new Bundle();
  354. Resources r = mContext.getResources();
  355. properties.putString(MidiDeviceInfo.PROPERTY_NAME, r.getString(
  356. com.android.internal.R.string.usb_midi_peripheral_name));
  357. properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
  358. com.android.internal.R.string.usb_midi_peripheral_manufacturer_name));
  359. properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, r.getString(
  360. com.android.internal.R.string.usb_midi_peripheral_product_name));
  361. properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
  362. properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
  363. mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device,
  364. 1 /* numInputs */, 1 /* numOutputs */);
  365. } else if (!enabled && mPeripheralMidiDevice != null) {
  366. IoUtils.closeQuietly(mPeripheralMidiDevice);
  367. mPeripheralMidiDevice = null;
  368. }
  369. }
  370. //
  371. // Devices List
  372. //
  373. /*
  374. //import java.util.ArrayList;
  375. public ArrayList<UsbAudioDevice> getConnectedDevices() {
  376. ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
  377. for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
  378. devices.add(entry.getValue());
  379. }
  380. return devices;
  381. }
  382. */
  383. /**
  384. * Dump the USB alsa state.
  385. */
  386. // invoked with "adb shell dumpsys usb"
  387. public void dump(DualDumpOutputStream dump, String idName, long id) {
  388. long token = dump.start(idName, id);
  389. dump.write("cards_parser", UsbAlsaManagerProto.CARDS_PARSER, mCardsParser.getScanStatus());
  390. for (UsbAlsaDevice usbAlsaDevice : mAlsaDevices) {
  391. usbAlsaDevice.dump(dump, "alsa_devices", UsbAlsaManagerProto.ALSA_DEVICES);
  392. }
  393. dump.end(token);
  394. }
  395. public void logDevicesList(String title) {
  396. if (DEBUG) {
  397. Slog.i(TAG, title + "----------------");
  398. for (UsbAlsaDevice alsaDevice : mAlsaDevices) {
  399. Slog.i(TAG, " -->");
  400. Slog.i(TAG, "" + alsaDevice);
  401. Slog.i(TAG, " <--");
  402. }
  403. Slog.i(TAG, "----------------");
  404. }
  405. }
  406. // This logs a more terse (and more readable) version of the devices list
  407. public void logDevices(String title) {
  408. if (DEBUG) {
  409. Slog.i(TAG, title + "----------------");
  410. for (UsbAlsaDevice alsaDevice : mAlsaDevices) {
  411. Slog.i(TAG, alsaDevice.toShortString());
  412. }
  413. Slog.i(TAG, "----------------");
  414. }
  415. }
  416. }

原生是在usbDeviceAdded、usbDeviceRemoved方法里面去做设备切换的。我们已经弃用,在selectAlsaOutputDevice、selectAlsaInputDevice做设备选择。

frameworks/base/services/usb/java/com/android/server/usb/UsbService.java
  1. BroadcastReceiver receiver = new BroadcastReceiver() {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. final String action = intent.getAction();
  5. if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
  6. .equals(action)) {
  7. if (mDeviceManager != null) {
  8. mDeviceManager.updateUserRestrictions();
  9. }
  10. } else if (action.equals("com.hardware.action.SELECT_MIC")) {
  11. UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
  12. if (mAlsaManager != null) {
  13. if (device != null) {
  14. mAlsaManager.selectAlsaInputDeviceByUsbDevice(device);
  15. } else {
  16. mAlsaManager.deselectAlsaInputDeviceByNothing();
  17. }
  18. }
  19. } else if (action.equals("com.hardware.action.SELECT_SPEAKER")) {
  20. UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
  21. if (mAlsaManager != null) {
  22. if (device != null) {
  23. mAlsaManager.selectAlsaOutputDeviceByUsbDevice(device);
  24. } else {
  25. mAlsaManager.deselectAlsaOutputDeviceByNothing();
  26. }
  27. }
  28. }
  29. }
  30. };

设计思路就是这样

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/988389
推荐阅读
相关标签
  

闽ICP备14008679号