Android系统开发编译环境配置 (感觉好经典的系列)(其四)

Ubuntu svn 安装和使用

第一步:安装软件。
安装客户端
sudo apt-get install subversion
安装服务器端
sudo apt-get install libapache2-svn


2 svn
的基本操作
(1)
从服务器上下载代码:svn checkout
举例:
svn checkout svn://192.168.6.10/project/Source_code/trunk/src
svn checkout
可以所写成svn co

(2)
添加新的文件或者文件夹到本地版本控制中
svn add 
文件()
如果指定的是一个文件夹,则会将文件夹的所有内容都添加进来,如果你只想要添加文件夹而不是文件夹里面的内容,则用如下参数
svn add --non-recursive 
目录名

(3)
提交本地更改到服务器
svn commit -m "
说明信息" [-N] [--no-unlock] [文件()]
文件()不填写则代码提交当前目录下(包含子目录)的所有更改
举例:
svn commit -m "modify some code"

(4)
显示本地修改状态
svn status [path]
缩写成svn st [path]
path
为空则代码显示当前目录下的所有修改文件(递归到子目录)的状态,状态显示如下:
不在svn控制中
内容被修改
发生冲突
预定加入到版本库中
被锁定
举例:svn st

(5)
显示指定目录下所有文件(递归到子目录)的状态
svn status -v [path] 
缩写成svn st -v [path]

(6)
同步服务器代码到本地仓库
svn up

(7)
显示指定目录下的文件和目录
svn list [path]
缩写成svn ls [path]

(8)
恢复本地修改(撤销指定目录下的未提交的所有修改)
svn revert path [--depth infinity]

(9)
删除文件()
svn delete 
文件()


3 svn
的配置文件
修改/root/.subversion目录下的config文件。
比如说修改svn所控制的文件类型,则可以修改config文件中的global-ignores参数,这个参数是指定了svn版本控制忽略的
文件类型,举例如下:
global-ignores = *.o *.lo *.la *.al .[0-9]* *.a *.pyc *.pyo

android系统开发()-HAL层开发基础


Android HAL层,即硬件抽象层,是Google响应厂家“希望不公开源码”的要求推出的新概念

1,源代码和目标位置

源代码: /hardware/libhardware目录,该目录的目录结构如下:

/hardware/libhardware/hardware.c编译成libhardware.so,目标位置为/system/lib目录

/hardware/libhardware/include/hardware目录下包含如下头文件:

hardware.h 通用硬件模块头文件

copybit.h copybit模块头文件

gralloc.h gralloc模块头文件

lights.h 背光模块头文件

overlay.h overlay模块头文件

qemud.h qemud模块头文件

sensors.h 传感器模块头文件

/hardware/libhardware/modules目录下定义了很多硬件模块

这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录


2HAL层的实现方式

JNI->通用硬件模块->硬件模块->内核驱动接口

具体一点:JNI->libhardware.so->xxx.xxx.so->kernel

具体来说:android frameworksJNI调用/hardware/libhardware/hardware.c中定义的hw_get_module函数来获取硬件模块,

然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能


3,通用硬件模块(libhardware.so)

(1)头文件为:/hardware/libhardware/include/hardware/hardware.h

头文件中主要定义了通用硬件模块结构体hw_module_t,声明了JNI调用的接口函数hw_get_module

hw_module_t定义如下:

typedef struct hw_module_t {

/** tag must be initialized to HARDWARE_MODULE_TAG */

uint32_t tag;


/** major version number for the module */

uint16_t version_major;


/** minor version number of the module */

uint16_t version_minor;


/** Identifier of module */

const char *id;


/** Name of this module */

const char *name;


/** Author/owner/implementor of the module */

const char *author;


/** Modules methods */

struct hw_module_methods_t* methods; //硬件模块的方法


/** module's dso */

void* dso;


/** padding to 128 bytes, reserved for future use */

uint32_t reserved[32-7];


} hw_module_t;

硬件模块方法结构体hw_module_methods_t定义如下:

typedef struct hw_module_methods_t {

/** Open a specific device */

int (*open)(const struct hw_module_t* module, const char* id,

struct hw_device_t** device);


} hw_module_methods_t;

只定义了一个open方法,其中调用的设备结构体参数hw_device_t定义如下:

