framework/base/media/java/android/media/AudioService.java
public void setMasterVolume(int volume, int flags, String callingPackage) {
if (mUseFixedVolume) {
return;
}
if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(),
callingPackage) != AppOpsManager.MODE_ALLOWED) {
return;
}
if (volume < 0) {
volume = 0;
} else if (volume > MAX_MASTER_VOLUME) {
volume = MAX_MASTER_VOLUME;
}
doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags);
}
private void doSetMasterVolume(float volume, int flags) {
// don't allow changing master volume when muted
if (!AudioSystem.getMasterMute()) {
int oldVolume = getMasterVolume();
AudioSystem.setMasterVolume(volume);
int newVolume = getMasterVolume();
if (newVolume != oldVolume) {
// Post a persist master volume msg
sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,
Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
}
// Send the volume update regardless whether there was a change.
sendMasterVolumeUpdate(flags, oldVolume, newVolume);
}
}
最後call 到 framework/av/service/audioflinger/AudioFlinger.cpp
status_t AudioFlinger::setMasterVolume(float value)
{
....
...
// Set master volume in the HALs which support it.
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
AutoMutex lock(mHardwareLock);
AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
if (dev->canSetMasterVolume()) {
dev->hwDevice()->set_master_volume(dev->hwDevice(), value);
}
mHardwareStatus = AUDIO_HW_IDLE;
}
所以 AudioHwDevice 要 implement canSetMasterVolume( ), 然後實做 set_master_volume( )
再查 canSetMasterVolume..
一樣,在 AudioFlinger.h:
class AudioHwDevice {
...
...
bool canSetMasterVolume() const {
return (0 != (mFlags & AHWD_CAN_SET_MASTER_VOLUME));
}
mFlag 是在 AudioHwDevice 生成時給定的...
AudioHwDevice(audio_module_handle_t handle,
const char *moduleName,
audio_hw_device_t *hwDevice,
Flags flags)
: mHandle(handle), mModuleName(strdup(moduleName))
, mHwDevice(hwDevice)
, mFlags(flags) { }
同樣的地方...
audioflinger 在 load audio.xxx.xxx module 時,會測試 audio module 是否有 implement set_master_volume( )
好決定生成 AudioHwDevice 時,flag 要不要加上 AHWD_CAN_SET_MASTER_VOLUME:
AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
{
....
....
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
if ((NULL != dev->set_master_volume) &&
(OK == dev->set_master_volume(dev, mMasterVolume))) {
flags = static_cast<AudioHwDevice::Flags>(flags |
AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
}
mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
if ((NULL != dev->set_master_mute) &&
(OK == dev->set_master_mute(dev, mMasterMute))) {
flags = static_cast<AudioHwDevice::Flags>(flags |
AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
}
...
}
...
audio_module_handle_t handle = nextUniqueId();
mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
然後在 hw_module 的 source (imx6): hardware/imx/alsa/tinyalsa_hal.c:
static int adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
....
adev->hw_device.set_master_volume = adev_set_master_volume;
有 module function table 的 assign,
implement 是:
static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
{
return -ENOSYS;
}
.. 也就是說...沒有提供這個功能。
所以把 return value 從 -ENOSYS 改成 0
然後,還要改...
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8006659..ecb8780 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -65,7 +65,7 @@
<!-- Flag indicating that the media framework should allow changing
master volume stream and nothing else . -->
- <bool name="config_useMasterVolume">false</bool>
+ <bool name="config_useMasterVolume">true</bool>
叫 ..
./media/java/android/media/AudioManager.java:585: com.android.internal.R.bool.config_useMasterVolume);
./media/java/android/media/AudioService.java:641: com.android.internal.R.bool.config_useMasterVolume);
這兩個 source 用 MasterVolume
另外 UI: