1,移植基础:
(1)内核声音驱动和alsa驱动
(2)alsa-lib和alsa-utils库移植
这两部分上一节已经介绍过了。
2,android的audio最核心的部分是audioflinger,audioflinger向上处理来自于应用程序的声音相关的所有请求
向下通过AudioHardwareInterface访问硬件,android的audio架构如下所示:
Applications
|
Frameworks
|
JNI
|
AudioFlinger
|
AudioHardwareInterface
| | |
专有audio库 | alsa用户库
| |
/dev/eac /dev/snd/*
| |
内核eac驱动 内核alsa驱动
AudioHardwareInterface是audioflinger和硬件驱动之间的桥梁,android默认编译的是generic audio,此时
AudioHardwareInterface直接指向了/dev/eac驱动,它通过eac驱动来操作声卡,android audio移植就是要让
AudioHardwareInterface直接或者间接指向我们自己定义的声音驱动,一般都采用alsa声音体系,所以我们的目的就是
要让AudioHardwareInterface指向alsa用户库。下面的内容开始移植alsa-audio
3,修改vendor/ardent/merlin/BoardConfig.mk文件内容如下:
BOARD_USES_GENERIC_AUDIO := false
BOARD_USES_ALSA_AUDIO := true
BUILD_WITH_ALSA_UTILS := true
上面配置的目的就是为了让要让AudioHardwareInterface指向alsa用户库
4,下面来添加audio库的编译
在vendor/ardent/merlin目录下新建一个libaudio目录,修改AndroidBoard.mk文件,添加编译路径如下:
LOCAL_PATH := $(call my-dir)
L_PATH := $(LOCAL_PATH)
include $(L_PATH)/libaudio/Mdroid.mk
5,vendor/ardent/merlin/libaudio目录下新建一个Mdroid.mk文件,内容如下:
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的实现方法,我们现看看接口部分,上面有说道audioflinger是通过AudioHardwareInterface指向驱动的
AudioHardwareInterface类的代码在frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp文件中
该文件中的create函数中定义了AudioHardwareInterface指向驱动的代码如下:
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;
当系统为generic audio的时候此函数返回的是一个指向AudioHardwareGeneric对象的指针,其实是返回一个指向AudioHardwareInterface对象
的指针,因为AudioHardwareGeneric是AudioHardwareInterface的子类,继承关系如下:
AudioHardwareInterface->AudioHardwareBase->AudioHardwareGeneric
如果系统不是generic audio,则通过调用createAudioHardware函数来返回一个指向一个指向AudioHardwareInterface对象的指针,
所以,简单的将,我们要做的事情就是实现这个函数以及它相关的内容即可。createAudioHardware函数我们可以在
hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h中也就是AudioHardwareInterface
的声明中找到原型如下:
extern "C" AudioHardwareInterface* createAudioHardware(void);
7,通过6我们不难知道,我们实现自己的audio接口完全可以模仿generic audio的做法,只是要多实现一个createAudioHardware函数而已,
因此我们将frameworks/base/libs/audioflinger/AudioHardwareInterface.h文件复制到
vendor/ardent/merlin/libaudio目录下,改名为AudioHardwareMerlin.h,然后将此文件中所有的Generic字段通通替换成Merlin
然后将frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp复制到
vendor/ardent/merlin/libaudio目录下,改名为AudioHardwareMerlin.cpp,然后将此文件中所有的Generic字段通通替换成Merlin
最后在AudioHardwareMerlin.cpp中定义createAudioHardware函数如下:
extern "C" AudioHardwareInterface* createAudioHardware(void)
{
return new AudioHardwareMerlin();
}
8,进行到7后直接编译,发现编译不过,错误如下
target thumb C++: libaudioflinger <= frameworks/base/libs/audioflinger/AudioFlinger.cpp
make: *** 没有规则可以创建“out/target/product/merlin/obj/SHARED_LIBRARIES/libaudioflinger_intermediates/LINKED/libaudioflinger.so”需要的目标“out/target/product/merlin/obj/lib/libaudiopolicy.so”。 停止。
原来是编译audioflinger的时候需要libaudiopolicy.so的支持
查看frameworks/base/libs/audioflinger/Android.mk文件,发现有如下内容:
ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
LOCAL_CFLAGS += -DGENERIC_AUDIO
else
LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
endif
看来generic audio的时候需要的是libaudiointerface和libaudiopolicybase静态库,否则需要libaudio和libaudiopolicy动态库
libaudio库上面我们已经实现,看来下面的内容就是要实现libaudiopolicy库了
9,audio policy接口的调用在frameworks/base/libs/audioflinger/AudioPolicyService.cpp文件中的AudioPolicyService类
的构造函数中,如下:
#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
可见,当系统为generic audio或者运行在模拟器上时,mpPolicyManager是一个指向AudioPolicyManagerBase对象的指针
否则就要通过createAudioPolicyManager函数来返回。
AudioPolicyInterface类和AudioPolicyManagerBase类声明在hardware/libhardware_legacy/include/hardware_legacy
目录下的AudioPolicyInterface.h和AudioPolicyManagerBase.h文件中,而且AudioPolicyManagerBase类是AudioPolicyInterface
的子类。
10,实现libaudiopolicy库
libaudiopolicy库的实现我们也可以模仿generic audio的实现方式,从8我们可以看出,generic audio的时候audiopolicy用的是
静态的libaudiopolicybase库,从frameworks/base/libs/audioflinger/Android.mk文件可以找到该静态库的编译内容如下:
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)
由此可见,libaudiopolicybase静态库编译的就是frameworks/base/libs/audioflinger/AudioPolicyManagerBase.cpp文件
11,通过9和10的分析,结合libaudio库的写法,要完成libaudiopolicy库,我们可以将AudioPolicyManagerBase.cpp
和AudioPolicyManagerBase.h复制到vendor/ardent/merlin/libaudio目录下,然后将这两个文件名改成和其中的内容作
一定修改,让它变成两外一个类如AudioPolicyManagerMerlin类的定义,然后在cpp文件中定义接口函数createAudioPolicyManager如下:
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManagerMerlin(clientInterface);
}
然后再修改相关Mdroid.mk文件编译成libaudiopolicy.so即可
采用这种方法可以实现,但是却不必要,因为generic audio所用的AudioPolicyManagerBase已经非常完善,所以我们只需要直接继承这个类即可
下面来实现它。
12,在vendor/ardent/merlin/libaudio目录下创建一个AudioPolicyManagerMerlin.h文件,内容如下:
#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,通过直接继承generic audio所用AudioPolicyManagerBase类来实现
13,在vendor/ardent/merlin/libaudio目录下创建一个AudioPolicyManagerMerlin.cpp文件,内容如下:
#include "AudioPolicyManagerMerlin.h"
#include <media/mediarecorder.h>
namespace android {
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManagerMerlin(clientInterface);
}
}; // namespace android
主要就是定义了接口函数createAudioPolicyManager
14,修改vendor/ardent/merlin/libaudio/Mdroid.mk函数,添加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)
经过以上过程再修改一些小错误,基本上就能编译通过,声音的框架也已经起来了,但是系统还是没哟声音,因为还需要进一步的工作,
下一节继续。