typedef struct hw_device_t {

/** tag must be initialized to HARDWARE_DEVICE_TAG */

uint32_t tag;


/** version number for hw_device_t */

uint32_t version;


/** reference to the module this device belongs to */

struct hw_module_t* module;


/** padding reserved for future use */

uint32_t reserved[12];


/** Close this device */

int (*close)(struct hw_device_t* device);


} hw_device_t;

hw_get_module函数声明如下:

int hw_get_module(const char *id, const struct hw_module_t **module);

参数id为模块标识,定义在/hardware/libhardware/include/hardware目录下的硬件模块头文件中,

参数module是硬件模块地址,定义了/hardware/libhardware/include/hardware/hardware.h


(2)hardware.c中主要是定义了hw_get_module函数如下:

#define HAL_LIBRARY_PATH "/system/lib/hw"

static const char *variant_keys[] = {

"ro.hardware",

"ro.product.board",

"ro.board.platform",

"ro.arch"

};

static const int HAL_VARIANT_KEYS_COUNT =

(sizeof(variant_keys)/sizeof(variant_keys[0]));


int hw_get_module(const char *id, const struct hw_module_t **module)

{

int status;

int i;

const struct hw_module_t *hmi = NULL;

char prop[PATH_MAX];

char path[PATH_MAX];

for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++)

{

if (i < HAL_VARIANT_KEYS_COUNT)

{

if (property_get(variant_keys[i], prop, NULL) == 0)

{

continue;

}

snprintf(path, sizeof(path), "%s/%s.%s.so",

HAL_LIBRARY_PATH, id, prop);

}

else

{

snprintf(path, sizeof(path), "%s/%s.default.so",

HAL_LIBRARY_PATH, id);

}

if (access(path, R_OK))

{

continue;

}

/* we found a library matching this id/variant */

break;

}


status = -ENOENT;

if (i < HAL_VARIANT_KEYS_COUNT+1) {

/* load the module, if this fails, we're doomed, and we should not try

* to load a different variant. */

status = load(id, path, module);

}


return status;

}

从源代码我们可以看出,hw_get_module完成的主要工作是根据模块id寻找硬件模块动态连接库地址,然后调用load函数去打开动态连接库

并从动态链接库中获取硬件模块结构体地址。硬件模块路径格式如下:

HAL_LIBRARY_PATH/id.prop.so

HAL_LIBRARY_PATH定义为/system/lib/hw

idhw_get_module函数的第一个参数所传入,prop部分首先按照variant_keys数组中的名称逐一调用property_get获取对应的系统属性,

然后访问HAL_LIBRARY_PATH/id.prop.so,如果找到能访问的就结束,否则就访问HAL_LIBRARY_PATH/id.default.so

举例如下:

假定访问的是背光模块,id定义为"lights"则系统会按照如下的顺序去访问文件:

/system/lib/hw/lights.[ro.hardware属性值].so

/system/lib/hw/lights.[ro.product.board属性值].so

/system/lib/hw/lights.[ro.board.platform属性值].so

/system/lib/hw/lights.[ro.arch属性值].so

/system/lib/hw/lights.default.so

所以开发硬件模块的时候Makefile文件(Android.mk)中模块的命名LOCAL_MODULE要参考上面的内容,否则就会访问不到没作用了。


load函数的关键部分代码如下:

handle = dlopen(path, RTLD_NOW); //打开动态链接库

if (handle == NULL) {

char const *err_str = dlerror();

LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");

status = -EINVAL;

goto done;

}


const char *sym = HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym); //从动态链接库中获取硬件模块结构体的指针

if (hmi == NULL) {

LOGE("load: couldn't find symbol %s", sym);

status = -EINVAL;

goto done;

}

HAL_MODULE_INFO_SYM_AS_STR是硬件模块在动态链接库中的标志,定义在hardware.h中如下:

#define HAL_MODULE_INFO_SYM HMI

#define HAL_MODULE_INFO_SYM_AS_STR "HMI"


4,硬件模块

硬件模块的开发主要是完成/hardware/libhardware/include/hardware目录下对应的头文件中的内容,主要是硬件模块头文件和hardware.h

的结构体中定义了一些函数指针,调用内核提供的接口将具体的函数实现,然后编译成指定名称的动态链接库放到/system/lib/hw目录下即可。

用一句话来概括:硬件模块的开发就是定义一个hardware.h中定义的hw_module_t结构体,结构体名称为宏HAL_MODULE_INFO_SYM,然后实现结构体

的相关内容即可。


5,内核驱动

主要是要向用户层开放接口,让硬件模块和内核可以交互。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/22/6026585.aspx


