阅读Android Framework层的源码可能是Android 开发者深入学习的必经之路。但在我学习的过程中看到最多的是各路大神的源码分析,而很少有展示如何一步一步找到相关代码的。直到前不久看到老罗的视频《Android源代码情景分析法》,很有启发。但是老罗也只是讲到Java层的分析追踪,在我的日常工作中,经常涉及从Java 层到JNI 层,再到Native层,经常追着追着就丢了。
之后我仿照老罗的方法,尝试追踪MediaRecorder的setOutputFormat方法是怎么实现的,现在总结如下。
准备:
Source Insight 3
Android Framework层源码
分析开始
首先看MediaRecorder.java内的setOutputFormat方法:
/**
* Sets the format of the output file produced during recording. Call this
* after setAudioSource()/setVideoSource() but before prepare().
*
* It is recommended to always use 3GP format when using the H.263
* video encoder and AMR audio encoder. Using an MPEG-4 container format
* may confuse some desktop players.
*
* @param output_format the output format to use. The output format
* needs to be specified before setting recording-parameters or encoders.
* @throws IllegalStateException if it is called after prepare() or before
* setAudioSource()/setVideoSource().
* @see android.media.MediaRecorder.OutputFormat
*/
public native void setOutputFormat(int output_format)
throws IllegalStateException;
这是一个native方法,根据JNI的规则,我们应该去android_media_MediaRecorder.cpp里看这个方法的实现:
static void
android_media_MediaRecorder_setVideoEncoder(JNIEnv *env, jobject thiz, jint ve)
{
ALOGV("setVideoEncoder(%d)", ve);
if (ve < VIDEO_ENCODER_DEFAULT || ve >= VIDEO_ENCODER_LIST_END) {
jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid video encoder");
return;
}
sp mr = getMediaRecorder(env, thiz);
process_media_recorder_call(env, mr->setVideoEncoder(ve), "java/lang/RuntimeException", "setVideoEncoder failed.");
}
关键是最后的两句,sp是Android 里的一个指针,就当没看见~ 所以最后两句的意思是调用Native层的MediaRecorder的setVideoEncoder方法。
继续去MediaRecorder.cpp里看setVideoEncoder方法:
status_t MediaRecorder::setVideoEncoder(int ve)
{
ALOGV("setVideoEncoder(%d)", ve);
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
}
if (!mIsVideoSourceSet) {
ALOGE("try to set the video encoder without setting the video source first");
return INVALID_OPERATION;
}
if (mIsVideoEncoderSet) {
ALOGE("video encoder has already been set");
return INVALID_OPERATION;
}
if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState);
return INVALID_OPERATION;
}
status_t ret = mMediaRecorder->setVideoEncoder(ve);
if (OK != ret) {
ALOGV("setVideoEncoder failed: %d", ret);
mCurrentState = MEDIA_RECORDER_ERROR;
return ret;
}
mIsVideoEncoderSet = true;
return ret;
}
这里的mMediaReocorder定义在MediaRecorder.h里:
sp mMediaRecorder;
可见其是一个IMediaRecorder类型的变量,这是一个接口类型,看一下其接口定义,在IMediaRecorder.h中:
class IMediaRecorder: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaRecorder);
virtual status_t setCamera(const sp& camera,
const sp& proxy) = 0;
virtual status_t setPreviewSurface(const sp& surface) = 0;
virtual status_t setVideoSource(int vs) = 0;
virtual status_t setAudioSource(int as) = 0;
virtual status_t setOutputFormat(int of) = 0;
virtual status_t setVideoEncoder(int ve) = 0;
virtual status_t setAudioEncoder(int ae) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
virtual status_t setParameters(const String8& params) = 0;
virtual status_t setListener(const sp& listener) = 0;
virtual status_t setClientName(const String16& clientName) = 0;
virtual status_t prepare() = 0;
virtual status_t getMaxAmplitude(int* max) = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t reset() = 0;
virtual status_t pause() = 0;
virtual status_t resume() = 0;
virtual status_t init() = 0;
virtual status_t close() = 0;
virtual status_t release() = 0;
virtual status_t setInputSurface(const sp& surface) = 0;
virtual sp querySurfaceMediaSource() = 0;
};
// ----------------------------------------------------------------------------
class BnMediaRecorder: public BnInterface
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
呐~关键的步骤来了,在以前我基本就追到这,就算完蛋了,不知道怎么继续往下追了,后来看Binder相关的内容,知道了BnInterface的作用,这是Binder中关键的一环,我们这就不展开讲了,只要记得,接下来我们要追的是BnMediaRecorder这个类。
全局搜索一下“: public BnMediaRecorder”,也就是去找它的实现类,发现在MediaRecorderClient.h当中有如下的定义:
class MediaRecorderClient : public BnMediaRecorder
{
class ServiceDeathNotifier: public IBinder::DeathRecipient
{
public:
ServiceDeathNotifier(
const sp& service,
const sp& listener,
int which);
virtual ~ServiceDeathNotifier();
virtual void binderDied(const wp& who);
private:
int mWhich;
sp mService;
wp mListener;
};
public:
virtual status_t setCamera(const sp& camera,
const sp& proxy);
virtual status_t setPreviewSurface(const sp& surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
virtual status_t setOutputFormat(int of);
virtual status_t setVideoEncoder(int ve);
virtual status_t setAudioEncoder(int ae);
virtual status_t setOutputFile(int fd, int64_t offset,
int64_t length);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8& params);
virtual status_t setListener(
const sp& listener);
virtual status_t setClientName(const String16& clientName);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
virtual status_t start();
virtual status_t stop();
virtual status_t reset();
virtual status_t pause();
virtual status_t resume();
virtual status_t init();
virtual status_t close();
virtual status_t release();
virtual status_t dump(int fd, const Vector& args);
virtual status_t setInputSurface(const sp& surface);
virtual sp querySurfaceMediaSource();
private:
friend class MediaPlayerService; // for accessing private constructor
MediaRecorderClient(
const sp& service,
pid_t pid,
const String16& opPackageName);
virtual ~MediaRecorderClient();
sp mCameraDeathListener;
sp mCodecDeathListener;
pid_t mPid;
Mutex mLock;
MediaRecorderBase *mRecorder;
sp mMediaPlayerService;
};
那么我们去MediaRecorderClient.cpp里看看:
status_t MediaRecorderClient::setVideoEncoder(int ve)
{
ALOGV("setVideoEncoder(%d)", ve);
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
return NO_INIT;
}
return mRecorder->setVideoEncoder((video_encoder)ve);
}
这里的mRecorder 定义在MediaRecorderClient.h当中:
MediaRecorderBase *mRecorder;
来,我们继续搜索“: public MediaRecorderBase”,在StagefrightRecorder.h中找到了,那么我们去StagefrightRecorder.cpp当中看看~
status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
ALOGV("setVideoEncoder: %d", ve);
if (ve < VIDEO_ENCODER_DEFAULT ||
ve >= VIDEO_ENCODER_LIST_END) {
ALOGE("Invalid video encoder: %d", ve);
return BAD_VALUE;
}
mVideoEncoder = ve;
return OK;
}
呐,这就算完了~最后我们会发现MediaRecorder中的接口实现基本到最后都会落在这个StagefrightRecorder.cpp当中。
总结
在Android源码阅读当中,由于大多数人都没接触过大型的C++工程,所以在Native层的追踪上一开始会有较大困难,但只要静下心来,会发现其实只要记住C++的继承、实现、接口的相关概念,和一般的读代码没啥区别。