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.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.bluetooth.BluetoothAdapter; | 8 import android.bluetooth.BluetoothAdapter; |
9 import android.bluetooth.BluetoothManager; | 9 import android.bluetooth.BluetoothManager; |
10 import android.content.BroadcastReceiver; | 10 import android.content.BroadcastReceiver; |
(...skipping 11 matching lines...) Expand all Loading... |
22 import android.media.AudioManager; | 22 import android.media.AudioManager; |
23 import android.media.AudioRecord; | 23 import android.media.AudioRecord; |
24 import android.media.AudioTrack; | 24 import android.media.AudioTrack; |
25 import android.media.audiofx.AcousticEchoCanceler; | 25 import android.media.audiofx.AcousticEchoCanceler; |
26 import android.os.Build; | 26 import android.os.Build; |
27 import android.os.Handler; | 27 import android.os.Handler; |
28 import android.os.HandlerThread; | 28 import android.os.HandlerThread; |
29 import android.os.Process; | 29 import android.os.Process; |
30 import android.provider.Settings; | 30 import android.provider.Settings; |
31 | 31 |
| 32 import org.chromium.base.ContextUtils; |
32 import org.chromium.base.Log; | 33 import org.chromium.base.Log; |
33 import org.chromium.base.annotations.CalledByNative; | 34 import org.chromium.base.annotations.CalledByNative; |
34 import org.chromium.base.annotations.JNINamespace; | 35 import org.chromium.base.annotations.JNINamespace; |
35 import org.chromium.base.annotations.SuppressFBWarnings; | 36 import org.chromium.base.annotations.SuppressFBWarnings; |
36 | 37 |
37 import java.util.ArrayList; | 38 import java.util.ArrayList; |
38 import java.util.Arrays; | 39 import java.util.Arrays; |
39 import java.util.List; | 40 import java.util.List; |
40 import java.util.Map; | 41 import java.util.Map; |
41 | 42 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 private static final int STATE_BLUETOOTH_SCO_TURNING_OFF = 3; | 153 private static final int STATE_BLUETOOTH_SCO_TURNING_OFF = 3; |
153 | 154 |
154 // Use 44.1kHz as the default sampling rate. | 155 // Use 44.1kHz as the default sampling rate. |
155 private static final int DEFAULT_SAMPLING_RATE = 44100; | 156 private static final int DEFAULT_SAMPLING_RATE = 44100; |
156 // Randomly picked up frame size which is close to return value on N4. | 157 // Randomly picked up frame size which is close to return value on N4. |
157 // Return this value when getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER) | 158 // Return this value when getProperty(PROPERTY_OUTPUT_FRAMES_PER_BUFFER) |
158 // fails. | 159 // fails. |
159 private static final int DEFAULT_FRAME_PER_BUFFER = 256; | 160 private static final int DEFAULT_FRAME_PER_BUFFER = 256; |
160 | 161 |
161 private final AudioManager mAudioManager; | 162 private final AudioManager mAudioManager; |
162 private final Context mContext; | |
163 private final long mNativeAudioManagerAndroid; | 163 private final long mNativeAudioManagerAndroid; |
164 | 164 |
165 // Enabled during initialization if MODIFY_AUDIO_SETTINGS permission is | 165 // Enabled during initialization if MODIFY_AUDIO_SETTINGS permission is |
166 // granted. Required to shift system-wide audio settings. | 166 // granted. Required to shift system-wide audio settings. |
167 private boolean mHasModifyAudioSettingsPermission; | 167 private boolean mHasModifyAudioSettingsPermission; |
168 | 168 |
169 // Enabled during initialization if BLUETOOTH permission is granted. | 169 // Enabled during initialization if BLUETOOTH permission is granted. |
170 private boolean mHasBluetoothPermission; | 170 private boolean mHasBluetoothPermission; |
171 | 171 |
172 // Stores the audio states related to Bluetooth SCO audio, where some | 172 // Stores the audio states related to Bluetooth SCO audio, where some |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 212 |
213 // The UsbManager of this system. | 213 // The UsbManager of this system. |
214 private final UsbManager mUsbManager; | 214 private final UsbManager mUsbManager; |
215 // Broadcast receiver for USB audio devices intent broadcasts. | 215 // Broadcast receiver for USB audio devices intent broadcasts. |
216 // Utilized to detect if a USB device is attached or detached. | 216 // Utilized to detect if a USB device is attached or detached. |
217 private BroadcastReceiver mUsbAudioReceiver; | 217 private BroadcastReceiver mUsbAudioReceiver; |
218 | 218 |
219 /** Construction */ | 219 /** Construction */ |
220 @CalledByNative | 220 @CalledByNative |
221 private static AudioManagerAndroid createAudioManagerAndroid( | 221 private static AudioManagerAndroid createAudioManagerAndroid( |
222 Context context, | |
223 long nativeAudioManagerAndroid) { | 222 long nativeAudioManagerAndroid) { |
224 return new AudioManagerAndroid(context, nativeAudioManagerAndroid); | 223 return new AudioManagerAndroid(nativeAudioManagerAndroid); |
225 } | 224 } |
226 | 225 |
227 private AudioManagerAndroid(Context context, long nativeAudioManagerAndroid)
{ | 226 private AudioManagerAndroid(long nativeAudioManagerAndroid) { |
228 mContext = context; | |
229 mNativeAudioManagerAndroid = nativeAudioManagerAndroid; | 227 mNativeAudioManagerAndroid = nativeAudioManagerAndroid; |
230 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_S
ERVICE); | 228 mAudioManager = (AudioManager) ContextUtils.getApplicationContext().getS
ystemService( |
231 mContentResolver = mContext.getContentResolver(); | 229 Context.AUDIO_SERVICE); |
232 mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE
); | 230 mContentResolver = ContextUtils.getApplicationContext().getContentResolv
er(); |
| 231 mUsbManager = (UsbManager) ContextUtils.getApplicationContext().getSyste
mService( |
| 232 Context.USB_SERVICE); |
233 } | 233 } |
234 | 234 |
235 /** | 235 /** |
236 * Saves the initial speakerphone and microphone state. | 236 * Saves the initial speakerphone and microphone state. |
237 * Populates the list of available audio devices and registers receivers for
broadcasting | 237 * Populates the list of available audio devices and registers receivers for
broadcasting |
238 * intents related to wired headset and Bluetooth devices and USB audio devi
ces. | 238 * intents related to wired headset and Bluetooth devices and USB audio devi
ces. |
239 */ | 239 */ |
240 @CalledByNative | 240 @CalledByNative |
241 private void init() { | 241 private void init() { |
242 checkIfCalledOnValidThread(); | 242 checkIfCalledOnValidThread(); |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 channelConfig = AudioFormat.CHANNEL_OUT_STEREO; | 500 channelConfig = AudioFormat.CHANNEL_OUT_STEREO; |
501 } else { | 501 } else { |
502 return -1; | 502 return -1; |
503 } | 503 } |
504 return AudioTrack.getMinBufferSize( | 504 return AudioTrack.getMinBufferSize( |
505 sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT) / 2 /
channels; | 505 sampleRate, channelConfig, AudioFormat.ENCODING_PCM_16BIT) / 2 /
channels; |
506 } | 506 } |
507 | 507 |
508 @CalledByNative | 508 @CalledByNative |
509 private boolean isAudioLowLatencySupported() { | 509 private boolean isAudioLowLatencySupported() { |
510 return mContext.getPackageManager().hasSystemFeature( | 510 return ContextUtils.getApplicationContext().getPackageManager().hasSyste
mFeature( |
511 PackageManager.FEATURE_AUDIO_LOW_LATENCY); | 511 PackageManager.FEATURE_AUDIO_LOW_LATENCY); |
512 } | 512 } |
513 | 513 |
514 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) | 514 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) |
515 @CalledByNative | 515 @CalledByNative |
516 private int getAudioLowLatencyOutputFrameSize() { | 516 private int getAudioLowLatencyOutputFrameSize() { |
517 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { | 517 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { |
518 return DEFAULT_FRAME_PER_BUFFER; | 518 return DEFAULT_FRAME_PER_BUFFER; |
519 } | 519 } |
520 String framesPerBuffer = | 520 String framesPerBuffer = |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 mAudioManager.setMicrophoneMute(on); | 603 mAudioManager.setMicrophoneMute(on); |
604 } | 604 } |
605 | 605 |
606 /** Gets the current microphone mute state. */ | 606 /** Gets the current microphone mute state. */ |
607 private boolean isMicrophoneMute() { | 607 private boolean isMicrophoneMute() { |
608 return mAudioManager.isMicrophoneMute(); | 608 return mAudioManager.isMicrophoneMute(); |
609 } | 609 } |
610 | 610 |
611 /** Gets the current earpiece state. */ | 611 /** Gets the current earpiece state. */ |
612 private boolean hasEarpiece() { | 612 private boolean hasEarpiece() { |
613 return mContext.getPackageManager().hasSystemFeature( | 613 return ContextUtils.getApplicationContext().getPackageManager().hasSyste
mFeature( |
614 PackageManager.FEATURE_TELEPHONY); | 614 PackageManager.FEATURE_TELEPHONY); |
615 } | 615 } |
616 | 616 |
617 /** | 617 /** |
618 * Checks whether a wired headset is connected or not. | 618 * Checks whether a wired headset is connected or not. |
619 * This is not a valid indication that audio playback is actually over | 619 * This is not a valid indication that audio playback is actually over |
620 * the wired headset as audio routing depends on other conditions. We | 620 * the wired headset as audio routing depends on other conditions. We |
621 * only use it as an early indicator (during initialization) of an attached | 621 * only use it as an early indicator (during initialization) of an attached |
622 * wired headset. | 622 * wired headset. |
623 */ | 623 */ |
624 @Deprecated | 624 @Deprecated |
625 private boolean hasWiredHeadset() { | 625 private boolean hasWiredHeadset() { |
626 return mAudioManager.isWiredHeadsetOn(); | 626 return mAudioManager.isWiredHeadsetOn(); |
627 } | 627 } |
628 | 628 |
629 /** Checks if the process has as specified permission or not. */ | 629 /** Checks if the process has as specified permission or not. */ |
630 private boolean hasPermission(String permission) { | 630 private boolean hasPermission(String permission) { |
631 return mContext.checkPermission( | 631 return ContextUtils.getApplicationContext().checkPermission( |
632 permission, | 632 permission, Process.myPid(), Process.myUid()) |
633 Process.myPid(), | 633 == PackageManager.PERMISSION_GRANTED; |
634 Process.myUid()) == PackageManager.PERMISSION_GRANTED; | |
635 } | 634 } |
636 | 635 |
637 /** | 636 /** |
638 * Gets the current Bluetooth headset state. | 637 * Gets the current Bluetooth headset state. |
639 * android.bluetooth.BluetoothAdapter.getProfileConnectionState() requires | 638 * android.bluetooth.BluetoothAdapter.getProfileConnectionState() requires |
640 * the BLUETOOTH permission. | 639 * the BLUETOOTH permission. |
641 */ | 640 */ |
642 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) | 641 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) |
643 private boolean hasBluetoothHeadset() { | 642 private boolean hasBluetoothHeadset() { |
644 if (!mHasBluetoothPermission) { | 643 if (!mHasBluetoothPermission) { |
645 Log.w(TAG, "hasBluetoothHeadset() requires BLUETOOTH permission"); | 644 Log.w(TAG, "hasBluetoothHeadset() requires BLUETOOTH permission"); |
646 return false; | 645 return false; |
647 } | 646 } |
648 | 647 |
649 // To get a BluetoothAdapter representing the local Bluetooth adapter, | 648 // To get a BluetoothAdapter representing the local Bluetooth adapter, |
650 // when running on JELLY_BEAN_MR1 (4.2) and below, call the static | 649 // when running on JELLY_BEAN_MR1 (4.2) and below, call the static |
651 // getDefaultAdapter() method; when running on JELLY_BEAN_MR2 (4.3) and | 650 // getDefaultAdapter() method; when running on JELLY_BEAN_MR2 (4.3) and |
652 // higher, retrieve it through getSystemService(String) with | 651 // higher, retrieve it through getSystemService(String) with |
653 // BLUETOOTH_SERVICE. | 652 // BLUETOOTH_SERVICE. |
654 BluetoothAdapter btAdapter = null; | 653 BluetoothAdapter btAdapter = null; |
655 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { | 654 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { |
656 // Use BluetoothManager to get the BluetoothAdapter for | 655 // Use BluetoothManager to get the BluetoothAdapter for |
657 // Android 4.3 and above. | 656 // Android 4.3 and above. |
658 BluetoothManager btManager = | 657 BluetoothManager btManager = |
659 (BluetoothManager) mContext.getSystemService( | 658 (BluetoothManager) ContextUtils.getApplicationContext().getS
ystemService( |
660 Context.BLUETOOTH_SERVICE); | 659 Context.BLUETOOTH_SERVICE); |
661 btAdapter = btManager.getAdapter(); | 660 btAdapter = btManager.getAdapter(); |
662 } else { | 661 } else { |
663 // Use static method for Android 4.2 and below to get the | 662 // Use static method for Android 4.2 and below to get the |
664 // BluetoothAdapter. | 663 // BluetoothAdapter. |
665 btAdapter = BluetoothAdapter.getDefaultAdapter(); | 664 btAdapter = BluetoothAdapter.getDefaultAdapter(); |
666 } | 665 } |
667 | 666 |
668 if (btAdapter == null) { | 667 if (btAdapter == null) { |
669 // Bluetooth not supported on this platform. | 668 // Bluetooth not supported on this platform. |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
777 updateDeviceActivation(); | 776 updateDeviceActivation(); |
778 } else if (DEBUG) { | 777 } else if (DEBUG) { |
779 reportUpdate(); | 778 reportUpdate(); |
780 } | 779 } |
781 } | 780 } |
782 }; | 781 }; |
783 | 782 |
784 // Note: the intent we register for here is sticky, so it'll tell us | 783 // Note: the intent we register for here is sticky, so it'll tell us |
785 // immediately what the last action was (plugged or unplugged). | 784 // immediately what the last action was (plugged or unplugged). |
786 // It will enable us to set the speakerphone correctly. | 785 // It will enable us to set the speakerphone correctly. |
787 mContext.registerReceiver(mWiredHeadsetReceiver, filter); | 786 ContextUtils.getApplicationContext().registerReceiver(mWiredHeadsetRecei
ver, filter); |
788 } | 787 } |
789 | 788 |
790 /** Unregister receiver for broadcasted ACTION_HEADSET_PLUG intent. */ | 789 /** Unregister receiver for broadcasted ACTION_HEADSET_PLUG intent. */ |
791 private void unregisterForWiredHeadsetIntentBroadcast() { | 790 private void unregisterForWiredHeadsetIntentBroadcast() { |
792 mContext.unregisterReceiver(mWiredHeadsetReceiver); | 791 ContextUtils.getApplicationContext().unregisterReceiver(mWiredHeadsetRec
eiver); |
793 mWiredHeadsetReceiver = null; | 792 mWiredHeadsetReceiver = null; |
794 } | 793 } |
795 | 794 |
796 /** | 795 /** |
797 * Registers receiver for the broadcasted intent related to BT headset | 796 * Registers receiver for the broadcasted intent related to BT headset |
798 * availability or a change in connection state of the local Bluetooth | 797 * availability or a change in connection state of the local Bluetooth |
799 * adapter. Example: triggers when the BT device is turned on or off. | 798 * adapter. Example: triggers when the BT device is turned on or off. |
800 * BLUETOOTH permission is required to receive this one. | 799 * BLUETOOTH permission is required to receive this one. |
801 */ | 800 */ |
802 private void registerForBluetoothHeadsetIntentBroadcast() { | 801 private void registerForBluetoothHeadsetIntentBroadcast() { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
845 loge("Invalid state"); | 844 loge("Invalid state"); |
846 break; | 845 break; |
847 } | 846 } |
848 | 847 |
849 if (DEBUG) { | 848 if (DEBUG) { |
850 reportUpdate(); | 849 reportUpdate(); |
851 } | 850 } |
852 } | 851 } |
853 }; | 852 }; |
854 | 853 |
855 mContext.registerReceiver(mBluetoothHeadsetReceiver, filter); | 854 ContextUtils.getApplicationContext().registerReceiver(mBluetoothHeadsetR
eceiver, filter); |
856 } | 855 } |
857 | 856 |
858 private void unregisterForBluetoothHeadsetIntentBroadcast() { | 857 private void unregisterForBluetoothHeadsetIntentBroadcast() { |
859 mContext.unregisterReceiver(mBluetoothHeadsetReceiver); | 858 ContextUtils.getApplicationContext().unregisterReceiver(mBluetoothHeadse
tReceiver); |
860 mBluetoothHeadsetReceiver = null; | 859 mBluetoothHeadsetReceiver = null; |
861 } | 860 } |
862 | 861 |
863 /** | 862 /** |
864 * Registers receiver for the broadcasted intent related the existence | 863 * Registers receiver for the broadcasted intent related the existence |
865 * of a BT SCO channel. Indicates if BT SCO streaming is on or off. | 864 * of a BT SCO channel. Indicates if BT SCO streaming is on or off. |
866 */ | 865 */ |
867 private void registerForBluetoothScoIntentBroadcast() { | 866 private void registerForBluetoothScoIntentBroadcast() { |
868 IntentFilter filter = new IntentFilter( | 867 IntentFilter filter = new IntentFilter( |
869 AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); | 868 AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 break; | 900 break; |
902 default: | 901 default: |
903 loge("Invalid state"); | 902 loge("Invalid state"); |
904 } | 903 } |
905 if (DEBUG) { | 904 if (DEBUG) { |
906 reportUpdate(); | 905 reportUpdate(); |
907 } | 906 } |
908 } | 907 } |
909 }; | 908 }; |
910 | 909 |
911 mContext.registerReceiver(mBluetoothScoReceiver, filter); | 910 ContextUtils.getApplicationContext().registerReceiver(mBluetoothScoRecei
ver, filter); |
912 } | 911 } |
913 | 912 |
914 private void unregisterForBluetoothScoIntentBroadcast() { | 913 private void unregisterForBluetoothScoIntentBroadcast() { |
915 mContext.unregisterReceiver(mBluetoothScoReceiver); | 914 ContextUtils.getApplicationContext().unregisterReceiver(mBluetoothScoRec
eiver); |
916 mBluetoothScoReceiver = null; | 915 mBluetoothScoReceiver = null; |
917 } | 916 } |
918 | 917 |
919 /** Enables BT audio using the SCO audio channel. */ | 918 /** Enables BT audio using the SCO audio channel. */ |
920 private void startBluetoothSco() { | 919 private void startBluetoothSco() { |
921 if (!mHasBluetoothPermission) { | 920 if (!mHasBluetoothPermission) { |
922 return; | 921 return; |
923 } | 922 } |
924 if (mBluetoothScoState == STATE_BLUETOOTH_SCO_ON | 923 if (mBluetoothScoState == STATE_BLUETOOTH_SCO_ON |
925 || mBluetoothScoState == STATE_BLUETOOTH_SCO_TURNING_ON) { | 924 || mBluetoothScoState == STATE_BLUETOOTH_SCO_TURNING_ON) { |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 } else if (DEBUG) { | 1235 } else if (DEBUG) { |
1237 reportUpdate(); | 1236 reportUpdate(); |
1238 } | 1237 } |
1239 } | 1238 } |
1240 }; | 1239 }; |
1241 | 1240 |
1242 IntentFilter filter = new IntentFilter(); | 1241 IntentFilter filter = new IntentFilter(); |
1243 filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); | 1242 filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); |
1244 filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); | 1243 filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); |
1245 | 1244 |
1246 mContext.registerReceiver(mUsbAudioReceiver, filter); | 1245 ContextUtils.getApplicationContext().registerReceiver(mUsbAudioReceiver,
filter); |
1247 } | 1246 } |
1248 | 1247 |
1249 /** Unregister receiver for broadcasted ACTION_USB_DEVICE_ATTACHED/DETACHED
intent. */ | 1248 /** Unregister receiver for broadcasted ACTION_USB_DEVICE_ATTACHED/DETACHED
intent. */ |
1250 private void unregisterForUsbAudioIntentBroadcast() { | 1249 private void unregisterForUsbAudioIntentBroadcast() { |
1251 mContext.unregisterReceiver(mUsbAudioReceiver); | 1250 ContextUtils.getApplicationContext().unregisterReceiver(mUsbAudioReceive
r); |
1252 mUsbAudioReceiver = null; | 1251 mUsbAudioReceiver = null; |
1253 } | 1252 } |
1254 | 1253 |
1255 private native void nativeSetMute(long nativeAudioManagerAndroid, boolean mu
ted); | 1254 private native void nativeSetMute(long nativeAudioManagerAndroid, boolean mu
ted); |
1256 } | 1255 } |
OLD | NEW |