android 系统开发 ( )- 背光模块

1,总论

背光模块属于HAL层开发,HAL层开发,用一句话来概括就是定义一个hardware.h中定义的名称为宏HAL_MODULE_INFO_SYMhw_module_t结构体,

然后实现结构体的相关内容


2,驱动方面的准备

简单的嵌入式linux驱动,编写LCD背光驱动,并提供接口给上层修改,我所用的是直接修改接口文件,接口如下:

/sys/class/backlight/pwm-backlight/brightness 这个是亮度调节

/sys/class/backlight/pwm-backlight/max_brightness 这个是最大亮度,按照android系统的要求应该设置成255

控制亮度直接写brightness文件即可

背光驱动主要是通过PWM来完成,这里不详细说明。


3,需要包含的头文件

/hardware/libhardware/include/hardware目录下的hardware.hlights.h

其中hardware.h中定义了通用硬件模块,lights.h中定义了背光设备相关的内容


4,android已有的硬件模块在/hardware/libhardware/modules目录下,为了区分,我们开发的背光模块放置在如下的目录:

vendor/ardent/merlin/lights目录下,编译成lights.default.so放置到/system/lib/hw目录下,模块命名规则可以

参考上一节的内容。


5,修改vendor/ardent/merlin目录下AndroidBoard.mk文件,添加如下内容:

include $(LOCAL_PATH)/lights/Mdroid.mk


6,lights目录新建Mdroid.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)


LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw

LOCAL_SRC_FILES:= lights.c


LOCAL_SHARED_LIBRARIES := \

libutils \

libcutils \

libhardware


LOCAL_PRELINK_MODULE := false


LOCAL_MODULE := lights.default


include $(BUILD_SHARED_LIBRARY)


7,lights目录下新建一个lights.c文件,如下:

const struct hw_module_t HAL_MODULE_INFO_SYM = {

.tag = HARDWARE_MODULE_TAG,

.version_major = 1,

.version_minor = 0,

.id = LIGHTS_HARDWARE_MODULE_ID,

.name = "lights module",

.author = "allen",

.methods = NULL,

};


8,上面的内容可以直接编译通过,但是因为我将其methods部分指向了空指针,因此没有任何功能,下面来实现此部分

hw_module_t机构体的methods成员是一个指向hw_module_methods_t结构体的一个指针,hw_module_methods_t结构体定义如下:

typedef struct hw_module_methods_t {

int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);

} hw_module_methods_t;

据此我们定义一个hw_module_methods_t类型的参数lights_module_methods如下:

struct hw_module_methods_t lights_module_methods = {

.open = lights_device_open

};

然后将上面的methodsNULL改成lights_module_methods


9,接下来就是定义lights_device_open函数了,此函数的参数和返回值由hw_module_methods_t结构体的open成员决定,此函数定义如下:

static int lights_device_open(const struct hw_module_t *module,const char *id, struct hw_device_t **device)

lights_device_open函数的参数来看,第一个参数和第二个参数是常量,第三个参数是 一个指向hw_device_t结构体的指针,因此可以断定

实现此函数也就是要完成第三个参数的内容,详细的内容我们可以参考直接调用该函数的内容,在frameworks/base/services/jni目录下的

com_android_server_LightsService.cpp文件中,内容如下:

static light_device_t* get_device(hw_module_t* module, char const* name)

{

int err;

hw_device_t* device;

err = module->methods->open(module, name, &device);

if (err == 0) {

return (light_device_t*)device;//devicehw_device_t指针强制转换成light_device_t指针

} else {

return NULL;

}

}


static jint init_native(JNIEnv *env, jobject clazz)

{

int err;

hw_module_t* module;

Devices* devices;

devices = (Devices*)malloc(sizeof(Devices));


err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);

if (err == 0) {

devices->lights[LIGHT_INDEX_BACKLIGHT]

= get_device(module, LIGHT_ID_BACKLIGHT);

devices->lights[LIGHT_INDEX_KEYBOARD]

= get_device(module, LIGHT_ID_KEYBOARD);

devices->lights[LIGHT_INDEX_BUTTONS]

= get_device(module, LIGHT_ID_BUTTONS);

devices->lights[LIGHT_INDEX_BATTERY]

= get_device(module, LIGHT_ID_BATTERY);

devices->lights[LIGHT_INDEX_NOTIFICATIONS]

= get_device(module, LIGHT_ID_NOTIFICATIONS);

devices->lights[LIGHT_INDEX_ATTENTION]

= get_device(module, LIGHT_ID_ATTENTION);

devices->lights[LIGHT_INDEX_BLUETOOTH]

= get_device(module, LIGHT_ID_BLUETOOTH);

devices->lights[LIGHT_INDEX_WIFI]

= get_device(module, LIGHT_ID_WIFI);

} else {

memset(devices, 0, sizeof(Devices));

}


