android系統(tǒng)開(kāi)發(fā)(十)-audio移植一
1,移植基礎(chǔ):
(1)內(nèi)核聲音驅(qū)動(dòng)和alsa驅(qū)動(dòng)
(2)alsa-lib和alsa-utils庫(kù)移植
這兩部分上一節(jié)已經(jīng)介紹過(guò)了。
2,android的audio最核心的部分是audioflinger,audioflinger向上處理來(lái)自于應(yīng)用程序的聲音相關(guān)的所有請(qǐng)求
向下通過(guò)AudioHardwareInterface訪問(wèn)硬件,android的audio架構(gòu)如下所示:
Applications
|
Frameworks
|
JNI
|
AudioFlinger
|
AudioHardwareInterface
| | |
專有audio庫(kù) | alsa用戶庫(kù)
| |
/dev/eac /dev/snd/*
| |
內(nèi)核eac驅(qū)動(dòng) 內(nèi)核alsa驅(qū)動(dòng)
AudioHardwareInterface是audioflinger和硬件驅(qū)動(dòng)之間的橋梁,android默認(rèn)編譯的是generic audio,此時(shí)
AudioHardwareInterface直接指向了/dev/eac驅(qū)動(dòng),它通過(guò)eac驅(qū)動(dòng)來(lái)操作聲卡,android audio移植就是要讓
AudioHardwareInterface直接或者間接指向我們自己定義的聲音驅(qū)動(dòng),一般都采用alsa聲音體系,所以我們的目的就是
要讓AudioHardwareInterface指向alsa用戶庫(kù)。下面的內(nèi)容開(kāi)始移植alsa-audio
3,修改vendor/ardent/merlin/BoardConfig.mk文件內(nèi)容如下:
BOARD_USES_GENERIC_AUDIO := false
BOARD_USES_ALSA_AUDIO := true
BUILD_WITH_ALSA_UTILS := true
上面配置的目的就是為了讓要讓AudioHardwareInterface指向alsa用戶庫(kù)
4,下面來(lái)添加audio庫(kù)的編譯
在vendor/ardent/merlin目錄下新建一個(gè)libaudio目錄,修改AndroidBoard.mk文件,添加編譯路徑如下:
LOCAL_PATH := $(call my-dir)
L_PATH := $(LOCAL_PATH)
include $(L_PATH)/libaudio/Mdroid.mk
5,vendor/ardent/merlin/libaudio目錄下新建一個(gè)Mdroid.mk文件,內(nèi)容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libaudio
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libmedia \
libhardware
LOCAL_SRC_FILES += AudioHardwareMerlin.cpp
LOCAL_CFLAGS +=
LOCAL_C_INCLUDES +=
LOCAL_STATIC_LIBRARIES += libaudiointerface
include $(BUILD_SHARED_LIBRARY)
6,android audio的實(shí)現(xiàn)方法,我們現(xiàn)看看接口部分,上面有說(shuō)道audioflinger是通過(guò)AudioHardwareInterface指向驅(qū)動(dòng)的
AudioHardwareInterface類的代碼在frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp文件中
該文件中的create函數(shù)中定義了AudioHardwareInterface指向驅(qū)動(dòng)的代碼如下:
AudioHardwareInterface* hw = 0;
char value[PROPERTY_VALUE_MAX];
#ifdef GENERIC_AUDIO
hw = new AudioHardwareGeneric();
#else
// if running in emulation - use the emulator driver
if (property_get("ro.kernel.qemu", value, 0)) {
LOGD("Running in emulation - using generic audio driver");
hw = new AudioHardwareGeneric();
}
else {
LOGV("Creating Vendor Specific AudioHardware");
hw = createAudioHardware();
}
#endif
return hw;
當(dāng)系統(tǒng)為generic audio的時(shí)候此函數(shù)返回的是一個(gè)指向AudioHardwareGeneric對(duì)象的指針,其實(shí)是返回一個(gè)指向AudioHardwareInterface對(duì)象
的指針,因?yàn)锳udioHardwareGeneric是AudioHardwareInterface的子類,繼承關(guān)系如下:
AudioHardwareInterface->AudioHardwareBase->AudioHardwareGeneric
如果系統(tǒng)不是generic audio,則通過(guò)調(diào)用createAudioHardware函數(shù)來(lái)返回一個(gè)指向一個(gè)指向AudioHardwareInterface對(duì)象的指針,
所以,簡(jiǎn)單的將,我們要做的事情就是實(shí)現(xiàn)這個(gè)函數(shù)以及它相關(guān)的內(nèi)容即可。createAudioHardware函數(shù)我們可以在
hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h中也就是AudioHardwareInterface
的聲明中找到原型如下:
extern "C" AudioHardwareInterface* createAudioHardware(void);
7,通過(guò)6我們不難知道,我們實(shí)現(xiàn)自己的audio接口完全可以模仿generic audio的做法,只是要多實(shí)現(xiàn)一個(gè)createAudioHardware函數(shù)而已,
因此我們將frameworks/base/libs/audioflinger/AudioHardwareInterface.h文件復(fù)制到
vendor/ardent/merlin/libaudio目錄下,改名為AudioHardwareMerlin.h,然后將此文件中所有的Generic字段通通替換成Merlin
然后將frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp復(fù)制到
vendor/ardent/merlin/libaudio目錄下,改名為AudioHardwareMerlin.cpp,然后將此文件中所有的Generic字段通通替換成Merlin
最后在AudioHardwareMerlin.cpp中定義createAudioHardware函數(shù)如下:
extern "C" AudioHardwareInterface* createAudioHardware(void)
{
return new AudioHardwareMerlin();
}
8,進(jìn)行到7后直接編譯,發(fā)現(xiàn)編譯不過(guò),錯(cuò)誤如下
target thumb C++: libaudioflinger <= frameworks/base/libs/audioflinger/AudioFlinger.cpp
make: *** 沒(méi)有規(guī)則可以創(chuàng)建“out/target/product/merlin/obj/SHARED_LIBRARIES/libaudioflinger_intermediates/LINKED/libaudioflinger.so”需要的目標(biāo)“out/target/product/merlin/obj/lib/libaudiopolicy.so”。 停止。
原來(lái)是編譯audioflinger的時(shí)候需要libaudiopolicy.so的支持
查看frameworks/base/libs/audioflinger/Android.mk文件,發(fā)現(xiàn)有如下內(nèi)容:
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
LOCAL_CFLAGS += -DGENERIC_AUDIO
else
LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
endif
看來(lái)generic audio的時(shí)候需要的是libaudiointerface和libaudiopolicybase靜態(tài)庫(kù),否則需要libaudio和libaudiopolicy動(dòng)態(tài)庫(kù)
libaudio庫(kù)上面我們已經(jīng)實(shí)現(xiàn),看來(lái)下面的內(nèi)容就是要實(shí)現(xiàn)libaudiopolicy庫(kù)了
9,audio policy接口的調(diào)用在frameworks/base/libs/audioflinger/AudioPolicyService.cpp文件中的AudioPolicyService類
的構(gòu)造函數(shù)中,如下:
#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
mpPolicyManager = new AudioPolicyManagerBase(this);
LOGV("build for GENERIC_AUDIO - using generic audio policy");
#else
// if running in emulation - use the emulator driver
if (property_get("ro.kernel.qemu", value, 0)) {
LOGV("Running in emulation - using generic audio policy");
mpPolicyManager = new AudioPolicyManagerBase(this);
}
else {
LOGV("Using hardware specific audio policy");
mpPolicyManager = createAudioPolicyManager(this);
}
#endif
該目錄下的AudioPolicyService.h文件中定義了mpPolicyManager如下:
AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager
可見(jiàn),當(dāng)系統(tǒng)為generic audio或者運(yùn)行在模擬器上時(shí),mpPolicyManager是一個(gè)指向AudioPolicyManagerBase對(duì)象的指針
否則就要通過(guò)createAudioPolicyManager函數(shù)來(lái)返回。
AudioPolicyInterface類和AudioPolicyManagerBase類聲明在hardware/libhardware_legacy/include/hardware_legacy
目錄下的AudioPolicyInterface.h和AudioPolicyManagerBase.h文件中,而且AudioPolicyManagerBase類是AudioPolicyInterface
的子類。
10,實(shí)現(xiàn)libaudiopolicy庫(kù)
libaudiopolicy庫(kù)的實(shí)現(xiàn)我們也可以模仿generic audio的實(shí)現(xiàn)方式,從8我們可以看出,generic audio的時(shí)候audiopolicy用的是
靜態(tài)的libaudiopolicybase庫(kù),從frameworks/base/libs/audioflinger/Android.mk文件可以找到該靜態(tài)庫(kù)的編譯內(nèi)容如下:
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
AudioPolicyManagerBase.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libmedia
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -ldl
else
LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_MODULE:= libaudiopolicybase
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_CFLAGS += -DWITH_A2DP
endif
ifeq ($(AUDIO_POLICY_TEST),true)
LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
endif
include $(BUILD_STATIC_LIBRARY)
由此可見(jiàn),libaudiopolicybase靜態(tài)庫(kù)編譯的就是frameworks/base/libs/audioflinger/AudioPolicyManagerBase.cpp文件
11,通過(guò)9和10的分析,結(jié)合libaudio庫(kù)的寫(xiě)法,要完成libaudiopolicy庫(kù),我們可以將AudioPolicyManagerBase.cpp
和AudioPolicyManagerBase.h復(fù)制到vendor/ardent/merlin/libaudio目錄下,然后將這兩個(gè)文件名改成和其中的內(nèi)容作
一定修改,讓它變成兩外一個(gè)類如AudioPolicyManagerMerlin類的定義,然后在cpp文件中定義接口函數(shù)createAudioPolicyManager如下:
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManagerMerlin(clientInterface);
}
然后再修改相關(guān)Mdroid.mk文件編譯成libaudiopolicy.so即可
采用這種方法可以實(shí)現(xiàn),但是卻不必要,因?yàn)間eneric audio所用的AudioPolicyManagerBase已經(jīng)非常完善,所以我們只需要直接繼承這個(gè)類即可
下面來(lái)實(shí)現(xiàn)它。
12,在vendor/ardent/merlin/libaudio目錄下創(chuàng)建一個(gè)AudioPolicyManagerMerlin.h文件,內(nèi)容如下:
#include <stdint.h>
#include <sys/types.h>
#include <utils/Timers.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <hardware_legacy/AudioPolicyManagerBase.h>
namespace android {
class AudioPolicyManagerMerlin: public AudioPolicyManagerBase
{
public:
AudioPolicyManagerMerlin(AudioPolicyClientInterface *clientInterface)
: AudioPolicyManagerBase(clientInterface) {}
virtual ~AudioPolicyManagerMerlin() {}
};
};
主要是聲明我們所用的AudioPolicyManagerMerlin,通過(guò)直接繼承g(shù)eneric audio所用AudioPolicyManagerBase類來(lái)實(shí)現(xiàn)
13,在vendor/ardent/merlin/libaudio目錄下創(chuàng)建一個(gè)AudioPolicyManagerMerlin.cpp文件,內(nèi)容如下:
#include "AudioPolicyManagerMerlin.h"
#include <media/mediarecorder.h>
namespace android {
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManagerMerlin(clientInterface);
}
}; // namespace android
主要就是定義了接口函數(shù)createAudioPolicyManager
14,修改vendor/ardent/merlin/libaudio/Mdroid.mk函數(shù),添加libaudiopolicy的編譯如下:
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
AudioPolicyManagerMerlin.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libmedia
LOCAL_STATIC_LIBRARIES += libaudiopolicybase
LOCAL_MODULE:= libaudiopolicy
include $(BUILD_SHARED_LIBRARY)
經(jīng)過(guò)以上過(guò)程再修改一些小錯(cuò)誤,基本上就能編譯通過(guò),聲音的框架也已經(jīng)起來(lái)了,但是系統(tǒng)還是沒(méi)喲聲音,因?yàn)檫€需要進(jìn)一步的工作,
下一節(jié)繼續(xù)。