转载请注明出处:http://blog.youkuaiyun.com/wangjihuanghun/article/details/56069283
耽搁了几天,最近一直在忙找工作的事情,今天把这篇文章补上。
本文基于Android7.1.1版本进行分析,主要涉及以下几个文件:
1 AudioManager –> /frameworks/base/media/java/android/media/
2 AudioService –> /frameworks/base/services/core/java/com/android/server/audio/
3 MediaFocusControl –>/frameworks/base/services/core/java/com/android/server/audio/
4 FocusRequester –> /frameworks/base/services/core/java/com/android/server/audio/
5 AudioAttributes –> /frameworks/base/media/java/android/media/
6 AudioFocusInfo –> /frameworks/base/media/java/android/media/
7 AudioSystem –> /frameworks/base/media/java/android/media/
之前一直用的是4.4的源码,这两天看了下7.1的源码发现这块内容改动还是挺大的,主要是新增了几个文件,并且对MediaFocusControl类进行了瘦身,代码从2700多行减到了500多行。
我们从入口方法requestAudioFocus开始,还记得我们是怎么使用该方法的么?
通过Audio Manager的对象来调用
mAudioManager.requestAudioFocus(mAudioFocusChange, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
具体请参考我的上篇博客点击这里
从AudioManager开始(有些方法里代码较多,只贴出来部分关键代码,下同)
public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) {
int status = AUDIOFOCUS_REQUEST_FAILED;
try {
//调用内部重载后的方法
status = requestAudioFocus(l,
new AudioAttributes.Builder()
.setInternalLegacyStreamType(streamType).build(),
durationHint,
0 /* flags, legacy behavior */);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Audio focus request denied due to ", e);
}
return status;
}
根据传进来的streamType,构造了一个AudioAttributes对象向下传递,这个AudioAttributes主要是存储了一些音频流信息的属性,后面会用到。接着看
@SystemApi
public int requestAudioFocus(OnAudioFocusChangeListener l,
@NonNull AudioAttributes requestAttributes,
int durationHint,
int flags) throws IllegalArgumentException {
return requestAudioFocus(l, requestAttributes, durationHint,
flags & AUDIOFOCUS_FLAGS_APPS,
null /* no AudioPolicy*/);
}
这里面对falgs进行了与操作,由于之前传进来的是0,所以转换后的结果还是0。接着看
@SystemApi
public int requestAudioFocus(OnAudioFocusChangeListener l,
@NonNull AudioAttributes requestAttributes,
int durationHint,
int flags,
AudioPolicy ap) throws IllegalArgumentException {
// 参数检查
//...
int status = AUDIOFOCUS_REQUEST_FAILED;
registerAudioFocusListener(l);
//获取AudioService实例,这里采用了binder通信,我们只需要知道从此处开始将会进入AudioServie的requestAudioFocus方法
IAudioService service = getService();
try {
status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
mAudioFocusDispatcher, getIdForAudioFocusListener(l),
getContext().getOpPackageName() /* package name */, flags,
ap != null ? ap.cb() : null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return status;
}
这里面重点看一下 registerAudioFocusListener(l);
private final HashMap<String, OnAudioFocusChangeListener> mAudioFocusIdListenerMap =
new HashMap<String, OnAudioFocusChangeListener>();