return (jint)devices;

}

从上面的内容我们可以看出lights_device_open的第一个参数是JNI层用hw_get_module所获得,第二个参数根据设备的不同有很多种情况

该参数的内容定义在lights.h中,全部情况如下:

#define LIGHT_ID_BACKLIGHT "backlight"

#define LIGHT_ID_KEYBOARD "keyboard"

#define LIGHT_ID_BUTTONS "buttons"

#define LIGHT_ID_BATTERY "battery"

#define LIGHT_ID_NOTIFICATIONS "notifications"

#define LIGHT_ID_ATTENTION "attention"

#define LIGHT_ID_BLUETOOTH "bluetooth"

#define LIGHT_ID_WIFI "wifi"

lights调节有背光,键盘,按键,电池,通知,提醒,蓝牙和WIF

第三个参数是一个指向一个hw_device_t的指针,但是com_android_server_LightsService.cpp文件中的背光调节函数定义如下:

static void setLight_native(JNIEnv *env, jobject clazz, int ptr,

int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)

{

Devices* devices = (Devices*)ptr;

light_state_t state;


if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {

return ;

}


memset(&state, 0, sizeof(light_state_t));

state.color = colorARGB;

state.flashMode = flashMode;

state.flashOnMS = onMS;

state.flashOffMS = offMS;

state.brightnessMode = brightnessMode;


devices->lights[light]->set_light(devices->lights[light], &state);

}

get_device函数中将hw_device_t指针强制转换成light_device_t指针给调节背光用,而light_device_t定义如下:

struct light_device_t {

struct hw_device_t common;

int (*set_light)(struct light_device_t* dev,

struct light_state_t const* state);

};

因此在实现lights_device_open的第三个参数的时候,我们应该定义一个light_device_t类型结构体,然后

将起common域的指针地址传递过去。这样虽然传递的是一个hw_device_t指针地址,但是JNI层可以将其强制转换

light_device_t指针地址用,否则devices->lights[light]->set_light就会起不到作用了。实现如下:

static int lights_device_open(const struct hw_module_t *module,const char *id, struct hw_device_t **device)

{

struct light_device_t *dev = NULL;

int resvalue = -1;

dev = calloc(sizeof(struct light_device_t),1);

dev->common.tag = HARDWARE_DEVICE_TAG;

dev->common.version = 0;

dev->common.module = (struct hw_module_t *)module;

dev->common.close = lights_device_close;

if(!strcmp(id, LIGHT_ID_BACKLIGHT))

{

dev->set_light = lcd_set_light;

resvalue = 0;

}

else

{

dev->set_light = other_set_light;

resvalue = 0;

}

*device = &dev->common;

return resvalue;

}


10,实现lights_device_closelcd_set_lightother_set_light,这个主要是调用驱动提供的接口直接控制硬件,举例如下:

static int lights_device_close(struct hw_device_t* device)

{

struct light_device_t *m_device = (struct light_device_t *)device;

if(m_device)

free(m_device);

return 0;

}

static int lcd_set_light(struct light_device_t* dev,struct light_state_t const* state)

{

int fd = -1;

int bytes = 0;

int rlt = -1;

unsigned char brightness = ((77*((state->color>>16)&0x00ff))

+ (150*((state->color>>8)&0x00ff))

+ (29*(state->color&0x00ff))) >> 8;

fd = open("/sys/class/backlight/pwm-backlight/brightness", O_RDWR);

if(fd>0)

{

char buffer[20];

memset(buffer, 0, 20);

bytes = sprintf(buffer, "%d", brightness);

rlt = write(fd, buffer, bytes);

if(rlt>0)

{

close(fd);

return 0;

}

}

close(fd);

return -1;

}


static int other_set_light(struct light_device_t* dev,struct light_state_t const* state)

{

return 0;

}


11,因为上面调节背光是通过写/sys/class/backlight/pwm-backlight/brightness文件来完成,因此一定要设置该文件的权限,

init.xxx.rc文件中添加如下的内容:

# for control LCD backlight

chown system system /sys/class/backlight/pwm-backlight/brightness

