Audio笔记之耳机插拔检测

来源:互联网 发布:什么软件可以升级显卡 编辑:程序博客网 时间:2024/06/10 03:18

System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。

在main函数中,首先检查系统时间设置和SamplingProfiler。然后加载一个叫android_servers的本地库,他提供本地方法的接口(源程序在framework/base/services/jni/目录中)。

然后调用本地方法设置服务。然后执行一个死循环线程,该线程中启动了很多服务。

   public static void main(String[] args) {        ... ...        Environment.setUserRequired(true);        System.loadLibrary("android_servers");        Slog.i(TAG, "Entered the Android system server!");        // Initialize native services.        nativeInit();        // This used to be its own separate thread, but now it is        // just the loop we run on the main thread.        ServerThread thr = new ServerThread();        thr.initAndLoop();    }}

在ServerThread中启动了监听有线耳机接入的服务。

            if (!disableMedia) {                try {                    Slog.i(TAG, "Wired Accessory Manager");                    // Listen for wired headset changes                    inputManager.setWiredAccessoryCallbacks(                            new WiredAccessoryManager(context, inputManager));                } catch (Throwable e) {                    reportWtf("starting WiredAccessoryManager", e);                }            }
在base/services/java/com/android/server/WiredAccessoryManager.java中
WiredAccessoryManager中使用了两种方式监听耳机的状态
在构造函数中获得mUseDevInputEventForAudioJack的状态,配置为false。

public WiredAccessoryManager(Context context, InputManagerService inputManager) {  PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);  mWakeLock = pm.newWakeLock(              PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryManager");        mWakeLock.setReferenceCounted(false);        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);        mInputManager = inputManager;        mContext= context;          mUseDevInputEventForAudioJack =        context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);        //构造监听耳机状态的对象        mObserver = new WiredAccessoryObserver();        context.registerReceiver(new BroadcastReceiver() {                    @Override                    public void onReceive(Context ctx, Intent intent) {                        bootCompleted();                    }                },                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);    }
在启动完成后就开启监听,注册了开机广播,开机后,会开始所有相关的UEvent,并且开始监听。在private void bootCompleted()中

    private void bootCompleted() {        if (mUseDevInputEventForAudioJack) {            int switchValues = 0;            if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {                switchValues |= SW_HEADPHONE_INSERT_BIT;            }            if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT) == 1) {                switchValues |= SW_MICROPHONE_INSERT_BIT;            }            notifyWiredAccessoryChanged(0, switchValues,                    SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT);        }        mObserver.init();    }
在WiredAccessoryManager中实例化了一个WiredAccessoryObserver,其就是通过UEvent方式来检测耳机的插入拔出状态,

        public WiredAccessoryObserver() {            mUEventInfo = makeObservedUEventList();        }        private List<UEventInfo> makeObservedUEventList() {            List<UEventInfo> retVal = new ArrayList<UEventInfo>();            UEventInfo uei;            // Monitor h2w            if (!mUseDevInputEventForAudioJack) {                uei = new UEventInfo(NAME_H2W, BIT_HEADSET, BIT_HEADSET_NO_MIC);                if (uei.checkSwitchExists()) {                    retVal.add(uei);                } else {                    Slog.w(TAG, "This kernel does not have wired headset support");                }            }            // Monitor USB            uei = new UEventInfo(NAME_USB_AUDIO, BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL);            if (uei.checkSwitchExists()) {                retVal.add(uei);            } else {                Slog.w(TAG, "This kernel does not have usb audio support");            }            // Monitor HDMI            uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);            if (uei.checkSwitchExists()) {                retVal.add(uei);            } else {                uei = new UEventInfo(NAME_HDMI, BIT_HDMI_AUDIO, 0);                if (uei.checkSwitchExists()) {                    retVal.add(uei);                } else {                    Slog.w(TAG, "This kernel does not have HDMI audio support");                }            }            return retVal;        }
在WiredAccessoryObserver 的init中

        void init() {            synchronized (mLock) {                if (LOG) Slog.v(TAG, "init()");                char[] buffer = new char[1024];                for (int i = 0; i < mUEventInfo.size(); ++i) {                    UEventInfo uei = mUEventInfo.get(i);                    try {                        int curState;                        FileReader file = new FileReader(uei.getSwitchStatePath());                        int len = file.read(buffer, 0, 1024);                        file.close();                        curState = Integer.valueOf((new String(buffer, 0, len)).trim());                        if (curState > 0) {                            updateStateLocked(uei.getDevPath(), uei.getDevName(), curState);                        }                    } catch (FileNotFoundException e) {                        Slog.w(TAG, uei.getSwitchStatePath() +                                " not found while attempting to determine initial switch state");                    } catch (Exception e) {                        Slog.e(TAG, "" , e);                    }                }            }            // At any given time accessories could be inserted            // one on the board, one on the dock and one on HDMI:            // observe three UEVENTs            // 设置监听节点,开始进行监听            for (int i = 0; i < mUEventInfo.size(); ++i) {                UEventInfo uei = mUEventInfo.get(i);                startObserving("DEVPATH="+uei.getDevPath());            }        }        public String getDevPath() {            return String.format(Locale.US, "/devices/virtual/switch/%s", mDevName);        } 
通过startObserving("DEVPATH="+uei.getDevPath()); 来进行监听,监听的节点是:

shell@hammerhead:/ $ ls sys/class/switch/ -l                                  

lrwxrwxrwx root     root              2014-05-06 09:44 h2w -> ../../devices/virtual/switch/h2w

    /**     * Begin observation of UEvent's.<p>     * This method will cause the UEvent thread to start if this is the first     * invocation of startObserving in this process.<p>     * Once called, the UEvent thread will call onUEvent() when an incoming     * UEvent matches the specified string.<p>     * This method can be called multiple times to register multiple matches.     * Only one call to stopObserving is required even with multiple registered     * matches.     *     * @param match A substring of the UEvent to match.  Try to be as specific     * as possible to avoid incurring unintended additional cost from processing     * irrelevant messages.  Netlink messages can be moderately high bandwidth and     * are expensive to parse.  For example, some devices may send one netlink message     * for each vsync period.     */    public final void startObserving(String match) {        if (match == null || match.isEmpty()) {            throw new IllegalArgumentException("match substring must be non-empty");        }        final UEventThread t = getThread();        t.addObserver(match, this);    }
在onUEvent时间到来的时候更新state
        @Override        public void onUEvent(UEventObserver.UEvent event) {            if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString());            try {                String devPath = event.get("DEVPATH");                String name = event.get("SWITCH_NAME");                int state = Integer.parseInt(event.get("SWITCH_STATE"));                synchronized (mLock) {                    updateStateLocked(devPath, name, state);                }            } catch (NumberFormatException e) {                Slog.e(TAG, "Could not parse switch state from event " + event);            }        }
updateStateLocked(devPath, name, state)
->   updateLocked(String newName, int newState)  
->   setDevicesState(int headsetState, int prevHeadsetState, String headsetName)  
->   setDeviceStateLocked()
->  mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);在setDeviceStateLocked中会更新device的状态,并最终调用mAudioManager.setWiredDeviceConnectionState
    private void setDevicesState(            int headsetState, int prevHeadsetState, String headsetName) {        synchronized (mLock) {            int allHeadsets = SUPPORTED_HEADSETS;            for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {                if ((curHeadset & allHeadsets) != 0) {                    setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);                    allHeadsets &= ~curHeadset;                }            }        }    }    private void setDeviceStateLocked(int headset,            int headsetState, int prevHeadsetState, String headsetName) {        if ((headsetState & headset) != (prevHeadsetState & headset)) {            int device;            int state;            if ((headsetState & headset) != 0) {                state = 1;            } else {                state = 0;            }            if (headset == BIT_HEADSET) {                device = AudioManager.DEVICE_OUT_WIRED_HEADSET;            } else if (headset == BIT_HEADSET_NO_MIC){                device = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;            } else if (headset == BIT_USB_HEADSET_ANLG) {                device = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;            } else if (headset == BIT_USB_HEADSET_DGTL) {                device = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;            } else if (headset == BIT_HDMI_AUDIO) {                device = AudioManager.DEVICE_OUT_AUX_DIGITAL;            } else {                Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);                return;            }            if (LOG)                Slog.v(TAG, "device "+headsetName+((state == 1) ? " connected" : " disconnected"));            mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);        }    }    public void setWiredDeviceConnectionState(int device, int state, String name) {        IAudioService service = getService();        try {            service.setWiredDeviceConnectionState(device, state, name);        } catch (RemoteException e) {            Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);        }    }    //AudioService进行处理设备插拔的消息    public void setWiredDeviceConnectionState(int device, int state, String name) {        synchronized (mConnectedDevices) {            int delay = checkSendBecomingNoisyIntent(device, state);            queueMsgUnderWakeLock(mAudioHandler,                    MSG_SET_WIRED_DEVICE_CONNECTION_STATE,                    device,                    state,                    name,                    delay);        }    }    private void queueMsgUnderWakeLock(Handler handler, int msg,            int arg1, int arg2, Object obj, int delay) {        final long ident = Binder.clearCallingIdentity();        // Always acquire the wake lock as AudioService because it is released by the        // message handler.        mAudioEventWakeLock.acquire();        Binder.restoreCallingIdentity(ident);        sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);    }    private static void sendMsg(Handler handler, int msg,            int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {        if (existingMsgPolicy == SENDMSG_REPLACE) {            handler.removeMessages(msg);        } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {            return;        }        handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);    }    //AudioHandler处理消息MSG_SET_WIRED_DEVICE_CONNECTION_STATE    private void onSetWiredDeviceConnectionState(int device, int state, String name)    {        synchronized (mConnectedDevices) {            //步骤一、如果是耳机设备的拔除,强制设置A2DP            if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {                setBluetoothA2dpOnInt(true);            }            //步骤二、所有设备的处理            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);            handleDeviceConnection((state == 1), device, (isUsb ? name : ""));            //步骤三、如果是耳机设备插入,强制设置A2DP无效            if (state != 0) {                if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) {                    setBluetoothA2dpOnInt(false);                }                if ((device & mSafeMediaVolumeDevices) != 0) {                    sendMsg(mAudioHandler,                            MSG_CHECK_MUSIC_ACTIVE,                            SENDMSG_REPLACE,                            0,                            0,                            null,                            MUSIC_ACTIVE_POLL_PERIOD_MS);                }            }            //步骤四、非USB设备的处理            if (!isUsb) {                sendDeviceConnectionIntent(device, state, name);            }        }    }    //步骤一、 对A2DP设备的处理,如果是插入操作,强制关闭A2DP    // Handles request to override default use of A2DP for media.    public void setBluetoothA2dpOnInt(boolean on) {        synchronized (mBluetoothA2dpEnabledLock) {            mBluetoothA2dpEnabled = on;            mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);        }    }    // 步骤二、处理所有设备连接的事件    private boolean handleDeviceConnection(boolean connected, int device, String params) {        synchronized (mConnectedDevices) {            boolean isConnected = (mConnectedDevices.containsKey(device) &&                    (params.isEmpty() || mConnectedDevices.get(device).equals(params)));            //移除动作            if (isConnected && !connected) {                AudioSystem.setDeviceConnectionState(device,                                              AudioSystem.DEVICE_STATE_UNAVAILABLE,                                              mConnectedDevices.get(device));                 mConnectedDevices.remove(device);                 return true;            } else if (!isConnected && connected) {//插入动作                 AudioSystem.setDeviceConnectionState(device,                                                      AudioSystem.DEVICE_STATE_AVAILABLE,                                                      params);                 mConnectedDevices.put(new Integer(device), params);                 return true;            }        }        return false;    }    //步骤四、如果不是USB设备,发送消息和广播    private void sendDeviceConnectionIntent(int device, int state, String name)    {        Intent intent = new Intent();        intent.putExtra("state", state);        intent.putExtra("name", name);        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);        int connType = 0;                if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {            connType = AudioRoutesInfo.MAIN_HEADSET;            intent.setAction(Intent.ACTION_HEADSET_PLUG);            intent.putExtra("microphone", 1);        } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) {            connType = AudioRoutesInfo.MAIN_HEADPHONES;            intent.setAction(Intent.ACTION_HEADSET_PLUG);            intent.putExtra("microphone", 0);        } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) {            connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;            intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);        } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) {            connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS;            intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);        } else if (device == AudioSystem.DEVICE_OUT_AUX_DIGITAL) {            connType = AudioRoutesInfo.MAIN_HDMI;            intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG);        }        //根据不同的设备连接类型切换声道        synchronized (mCurAudioRoutes) {            if (connType != 0) {                int newConn = mCurAudioRoutes.mMainType;                if (state != 0) {                    newConn |= connType;                } else {                    newConn &= ~connType;                }                //通过IAudioRoutesObserver接口调用dispatchAudioRoutesChanged                //函数来通知媒体路由切换相关进程和服务进行相应处理。                if (newConn != mCurAudioRoutes.mMainType) {                    mCurAudioRoutes.mMainType = newConn;                    sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,                            SENDMSG_NOOP, 0, 0, null, 0);                }            }        }        //给上层发广播,进行事件通知,不过在AudioServiceBroadcastReceiver中没有找到这些action的处理        final long ident = Binder.clearCallingIdentity();        try {            ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);        } finally {            Binder.restoreCallingIdentity(ident);        }    }     //AudioHandler处理消息MSG_REPORT_NEW_ROUTES     public void handleMessage(Message msg) {                case MSG_REPORT_NEW_ROUTES: {                    int N = mRoutesObservers.beginBroadcast();                    if (N > 0) {                        AudioRoutesInfo routes;                        synchronized (mCurAudioRoutes) {                            routes = new AudioRoutesInfo(mCurAudioRoutes);                        }                        while (N > 0) {                            N--;                            IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);                            try {                                //调用注册的IAudioRoutesObserver对象                                obs.dispatchAudioRoutesChanged(routes);                            } catch (RemoteException e) {                            }                        }                    }                    mRoutesObservers.finishBroadcast();                    break;                }     }    //其它对象或应用可以调用service的该对象来进行注册,后续如果route有变化,service会通知这些对象    @Override    public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {        synchronized (mCurAudioRoutes) {            AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);            mRoutesObservers.register(observer);            return routes;        }    }
