Home | History | Annotate | Download | only in android
      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 
     17 namespace media {
     18 
     19 // Maximum number of output streams that can be open simultaneously.
     20 static const int kMaxOutputStreams = 10;
     21 
     22 static const int kAudioModeNormal = 0x00000000;
     23 static const int kAudioModeInCommunication = 0x00000003;
     24 
     25 static const int kDefaultInputBufferSize = 1024;
     26 static const int kDefaultOutputBufferSize = 2048;
     27 
     28 AudioManager* CreateAudioManager() {
     29   return new AudioManagerAndroid();
     30 }
     31 
     32 AudioManagerAndroid::AudioManagerAndroid() {
     33   SetMaxOutputStreamsAllowed(kMaxOutputStreams);
     34 
     35   j_audio_manager_.Reset(
     36       Java_AudioManagerAndroid_createAudioManagerAndroid(
     37           base::android::AttachCurrentThread(),
     38           base::android::GetApplicationContext()));
     39 }
     40 
     41 AudioManagerAndroid::~AudioManagerAndroid() {
     42   Shutdown();
     43 }
     44 
     45 bool AudioManagerAndroid::HasAudioOutputDevices() {
     46   return true;
     47 }
     48 
     49 bool AudioManagerAndroid::HasAudioInputDevices() {
     50   return true;
     51 }
     52 
     53 void AudioManagerAndroid::GetAudioInputDeviceNames(
     54     media::AudioDeviceNames* device_names) {
     55   DCHECK(device_names->empty());
     56   device_names->push_front(
     57       media::AudioDeviceName(kDefaultDeviceName, kDefaultDeviceId));
     58 }
     59 
     60 AudioParameters AudioManagerAndroid::GetInputStreamParameters(
     61     const std::string& device_id) {
     62   // Use mono as preferred number of input channels on Android to save
     63   // resources. Using mono also avoids a driver issue seen on Samsung
     64   // Galaxy S3 and S4 devices. See http://crbug.com/256851 for details.
     65   ChannelLayout channel_layout = CHANNEL_LAYOUT_MONO;
     66   int buffer_size = Java_AudioManagerAndroid_getMinInputFrameSize(
     67       base::android::AttachCurrentThread(), GetNativeOutputSampleRate(),
     68       ChannelLayoutToChannelCount(channel_layout));
     69 
     70   return AudioParameters(
     71       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
     72       GetNativeOutputSampleRate(), 16,
     73       buffer_size <= 0 ? kDefaultInputBufferSize : buffer_size);
     74 }
     75 
     76 AudioOutputStream* AudioManagerAndroid::MakeAudioOutputStream(
     77     const AudioParameters& params, const std::string& input_device_id) {
     78   AudioOutputStream* stream =
     79     AudioManagerBase::MakeAudioOutputStream(params, std::string());
     80   if (stream && output_stream_count() == 1) {
     81     SetAudioMode(kAudioModeInCommunication);
     82     RegisterHeadsetReceiver();
     83   }
     84   return stream;
     85 }
     86 
     87 AudioInputStream* AudioManagerAndroid::MakeAudioInputStream(
     88     const AudioParameters& params, const std::string& device_id) {
     89   AudioInputStream* stream =
     90     AudioManagerBase::MakeAudioInputStream(params, device_id);
     91   return stream;
     92 }
     93 
     94 void AudioManagerAndroid::ReleaseOutputStream(AudioOutputStream* stream) {
     95   AudioManagerBase::ReleaseOutputStream(stream);
     96   if (!output_stream_count()) {
     97     UnregisterHeadsetReceiver();
     98     SetAudioMode(kAudioModeNormal);
     99   }
    100 }
    101 
    102 void AudioManagerAndroid::ReleaseInputStream(AudioInputStream* stream) {
    103   AudioManagerBase::ReleaseInputStream(stream);
    104 }
    105 
    106 AudioOutputStream* AudioManagerAndroid::MakeLinearOutputStream(
    107       const AudioParameters& params) {
    108   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    109   return new OpenSLESOutputStream(this, params);
    110 }
    111 
    112 AudioOutputStream* AudioManagerAndroid::MakeLowLatencyOutputStream(
    113       const AudioParameters& params, const std::string& input_device_id) {
    114   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    115   return new OpenSLESOutputStream(this, params);
    116 }
    117 
    118 AudioInputStream* AudioManagerAndroid::MakeLinearInputStream(
    119     const AudioParameters& params, const std::string& device_id) {
    120   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
    121   return new OpenSLESInputStream(this, params);
    122 }
    123 
    124 AudioInputStream* AudioManagerAndroid::MakeLowLatencyInputStream(
    125     const AudioParameters& params, const std::string& device_id) {
    126   DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
    127   return new OpenSLESInputStream(this, params);
    128 }
    129 
    130 int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate,
    131                                                    int channels) {
    132   if (IsAudioLowLatencySupported()) {
    133     return GetAudioLowLatencyOutputFrameSize();
    134   } else {
    135     return std::max(kDefaultOutputBufferSize,
    136                     Java_AudioManagerAndroid_getMinOutputFrameSize(
    137                         base::android::AttachCurrentThread(),
    138                         sample_rate, channels));
    139   }
    140 }
    141 
    142 AudioParameters AudioManagerAndroid::GetPreferredOutputStreamParameters(
    143     const AudioParameters& input_params) {
    144   ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
    145   int sample_rate = GetNativeOutputSampleRate();
    146   int buffer_size = GetOptimalOutputFrameSize(sample_rate, 2);
    147   int bits_per_sample = 16;
    148   int input_channels = 0;
    149   if (input_params.IsValid()) {
    150     // Use the client's input parameters if they are valid.
    151     sample_rate = input_params.sample_rate();
    152     bits_per_sample = input_params.bits_per_sample();
    153     channel_layout = input_params.channel_layout();
    154     input_channels = input_params.input_channels();
    155     buffer_size = GetOptimalOutputFrameSize(
    156         sample_rate, ChannelLayoutToChannelCount(channel_layout));
    157   }
    158 
    159   int user_buffer_size = GetUserBufferSize();
    160   if (user_buffer_size)
    161     buffer_size = user_buffer_size;
    162 
    163   return AudioParameters(
    164       AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, input_channels,
    165       sample_rate, bits_per_sample, buffer_size);
    166 }
    167 
    168 // static
    169 bool AudioManagerAndroid::RegisterAudioManager(JNIEnv* env) {
    170   return RegisterNativesImpl(env);
    171 }
    172 
    173 void AudioManagerAndroid::SetAudioMode(int mode) {
    174   Java_AudioManagerAndroid_setMode(
    175       base::android::AttachCurrentThread(),
    176       j_audio_manager_.obj(), mode);
    177 }
    178 
    179 void AudioManagerAndroid::RegisterHeadsetReceiver() {
    180   Java_AudioManagerAndroid_registerHeadsetReceiver(
    181       base::android::AttachCurrentThread(),
    182       j_audio_manager_.obj());
    183 }
    184 
    185 void AudioManagerAndroid::UnregisterHeadsetReceiver() {
    186   Java_AudioManagerAndroid_unregisterHeadsetReceiver(
    187       base::android::AttachCurrentThread(),
    188       j_audio_manager_.obj());
    189 }
    190 
    191 int AudioManagerAndroid::GetNativeOutputSampleRate() {
    192   return Java_AudioManagerAndroid_getNativeOutputSampleRate(
    193       base::android::AttachCurrentThread(),
    194       j_audio_manager_.obj());
    195 }
    196 
    197 bool AudioManagerAndroid::IsAudioLowLatencySupported() {
    198   return Java_AudioManagerAndroid_isAudioLowLatencySupported(
    199       base::android::AttachCurrentThread(),
    200       j_audio_manager_.obj());
    201 }
    202 
    203 int AudioManagerAndroid::GetAudioLowLatencyOutputFrameSize() {
    204   return Java_AudioManagerAndroid_getAudioLowLatencyOutputFrameSize(
    205       base::android::AttachCurrentThread(),
    206       j_audio_manager_.obj());
    207 }
    208 
    209 }  // namespace media
    210