chmod 0666 /sys/class/backlight/pwm-backlight/brightness


12,修改完成后经验证亮度调节可用,上面的例子只是实现了lights部分功能,如果需要完成所有的功能,请参考hardware.h, lights.hcom_android_server_LightsService.cpp文件中的内容。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/23/6030405.aspx


android 系统开发 ( )-SDCARD

关于android系统开发sdcard移植,主要有如下工作:

1,内核驱动开发,完成后每次插入和拔出sdcard系统都会有相关的信息显示,而且sdcard可以手动挂载。


2androidsdcard挂载主要是vold来完成,vold的源代码在/system/vold目录下,编译成/system/bin/vold

init.rc文件中有vold系统服务,确保android系统开机后vold有正常运行。


3,添加vold的配置文件,先查看/system/bin/vold/main.cpp文件中的process_config函数,发现配置文件路径如下:

/etc/vold.fstab

android2.2/etc目录指向了/system/etc目录,因此我们要新建一个vold.fstab文件,目标路径为/system/etc/vold.fstab


4,vold.fstab文件的写法,参考/system/core/rootdir/etc目录下的vold.fstab,里面有详细的说明和例子,写法如下:

dev_mount <label> <mount_point> <part> <sysfs_path1...>

dev_mount命令 标签 挂载点 子分区 设备在sysfs文件系统下的路径(可多个)

按照上面的要求和我的平台的实际情况,在vold.fstab中添加如下内容:

dev_mount sdcard /mnt/sdcard auto /block/mmcblk0

上面的/block/mmcblk0表示sysfs下的路径,由于linuxsysfs文件系统是在sys目录下,所以对应到/sys/block/mmcblk0目录


5,完成后发现android系统中sdcard可用了,总结下载,sdcard部分很简单,主要是找到sdcard设备对应的sysfs文件系统路径



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/25/6035369.aspx


android 系统开发 ( )-Audio 部分准备工作 alsa 移植

1,audio内核部分的开发,包含codec驱动,cpu的声音驱动和内核alsa驱动等,

这个是完全的嵌入式linux的开发内容,这里跳过,请确保这几部分正确。


2,alsa的官方网站下载最新的alsa-lib-1.0.23alsa-utils-1.0.23

官方网站:http://www.alsa-project.org

alsa-lib基于内核alsa驱动,它将对内核alsa接口的操作封装成libasound

alsa-utils是一个工具包,基于alsa-lib来控制底层alsa驱动,包含aplay/amixer/control等工具

alsa的系统架构如下:

alsa应用

|

alsa-utils

|

alsa-lib

|

alsa-driver

alsa-driver已经集成在linux内核中,alsa应用直接调用alsa-utils工具包的工具来控制底层驱动以操作声卡


3,vendor/ardent/merlin目录下新建一个alsa目录,然后将下载的alsa-lib-1.0.23alsa-utils-1.0.23

解压缩到alsa目录下,将解压缩后的文件夹去掉版本号改成alsa-libalsa-utils


4,vendor/ardent/merlin/AndroidBoard.mk文件中加入如下内容:

L_PATH := $(LOCAL_PATH)

include $(L_PATH)/alsa/Mdroid.mk


5,vendor/ardent/merlin/alsa目录下新建Mdroid.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

ALSA_PATH := $(LOCAL_PATH)

include $(ALSA_PATH)/alsa-lib/Mdroid.mk

include $(ALSA_PATH)/alsa-utils/Mdroid.mk


6,vendor/ardent/merlin/alsa/alsa-lib目录下新建Mdroid.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/src/Mdroid.mk


7,vendor/ardent/merlin/alsa/alsa-lib/src目录下新建Mdroid.mk文件,内容在文章后面。



注:alsa-lib中编译的内容很多,我们可以先将alsa-lib当成普通的linux库来编译,编译完成后通过查找lo文件的方法

看那些文件被编译到了,同而找到需要编译的c文件,通过make install到指定目录找到需要复制的库和其它文件。代码中

的很多部分是不需要用到了,目前暂时未作详细处理,alsa-lib/modules/mixer/simple目录下的内容编译成了另外的几个

动态库(smixer-ac97,smixer-hda.so,smixer-sbase.so),alsa-lib/aserver目录下的内容编译成aserver,

这两部分因为不会用到,所以未加入到android编译系统中。


8,找个目录将alsa-lib当成普通的linux库编译一次,在include目录下会生成config.h文件,将该文件复制到