接着调用AudioSystem.java,通过JNI.层,进入到AudioSystem.c
//继续分析步骤二,接着进行handleDeviceConnection函数调用status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,                                               audio_policy_dev_state_t state,                                               const char *device_address){    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();    const char *address = "";    if (aps == 0) return PERMISSION_DENIED;    if (device_address != NULL) {        address = device_address;    }    return aps->setDeviceConnectionState(device, state, address);}
最终会调用到AuidoPolicyMnangerBase.cpp

status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device,                                                  AudioSystem::device_connection_state state,                                                  const char *device_address){    SortedVector <audio_io_handle_t> outputs;    ALOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);    // connect/disconnect only 1 device at a time    if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;    if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {        ALOGE("setDeviceConnectionState() invalid address: %s", device_address);        return BAD_VALUE;    }    // 处理输出设备的插拔    // handle output devices    if (audio_is_output_device(device)) {        if (!mHasA2dp && audio_is_a2dp_device(device)) {            ALOGE("setDeviceConnectionState() invalid A2DP device: %x", device);            return BAD_VALUE;        }        if (!mHasUsb && audio_is_usb_device(device)) {            ALOGE("setDeviceConnectionState() invalid USB audio device: %x", device);            return BAD_VALUE;        }        if (!mHasRemoteSubmix && audio_is_remote_submix_device((audio_devices_t)device)) {            ALOGE("setDeviceConnectionState() invalid remote submix audio device: %x", device);            return BAD_VALUE;        }        // save a copy of the opened output descriptors before any output is opened or closed        // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()        mPreviousOutputs = mOutputs;        // 设置可用设备对应位,        switch (state)        {        // handle output device connection        case AudioSystem::DEVICE_STATE_AVAILABLE:            if (mAvailableOutputDevices & device) {                ALOGW("setDeviceConnectionState() device already connected: %x", device);                return INVALID_OPERATION;            }            ALOGV("setDeviceConnectionState() connecting device %x", device);            if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {                return INVALID_OPERATION;            }            ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %d outputs",                  outputs.size());            // register new device as available            // 将插入的设备在可用设备变量中对应的位置1            mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices | device);            if (!outputs.isEmpty()) {                String8 paramStr;                if (mHasA2dp && audio_is_a2dp_device(device)) {                    // handle A2DP device connection                    AudioParameter param;                    param.add(String8(AUDIO_PARAMETER_A2DP_SINK_ADDRESS), String8(device_address));                    paramStr = param.toString();                    mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);                    mA2dpSuspended = false;                } else if (audio_is_bluetooth_sco_device(device)) {                    // handle SCO device connection                    mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);                } else if (mHasUsb && audio_is_usb_device(device)) {                    // handle USB device connection                    mUsbCardAndDevice = String8(device_address, MAX_DEVICE_ADDRESS_LEN);                    paramStr = mUsbCardAndDevice;                }                // not currently handling multiple simultaneous submixes: ignoring remote submix                //   case and address                if (!paramStr.isEmpty()) {                    for (size_t i = 0; i < outputs.size(); i++) {                        mpClientInterface->setParameters(outputs[i], paramStr);                    }                }            }            break;        // handle output device disconnection        case AudioSystem::DEVICE_STATE_UNAVAILABLE: {            if (!(mAvailableOutputDevices & device)) {                ALOGW("setDeviceConnectionState() device not connected: %x", device);                return INVALID_OPERATION;            }            ALOGV("setDeviceConnectionState() disconnecting device %x", device);            // remove device from available output devices            // 将拔除的设备在可用设备变量中对应的位置0            mAvailableOutputDevices = (audio_devices_t)(mAvailableOutputDevices & ~device);            checkOutputsForDevice(device, state, outputs);            if (mHasA2dp && audio_is_a2dp_device(device)) {                // handle A2DP device disconnection                mA2dpDeviceAddress = "";                mA2dpSuspended = false;            } else if (audio_is_bluetooth_sco_device(device)) {                // handle SCO device disconnection                mScoDeviceAddress = "";            } else if (mHasUsb && audio_is_usb_device(device)) {                // handle USB device disconnection                mUsbCardAndDevice = "";            }            // not currently handling multiple simultaneous submixes: ignoring remote submix            //   case and address            } break;        default:            ALOGE("setDeviceConnectionState() invalid state: %x", state);            return BAD_VALUE;        }        //步骤一、更新A2DP设备的状态        checkA2dpSuspend();                //步骤二、更新所有的Strategy对应的output        checkOutputForAllStrategies();        // outputs must be closed after checkOutputForAllStrategies() is executed        if (!outputs.isEmpty()) {            for (size_t i = 0; i < outputs.size(); i++) {                // close unused outputs after device disconnection or direct outputs that have been                // opened by checkOutputsForDevice() to query dynamic parameters                if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) ||                        (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {                    closeOutput(outputs[i]);                }            }        }        //步骤三、更新当前系统可用的输出设备        updateDevicesAndOutputs();        //步骤四、        for (size_t i = 0; i < mOutputs.size(); i++) {            // do not force device change on duplicated output because if device is 0, it will            // also force a device 0 for the two outputs it is duplicated to which may override            // a valid device selection on those outputs.            setOutputDevice(mOutputs.keyAt(i),                            getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),                            !mOutputs.valueAt(i)->isDuplicated(),                            0);        }        if (device == AUDIO_DEVICE_OUT_WIRED_HEADSET) {            device = AUDIO_DEVICE_IN_WIRED_HEADSET;        } else if (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO ||                   device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||                   device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;        } else {            return NO_ERROR;        }    }    // 处理输入设备的插拔    // handle input devices    if (audio_is_input_device(device)) {        switch (state)        {        // handle input device connection        case AudioSystem::DEVICE_STATE_AVAILABLE: {            if (mAvailableInputDevices & device) {                ALOGW("setDeviceConnectionState() device already connected: %d", device);                return INVALID_OPERATION;            }            mAvailableInputDevices = mAvailableInputDevices | (device & ~AUDIO_DEVICE_BIT_IN);            }            break;        // handle input device disconnection        case AudioSystem::DEVICE_STATE_UNAVAILABLE: {            if (!(mAvailableInputDevices & device)) {                ALOGW("setDeviceConnectionState() device not connected: %d", device);                return INVALID_OPERATION;            }            mAvailableInputDevices = (audio_devices_t) (mAvailableInputDevices & ~device);            } break;        default:            ALOGE("setDeviceConnectionState() invalid state: %x", state);            return BAD_VALUE;        }        audio_io_handle_t activeInput = getActiveInput();        if (activeInput != 0) {            AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);            audio_devices_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);            if ((newDevice != AUDIO_DEVICE_NONE) && (newDevice != inputDesc->mDevice)) {                ALOGV("setDeviceConnectionState() changing device from %x to %x for input %d",                        inputDesc->mDevice, newDevice, activeInput);                inputDesc->mDevice = newDevice;                AudioParameter param = AudioParameter();                param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);                mpClientInterface->setParameters(activeInput, param.toString());            }        }        return NO_ERROR;    }    ALOGW("setDeviceConnectionState() invalid device: %x", device);    return BAD_VALUE;}

