OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.media; | 5 package org.chromium.media; |
6 | 6 |
7 import android.bluetooth.BluetoothAdapter; | |
8 import android.bluetooth.BluetoothManager; | |
7 import android.content.BroadcastReceiver; | 9 import android.content.BroadcastReceiver; |
8 import android.content.Context; | 10 import android.content.Context; |
9 import android.content.Intent; | 11 import android.content.Intent; |
10 import android.content.IntentFilter; | 12 import android.content.IntentFilter; |
11 import android.content.pm.PackageManager; | 13 import android.content.pm.PackageManager; |
12 import android.media.AudioFormat; | 14 import android.media.AudioFormat; |
13 import android.media.AudioManager; | 15 import android.media.AudioManager; |
14 import android.media.AudioRecord; | 16 import android.media.AudioRecord; |
15 import android.media.AudioTrack; | 17 import android.media.AudioTrack; |
16 import android.os.Build; | 18 import android.os.Build; |
19 import android.os.Process; | |
17 import android.util.Log; | 20 import android.util.Log; |
18 | 21 |
22 import java.util.Arrays; | |
23 import java.util.ArrayList; | |
24 import java.util.HashSet; | |
25 import java.util.List; | |
26 import java.util.Set; | |
27 | |
19 import org.chromium.base.CalledByNative; | 28 import org.chromium.base.CalledByNative; |
20 import org.chromium.base.JNINamespace; | 29 import org.chromium.base.JNINamespace; |
21 | 30 |
22 @JNINamespace("media") | 31 @JNINamespace("media") |
23 class AudioManagerAndroid { | 32 class AudioManagerAndroid { |
24 private static final String TAG = "AudioManagerAndroid"; | 33 private static final String TAG = "AudioManagerAndroid"; |
25 | 34 |
26 // Most of Google lead devices use 44.1K as the default sampling rate, 44.1K | 35 /** Simple container for device information. */ |
27 // is also widely used on other android devices. | 36 private static class AudioDeviceName { |
37 private final int mId; | |
38 private final String mName; | |
39 | |
40 private AudioDeviceName(int id, String name) { | |
41 mId = id; | |
42 mName = name; | |
43 } | |
44 | |
45 @CalledByNative("AudioDeviceName") | |
46 private String id() { return String.valueOf(mId); } | |
47 | |
48 @CalledByNative("AudioDeviceName") | |
49 private String name() { return mName; } | |
50 } | |
51 | |
52 // Supported audio device types. | |
53 private static final int DEVICE_INVALID = 0; | |
54 private static final int DEVICE_SPEAKERPHONE = 1; | |
55 private static final int DEVICE_WIRED_HEADSET = 2; | |
56 private static final int DEVICE_EARPIECE = 3; | |
57 private static final int DEVICE_BLUETOOTH_HEADSET = 4; | |
58 | |
59 // List of valid device types. | |
60 private static Integer[] VALID_DEVICES = new Integer[] { | |
61 DEVICE_SPEAKERPHONE, | |
62 DEVICE_WIRED_HEADSET, | |
63 DEVICE_EARPIECE, | |
64 DEVICE_BLUETOOTH_HEADSET, | |
65 }; | |
66 | |
67 // Maps audio device types to string values. | |
Jói
2013/11/29 14:40:46
Maybe it would be better to have this right after
henrika (OOO until Aug 14)
2013/11/29 15:31:49
Done.
| |
68 // TODO(henrika): add support for proper detection of device names and | |
69 // localize the name strings. | |
70 private static final String[] DEVICE_NAMES = new String[] { | |
71 "Invalid device", | |
72 "Speakerphone", | |
73 "Wired headset", // With or without microphone | |
74 "Headset earpiece", // Only available on mobile phones | |
75 "Bluetooth headset", | |
76 }; | |
77 | |
78 // The device does not have any audio device. | |
Jói
2013/11/29 14:40:46
It would be cool to document the valid state trans
henrika (OOO until Aug 14)
2013/11/29 15:31:49
Added TODO.
| |
79 static final int STATE_NO_DEVICE_SELECTED = 0; | |
80 // The speakerphone is on and an associated microphone is used. | |
81 static final int STATE_SPEAKERPHONE_ON = 1; | |
82 // The phone's earpiece is on and an associated microphone is used. | |
83 static final int STATE_EARPIECE_ON = 2; | |
84 // A wired headset (with or without a microphone) is plugged in. | |
85 static final int STATE_WIRED_HEADSET_ON = 3; | |
86 // The audio stream is being directed to a Bluetooth headset. | |
87 static final int STATE_BLUETOOTH_ON = 4; | |
88 // We've requested that the audio stream be directed to Bluetooth, but | |
89 // have not yet received a response from the framework. | |
90 static final int STATE_BLUETOOTH_TURNING_ON = 5; | |
91 // We've requested that the audio stream stop being directed to | |
92 // Bluetooth, but have not yet received a response from the framework. | |
93 static final int STATE_BLUETOOTH_TURNING_OFF = 6; | |
94 | |
95 // Use 44.1kHz as the default sampling rate. | |
28 private static final int DEFAULT_SAMPLING_RATE = 44100; | 96 private static final int DEFAULT_SAMPLING_RATE = 44100; |
29 // Randomly picked up frame size which is close to return value on N4. | 97 // Randomly picked up frame size which is close to return value on N4. |
30 // Return this default value when | 98 // Return this value when getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER) |
31 // getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER) fails. | 99 // fails. |
32 private static final int DEFAULT_FRAME_PER_BUFFER = 256; | 100 private static final int DEFAULT_FRAME_PER_BUFFER = 256; |
33 | 101 |
34 private final AudioManager mAudioManager; | 102 private final AudioManager mAudioManager; |
35 private final Context mContext; | 103 private final Context mContext; |
36 | 104 |
37 private BroadcastReceiver mReceiver; | 105 private boolean mHasBluetoothPermission = false; |
38 private boolean mOriginalSpeakerStatus; | 106 private boolean mIsInitialized = false; |
107 private boolean mSavedSpeakerPhoneState; | |
108 private boolean mSavedMicrophoneMuteState; | |
39 | 109 |
40 @CalledByNative | 110 private Integer mAudioDeviceState = STATE_NO_DEVICE_SELECTED; |
41 public void setMode(int mode) { | |
42 try { | |
43 mAudioManager.setMode(mode); | |
44 } catch (SecurityException e) { | |
45 Log.e(TAG, "setMode exception: " + e.getMessage()); | |
46 logDeviceInfo(); | |
47 } | |
48 } | |
49 | 111 |
112 // Contains a list of currently available audio devices. | |
113 private Set<Integer> mAudioDevices = new HashSet<Integer>(); | |
114 | |
115 // Broadcast receiver for wired headset intent broadcasts. | |
116 private BroadcastReceiver mWiredHeadsetReceiver; | |
117 | |
118 /** Construction */ | |
50 @CalledByNative | 119 @CalledByNative |
51 private static AudioManagerAndroid createAudioManagerAndroid(Context context ) { | 120 private static AudioManagerAndroid createAudioManagerAndroid(Context context ) { |
52 return new AudioManagerAndroid(context); | 121 return new AudioManagerAndroid(context); |
53 } | 122 } |
54 | 123 |
55 private AudioManagerAndroid(Context context) { | 124 private AudioManagerAndroid(Context context) { |
56 mContext = context; | 125 mContext = context; |
57 mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SE RVICE); | 126 mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SE RVICE); |
58 } | 127 } |
59 | 128 |
129 /** | |
130 * Saves the initial speakerphone and microphone state. | |
131 * Populates the list of available audio devices and registers receivers | |
132 * for broadcasted intents related to wired headset and bluetooth devices. | |
133 */ | |
60 @CalledByNative | 134 @CalledByNative |
61 public void registerHeadsetReceiver() { | 135 public void init() { |
62 if (mReceiver != null) { | 136 if (mIsInitialized) |
63 return; | 137 return; |
138 | |
139 // Store microphone mute state and speakerphone state so it can | |
140 // be restored when closing. | |
141 mSavedSpeakerPhoneState = mAudioManager.isSpeakerphoneOn(); | |
Jói
2013/11/29 14:40:46
Naming suggestion: mSavedIsSpeakerphoneOn and mSav
henrika (OOO until Aug 14)
2013/11/29 15:31:49
thx
| |
142 mSavedMicrophoneMuteState = mAudioManager.isMicrophoneMute(); | |
143 | |
144 // Always enable speaker phone by default. This state might be reset | |
145 // by the wired headset receiver when it gets its initial sticky | |
146 // intent, if any. | |
147 setSpeakerphoneOn(true); | |
148 mAudioDeviceState = STATE_SPEAKERPHONE_ON; | |
149 | |
150 // Initialize audio device list with things we know is always available. | |
151 if (hasEarpiece()) { | |
152 mAudioDevices.add(DEVICE_EARPIECE); | |
64 } | 153 } |
154 mAudioDevices.add(DEVICE_SPEAKERPHONE); | |
65 | 155 |
66 mOriginalSpeakerStatus = mAudioManager.isSpeakerphoneOn(); | 156 // Register receiver for broadcasted intents related to adding/ |
67 if (!mOriginalSpeakerStatus) { | 157 // removing a wired headset (Intent.ACTION_HEADSET_PLUG). |
68 mAudioManager.setSpeakerphoneOn(true); | 158 // Also starts routing to the wired headset/headphone if one is |
69 } | 159 // already attached (can be overridden by a Bluetooth headset). |
70 IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); | 160 registerForWiredHeadsetIntentBroadcast(); |
71 | 161 |
72 mReceiver = new BroadcastReceiver() { | 162 // Start routing to Bluetooth if there's a connected device. |
73 @Override | 163 // TODO(henrika): the actual routing part is not implemented yet. |
74 public void onReceive(Context context, Intent intent) { | 164 // All we do currently is to detect if BT headset is attached or not. |
75 if (Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) { | 165 initBluetooth(); |
76 try { | 166 |
77 mAudioManager.setSpeakerphoneOn( | 167 mIsInitialized = true; |
78 intent.getIntExtra("state", 0) == 0); | 168 } |
79 } catch (SecurityException e) { | 169 |
80 Log.e(TAG, "setMode exception: " + e.getMessage()); | 170 /** |
81 logDeviceInfo(); | 171 * Unregister all previously registered intent receivers and restore |
82 } | 172 * the stored state (stored in {@link #init()}). |
83 } | 173 */ |
84 } | 174 @CalledByNative |
85 }; | 175 public void close() { |
86 mContext.registerReceiver(mReceiver, filter); | 176 if (!mIsInitialized) |
177 return; | |
178 | |
179 unregisterForWiredHeadsetIntentBroadcast(); | |
180 | |
181 // Restore previously stored audio states. | |
182 setMicrophoneMute(mSavedMicrophoneMuteState); | |
183 setSpeakerphoneOn(mSavedSpeakerPhoneState); | |
184 | |
185 mIsInitialized = false; | |
87 } | 186 } |
88 | 187 |
89 @CalledByNative | 188 @CalledByNative |
90 public void unregisterHeadsetReceiver() { | 189 public void setMode(int mode) { |
91 mContext.unregisterReceiver(mReceiver); | 190 try { |
92 mReceiver = null; | 191 mAudioManager.setMode(mode); |
93 mAudioManager.setSpeakerphoneOn(mOriginalSpeakerStatus); | 192 } catch (SecurityException e) { |
193 Log.e(TAG, "setMode exception: " + e.getMessage()); | |
194 logDeviceInfo(); | |
195 } | |
94 } | 196 } |
95 | 197 |
96 private void logDeviceInfo() { | 198 /** |
97 Log.i(TAG, "Manufacturer:" + Build.MANUFACTURER + | 199 * Activates, i.e., starts routing audio to, the specified audio device. |
98 " Board: " + Build.BOARD + " Device: " + Build.DEVICE + | 200 * |
99 " Model: " + Build.MODEL + " PRODUCT: " + Build.PRODUCT); | 201 * @param deviceId Unique device ID (integer converted to string) |
202 * representing the selected device. This string is empty if the so-called | |
203 * default device is selected. | |
204 */ | |
205 @CalledByNative | |
206 public void setDevice(String deviceId) { | |
207 if (deviceId.isEmpty()) { | |
208 logd("setDevice: default"); | |
209 // Use a special selection scheme if the default device is selected. | |
210 // The "most unique" device will be selected; Bluetooth first, then | |
211 // wired headset and last the speaker phone. | |
212 if (mAudioDevices.contains(DEVICE_BLUETOOTH_HEADSET)) { | |
213 // TODO(henrika): possibly need improvements here if we are | |
214 // in a STATE_BLUETOOTH_TURNING_OFF state. | |
215 setAudioDevice(DEVICE_BLUETOOTH_HEADSET); | |
216 } else if (mAudioDevices.contains(DEVICE_WIRED_HEADSET)) { | |
217 setAudioDevice(DEVICE_WIRED_HEADSET); | |
218 } else { | |
219 setAudioDevice(DEVICE_SPEAKERPHONE); | |
220 } | |
221 } else { | |
222 logd("setDevice: " + deviceId); | |
223 // A non-default device is specified. Verify that it is valid | |
224 // device, and if so, start using it. | |
225 List<Integer> validIds = Arrays.asList(VALID_DEVICES); | |
226 Integer id = Integer.valueOf(deviceId); | |
227 if (validIds.contains(id)) { | |
228 setAudioDevice(id.intValue()); | |
229 } else { | |
230 loge("Invalid device ID!"); | |
231 } | |
232 } | |
233 } | |
234 | |
235 /** | |
236 * @return the current list of available audio devices. | |
237 * Note that this call does not trigger any update of the list of devices, | |
238 * it only copies the current state in to the output array. | |
239 */ | |
240 @CalledByNative | |
241 public AudioDeviceName[] getAudioInputDeviceNames() { | |
242 List<String> devices = new ArrayList<String>(); | |
243 AudioDeviceName[] array = new AudioDeviceName[mAudioDevices.size()]; | |
244 int i = 0; | |
245 for (Integer dev : mAudioDevices) { | |
246 array[i] = new AudioDeviceName(dev, DEVICE_NAMES[dev]); | |
247 devices.add(DEVICE_NAMES[dev]); | |
248 i++; | |
249 } | |
250 logd("getAudioInputDeviceNames: " + devices); | |
251 return array; | |
100 } | 252 } |
101 | 253 |
102 @CalledByNative | 254 @CalledByNative |
103 private int getNativeOutputSampleRate() { | 255 private int getNativeOutputSampleRate() { |
104 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.J ELLY_BEAN_MR1) { | 256 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.J ELLY_BEAN_MR1) { |
105 String sampleRateString = mAudioManager.getProperty( | 257 String sampleRateString = mAudioManager.getProperty( |
106 AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); | 258 AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); |
107 return (sampleRateString == null ? | 259 return (sampleRateString == null ? |
108 DEFAULT_SAMPLING_RATE : Integer.parseInt(sampleRateString)); | 260 DEFAULT_SAMPLING_RATE : Integer.parseInt(sampleRateString)); |
109 } else { | 261 } else { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 } | 310 } |
159 | 311 |
160 @CalledByNative | 312 @CalledByNative |
161 private int getAudioLowLatencyOutputFrameSize() { | 313 private int getAudioLowLatencyOutputFrameSize() { |
162 String framesPerBuffer = | 314 String framesPerBuffer = |
163 mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PE R_BUFFER); | 315 mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PE R_BUFFER); |
164 return (framesPerBuffer == null ? | 316 return (framesPerBuffer == null ? |
165 DEFAULT_FRAME_PER_BUFFER : Integer.parseInt(framesPerBuffer)); | 317 DEFAULT_FRAME_PER_BUFFER : Integer.parseInt(framesPerBuffer)); |
166 } | 318 } |
167 | 319 |
320 /** Sets the speaker phone mode. */ | |
321 public void setSpeakerphoneOn(boolean on) { | |
322 boolean wasOn = mAudioManager.isSpeakerphoneOn(); | |
323 if (wasOn == on) { | |
324 return; | |
325 } | |
326 mAudioManager.setSpeakerphoneOn(on); | |
327 } | |
328 | |
329 /** Sets the microphone mute state. */ | |
330 public void setMicrophoneMute(boolean on) { | |
331 boolean wasOn = mAudioManager.isMicrophoneMute(); | |
Jói
2013/11/29 14:40:46
nit: wasMuted maybe instead of wasOn?
henrika (OOO until Aug 14)
2013/11/29 15:31:49
Done.
| |
332 if (wasOn == on) { | |
333 return; | |
334 } | |
335 mAudioManager.setMicrophoneMute(on); | |
336 } | |
337 | |
338 /** Gets the current microphone mute state. */ | |
339 public boolean isMicrophoneMute() { | |
340 return mAudioManager.isMicrophoneMute(); | |
341 } | |
342 | |
343 /** Gets the current earpice state. */ | |
344 private boolean hasEarpiece() { | |
345 boolean hasFeature = mContext.getPackageManager().hasSystemFeature( | |
Jói
2013/11/29 14:40:46
could just return directly
henrika (OOO until Aug 14)
2013/11/29 15:31:49
Done.
| |
346 PackageManager.FEATURE_TELEPHONY); | |
347 return hasFeature; | |
348 } | |
349 | |
350 /** | |
351 * Registers receiver for the broadcasted intent when a wired headset is | |
352 * plugged in or unplugged. The received intent will have an extra | |
353 * 'state' value where 0 means unplugged, and 1 means plugged. | |
354 */ | |
355 private void registerForWiredHeadsetIntentBroadcast() { | |
356 IntentFilter filter = new IntentFilter(); | |
357 filter.addAction(Intent.ACTION_HEADSET_PLUG); | |
358 | |
359 /** | |
360 * Receiver which handles changes in wired headset availablilty. | |
361 */ | |
362 mWiredHeadsetReceiver = new BroadcastReceiver() { | |
363 private static final int STATE_UNPLUGGED = 0; | |
364 private static final int STATE_PLUGGED = 1; | |
365 private static final int HAS_NO_MIC = 0; | |
366 private static final int HAS_MIC = 1; | |
367 | |
368 @Override | |
369 public void onReceive(Context context, Intent intent) { | |
370 String action = intent.getAction(); | |
371 if (action.equals(Intent.ACTION_HEADSET_PLUG)) { | |
Jói
2013/11/29 14:40:46
Will it not always equal this, since you have a fi
tommi (sloooow) - chröme
2013/11/29 15:04:33
+1 - and if it isn't then it might be better to sa
henrika (OOO until Aug 14)
2013/11/29 15:31:49
You guys ;-)
| |
372 int state = intent.getIntExtra("state", STATE_UNPLUGGED); | |
373 int microphone = intent.getIntExtra("microphone", HAS_NO_MIC ); | |
374 String name = intent.getStringExtra("name"); | |
375 logd("==> onReceive: s=" + state | |
376 + ", m=" + microphone | |
377 + ", n=" + name | |
378 + ", s=" + isInitialStickyBroadcast()); | |
379 | |
380 switch (state) { | |
381 case STATE_UNPLUGGED: | |
382 // Wired headset and earpiece are mutually exclusive . | |
383 mAudioDevices.remove(DEVICE_WIRED_HEADSET); | |
384 if (hasEarpiece()) { | |
385 mAudioDevices.add(DEVICE_EARPIECE); | |
386 } | |
387 // If wired headset was used before it was unplugged , | |
388 // switch to speaker phone. If it was not in use; ju st | |
389 // log the change. | |
390 if (mAudioDeviceState == STATE_WIRED_HEADSET_ON) { | |
391 setAudioDevice(DEVICE_SPEAKERPHONE); | |
392 } else { | |
393 reportUpdate(); | |
394 } | |
395 break; | |
396 case STATE_PLUGGED: | |
397 // Wired headset and earpiece are mutually exclusive . | |
398 mAudioDevices.add(DEVICE_WIRED_HEADSET); | |
399 mAudioDevices.remove(DEVICE_EARPIECE); | |
400 setAudioDevice(DEVICE_WIRED_HEADSET); | |
401 break; | |
402 } | |
403 } | |
404 } | |
405 }; | |
406 | |
407 // Note: the intent we register for here is sticky, so it'll tell us | |
408 // immediately what the last action was (plugged or unplugged). | |
409 // It will enable us to set the speakerphone correctly. | |
410 mContext.registerReceiver(mWiredHeadsetReceiver, filter); | |
411 } | |
412 | |
413 /** Unregister receiver for broadcasted ACTION_HEADSET_PLUG intent. */ | |
414 private void unregisterForWiredHeadsetIntentBroadcast() { | |
415 mContext.unregisterReceiver(mWiredHeadsetReceiver); | |
416 mWiredHeadsetReceiver = null; | |
417 } | |
418 | |
419 | |
Jói
2013/11/29 14:40:46
nit: just one blank line?
henrika (OOO until Aug 14)
2013/11/29 15:31:49
Done.
| |
420 /** | |
421 * Check if Bluetooth device is connected, register Bluetooth receiver | |
422 * and start routing to Bluetooth if a device is connected. | |
423 * TODO(henrika): currently only supports the detecion part at startup. | |
424 */ | |
425 private void initBluetooth() { | |
426 // Bail out if we don't have the required permission. | |
427 mHasBluetoothPermission = mContext.checkPermission( | |
428 android.Manifest.permission.BLUETOOTH, | |
429 Process.myPid(), | |
430 Process.myUid()) == PackageManager.PERMISSION_GRANTED; | |
431 if (!mHasBluetoothPermission) { | |
432 loge("BLUETOOTH permission is missing!"); | |
433 return; | |
434 } | |
435 | |
436 // To get a BluetoothAdapter representing the local Bluetooth adapter, | |
437 // when running on JELLY_BEAN_MR1 (4.2) and below, call the static | |
438 // getDefaultAdapter() method; when running on JELLY_BEAN_MR2 (4.3) and | |
439 // higher, retrieve it through getSystemService(String) with | |
440 // BLUETOOTH_SERVICE. | |
441 // Note: Most methods require the BLUETOOTH permission. | |
442 BluetoothAdapter btAdapter = null; | |
443 if (android.os.Build.VERSION.SDK_INT <= | |
444 android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { | |
445 // Use static method for Android 4.2 and below to get the | |
446 // BluetoothAdapter. | |
447 btAdapter = BluetoothAdapter.getDefaultAdapter(); | |
448 } else { | |
449 // Use BluetoothManager to get the BluetoothAdapter for | |
450 // Android 4.3 and above. | |
451 BluetoothManager btManager = | |
452 (BluetoothManager)mContext.getSystemService( | |
453 Context.BLUETOOTH_SERVICE); | |
454 btAdapter = btManager.getAdapter(); | |
455 } | |
456 | |
457 if (btAdapter != null && | |
458 // android.bluetooth.BluetoothAdapter.getProfileConnectionState | |
459 // requires BLUETOOTH permission. | |
460 android.bluetooth.BluetoothProfile.STATE_CONNECTED == | |
461 btAdapter.getProfileConnectionState( | |
462 android.bluetooth.BluetoothProfile.HEADSET)) { | |
463 mAudioDevices.add(DEVICE_BLUETOOTH_HEADSET); | |
464 // TODO(henrika): ensure that we set the active audio | |
465 // device to Bluetooth (not trivial). | |
466 setAudioDevice(DEVICE_BLUETOOTH_HEADSET); | |
467 } | |
468 } | |
469 | |
470 /** | |
471 * Changes selection of the currently active audio device. | |
472 * | |
473 * @param device Specifies the selected audio device. | |
474 */ | |
475 public void setAudioDevice(int device) { | |
476 switch (device) { | |
477 case DEVICE_BLUETOOTH_HEADSET: | |
478 // TODO(henrika): add support for turning on an routing to | |
479 // BT here. | |
480 logd("--- TO BE IMPLEMENTED ---"); | |
tommi (sloooow) - chröme
2013/11/29 15:04:33
use |if (DEBUG)| for debug logging?
henrika (OOO until Aug 14)
2013/11/29 15:31:49
Forgot, will do.
| |
481 break; | |
482 case DEVICE_SPEAKERPHONE: | |
483 // TODO(henrika): turn off BT if required. | |
484 mAudioDeviceState = STATE_SPEAKERPHONE_ON; | |
485 setSpeakerphoneOn(true); | |
486 break; | |
487 case DEVICE_WIRED_HEADSET: | |
488 // TODO(henrika): turn off BT if required. | |
489 mAudioDeviceState = STATE_WIRED_HEADSET_ON; | |
490 setSpeakerphoneOn(false); | |
491 break; | |
492 case DEVICE_EARPIECE: | |
493 // TODO(henrika): turn off BT if required. | |
494 mAudioDeviceState = STATE_EARPIECE_ON; | |
495 setSpeakerphoneOn(false); | |
496 break; | |
497 default: | |
498 loge("Invalid audio device selection!"); | |
499 break; | |
500 } | |
501 reportUpdate(); | |
502 } | |
503 | |
504 /** | |
505 * For now, just log the state change but the idea is that we should | |
506 * notifies a registered state change listener (if any) that there has | |
507 * been a change in the state. | |
508 * TODO(henrika): add support for state change listener. | |
509 */ | |
510 private void reportUpdate() { | |
511 List<String> devices = new ArrayList<String>(); | |
512 for (Integer dev : mAudioDevices) { | |
513 devices.add(DEVICE_NAMES[dev]); | |
514 } | |
515 logd("reportUpdate: state=" + mAudioDeviceState | |
516 + ", devices=" + devices); | |
517 } | |
518 | |
519 private void logDeviceInfo() { | |
520 Log.i(TAG, "Manufacturer:" + Build.MANUFACTURER + | |
521 " Board: " + Build.BOARD + " Device: " + Build.DEVICE + | |
522 " Model: " + Build.MODEL + " PRODUCT: " + Build.PRODUCT); | |
523 } | |
524 | |
525 /** Trivial helper method for debug logging */ | |
526 private void logd(String msg) { | |
527 Log.d(TAG, msg); | |
528 } | |
529 | |
530 /** Trivial helper method for error logging */ | |
531 private void loge(String msg) { | |
532 Log.e(TAG, msg); | |
533 } | |
168 } | 534 } |
OLD | NEW |