vendor/ardent/merlin/alsa/alsa-lib/include目录下并修改config.h的部分内容如下:

#define ALOAD_DEVICE_DIRECTORY "/dev/snd"

#define ALSA_CONFIG_DIR "/etc"

#define ALSA_DEVICE_DIRECTORY "/dev/snd/"

//#define HAVE_WORDEXP_H 1

//#define VERSIONED_SYMBOLS


9,修改alsa-lib/include/global.h文件,删除如下内容:

#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)

struct timeval {

time_t tv_sec; /* seconds */

long tv_usec; /* microseconds */

};


struct timespec {

time_t tv_sec; /* seconds */

long tv_nsec; /* nanoseconds */

};

#endif


10,将源代码中所有的

#include <sys/shm.h>

改成

#include <linux/shm.h>

类似

#include <sys/sem.h>

改成

#include <linux/sem.h>


11,修改alsa-lib/src/alisp/alisp.c,在obj_type_str函数最后面位置加上如下内容:

return NULL;


12,alsa-lib当普通linux库编译时alsa-lib/src/control目录下生成的ctl_symbols_list.c文件和

alsa-lib/src/pcm目录下生成的pcm_symbols_list.c文件复制到androidalsa-lib对应位置。


13,修改alsa-lib/src/pcm/pcm_direct.c文件,删除如下内容:

union semun {

int val; /* Value for SETVAL */

struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */

unsigned short *array; /* Array for GETALL, SETALL */

struct seminfo *__buf; /* Buffer for IPC_INFO (Linux specific) */

};


14,查找alsa-lib源代码所有文件,确保

#include <linux/shm.h>的前面有

#include <stdlib.h>

没有的自己加上,否则会报告错误说size_t未定义


15,修改alsa-lib/src/pcm/pcm_ladspa.c文件,将

*strrchr (labellocale, '.') = *lc->decimal_point;

改成

*strrchr (labellocale, '.') = ".";

屏蔽掉如下内容:

//lc = localeconv ();

这个是因为android用的C库是bionic,和标准C库不同,对应的locale.h文件中的lconv结构体定义不同所导致。


16,修改alsa-lib/src/pcm/pcm_mmap.c文件中的snd_pcm_mmap函数,将switch (i->type)语句下SND_PCM_AREA_SHM分支的内容

屏蔽掉,同时修改该文件中snd_pcm_munmap函数,将switch (i->type)语句下的SND_PCM_AREA_SHM分支内容屏蔽掉。


17,搜索alsa-lib/src目录下的所有文件,搜索shmctlshmgetshmatshmdt4个函数的调用处,将调用到的地方删除。

这个主要是因为androidbionic libc库不支持System V IPC所导致,具体的可以从头文件中看出来。System V IPC通过共享

内存的方式来实现,GNU C库对应共享内存头文件为linux pc/usr/include/sys/shm.h文件,在此文件中,你可以看到

shmctlshmgetshmatshmdt4个函数的声明,bionic libc库也有一个同样的头文件,在android源代码目录的

bionic/libc/kernel/common/linux目录下,但是文件中的内容却没有上面4个函数的声明。上面16所作的修改也是基于这个原因。


18,按照1617的结论,由于bionic libc所引发的System V IPC功能的缺失,导致alsa库中的相关功能不能正常实现,所以最好的

方法是将相关的部分不编译进来,以免找成不必要的错误。据此将一些文件从编译中删除,修改alsa-lib/src/Mdroid.mk文件即可

alsa-lib/src/control/control_shm.c

alsa-lib/src/pcm/pcm_direct.c

alsa-lib/src/pcm/pcm_dmix.c

alsa-lib/src/pcm/pcm_dshare.c

alsa-lib/src/pcm/pcm_dsnoop.c

alsa-lib/src/pcm/pcm_ladspa.c

alsa-lib/src/pcm/pcm_shm.c

alsa-lib/src/shmarea.c

删除了这几个模块后要将alsa-lib/src/control目录下的ctl_symbols_list.c文件和

alsa-lib/src/pcm目录下的pcm_symbols_list.c文件中的相关内容删除,否则会编译不过。


19,最后要实现的功能当然是复制alsa-lib的配置文件了,在alsa-lib/src/conf目录下,复制操作在alsa-lib/src/Mdroid.mk中实现,

最终的Mdroid.mk文件内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

async.c conf.c confmisc.c dlmisc.c error.c input.c \

names.c output.c socket.c userfile.c \

