1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/audio/android/audio_manager_android.h"
7 #include "base/logging.h"
8 #include "jni/AudioManagerAndroid_jni.h"
9 #include "media/audio/android/opensles_input.h"
10 #include "media/audio/android/opensles_output.h"
11 #include "media/audio/audio_manager.h"
12 #include "media/audio/audio_parameters.h"
13 #include "media/audio/fake_audio_input_stream.h"
14 #include "media/base/channel_layout.h"
18 static void AddDefaultDevice(AudioDeviceNames
* device_names
) {
19 DCHECK(device_names
->empty());
20 device_names
->push_front(
21 AudioDeviceName(AudioManagerBase::kDefaultDeviceName
,
22 AudioManagerBase::kDefaultDeviceId
));
25 // Maximum number of output streams that can be open simultaneously.
26 static const int kMaxOutputStreams
= 10;
28 static const int kAudioModeNormal
= 0x00000000;
29 static const int kAudioModeInCommunication
= 0x00000003;
31 static const int kDefaultInputBufferSize
= 1024;
32 static const int kDefaultOutputBufferSize
= 2048;
34 AudioManager
* CreateAudioManager() {
35 return new AudioManagerAndroid();
38 AudioManagerAndroid::AudioManagerAndroid() {
39 SetMaxOutputStreamsAllowed(kMaxOutputStreams
);
41 j_audio_manager_
.Reset(
42 Java_AudioManagerAndroid_createAudioManagerAndroid(
43 base::android::AttachCurrentThread(),
44 base::android::GetApplicationContext()));
47 AudioManagerAndroid::~AudioManagerAndroid() {
51 bool AudioManagerAndroid::HasAudioOutputDevices() {
55 bool AudioManagerAndroid::HasAudioInputDevices() {
59 void AudioManagerAndroid::GetAudioInputDeviceNames(
60 AudioDeviceNames
* device_names
) {
61 AddDefaultDevice(device_names
);
64 void AudioManagerAndroid::GetAudioOutputDeviceNames(
65 AudioDeviceNames
* device_names
) {
66 AddDefaultDevice(device_names
);
69 AudioParameters
AudioManagerAndroid::GetInputStreamParameters(
70 const std::string
& device_id
) {
71 // Use mono as preferred number of input channels on Android to save
72 // resources. Using mono also avoids a driver issue seen on Samsung
73 // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details.
74 ChannelLayout channel_layout
= CHANNEL_LAYOUT_MONO
;
75 int buffer_size
= Java_AudioManagerAndroid_getMinInputFrameSize(
76 base::android::AttachCurrentThread(), GetNativeOutputSampleRate(),
77 ChannelLayoutToChannelCount(channel_layout
));
79 return AudioParameters(
80 AudioParameters::AUDIO_PCM_LOW_LATENCY
, channel_layout
,
81 GetNativeOutputSampleRate(), 16,
82 buffer_size
<= 0 ? kDefaultInputBufferSize
: buffer_size
);
85 AudioOutputStream
* AudioManagerAndroid::MakeAudioOutputStream(
86 const AudioParameters
& params
,
87 const std::string
& device_id
,
88 const std::string
& input_device_id
) {
89 AudioOutputStream
* stream
=
90 AudioManagerBase::MakeAudioOutputStream(params
, std::string(),
92 if (stream
&& output_stream_count() == 1) {
93 SetAudioMode(kAudioModeInCommunication
);
94 RegisterHeadsetReceiver();
99 AudioInputStream
* AudioManagerAndroid::MakeAudioInputStream(
100 const AudioParameters
& params
, const std::string
& device_id
) {
101 AudioInputStream
* stream
=
102 AudioManagerBase::MakeAudioInputStream(params
, device_id
);
106 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream
* stream
) {
107 AudioManagerBase::ReleaseOutputStream(stream
);
108 if (!output_stream_count()) {
109 UnregisterHeadsetReceiver();
110 SetAudioMode(kAudioModeNormal
);
114 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream
* stream
) {
115 AudioManagerBase::ReleaseInputStream(stream
);
118 AudioOutputStream
* AudioManagerAndroid::MakeLinearOutputStream(
119 const AudioParameters
& params
) {
120 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR
, params
.format());
121 return new OpenSLESOutputStream(this, params
);
124 AudioOutputStream
* AudioManagerAndroid::MakeLowLatencyOutputStream(
125 const AudioParameters
& params
,
126 const std::string
& device_id
,
127 const std::string
& input_device_id
) {
128 DLOG_IF(ERROR
, !device_id
.empty()) << "Not implemented!";
129 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY
, params
.format());
130 return new OpenSLESOutputStream(this, params
);
133 AudioInputStream
* AudioManagerAndroid::MakeLinearInputStream(
134 const AudioParameters
& params
, const std::string
& device_id
) {
135 DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR
, params
.format());
136 return new OpenSLESInputStream(this, params
);
139 AudioInputStream
* AudioManagerAndroid::MakeLowLatencyInputStream(
140 const AudioParameters
& params
, const std::string
& device_id
) {
141 DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY
, params
.format());
142 return new OpenSLESInputStream(this, params
);
145 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate
,
147 if (IsAudioLowLatencySupported()) {
148 return GetAudioLowLatencyOutputFrameSize();
150 return std::max(kDefaultOutputBufferSize
,
151 Java_AudioManagerAndroid_getMinOutputFrameSize(
152 base::android::AttachCurrentThread(),
153 sample_rate
, channels
));
157 AudioParameters
AudioManagerAndroid::GetPreferredOutputStreamParameters(
158 const std::string
& output_device_id
,
159 const AudioParameters
& input_params
) {
160 // TODO(tommi): Support |output_device_id|.
161 DLOG_IF(ERROR
, !output_device_id
.empty()) << "Not implemented!";
162 ChannelLayout channel_layout
= CHANNEL_LAYOUT_STEREO
;
163 int sample_rate
= GetNativeOutputSampleRate();
164 int buffer_size
= GetOptimalOutputFrameSize(sample_rate
, 2);
165 int bits_per_sample
= 16;
166 int input_channels
= 0;
167 if (input_params
.IsValid()) {
168 // Use the client's input parameters if they are valid.
169 sample_rate
= input_params
.sample_rate();
170 bits_per_sample
= input_params
.bits_per_sample();
171 channel_layout
= input_params
.channel_layout();
172 input_channels
= input_params
.input_channels();
173 buffer_size
= GetOptimalOutputFrameSize(
174 sample_rate
, ChannelLayoutToChannelCount(channel_layout
));
177 int user_buffer_size
= GetUserBufferSize();
178 if (user_buffer_size
)
179 buffer_size
= user_buffer_size
;
181 return AudioParameters(
182 AudioParameters::AUDIO_PCM_LOW_LATENCY
, channel_layout
, input_channels
,
183 sample_rate
, bits_per_sample
, buffer_size
);
187 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv
* env
) {
188 return RegisterNativesImpl(env
);
191 void AudioManagerAndroid::SetAudioMode(int mode
) {
192 Java_AudioManagerAndroid_setMode(
193 base::android::AttachCurrentThread(),
194 j_audio_manager_
.obj(), mode
);
197 void AudioManagerAndroid::RegisterHeadsetReceiver() {
198 Java_AudioManagerAndroid_registerHeadsetReceiver(
199 base::android::AttachCurrentThread(),
200 j_audio_manager_
.obj());
203 void AudioManagerAndroid::UnregisterHeadsetReceiver() {
204 Java_AudioManagerAndroid_unregisterHeadsetReceiver(
205 base::android::AttachCurrentThread(),
206 j_audio_manager_
.obj());
209 int AudioManagerAndroid::GetNativeOutputSampleRate() {
210 return Java_AudioManagerAndroid_getNativeOutputSampleRate(
211 base::android::AttachCurrentThread(),
212 j_audio_manager_
.obj());
215 bool AudioManagerAndroid::IsAudioLowLatencySupported() {
216 return Java_AudioManagerAndroid_isAudioLowLatencySupported(
217 base::android::AttachCurrentThread(),
218 j_audio_manager_
.obj());
221 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() {
222 return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize(
223 base::android::AttachCurrentThread(),
224 j_audio_manager_
.obj());