audioservice.java_android audio 源码分析之AudioService

本文深入分析了Android的AudioService.java,特别是doSetMasterVolume()方法,涉及音量设置、消息处理及广播通知。通过发送消息到mAudioHandler,更新UI并广播音量变化,同时探讨了线程、Handler机制和广播的使用。后续将分析audioflinger和audiopolicy。
摘要由CSDN通过智能技术生成

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();

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);

setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags);

}

// Send the volume update regardless whether there was a change.

sendMasterVolumeUpdate(flags, oldVolume, newVolume);

}

}

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 {

....

....

public void handleMessage(Message msg) {

switch (msg.what) {

....

....

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;

}

}

}

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来逐行分析Android T的AudioService.java中setMode函数。 ```java /** * @see AudioManager#setMode(int) */ public void setMode(int mode, IBinder cb, String callingPackageName) { enforceModifyAudioRoutingPermission(); synchronized (mConnectedDevices) { final int newModeOwnerPid = Binder.getCallingPid(); final int newModeOwnerUid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); final boolean modeOwnerChanged = (mModeOwnerPid != newModeOwnerPid || mModeOwnerUid != newModeOwnerUid); try { setModeInt(mode, cb, callingPackageName, modeOwnerChanged, newModeOwnerPid, newModeOwnerUid); } finally { Binder.restoreCallingIdentity(ident); } } } ``` 这个函数的作用是设置音频模式,它是实现了AudioManager类的setMode方法。 函数的第一个参数mode是要设置的音频模式。 函数的第二个参数cb是一个Binder对象,它可以在AudioFocusManager中使用,用来管理音频焦点。 函数的第三个参数callingPackageName是调用这个函数的应用程序的包名。 接下来是函数的实现。 首先,它调用enforceModifyAudioRoutingPermission()方法来检查是否有修改音频路由的权限。 然后,它使用synchronized关键字同步了mConnectedDevices,这是一个存储连接的设备信息的集合。 接着,它获取了调用这个函数的应用程序的PID和UID,以及清除了调用者的身份验证标识符。 接下来,它检查是否有新的模式所有者,并设置了一个用于检测模式所有者更改的标志。 最后,它调用了setModeInt方法来实际设置音频模式,传递了所有必要的参数,并在结束时恢复了调用者的身份验证标识符。 至此,Android T的AudioService.java中setMode函数的分析就结束了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值