alisp/alisp.c \

control/cards.c control/control.c control/control_ext.c \

control/control_hw.c control/control_symbols.c \

control/hcontrol.c control/namehint.c control/setup.c control/tlv.c \

hwdep/hwdep.c hwdep/hwdep_hw.c hwdep/hwdep_symbols.c \

mixer/bag.c mixer/mixer.c mixer/simple.c mixer/simple_abst.c mixer/simple_none.c \

pcm/atomic.c pcm/interval.c pcm/mask.c pcm/pcm.c pcm/pcm_adpcm.c \

pcm/pcm_alaw.c pcm/pcm_asym.c pcm/pcm_copy.c pcm/pcm_empty.c \

pcm/pcm_extplug.c pcm/pcm_file.c pcm/pcm_generic.c pcm/pcm_hooks.c \

pcm/pcm_hw.c pcm/pcm_iec958.c pcm/pcm_ioplug.c \

pcm/pcm_lfloat.c pcm/pcm_linear.c pcm/pcm_meter.c pcm/pcm_misc.c \

pcm/pcm_mmap.c pcm/pcm_mmap_emul.c pcm/pcm_mulaw.c pcm/pcm_multi.c \

pcm/pcm_null.c pcm/pcm_params.c pcm/pcm_plug.c pcm/pcm_plugin.c \

pcm/pcm_rate.c pcm/pcm_rate_linear.c pcm/pcm_route.c pcm/pcm_share.c \

pcm/pcm_simple.c pcm/pcm_softvol.c pcm/pcm_symbols.c \

rawmidi/rawmidi.c rawmidi/rawmidi_hw.c rawmidi/rawmidi_symbols.c \

rawmidi/rawmidi_virt.c \

seq/seq.c seq/seq_event.c seq/seq_hw.c seq/seqmid.c \

seq/seq_midi_event.c seq/seq_old.c seq/seq_symbols.c \

timer/timer.c timer/timer_hw.c timer/timer_query.c \

timer/timer_query_hw.c timer/timer_symbols.c


LOCAL_C_INCLUDES += \

$(LOCAL_PATH)/../include


LOCAL_SHARED_LIBRARIES := libdl


LOCAL_ARM_MODE := arm


LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := libasound

include $(BUILD_SHARED_LIBRARY)


TARGET_ALSA_CONF_DIR := $(TARGET_OUT)/usr/share/alsa

LOCAL_ALSA_CONF_DIR := $(LOCAL_PATH)/conf


copy_from := \

alsa.conf \

pcm/dsnoop.conf \

pcm/modem.conf \

pcm/dpl.conf \

pcm/default.conf \

pcm/surround51.conf \

pcm/surround41.conf \

pcm/surround50.conf \

pcm/dmix.conf \

pcm/center_lfe.conf \

pcm/surround40.conf \

pcm/side.conf \

pcm/iec958.conf \

pcm/rear.conf \

pcm/surround71.conf \

pcm/front.conf \

cards/aliases.conf


copy_to := $(addprefix $(TARGET_ALSA_CONF_DIR)/,$(copy_from))

copy_from := $(addprefix $(LOCAL_ALSA_CONF_DIR)/,$(copy_from))


$(copy_to) : $(TARGET_ALSA_CONF_DIR)/% : $(LOCAL_ALSA_CONF_DIR)/% | $(ACP)

$(transform-prebuilt-to-target)


ALL_PREBUILT += $(copy_to)


20,alsa-utils的移植方法也类似,这里就不再介绍,上面的过程只是体验了一下android下开源库的移植方法,

实际上google服务器上已经有alsa的代码,直接下载下载便可用,下载方法如下:

git clone git://android.git.kernel.org/platform/external/alsa-lib.git

git clone git://android.git.kernel.org/platform/external/alsa-utils.git

将下载的alsa-libalsa-utils部分复制到vendor/ardent/merlin/alsa目录下参考上面的方法只需对以上

45部分稍作修改即可。



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/30/6045507.aspx


android 系统开发编译过程中的汇编错误

android系统开发移植alsa-lib库的过程中编译的时候出现了如下的错误:

错误1

/tmp/cckyaR40.s: Assembler messages:

/tmp/cckyaR40.s:2763: Error: selected processor does not support `mrs ip,cpsr'

/tmp/cckyaR40.s:2764: Error: unshifted register required -- `orr r2,ip,#128'