//步骤一、设置A2DP设备的状态

void AudioPolicyManagerBase::checkA2dpSuspend(){    if (!mHasA2dp) {        return;    }    //找到A2DP的输出线程    audio_io_handle_t a2dpOutput = getA2dpOutput();    if (a2dpOutput == 0) {        return;    }    // suspend A2DP output if:    //      (NOT already suspended) &&    //      ((SCO device is connected &&    //       (forced usage for communication || for record is SCO))) ||    //      (phone state is ringing || in call)    //    // restore A2DP output if:    //      (Already suspended) &&    //      ((SCO device is NOT connected ||    //       (forced usage NOT for communication && NOT for record is SCO))) &&    //      (phone state is NOT ringing && NOT in call)    // 如果处于暂停状态,则进行重置,否则进入暂停状态    if (mA2dpSuspended) {        if (((mScoDeviceAddress == "") ||             ((mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO) &&              (mForceUse[AudioSystem::FOR_RECORD] != AudioSystem::FORCE_BT_SCO))) &&             ((mPhoneState != AudioSystem::MODE_IN_CALL) &&              (mPhoneState != AudioSystem::MODE_RINGTONE))) {            mpClientInterface->restoreOutput(a2dpOutput);            mA2dpSuspended = false;        }    } else {        if (((mScoDeviceAddress != "") &&             ((mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||              (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO))) ||             ((mPhoneState == AudioSystem::MODE_IN_CALL) ||              (mPhoneState == AudioSystem::MODE_RINGTONE))) {            mpClientInterface->suspendOutput(a2dpOutput);            mA2dpSuspended = true;        }    }}//查找A2DP类型的输出线程,对应conf文件中的一个profile对象,audio_io_handle_t AudioPolicyManagerBase::getA2dpOutput(){    if (!mHasA2dp) {        return 0;    }    for (size_t i = 0; i < mOutputs.size(); i++) {        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i);        if (!outputDesc->isDuplicated() && outputDesc->device() & AUDIO_DEVICE_OUT_ALL_A2DP) {            return mOutputs.keyAt(i);        }    }    return 0;}status_t AudioPolicyCompatClient::suspendOutput(audio_io_handle_t output){    return mServiceOps->suspend_output(mService, output);}//mServiceOps实际上是audio_policy_service_opsstatic int aps_suspend_output(void *service, audio_io_handle_t output){    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();    if (af == 0) {        ALOGW("%s: could not get AudioFlinger", __func__);        return PERMISSION_DENIED;    }    return af->suspendOutput(output);}//暂停该输出线程status_t AudioFlinger::suspendOutput(audio_io_handle_t output){    Mutex::Autolock _l(mLock);    PlaybackThread *thread = checkPlaybackThread_l(output);    if (thread == NULL) {        return BAD_VALUE;    }    ALOGV("suspendOutput() %d", output);    thread->suspend();    return NO_ERROR;}

//步骤二、更新所有的Strategy对应的output

void AudioPolicyManagerBase::checkOutputForAllStrategies(){    checkOutputForStrategy(STRATEGY_ENFORCED_AUDIBLE);    checkOutputForStrategy(STRATEGY_PHONE);    checkOutputForStrategy(STRATEGY_SONIFICATION);    checkOutputForStrategy(STRATEGY_SONIFICATION_RESPECTFUL);    checkOutputForStrategy(STRATEGY_MEDIA);    checkOutputForStrategy(STRATEGY_DTMF);}void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy){    audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/);    audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/);    SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs);    SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);    //如果设备的插拔导致了Strategy关联的输出发生了变化,则需要调整Strategy相关的Effect和Track    //到新的输出上    if (!vectorsEqual(srcOutputs,dstOutputs)) {        ALOGV("checkOutputForStrategy() strategy %d, moving from output %d to output %d",              strategy, srcOutputs[0], dstOutputs[0]);        // mute strategy while moving tracks from one output to another        for (size_t i = 0; i < srcOutputs.size(); i++) {            AudioOutputDescriptor *desc = mOutputs.valueFor(srcOutputs[i]);            //通过检查Stream的引用数,判断对应的Strategy是否处于活动状态            //每个Output都会保存关联的所有Stream的数量,如果Stream都为0,            //则表示该Output没有在输出任何声音            if (desc->isStrategyActive(strategy)) {                setStrategyMute(strategy, true, srcOutputs[i]);                setStrategyMute(strategy, false, srcOutputs[i], MUTE_TIME_MS, newDevice);            }        }        // Move effects associated to this strategy from previous output to new output        if (strategy == STRATEGY_MEDIA) {            int outIdx = 0;            for (size_t i = 0; i < dstOutputs.size(); i++) {                AudioOutputDescriptor *desc = mOutputs.valueFor(dstOutputs[i]);                if (desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {                    outIdx = i;                }            }            SortedVector<audio_io_handle_t> moved;            for (size_t i = 0; i < mEffects.size(); i++) {                EffectDescriptor *desc = mEffects.valueAt(i);                if (desc->mSession == AUDIO_SESSION_OUTPUT_MIX &&                        desc->mIo != dstOutputs[outIdx]) {                    if (moved.indexOf(desc->mIo) < 0) {                        ALOGV("checkOutputForStrategy() moving effect %d to output %d",                              mEffects.keyAt(i), dstOutputs[outIdx]);                        mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, desc->mIo,                                                       dstOutputs[outIdx]);                        moved.add(desc->mIo);                    }                    desc->mIo = dstOutputs[outIdx];                }            }        }        // Move tracks associated to this strategy from previous output to new output        for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {            if (getStrategy((AudioSystem::stream_type)i) == strategy) {                //FIXME see fixme on name change                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i,                                                   dstOutputs[0] /* ignored */);            }        }    }}//反向推导,查找与该Strategy关联的Stream,然后将该void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy,                                             bool on,                                             audio_io_handle_t output,                                             int delayMs,                                             audio_devices_t device){    ALOGVV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {        if (getStrategy((AudioSystem::stream_type)stream) == strategy) {            setStreamMute(stream, on, output, delayMs, device);        }    }}void AudioPolicyManagerBase::setStreamMute(int stream,                                           bool on,                                           audio_io_handle_t output,                                           int delayMs,                                           audio_devices_t device){    StreamDescriptor &streamDesc = mStreams[stream];    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);    if (device == AUDIO_DEVICE_NONE) {        device = outputDesc->device();    }    ALOGVV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d device %04x",          stream, on, output, outputDesc->mMuteCount[stream], device);    if (on) {        if (outputDesc->mMuteCount[stream] == 0) {            if (streamDesc.mCanBeMuted &&                    ((stream != AudioSystem::ENFORCED_AUDIBLE) ||                     (mForceUse[AudioSystem::FOR_SYSTEM] == AudioSystem::FORCE_NONE))) {                checkAndSetVolume(stream, 0, output, device, delayMs);            }        }        // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored        outputDesc->mMuteCount[stream]++;    } else {        if (outputDesc->mMuteCount[stream] == 0) {            ALOGV("setStreamMute() unmuting non muted stream!");            return;        }        if (--outputDesc->mMuteCount[stream] == 0) {            checkAndSetVolume(stream,                              streamDesc.getVolumeIndex(device),                              output,                              device,                              delayMs);        }    }}status_t AudioPolicyManagerBase::checkAndSetVolume(int stream,                                                   int index,                                                   audio_io_handle_t output,                                                   audio_devices_t device,                                                   int delayMs,                                                   bool force){    // do not change actual stream volume if the stream is muted    if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {        ALOGVV("checkAndSetVolume() stream %d muted count %d",              stream, mOutputs.valueFor(output)->mMuteCount[stream]);        return NO_ERROR;    }    // do not change in call volume if bluetooth is connected and vice versa    if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||        (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {        ALOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",             stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);        return INVALID_OPERATION;    }    float volume = computeVolume(stream, index, output, device);    // We actually change the volume if:    // - the float value returned by computeVolume() changed    // - the force flag is set    if (volume != mOutputs.valueFor(output)->mCurVolume[stream] ||            force) {        mOutputs.valueFor(output)->mCurVolume[stream] = volume;        ALOGVV("checkAndSetVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);        // Force VOICE_CALL to track BLUETOOTH_SCO stream volume when bluetooth audio is        // enabled        if (stream == AudioSystem::BLUETOOTH_SCO) {            mpClientInterface->setStreamVolume(AudioSystem::VOICE_CALL, volume, output, delayMs);        }        mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);    }    if (stream == AudioSystem::VOICE_CALL ||        stream == AudioSystem::BLUETOOTH_SCO) {        float voiceVolume;        // Force voice volume to max for bluetooth SCO as volume is managed by the headset        if (stream == AudioSystem::VOICE_CALL) {            voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;        } else {            voiceVolume = 1.0;        }        if (voiceVolume != mLastVoiceVolume && output == mPrimaryOutput) {            mpClientInterface->setVoiceVolume(voiceVolume, delayMs);            mLastVoiceVolume = voiceVolume;        }    }    return NO_ERROR;}status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,        audio_io_handle_t output){    // check calling permissions    if (!settingsAllowed()) {        return PERMISSION_DENIED;    }    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {        ALOGE("setStreamVolume() invalid stream %d", stream);        return BAD_VALUE;    }    AutoMutex lock(mLock);    PlaybackThread *thread = NULL;    if (output) {        thread = checkPlaybackThread_l(output);        if (thread == NULL) {            return BAD_VALUE;        }    }    mStreamTypes[stream].volume = value;    if (thread == NULL) {        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {            mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);        }    } else {        thread->setStreamVolume(stream, value);    }    return NO_ERROR;}void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value){    Mutex::Autolock _l(mLock);    mStreamTypes[stream].volume = value;}//步骤三、更新当前系统可用的输出设备setOutputDevice(mOutputs.keyAt(i),                getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),                !mOutputs.valueAt(i)->isDuplicated(),                0);// 设备插拔事件导致当前系统设备有变化,首先需要根据Strategy获得设备,然后重新分配给outputaudio_devices_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache){    audio_devices_t device = AUDIO_DEVICE_NONE;    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);    // check the following by order of priority to request a routing change if necessary:    // 1: the strategy enforced audible is active on the output:    //      use device for strategy enforced audible    // 2: we are in call or the strategy phone is active on the output:    //      use device for strategy phone    // 3: the strategy sonification is active on the output:    //      use device for strategy sonification    // 4: the strategy "respectful" sonification is active on the output:    //      use device for strategy "respectful" sonification    // 5: the strategy media is active on the output:    //      use device for strategy media    // 6: the strategy DTMF is active on the output:    //      use device for strategy DTMF    if (outputDesc->isStrategyActive(STRATEGY_ENFORCED_AUDIBLE)) {        device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);    } else if (isInCall() ||                    outputDesc->isStrategyActive(STRATEGY_PHONE)) {        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);    } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION)) {        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);    } else if (outputDesc->isStrategyActive(STRATEGY_SONIFICATION_RESPECTFUL)) {        device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);    } else if (outputDesc->isStrategyActive(STRATEGY_MEDIA)) {        device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);    } else if (outputDesc->isStrategyActive(STRATEGY_DTMF)) {        device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);    }    ALOGV("getNewDevice() selected device %x", device);    return device;}uint32_t AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output,                                             audio_devices_t device,                                             bool force,                                             int delayMs){    ALOGV("setOutputDevice() output %d device %04x delayMs %d", output, device, delayMs);    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);    AudioParameter param;    uint32_t muteWaitMs;    if (outputDesc->isDuplicated()) {        muteWaitMs = setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);        muteWaitMs += setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);        return muteWaitMs;    }    // no need to proceed if new device is not AUDIO_DEVICE_NONE and not supported by current    // output profile    if ((device != AUDIO_DEVICE_NONE) &&            ((device & outputDesc->mProfile->mSupportedDevices) == 0)) {        return 0;    }    // filter devices according to output selected    device = (audio_devices_t)(device & outputDesc->mProfile->mSupportedDevices);    audio_devices_t prevDevice = outputDesc->mDevice;    ALOGV("setOutputDevice() prevDevice %04x", prevDevice);    // 将输出线程的当前输出设备设置为该设备    if (device != AUDIO_DEVICE_NONE) {        outputDesc->mDevice = device;    }    muteWaitMs = checkDeviceMuteStrategies(outputDesc, prevDevice, delayMs);    // Do not change the routing if:    //  - the requested device is AUDIO_DEVICE_NONE    //  - the requested device is the same as current device and force is not specified.    // Doing this check here allows the caller to call setOutputDevice() without conditions    if ((device == AUDIO_DEVICE_NONE || device == prevDevice) && !force) {        ALOGV("setOutputDevice() setting same device %04x or null device for output %d", device, output);        return muteWaitMs;    }    ALOGV("setOutputDevice() changing device");    // do the routing    param.addInt(String8(AudioParameter::keyRouting), (int)device);    mpClientInterface->setParameters(output, param.toString(), delayMs);    // update stream volumes according to new device    applyStreamVolumes(output, device, delayMs);    return muteWaitMs;}status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs){    ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d",            ioHandle, keyValuePairs.string(), IPCThreadState::self()->getCallingPid());    // check calling permissions    if (!settingsAllowed()) {        return PERMISSION_DENIED;    }    // ioHandle == 0 means the parameters are global to the audio hardware interface    if (ioHandle == 0) {        Mutex::Autolock _l(mLock);        status_t final_result = NO_ERROR;        {            AutoMutex lock(mHardwareLock);            mHardwareStatus = AUDIO_HW_SET_PARAMETER;            for (size_t i = 0; i < mAudioHwDevs.size(); i++) {                audio_hw_device_t *dev = mAudioHwDevs.valueAt(i)->hwDevice();                status_t result = dev->set_parameters(dev, keyValuePairs.string());                final_result = result ?: final_result;            }            mHardwareStatus = AUDIO_HW_IDLE;        }        // disable AEC and NS if the device is a BT SCO headset supporting those pre processings        AudioParameter param = AudioParameter(keyValuePairs);        String8 value;        if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {            bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);            if (mBtNrecIsOff != btNrecIsOff) {                for (size_t i = 0; i < mRecordThreads.size(); i++) {                    sp<RecordThread> thread = mRecordThreads.valueAt(i);                    audio_devices_t device = thread->inDevice();                    bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;                    // collect all of the thread's session IDs                    KeyedVector<int, bool> ids = thread->sessionIds();                    // suspend effects associated with those session IDs                    for (size_t j = 0; j < ids.size(); ++j) {                        int sessionId = ids.keyAt(j);                        thread->setEffectSuspended(FX_IID_AEC,                                                   suspend,                                                   sessionId);                        thread->setEffectSuspended(FX_IID_NS,                                                   suspend,                                                   sessionId);                    }                }                mBtNrecIsOff = btNrecIsOff;            }        }        String8 screenState;        if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {            bool isOff = screenState == "off";            if (isOff != (AudioFlinger::mScreenState & 1)) {                AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;            }        }        return final_result;    }    // hold a strong ref on thread in case closeOutput() or closeInput() is called    // and the thread is exited once the lock is released    sp<ThreadBase> thread;    {        Mutex::Autolock _l(mLock);        thread = checkPlaybackThread_l(ioHandle);        if (thread == 0) {            thread = checkRecordThread_l(ioHandle);        } else if (thread == primaryPlaybackThread_l()) {            // indicate output device change to all input threads for pre processing            AudioParameter param = AudioParameter(keyValuePairs);            int value;            if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&                    (value != 0)) {                for (size_t i = 0; i < mRecordThreads.size(); i++) {                    mRecordThreads.valueAt(i)->setParameters(keyValuePairs);                }            }        }    }    if (thread != 0) {        return thread->setParameters(keyValuePairs);    }    return BAD_VALUE;}status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs){    status_t status;    ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());    Mutex::Autolock _l(mLock);    mNewParameters.add(keyValuePairs);    mWaitWorkCV.signal();    // wait condition with timeout in case the thread loop has exited    // before the request could be processed    if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {        status = mParamStatus;        mWaitWorkCV.signal();    } else {        status = TIMED_OUT;    }    return status;} 



0 0
原创粉丝点击