(L1) AudioService set , adjust , setAll , get Index, setStreamVolumeInt, adjustStreamVolume

前言

音量最终下派到native是通过

public static native int setStreamVolumeIndex(int stream, int index, int device);

所以设置音量关键找到 (stream, index, device) 的一个组合

音量值保存在

        private final ConcurrentHashMap<Integer, Integer> mIndex =
                                            new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);


那么在下派参数前,如何在VolumeStreamState中修改和获得某个device的音量呢?

VolumeStreamState.setIndex

参数便是index, device
        public boolean setIndex(int index, int device) {
            synchronized (VolumeStreamState.class) {
                int oldIndex = getIndex(device);
                index = getValidIndex(index);
                synchronized (mCameraSoundForced) {
                    if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
                        index = mIndexMax;
                    }
                }
//存入device  -> index
                mIndex.put(device, index);

                if (oldIndex != index) {
下面的注释讲了两点:
                    // Apply change to all streams using this one as alias
                    // if changing volume of current device, also change volume of current
                    // device on aliased stream
                    boolean currentDevice = (device == getDeviceForStream(mStreamType));
                    int numStreamTypes = AudioSystem.getNumStreamTypes();
                    for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
                        if (streamType != mStreamType &&
                                mStreamVolumeAlias[streamType] == mStreamType) {
                            int scaledIndex = rescaleIndex(index, mStreamType, streamType);
                            mStreamStates[streamType].setIndex(scaledIndex,
                                                               device);
                            if (currentDevice) {
                                mStreamStates[streamType].setIndex(scaledIndex,
                                                                   getDeviceForStream(streamType));
                            }
                        }
                    }
                    return true;
                } else {
                    return false;
                }
            }
        }

目前对上面注释的第二点还理解不到

相关函数

getDeviceForStream

    private int getDeviceForStream(int stream) {
//先从native取device for stream
        int device = AudioSystem.getDevicesForStream(stream);
        if ((device & (device - 1)) != 0) {
<span style="font-family: Arial, Helvetica, sans-serif;">//如果native返回多个设备,上层只作为一个设备处理</span>
<pre name="code" class="java"><pre name="code" class="java">//选择的原则根据priority
//这里定义了三种情况:
//1.speaker + one other devie
 
//2.one A2DP device + another device

//3.HDMI-CEC system audio mode // Multiple device selection is either: // - speaker + one other device: give priority to speaker in this case. // - one A2DP device + another device: happens with duplicated output. In this case // retain the device on the A2DP output as the other must not correspond to an active // selection if not the speaker. // - HDMI-CEC system audio mode only output: give priority to available item in order. if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { device = AudioSystem.DEVICE_OUT_SPEAKER; } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) { device = AudioSystem.DEVICE_OUT_HDMI_ARC; } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) { device = AudioSystem.DEVICE_OUT_SPDIF; } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) { device = AudioSystem.DEVICE_OUT_AUX_LINE; } else { device &= AudioSystem.DEVICE_OUT_ALL_A2DP; //最后是与运算 } } return device; }

 

VolumeStreamState.adjustIndex

还是调用setIndex(),殊途同归

        public boolean adjustIndex(int deltaIndex, int device) {
            return setIndex(getIndex(device) + deltaIndex,
                            device);
        }

VolumeStreamState.getIndex

 
public int getIndex(int device) { synchronized (VolumeStreamState.class) { Integer index = mIndex.get(device); if (index == null) { // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); } return index.intValue(); } }



VolumeStreamState.setAllIndexes

<pre style="border: 0px; margin-top: 0px; margin-bottom: 0px; background-color: rgb(255, 255, 255);"><pre name="code" class="java">        public void setAllIndexes(VolumeStreamState srcStream) {
            synchronized (VolumeStreamState.class) {
                int srcStreamType = srcStream.getStreamType();
                
<pre name="code" class="java">有些device 在当前的stream state但是不在src stream state

// apply default device volume from source stream to all devices first in case // some devices are present in this stream state but not in source stream state int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); //取得 srcStream default device index index = rescaleIndex(index, srcStreamType, mStreamType); Set set = mIndex.entrySet(); Iterator i = set.iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry)i.next(); entry.setValue(index); } // Now apply actual volume for devices in source stream state set = srcStream.mIndex.entrySet(); //用 src mIndex 的值处理 i = set.iterator(); while (i.hasNext()) { Map.Entry entry = (Map.Entry)i.next(); int device = ((Integer)entry.getKey()).intValue(); index = ((Integer)entry.getValue()).intValue(); index = rescaleIndex(index, srcStreamType, mStreamType); setIndex(index, device); } } }

 
 
 
 

setStreamVolumeInt

调用setIndex, 然后发送 MSG_SET_DEVICE_VOLUME 广播

 
    private void setStreamVolumeInt(int streamType,
                                    int index,
                                    int device,
                                    boolean force) {
        VolumeStreamState streamState = mStreamStates[streamType];

        if (streamState.setIndex(index, device) || force) {
            // Post message to set system volume (it in turn will post a message
            // to persist).
            sendMsg(mAudioHandler,
                    MSG_SET_DEVICE_VOLUME,
                    SENDMSG_QUEUE,
                    device,
                    0,
                    streamState,
                    0);
        }
    }
 
public void handleMessage(Message msg) { switch (msg.what) { case MSG_SET_DEVICE_VOLUME: setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); break;
        private void setDeviceVolume(VolumeStreamState streamState, int device) {

            synchronized (VolumeStreamState.class) {
                // Apply volume
//调回VolumeStreamState, 只传入device即可
                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);

        }
        public void applyDeviceVolume_syncVSS(int device) {
            int index;
            if (isMuted_syncVSS()) {
                index = 0;
            } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported)
                    || ((device & mFullVolumeDevices) != 0)) {
                index = (mIndexMax + 5)/10;
            } else {
                index = (getIndex(device) + 5)/10;
            }
            AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
        }


 

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

猜你喜欢

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