/tmp/cckyaR40.s:2765: Error: selected processor does not support `msr cpsr_c,r2'

/tmp/cckyaR40.s:2777: Error: selected processor does not support `msr cpsr_c,ip'

/tmp/cckyaR40.s:2945: Error: selected processor does not support `mrs r3,cpsr'

/tmp/cckyaR40.s:2946: Error: unshifted register required -- `orr r2,r3,#128'

/tmp/cckyaR40.s:2947: Error: selected processor does not support `msr cpsr_c,r2'

/tmp/cckyaR40.s:2959: Error: selected processor does not support `msr cpsr_c,r3'

/tmp/cckyaR40.s:3551: Error: selected processor does not support `mrs ip,cpsr'

/tmp/cckyaR40.s:3552: Error: unshifted register required -- `orr r1,ip,#128'

/tmp/cckyaR40.s:3553: Error: selected processor does not support `msr cpsr_c,r1'

/tmp/cckyaR40.s:3564: Error: selected processor does not support `msr cpsr_c,ip'

字面的意思报的是汇编错误,选择的处理器不支持mrsmsr指令。

原来的ARM指令有32位和16位两种指令模式,16位为thumb指令集,thumb指令集编译出的代码占用空间小,

而且效率也高,所以androidarm编译器默认用的是thumb模式编译,问题在于alsa的代码中有部分的内容

用到了32位的指令,所以才会报如下的错误,修改的方法也很简单,在Android.mk中加入如下内容即可:

LOCAL_ARM_MODE := arm

android的编译系统中LOCAL_ARM_MODE变量的取值为arm或者thumb,代表32位和16位两种arm指令集,

默认为thumb


错误2

target SharedLib: libasound (out/target/product/merlin/obj/SHARED_LIBRARIES/libasound_intermediates/LINKED/libasound.so)

/work/android-froyo-r3/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/bin/ld: out/target/product/merlin/obj/SHARED_LIBRARIES/libasound_intermediates/LINKED/libasound.so: version node not found for symbol snd_pcm_sw_params_get_start_threshold@ALSA_0.9

/work/android-froyo-r3/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/bin/ld: failed to set dynamic section sizes: Bad value

collect2: ld returned 1 exit status

make: *** [out/target/product/merlin/obj/SHARED_LIBRARIES/libasound_intermediates/LINKED/libasound.so] 错误 1

解决此问题将alsa-lib/include/config.h文件中的如下宏定义去掉即可:

#define VERSIONED_SYMBOLS



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/30/6045513.aspx


android 系统开发 ( )-audio 移植

1,移植基础:

(1)内核声音驱动和alsa驱动

(2)alsa-libalsa-utils库移植

这两部分上一节已经介绍过了。


2,androidaudio最核心的部分是audioflingeraudioflinger向上处理来自于应用程序的声音相关的所有请求

向下通过AudioHardwareInterface访问硬件,androidaudio架构如下所示:

Applications

|

Frameworks

|

JNI

|

AudioFlinger

|

AudioHardwareInterface

| | |

专有audio库 | alsa用户库

| |

/dev/eac /dev/snd/*

| |

内核eac驱动 内核alsa驱动

AudioHardwareInterfaceaudioflinger和硬件驱动之间的桥梁,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对象

的指针,因为AudioHardwareGenericAudioHardwareInterface的子类,继承关系如下:

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的时候需要的是libaudiointerfacelibaudiopolicybase静态库,否则需要libaudiolibaudiopolicy动态库

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.hAudioPolicyManagerBase.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,通过910的分析,结合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)

经过以上过程再修改一些小错误,基本上就能编译通过,声音的框架也已经起来了,但是系统还是没哟声音,因为还需要进一步的工作,

下一节继续。

android系统开发小知识-启动脚本文件内部的执行顺序

我们知道android在启动的时候通过init进程来解析init.rcinit.xxx.rc文件,

然后执行这两个文件解析出来的内容,init.rcinit.xxx.rc文件中的内容却并不是

按照顺序来执行的,而是有固定的执行顺序,首先,init.rcinit.xxx.rc文件中的内容

全部会放在4个关键字下:

early-init, init, early-boot, boot

所以一个典型的rc文件的写法如下:

on early-init

--------------


on init

--------------


on early-boot

--------------


on boot

--------------

rc文件中这4个部分是可以打乱顺序随便写的,甚至可以有多个部分出现,但是解析完了以后的执行

顺序确实固定的,执行顺序如下:

early-init -> init -> early-boot -> boot




本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/12/01/6047219.aspx

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值