| // Copyright 2017 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "starboard/media.h" |
| |
| #include "starboard/android/shared/jni_env_ext.h" |
| #include "starboard/android/shared/jni_utils.h" |
| #include "starboard/android/shared/media_capabilities_cache.h" |
| |
| // Constants for output types from |
| // https://developer.android.com/reference/android/media/AudioDeviceInfo. |
| constexpr int TYPE_AUX_LINE = 19; |
| constexpr int TYPE_BLE_BROADCAST = 30; |
| constexpr int TYPE_BLE_HEADSET = 26; |
| constexpr int TYPE_BLE_SPEAKER = 27; |
| constexpr int TYPE_BLUETOOTH_A2DP = 8; |
| constexpr int TYPE_BLUETOOTH_SCO = 7; |
| constexpr int TYPE_BUILTIN_EARPIECE = 1; |
| constexpr int TYPE_BUILTIN_MIC = 15; |
| constexpr int TYPE_BUILTIN_SPEAKER = 2; |
| constexpr int TYPE_BUILTIN_SPEAKER_SAFE = 24; |
| constexpr int TYPE_BUS = 21; |
| constexpr int TYPE_DOCK = 13; |
| constexpr int TYPE_DOCK_ANALOG = 31; |
| constexpr int TYPE_FM = 14; |
| constexpr int TYPE_FM_TUNER = 16; |
| constexpr int TYPE_HDMI = 9; |
| constexpr int TYPE_HDMI_ARC = 10; |
| constexpr int TYPE_HDMI_EARC = 29; |
| constexpr int TYPE_HEARING_AID = 23; |
| constexpr int TYPE_IP = 20; |
| constexpr int TYPE_LINE_ANALOG = 5; |
| constexpr int TYPE_LINE_DIGITAL = 6; |
| constexpr int TYPE_REMOTE_SUBMIX = 25; |
| constexpr int TYPE_TELEPHONY = 18; |
| constexpr int TYPE_TV_TUNER = 17; |
| constexpr int TYPE_UNKNOWN = 0; |
| constexpr int TYPE_USB_ACCESSORY = 12; |
| constexpr int TYPE_USB_DEVICE = 11; |
| constexpr int TYPE_USB_HEADSET = 22; |
| constexpr int TYPE_WIRED_HEADPHONES = 4; |
| constexpr int TYPE_WIRED_HEADSET = 3; |
| |
| SbMediaAudioConnector GetConnectorFromAndroidOutputType( |
| int android_output_device_type) { |
| switch (android_output_device_type) { |
| case TYPE_AUX_LINE: |
| return kSbMediaAudioConnectorAnalog; |
| case TYPE_BLE_BROADCAST: |
| return kSbMediaAudioConnectorBluetooth; |
| case TYPE_BLE_HEADSET: |
| return kSbMediaAudioConnectorBluetooth; |
| case TYPE_BLE_SPEAKER: |
| return kSbMediaAudioConnectorBluetooth; |
| case TYPE_BLUETOOTH_A2DP: |
| return kSbMediaAudioConnectorBluetooth; |
| case TYPE_BLUETOOTH_SCO: |
| return kSbMediaAudioConnectorBluetooth; |
| case TYPE_BUILTIN_EARPIECE: |
| return kSbMediaAudioConnectorBuiltIn; |
| case TYPE_BUILTIN_MIC: |
| return kSbMediaAudioConnectorBuiltIn; |
| case TYPE_BUILTIN_SPEAKER: |
| return kSbMediaAudioConnectorBuiltIn; |
| case TYPE_BUILTIN_SPEAKER_SAFE: |
| return kSbMediaAudioConnectorBuiltIn; |
| case TYPE_BUS: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_DOCK: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_DOCK_ANALOG: |
| return kSbMediaAudioConnectorAnalog; |
| case TYPE_FM: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_FM_TUNER: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_HDMI: |
| return kSbMediaAudioConnectorHdmi; |
| case TYPE_HDMI_ARC: |
| return kSbMediaAudioConnectorHdmi; |
| case TYPE_HDMI_EARC: |
| return kSbMediaAudioConnectorHdmi; |
| case TYPE_HEARING_AID: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_IP: |
| return kSbMediaAudioConnectorRemoteWired; |
| case TYPE_LINE_ANALOG: |
| return kSbMediaAudioConnectorAnalog; |
| case TYPE_LINE_DIGITAL: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_REMOTE_SUBMIX: |
| return kSbMediaAudioConnectorRemoteOther; |
| case TYPE_TELEPHONY: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_TV_TUNER: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_UNKNOWN: |
| return kSbMediaAudioConnectorUnknown; |
| case TYPE_USB_ACCESSORY: |
| return kSbMediaAudioConnectorUsb; |
| case TYPE_USB_DEVICE: |
| return kSbMediaAudioConnectorUsb; |
| case TYPE_USB_HEADSET: |
| return kSbMediaAudioConnectorUsb; |
| case TYPE_WIRED_HEADPHONES: |
| return kSbMediaAudioConnectorAnalog; |
| case TYPE_WIRED_HEADSET: |
| return kSbMediaAudioConnectorAnalog; |
| } |
| |
| SB_LOG(WARNING) << "Encountered unknown audio output device type " |
| << android_output_device_type; |
| return kSbMediaAudioConnectorUnknown; |
| } |
| |
| // TODO(b/284140486): Refine the implementation so it works when the audio |
| // outputs are changed during the query. |
| bool SbMediaGetAudioConfiguration( |
| int output_index, |
| SbMediaAudioConfiguration* out_configuration) { |
| using starboard::android::shared::JniEnvExt; |
| using starboard::android::shared::MediaCapabilitiesCache; |
| using starboard::android::shared::ScopedLocalJavaRef; |
| |
| if (output_index < 0 || out_configuration == NULL) { |
| return false; |
| } |
| |
| *out_configuration = {}; |
| |
| JniEnvExt* env = JniEnvExt::Get(); |
| ScopedLocalJavaRef<jobject> j_audio_output_manager( |
| env->CallStarboardObjectMethodOrAbort( |
| "getAudioOutputManager", "()Ldev/cobalt/media/AudioOutputManager;")); |
| ScopedLocalJavaRef<jobject> j_output_device_info(env->NewObjectOrAbort( |
| "dev/cobalt/media/AudioOutputManager$OutputDeviceInfo", "()V")); |
| |
| bool succeeded = env->CallBooleanMethodOrAbort( |
| j_audio_output_manager.Get(), "getOutputDeviceInfo", |
| "(ILdev/cobalt/media/AudioOutputManager$OutputDeviceInfo;)Z", |
| output_index, j_output_device_info.Get()); |
| |
| if (!succeeded) { |
| return false; |
| } |
| |
| auto call_int_method = [env, &j_output_device_info](const char* name) { |
| return env->CallIntMethodOrAbort(j_output_device_info.Get(), name, "()I"); |
| }; |
| |
| out_configuration->connector = |
| GetConnectorFromAndroidOutputType(call_int_method("getType")); |
| out_configuration->latency = 0; |
| out_configuration->coding_type = kSbMediaAudioCodingTypePcm; |
| out_configuration->number_of_channels = call_int_method("getChannels"); |
| |
| if (out_configuration->connector == kSbMediaAudioConnectorHdmi) { |
| // Keep the previous logic for HDMI to reduce risk. |
| // TODO(b/284140486): Update this using same logic as other connectors. |
| int channels = |
| MediaCapabilitiesCache::GetInstance()->GetMaxAudioOutputChannels(); |
| if (channels < 2) { |
| SB_LOG(WARNING) |
| << "The supported channels from output device is smaller than 2. " |
| "Fallback to 2 channels"; |
| out_configuration->number_of_channels = 2; |
| } else { |
| out_configuration->number_of_channels = channels; |
| } |
| } else { |
| out_configuration->number_of_channels = 2; |
| } |
| |
| return true; |
| } |