android audio 源码分析之AudioService

1. 从AudioService.java 的方法入手,

doSetMasterVolume(),主要干了三件事,

1)AudioSystem.setMasterVolume(volume); 

2)sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);

3)sendMasterVolumeUpdate(flags, oldVolume, newVolume);

    private void doSetMasterVolume(float volume, int flags) {
        // don't allow changing master volume when muted
        if (!AudioSystem.getMasterMute()) {
            int oldVolume = getMasterVolume();
            A<span style="background-color: rgb(102, 255, 255);">udioSystem.setMasterVolume(volume);</span>

            int newVolume = getMasterVolume();
            if (newVolume != oldVolume) {
                // Post a persist master volume msg
                <span style="background-color: rgb(102, 255, 255);">sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,</span>
                        Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
                setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags);
            }
            // Send the volume update regardless whether there was a change.
            <span style="background-color: rgb(102, 255, 255);">sendMasterVolumeUpdate(flags, oldVolume, newVolume);</span>
        }
    }

1.1 sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,..)

setMasterVolume 是调用的audiosystem.java,暂时先放一放。先来分析sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,

其实就是往mAudioHandler发消息。handler机制。mAudioHandler的创建的位置。

1)这个是再另一个线程中创建的,下面看下创建的流程:

》》    AudioService对象的构造函数中,调用  createAudioSystemThread();  创建音频audiosystem线程,并运行此线程。

》》    AudioSystemThread 线程类。

    private void createAudioSystemThread() {
        mAudioSystemThread = new AudioSystemThread();
        mAudioSystemThread.start();
        waitForAudioHandlerCreation();
    }

》》 在audiosystem线程类中创建mAudioHandler,,用来不断的接受其他线程发送来的消息。handler的创建方法,请参考其他资料。

    /** Thread that handles native AudioSystem control. */
    private class AudioSystemThread extends Thread {
        AudioSystemThread() {
            super("AudioService");
        }

        @Override
        public void run() {
            // Set this thread up so the handler will work on it
            Looper.prepare();

            synchronized(AudioService.this) {
                mAudioHandler = new AudioHandler();

                // Notify that the handler has been created
                AudioService.this.notify();
            }

            // Listen for volume change requests that are set by VolumePanel
            Looper.loop();
        }
    }

》》   AudioHandler 继承于Handler ,并实现handleMessage 方法,通过handleMessage方法处理不同的消息。

private class AudioHandler extends Handler {
<span style="white-space:pre">				</span>....
<span style="white-space:pre">				</span>....
        public void handleMessage(Message msg) {
            switch (msg.what) {
<span style="white-space:pre">				</span>....
<span style="white-space:pre">				</span>....
                case MSG_PERSIST_MASTER_VOLUME:
                    if (mUseFixedVolume) {
                        return;
                    }
                    Settings.System.putFloatForUser(mContentResolver,
                                                    Settings.System.VOLUME_MASTER,
                                                    msg.arg1 / (float)1000.0,
                                                    UserHandle.USER_CURRENT);
                    break;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
}

1.2 sendMasterVolumeUpdate(flags, oldVolume, newVolume);

1) 主要有两个动作,一个是更新UI,另一个是广播音量变化的消息。

    // UI update and Broadcast Intent
    private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {
        mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));

        Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
        intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
        intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
        sendBroadcastToAll(intent);
    }

2) 更新音量相关的UI。

        mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));
 

这个操作时由音量控制器的类完成的。控制器中的setController 方法将传入一个IVolumeController 类型的controller。

    /** The controller for the volume UI. */
    private final VolumeController mVolumeController = new VolumeController();

        public void setController(IVolumeController controller) {
            mController = controller;
            mVisible = false;
        }

3) 通过广播的形式发送音量变化的消息,带由于两个参数,一个是修改前的音量,一个是修改后的音量。

        Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
        intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
        intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
        sendBroadcastToAll(intent);

在看下sendBroadcastToAll 方法,其中调用的

Binder.clearCallingIdentity();  —- 清除远程调用的PID UID,设置为本进程的PID,UID.

 Binder.restoreCallingIdentity(ident);  —恢复远程调用进程的PID,UID.

sendBroadcastAsUser() 和 sendBroadcast(),只不过sendBroadcastAsUser()是4.2以后为多用户而新增加的方法。

UserHandle.ALL   —设备所有用户可以接收到

UserHandle.CURRENT   —设备当前用户
UserHandle.CURRENT_OR_SELF  —当前用户和应用所属用户

UserHandle.OWNER   — 设备的所有者

源码:

    private void sendBroadcastToAll(Intent intent) {
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        final long ident = Binder.clearCallingIdentity();
        try {
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

接下来需要分析audioflinger 和 audiopolicy, 画流程图会比较清晰些。

参考:

http://blog.csdn.net/ffmpeg4976/article/details/50568517

http://blog.csdn.net/ffmpeg4976/article/details/50568485

http://blog.csdn.net/ffmpeg4976/article/details/50568637

http://blog.csdn.net/windskier/article/details/6921672

    原文作者:Android源码分析
    原文地址: https://blog.csdn.net/u012109245/article/details/52092104
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