(L1)音量调节 自下而上

前言

分为两部分分析
 AudioService ---> AudioSystem
 AudioManager ---> AudioService
 
 
AudioSystem只提供了一个可以使用的接口
 
http://androidxref.com/5.1.1_r6/xref/frameworks/base/media/java/android/media/AudioSystem.java
 
public static native int setStreamVolumeIndex(int stream, int index, int device);
参数有stream, index, device

setStreamVolumeIndex调用位置

通过如下两个函数,可以了解到
1.判断是否为mute, 若是则直接设置为0
2.判断是否最大音量的情况,若是则最大音量
3.两个边界完了才是从index取值
 
下面两个函数都是VolumeStreamState的方法,apply打头

VolumeStreamState.applyDeviceVolume_syncVSS

参数只有device
        // must be called while synchronized VolumeStreamState.class
        public void applyDeviceVolume_syncVSS(int device) {
            int index;
            if (isMuted_syncVSS()) {          // muted
                index = 0;
            } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
                    || ((device & mFullVolumeDevices) != 0)) {                                      // abs , full volume
                index = (mIndexMax + 5)/10;
            } else {
                index = (getIndex(device) + 5)/10;
            }
            AudioSystem.setStreamVolumeIndex(mStreamType, index, device); //  <-------------
        }
 

VolumeStreamState.applyAllVolumes

        public void applyAllVolumes() {
            synchronized (VolumeStreamState.class) {
                // apply default volume first: by convention this will reset all
                // devices volumes in audio policy manager to the supplied value
                int index;
                if (isMuted_syncVSS()) {             //  mute
                    index = 0;
                } else {
                    index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
                }
                AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);  //    <-----------
                // then apply device specific volumes
                Set set = mIndex.entrySet();
                Iterator i = set.iterator();
                while (i.hasNext()) {
                    Map.Entry entry = (Map.Entry)i.next();
                    int device = ((Integer)entry.getKey()).intValue();
                    if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
                        if (isMuted_syncVSS()) {
                            index = 0;
                        } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
                                mAvrcpAbsVolSupported)
                                    || ((device & mFullVolumeDevices) != 0))
                        {
                            index = (mIndexMax + 5)/10;
                        } else {
                            index = ((Integer)entry.getValue() + 5)/10;
                        }
                        AudioSystem.setStreamVolumeIndex(mStreamType, index, device); //    <----------------
                    }
                }
            }
        }
 

applyDeviceVolume_syncVSS 调用位置

public void checkFixedVolumeDevices

        public void checkFixedVolumeDevices() {
            synchronized (VolumeStreamState.class) {
                // ignore settings for fixed volume devices: volume should always be at max or 0
                if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
                    Set set = mIndex.entrySet();
                    Iterator i = set.iterator();
                    while (i.hasNext()) {
                        Map.Entry entry = (Map.Entry)i.next();
                        int device = ((Integer)entry.getKey()).intValue();
                        int index = ((Integer)entry.getValue()).intValue();
                        if (((device & mFullVolumeDevices) != 0)
                                || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
                            entry.setValue(mIndexMax);
                        }
                        applyDeviceVolume_syncVSS(device);  // <--------
                    }
                }
            }
        }
 

AudioHandler.setDeviceVolume

    private class AudioHandler extends Handler {

        private void setDeviceVolume(VolumeStreamState streamState, int device) {      <-----------

            synchronized (VolumeStreamState.class) {
                // Apply volume
                streamState.applyDeviceVolume_syncVSS(device);

                // Apply change to all streams using this one as alias
                int numStreamTypes = AudioSystem.getNumStreamTypes();
                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
                    if (streamType != streamState.mStreamType &&
                            mStreamVolumeAlias[streamType] == streamState.mStreamType) {
                        // Make sure volume is also maxed out on A2DP device for aliased stream
                        // that may have a different device selected
                        int streamDevice = getDeviceForStream(streamType);
                        if ((device != streamDevice) && mAvrcpAbsVolSupported &&
                                ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
                            mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
                        }
                        mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
                    }
                }
            }
            // Post a persist volume msg
            sendMsg(mAudioHandler,
                    MSG_PERSIST_VOLUME,
                    SENDMSG_QUEUE,
                    device,
                    0,
                    streamState,
                    PERSIST_DELAY);

        }
 

applyAllVolumes调用位置

private void checkAllAliasStreamVolumes

public void forceRemoteSubmixFullVolume

private void setAllVolumes(VolumeStreamState streamState)

MSG_MEDIA_SERVER_DIED

Basic Principle & Model

AudioSevice                  VolumeStreamState                                                      AudioSystem
   Fuctions         ------>         applyDeviceVolume_syncVSS       ------->             setStreamVolumeIndex
                                               applyAllVolumes
 
解决了 AudioService ---> AudioSystem,接下来解决 AudioManager ---> AudioService
 

Develper API call follow

从物理按键调节音量,会看到弹出进度条,进度条上的刻度移动,并且伴有响声。通过Developer API调用,会有更多的元素,这里只考虑音量变化,其他的元素之后做分析。
http://developer.android.com/reference/android/media/AudioManager.html
 
AudioManager.adjustStreamVolume(int streamType, int direction, int flags)
AudioManager.adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)
AudioManager.setStreamVolume(int streamType, int index, int flags)
 

adjustStreamVolume(int streamType, int direction, int flags)

 

adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags)

 

setStreamVolume(int streamType, int index, int flags)

 

Mute

发布了27 篇原创文章 · 获赞 2 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/wlia/article/details/47398813