一. 底层背景初探

      了解了AudioTrack的上层实现只是非常微小的一步。因为在Android的四层架构中,所有的AudioTrack.java以及其他的java类都是framework层中的元素,没有HAL层以及更下层的Linux Kernel是根本做不到播放功能的。可以简单理解为下图,Libraries依赖可以当作HAL层的主要工作。

   

二. 仍从AudioTrack类说起

     之前所说的AudioTrack样例中的部分Java方法,其实都对应了在Hal层的native方法,直接上代码

... ...

public void play( ){

    final int delay = getStartDelayMS( );               //AudioTrack继承父类计算播放时延方法

    if(delay == 0){

        startImpl();

     }

    else{

        new Thread( ){

             public void run( ){

                   Thread.sleep(delay);                       //播放器player启动,audioMedia还未输入,推迟启动

                   baseSetStartDelayMS(0);                  

                   startImpl();

               }

           }

    }

}

private void startImpl( ){

     synchronized(mPlayStateLock){

          baseStart( );

          native_start();

          mPlayState = PLAYSTATE_PLAYING;

    }

}

... ...

      仔细搜索AudioTrack.java发现native_start其实是jni映射到Hal层的java本地方法。同理,你所看到的stop( ),realese( ),pause( )全都依靠C++的函数实现,AudioTrack中主要本地方法如下:

... ...

 private native final void native_finalize();
 public native final void native_release();

 private native final void native_start();

 private native final void native_stop();

 private native final void native_pause();

 private native final void native_flush();

 private native final int native_write_byte(byte[] audioData, int offsetInBytes, int sizeInBytes, int format, boolean isBlocking);

 private native final int native_write_short(short[] audioData, int offsetInShorts, int sizeInShorts, int format, boolean isBlocking);

 private native final int native_write_float(float[] audioData, int offsetInFloats, int sizeInFloats, int format, boolean isBlocking);

... ...

三. JNI方法生成(Tip)

      Java当中一旦引入native方法,需要利用javah生成.h头文件,将.h中定义的函数在.c或.cpp中进行实现。

      这个过程的实现首先需要将android.jar加入环境变量。对于Linux操作系统,主要办法为

# cp  android.jar  ./usr/bin                                  //不可用mv,mv相当于剪切,这样Android Studio缺乏Library了

      接下来主要过程可以描述为,例如我的Demo.java路径为android/app/src/main/java/sample/

(1)生成.class

 package sample

 public class Demo{ ... }

      我利用java compiler生成.class

xzhan150@GOT120CND80941NN:/android/app/src/main/java/sample$ javac Demo.java

(2) 生成.h头文件

      需要退到package的上层目录,(必须和(1)操作在同一个console中!否则会报Demo class not found错误) 如下:

xzhan150@GOT120CND80941NN:/android/app/src/main/java$ javah -jni sample.Demo

      这样就会在/android/app/src/main/java路径下生成sample_Demo.h头文件了           

四. JNI路径查找

     言归正传,找到AudioTrack.java中的native方法,在整个源代码目录下查找。例如我想要寻找包含native_start的代码块,可以利用如下命令:

xzhan150@GOT120CND80941NN:/workspace/frameworks$ grep -rn 'native_start'
base/media/java/android/media/AudioTrack.java:2102:            native_start();
base/media/java/android/media/AudioTrack.java:3192:    private native final void native_start();
base/media/java/android/media/MediaCodec.java:2051:        native_start();
base/media/java/android/media/MediaCodec.java:2057:    private native final void native_start();
base/media/java/android/media/AudioRecord.java:989:            if (native_start(MediaSyncEvent.SYNC_EVENT_NONE, 0) == SUCCESS) {
base/media/java/android/media/AudioRecord.java:1012:            if (native_start(syncEvent.getType(), syncEvent.getAudioSessionId()) == SUCCESS) {
base/media/java/android/media/AudioRecord.java:1761:    private native final int native_start(int syncEvent, int sessionId);
base/media/jni/android_media_MediaCodec.cpp:1965:    { "native_start", "()V", (void *)android_media_MediaCodec_start },
base/core/java/com/android/internal/os/FuseAppLoop.java:81:            native_start(mInstance);
base/core/java/com/android/internal/os/FuseAppLoop.java:311:    native void native_start(long ptr);
base/core/jni/com_android_internal_os_FuseAppLoop.cpp:188:        "native_start",
base/core/jni/android_media_AudioTrack.cpp:1281:    {"native_start",         "()V",      (void *)android_media_AudioTrack_start},
base/core/jni/android_media_AudioRecord.cpp:839:    {"native_start",         "(II)I",    (void *)android_media_AudioRecord_start},

... ...

     可以看到base/core/jni/android_media_AudioTrack.cpp是我们想要定位的native方法所在.cpp的C++函数实现。

更多相关文章

  1. C语言函数的递归(上)
  2. Android实现类似excel表格的方法整理
  3. 【Android性能优化】使用NDK进行Java和C++混编
  4. 一文彻底搞懂Android(安卓)View的绘制流程
  5. Android(安卓)-- 系统进程Zygote的启动分析
  6. 剖析 Android(安卓)架构组件之 ViewModel
  7. AIDL跨进程通信和Service调用
  8. Android(安卓)ContentProvider 使用
  9. Android(安卓)GSM驱动模块(rild)详细分析(三)response流程

随机推荐

  1. Android之MediaPlayer
  2. Android(安卓)基本Dialog和自定义Dialog
  3. android 进程间通信示例
  4. Eclipse build Android时不生成apk问题解
  5. Android(安卓)系统跳转实现分享功能(如 微
  6. android 设计比较美观的登录界面
  7. Android之Intent的基本使用
  8. Android(安卓)Layout XML属性
  9. Android(安卓)Permission大全
  10. Android(安卓)Window系列(一)- window与dec