audio_manager_android.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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.
4
5#include "media/audio/android/audio_manager_android.h"
6
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/audio_util.h"
14#include "media/audio/fake_audio_input_stream.h"
15#include "media/base/channel_layout.h"
16
17namespace media {
18
19// Maximum number of output streams that can be open simultaneously.
20static const int kMaxOutputStreams = 10;
21
22static const int kAudioModeNormal = 0x00000000;
23static const int kAudioModeInCommunication = 0x00000003;
24
25AudioManager* CreateAudioManager() {
26  return new AudioManagerAndroid();
27}
28
29AudioManagerAndroid::AudioManagerAndroid() {
30  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
31
32  j_audio_manager_.Reset(
33      Java_AudioManagerAndroid_createAudioManagerAndroid(
34          base::android::AttachCurrentThread(),
35          base::android::GetApplicationContext()));
36}
37
38AudioManagerAndroid::~AudioManagerAndroid() {
39  Shutdown();
40}
41
42bool AudioManagerAndroid::HasAudioOutputDevices() {
43  return true;
44}
45
46bool AudioManagerAndroid::HasAudioInputDevices() {
47  return true;
48}
49
50void AudioManagerAndroid::GetAudioInputDeviceNames(
51    media::AudioDeviceNames* device_names) {
52  DCHECK(device_names->empty());
53  device_names->push_front(
54      media::AudioDeviceName(kDefaultDeviceName, kDefaultDeviceId));
55}
56
57AudioParameters AudioManagerAndroid::GetInputStreamParameters(
58    const std::string& device_id) {
59  // TODO(xians): figure out the right input sample rate and buffer size to
60  // achieve the best audio performance for Android devices.
61  // TODO(xians): query the native channel layout for the specific device.
62  static const int kDefaultSampleRate = 16000;
63  static const int kDefaultBufferSize = 1024;
64  return AudioParameters(
65      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
66      kDefaultSampleRate, 16, kDefaultBufferSize);
67}
68
69AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
70    const AudioParameters& params) {
71  AudioOutputStream* stream =
72    AudioManagerBase::MakeAudioOutputStream(params);
73  if (stream && output_stream_count() == 1)
74    RegisterHeadsetReceiver();
75  return stream;
76}
77
78AudioInputStream* AudioManagerAndroid::MakeAudioInputStream(
79    const AudioParameters& params, const std::string& device_id) {
80  AudioInputStream* stream =
81    AudioManagerBase::MakeAudioInputStream(params, device_id);
82  if (stream && input_stream_count() == 1)
83    SetAudioMode(kAudioModeInCommunication);
84  return stream;
85}
86
87void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) {
88  AudioManagerBase::ReleaseOutputStream(stream);
89  if (!output_stream_count())
90    UnregisterHeadsetReceiver();
91}
92
93void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) {
94  AudioManagerBase::ReleaseInputStream(stream);
95  if (!input_stream_count())
96    SetAudioMode(kAudioModeNormal);
97}
98
99AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
100      const AudioParameters& params) {
101  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
102  return new OpenSLESOutputStream(this, params);
103}
104
105AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
106      const AudioParameters& params) {
107  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
108  return new OpenSLESOutputStream(this, params);
109}
110
111AudioInputStream* AudioManagerAndroid::MakeLinearInputStream(
112    const AudioParameters& params, const std::string& device_id) {
113  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
114  return new OpenSLESInputStream(this, params);
115}
116
117AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
118    const AudioParameters& params, const std::string& device_id) {
119  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
120  return new OpenSLESInputStream(this, params);
121}
122
123AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters(
124    const AudioParameters& input_params) {
125  // TODO(xians): figure out the right output sample rate and buffer size to
126  // achieve the best audio performance for Android devices.
127  static const int kDefaultSampleRate = 44100;
128  static const int kDefaultBufferSize = 2048;
129
130  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
131  int sample_rate = kDefaultSampleRate;
132  int buffer_size = kDefaultBufferSize;
133  int bits_per_sample = 16;
134  int input_channels = 0;
135  if (input_params.IsValid()) {
136    // Use the client's input parameters if they are valid.
137    sample_rate = input_params.sample_rate();
138    bits_per_sample = input_params.bits_per_sample();
139    channel_layout = input_params.channel_layout();
140    input_channels = input_params.input_channels();
141
142    // TODO(leozwang): Android defines the minimal buffer size requirment
143    // we should follow it. From Android 4.1, a new audio low latency api
144    // set was introduced and is under development, we want to take advantage
145    // of it.
146    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
147  }
148
149  int user_buffer_size = GetUserBufferSize();
150  if (user_buffer_size)
151    buffer_size = user_buffer_size;
152
153  return AudioParameters(
154      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
155      sample_rate, bits_per_sample, buffer_size);
156}
157
158// static
159bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) {
160  return RegisterNativesImpl(env);
161}
162
163void AudioManagerAndroid::SetAudioMode(int mode) {
164  Java_AudioManagerAndroid_setMode(
165      base::android::AttachCurrentThread(),
166      j_audio_manager_.obj(), mode);
167}
168
169void AudioManagerAndroid::RegisterHeadsetReceiver() {
170  Java_AudioManagerAndroid_registerHeadsetReceiver(
171      base::android::AttachCurrentThread(),
172      j_audio_manager_.obj());
173}
174
175void AudioManagerAndroid::UnregisterHeadsetReceiver() {
176  Java_AudioManagerAndroid_unregisterHeadsetReceiver(
177      base::android::AttachCurrentThread(),
178      j_audio_manager_.obj());
179}
180
181}  // namespace media
182