从一个bug教你如何分析Android系统代码


最近项目遇到一个bug,我先描述下bug现象。耳机模式下,播放音乐,手动背光灭屏(或者自动背光灭屏),音乐暂停;手动点亮屏音乐又可以继续播放,从bug描述上猜测应该是灭屏的时候把音乐暂停了,然而并不是。因为亮屏时发现播放的时间并不是灭屏的时间,也就说灭屏状态下音乐依旧在播放,只是耳机没有输出罢了。

既然找到问题原因了,我们接着来分析下声音播放流程。


上图是使用MediaPlayer播放mp3文件的一个简单流程。调用start函数开始播放。


调用了JNI函数_start(),继续跟踪_start()函数


可以看下mp,熟悉android C++开发都知道这个是一个强指针,使用强指针开发者不用过分关注指针释放的问题,为了防止内存泄漏。跟踪代码可以发现MediaPlayer对应的是mediaplayer.cpp文件,看下该文件中start是如何实现的?


重点看下mPlayer,是sp<IMediaPlayer> 指针类型,IMediaPlayer是一个Interface类型,也就是说可以用于IPC通信,来看下他的Bn和Bp端,


通过跟踪源码发现真正实现它的是


他是一个Client,也就是说在在新建一个MediaPlayer的时候都会去创建一个Client端,继续跟踪源码看下是不是和我们猜测的一样。在mediaplayer.cpp文件中的setDataSource函数里有IMediaPlayer引起了我们的注意。


看下这个create函数,IMediaPlayerService也是一个Interface,从命名上看应该是个服务类,看下getMediaPlayerService函数,他是在IMediaDeathNotifier类中的


其中linkToDeath函数,从字面上理解就是“绑到死”,可以理解当服务出现异常died了,这个类是帮助这个服务处理后事的,主要是发布讣告,notify使用者。

再看IMediaPlayerService它只是一个Proxy类,找到实现Bn的服务类。


原来是MediaPlayerService,这是个系统服务类,在mediaserver进程中启动。接着看下create函数。


果然和我们之前猜想的一致,create的时候实例了一个Client,并将Client放在了mClients里,也就说ap端是可以实现多个MediaPlayer的。分析到这可以知道前面start函数中的mPlayer实际上是一个Client,真正实现它的接口是MediaPlayerService::Client,看下Client端的start函数:


有一个MediaPlayerBase,这又是个什么鬼,继续分析MediaPlayerBase,MediaPlayerBase是一个abstract类,找到他的实现类MediaPlayerInterface,MediaPlayerInterface主要是和AudioFlinger打交道的,主要是用于audio mixer。继续分析发现真正实现它的是


Android4.0以后就用NuPlayer框架代替了之前的AwesomePlayer,因为NuPlayer采用的是异步消息机制,这样加载大的文件,不会导致UI主线程阻塞了。有时间给大家分析下NuPlayer播放框架。今天主要还是要通过分析来解决这个bug的。由上面可知,我们从Java层、JNI、Native貌似都没有发现播放异常情况。猜测可能就是Hal层声音通道切换出了问题。下面我们继续分下Hal层代码。


这个是Hal层的一个入口接口。看下adev_open函数,


这个是adev——open函数中的部分代码,重点看下adev_open_input_stream打打开一个输入流,


看下in_read函数


进入start_input_stream


select_devices根据当前设备状态选择通道设备,


获取到out_snd_device,进入platform_get_output_snd_device,根据传入的devices,选择声音输出的通道为


分析到这发现声音的输出通道也没有问题。


从log中看,虽然可以看见screen on和screen off信息,但是这块并没有针对处理过这2个状态信息。

所以怀疑可能是驱动问题,找到驱动同事去查,分析log发现在通道切换的时候,左右耳机声道的gpio都是拉高的,也就是说声道已经切换过去,最后看原理图才知耳机部分用到了TP的电源,灭屏的时候,没有关闭该电源导致通路不通。至此问题解决。


其实上面说了这么多,但是还有涉及到的一些没有分析到,这里只是给大家一个分析问题的思路,及如何跟踪源码的方法,从Java,JNI,Native到Hal层,中间有关于查找IPC通信的流程。看源码你会发现有很多Interface、Bn,Bp的东西,只要理解其原理,分析起来就很得心应手。还有要有怀疑精神,大胆的怀疑提出假设,然后根据你的假设,结合源码去分析解决。不过这些假设是建立在你有一定的定位问题的经验上。如果你经验很丰富就不用再去从Java、JNI、Native跟踪了,可以直接定位到Hal层,从Hal层在去进一步分析。

上次分析的源码是截图发的,有热心朋友反馈说,不方面查找,这次保证不用截图:

Hal:

hardware/qcom/audio/hal/msm8916/platform.c

hardware/qcom/audio/hal/audio_hw.c

framework:

frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.h

frameworks/av/media/libmedia/IMediaDeathNotifier.cpp

frameworks/av/include/media/IMediaDeathNotifier.h

frameworks/av/media/mediaserver/main_mediaserver.cpp

frameworks/av/include/media/mediaplayer.h

frameworks/av/media/libmedia/mediaplayer.cpp

frameworks/av/media/libmediaplayerservice/MediaPlayerService.h

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp

frameworks/av/include/media/MediaPlayerInterface.h

frameworks/av/include/media/IMediaPlayerService.h

frameworks/av/media/libmedia/IMediaPlayer.cpp

frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp

frameworks/base/media/jni/android_media_MediaPlayer.cpp

frameworks/av/include/media/IMediaPlayerClient.h

frameworks/av/services/audioflinger/AudioFlinger.cpp

frameworks/base/media/java/android/media/MediaPlayer.java


原创不易,如果您觉得好,可以分享此公众号给你更多的人。





  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值