diff options
author | 2024-12-11 20:43:07 +0000 | |
---|---|---|
committer | 2024-12-12 17:49:34 +0000 | |
commit | aef77326754762d6390242f4a332651352ff7ac5 (patch) | |
tree | 1fa963c9f1381db8fad50f5805ca3d1f3e31468a | |
parent | d1d03a20c92a21219456bf763333f2435fda0621 (diff) |
Maximize USB audio volume when connecting.
Some of the USB audio devices have low hardware volume by default. If
the audio system doesn't set the hardware volume, the user will not be
able to get the full range of volume that is supported by the device.
Bug: 245041322
Test: connect USB device with default low hw volume
Flag: com.android.server.usb.flags.maximize_usb_audio_volume_when_connecting
Change-Id: I86874254c31bfb009ad7c36add11f8ab6496fe96
-rw-r--r-- | services/core/jni/Android.bp | 1 | ||||
-rw-r--r-- | services/core/jni/com_android_server_UsbAlsaDevice.cpp | 70 | ||||
-rw-r--r-- | services/core/jni/onload.cpp | 2 | ||||
-rw-r--r-- | services/usb/java/com/android/server/usb/UsbAlsaDevice.java | 6 |
4 files changed, 79 insertions, 0 deletions
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 82699ea3badb..01639cc3b516 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -61,6 +61,7 @@ cc_library_static { "com_android_server_SystemServer.cpp", "com_android_server_tv_TvUinputBridge.cpp", "com_android_server_tv_TvInputHal.cpp", + "com_android_server_UsbAlsaDevice.cpp", "com_android_server_UsbAlsaJackDetector.cpp", "com_android_server_UsbAlsaMidiDevice.cpp", "com_android_server_UsbDeviceManager.cpp", diff --git a/services/core/jni/com_android_server_UsbAlsaDevice.cpp b/services/core/jni/com_android_server_UsbAlsaDevice.cpp new file mode 100644 index 000000000000..166932f167ed --- /dev/null +++ b/services/core/jni/com_android_server_UsbAlsaDevice.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * 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. + */ + +#define LOG_TAG "UsbAlsaDeviceJNI" + +#include <nativehelper/JNIPlatformHelp.h> +#include <tinyalsa/asoundlib.h> + +#include <string> +#include <vector> + +#include "jni.h" +#include "utils/Log.h" + +static const std::vector<std::string> POSSIBLE_HARDWARE_VOLUME_MIXER_NAMES = + {"Headphone Playback Volume", "Headset Playback Volume", "PCM Playback Volume"}; + +namespace android { + +static void android_server_UsbAlsaDevice_setVolume(JNIEnv* /*env*/, jobject /*thiz*/, jint card, + float volume) { + ALOGD("%s(%d, %f)", __func__, card, volume); + struct mixer* alsaMixer = mixer_open(card); + if (alsaMixer == nullptr) { + ALOGW("%s(%d, %f) returned as no mixer is opened", __func__, card, volume); + return; + } + struct mixer_ctl* ctl = nullptr; + for (const auto& mixerName : POSSIBLE_HARDWARE_VOLUME_MIXER_NAMES) { + ctl = mixer_get_ctl_by_name(alsaMixer, mixerName.c_str()); + if (ctl != nullptr) { + break; + } + } + if (ctl == nullptr) { + ALOGW("%s(%d, %f) returned as no volume mixer is found", __func__, card, volume); + return; + } + const unsigned int n = mixer_ctl_get_num_values(ctl); + for (unsigned int id = 0; id < n; id++) { + if (int error = mixer_ctl_set_percent(ctl, id, 100 * volume); error != 0) { + ALOGE("%s(%d, %f) failed, error=%d", __func__, card, volume, error); + return; + } + } + ALOGD("%s(%d, %f) succeed", __func__, card, volume); +} + +static JNINativeMethod method_table[] = { + {"nativeSetVolume", "(IF)V", (void*)android_server_UsbAlsaDevice_setVolume}, +}; + +int register_android_server_UsbAlsaDevice(JNIEnv* env) { + return jniRegisterNativeMethods(env, "com/android/server/usb/UsbAlsaDevice", method_table, + NELEM(method_table)); +} +} // namespace android diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 09fd8d4ac02e..e3bd69c30de7 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -33,6 +33,7 @@ int register_android_server_power_stats_CpuPowerStatsCollector(JNIEnv* env); int register_android_server_HintManagerService(JNIEnv* env); int register_android_server_storage_AppFuse(JNIEnv* env); int register_android_server_SystemServer(JNIEnv* env); +int register_android_server_UsbAlsaDevice(JNIEnv* env); int register_android_server_UsbAlsaJackDetector(JNIEnv* env); int register_android_server_UsbAlsaMidiDevice(JNIEnv* env); int register_android_server_UsbDeviceManager(JavaVM* vm, JNIEnv* env); @@ -98,6 +99,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_InputManager(env); register_android_server_LightsService(env); register_android_server_UsbDeviceManager(vm, env); + register_android_server_UsbAlsaDevice(env); register_android_server_UsbAlsaJackDetector(env); register_android_server_UsbAlsaMidiDevice(env); register_android_server_UsbHostManager(env); diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java index c508fa968b14..ce3cd29a3ce2 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java @@ -26,6 +26,7 @@ import android.util.Slog; import com.android.internal.util.dump.DualDumpOutputStream; import com.android.server.audio.AudioService; +import com.android.server.usb.flags.Flags; import java.util.Arrays; @@ -211,6 +212,9 @@ public final class UsbAlsaDevice { mIsSelected[direction] = true; mState[direction] = 0; startJackDetect(); + if (direction == OUTPUT && Flags.maximizeUsbAudioVolumeWhenConnecting()) { + nativeSetVolume(mCardNum, 1.0f /*volume*/); + } updateWiredDeviceConnectionState(direction, true /*enable*/); } @@ -412,5 +416,7 @@ public final class UsbAlsaDevice { return result; } + + private native void nativeSetVolume(int card, float volume); } |