//耳机判断
1. android系统启动完成会发送Intent.ACTION_BOOT_COMPLETED事件,我们在 base/services/java/com/android/server/WiredAccessoryObserver.java中可以看到类似代码
linux-3.0/drivers/switch/ switch_headset.c中会根据无耳机,三段耳机,四段耳机和四段耳机是否有hook键按下4个状态更新state的值为0 ,1, 2,3,并且切换机台
MIC和耳机
private static final String uEventInfo[][] = { {"DEVPATH=/devices/virtual/switch/h2w",
"/sys/class/switch/h2w/state",
"/sys/class/switch/h2w/name"},
{"DEVPATH=/devices/virtual/switch/usb_audio",
"/sys/class/switch/usb_audio/state",
"/sys/class/switch/usb_audio/name"},
{"DEVPATH=/devices/virtual/switch/hdmi",
"/sys/class/switch/hdmi/state",
"/sys/class/switch/hdmi/name"} };
大体流程是用定时器每200ms检查一次是否有耳机插入,如果有4段耳机,延时30ms检查hook key是否按下,这样,如果旧的state和新的state不相等,就用uevent上报状态改变
事件
可参考电路图P11的说明:
检测耳机插入:
1、0V-0.2V 则判定为3节耳机;
2、1V-2.5V 则判定为4节耳机;
3、检测为4接耳机后如果ADC再次检测为0V则认为HOOK见按下。
2. 在drivers/media/pa中的是提供借口给上层做外音和内音切换的,也就是如FM,播放器等都会检测耳机是否插入,以进行外音和内音切换,看看其中的代码:
pa_dev_class = class_create(THIS_MODULE, "pa_cls");//这一句运行后,会创建虚拟文件系统/sys/class/pa_cls
139 device_create(pa_dev_class, NULL,dev_num, NULL, "pa_dev");//这一句运行后,会创建节点/dev/pa_dev
141 printk("[pa_drv] init end!!!\n");
他对应的framework层代码在device/softwinner/common/hardware/audio/audio_hw.c中
而file_operations结构体和节点对应起来则是通过如下的关系,如touch中:
ret= register_chrdev(I2C_MAJOR,"aw_i2c_ts",&aw_i2c_ts_fops );//I2C_MAJOR是自己定义的主设备号
接着调用:device_create(i2c_dev_class, &client->adapter->dev, MKDEV(I2C_MAJOR,client->adapter->nr), NULL, "aw_i2c_ts%d", client->adapter->nr);这样
就关联起来了
3. 两种定时器的使用:
1. static struct hrtimer vibe_timer;
INIT_WORK(&vibrator_work, update_vibrator);
static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
{
schedule_work(&vibrator_work);
}
hrtimer_init(&vibe_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
vibe_timer.function = vibrator_timer_func;
这样在你想要启动定时器的函数中调用如下语句:
hrtimer_start(&vibe_timer,
ktime_set(value / 1000, (value % 1000) * 1000000), //ktime_set的第一个参数单位时秒,第二个单位是纳秒
HRTIMER_MODE_REL);
schedule_work(&vibrator_work);//hrtimer_start后调用一次schedule_work,时间到后,再调用一次schedule_work,这样在两次schedule_work中可以做如控制按键灯
亮灭等动作,具体例子可参考drivers/misc/sun4i-vibrator.c
这个定时器还提供了一些查询功能,如可以查询定时器当前是否激活的,定时器当前的剩余时间等,如下面的函数:
static int vibrator_get_time(struct timed_output_dev *dev)
{
struct timespec time_tmp;
if (hrtimer_active(&vibe_timer)) {//判断是否激活
ktime_t r = hrtimer_get_remaining(&vibe_timer);//取得定时器剩余时间
time_tmp = ktime_to_timespec(r);//时间单位转换,他和上面的ktime_set相当于相反过程的转换
//return r.tv.sec * 1000 + r.tv.nsec/1000000;
return time_tmp.tv_sec* 1000 + time_tmp.tv_nsec/1000000;//返回的单位是毫秒
} else
return 0;
}
2. struct timer_list timer;
static void earphone_hook_handle(unsigned long data)
{
mod_timer(&switch_data->timer, jiffies + msecs_to_jiffies(200));
}
init_timer(&timer);
timer.function = &earphone_hook_handle;
timer.data = (unsigned long)switch_data;
add_timer(&switch_data->timer);//这一句之后已经启动定时器了
4. 声卡的设备节点在/proc/asound/card0,创建过程为snd_card_create -> snd_ctl_create
创建sys节点snd_card_register-> device_create(sound_class, card->dev, MKDEV(0, 0), card, "card%i", card->number)
sound_class = class_create(THIS_MODULE, "sound");
sound_class->devnode = sound_devnode;
其中:
static char *sound_devnode(struct device *dev, mode_t *mode)
{
if (MAJOR(dev->devt) == SOUND_MAJOR)
return NULL;
return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
}
这样声卡的class出现在/class/sys/sound/中,sound_devnode就决定了设备节点出现在/dev/snd/中,用户空间操作的就是/dev/snd/中的设备节点。
接着调用snd_device_register_all函数注册前面挂接在card->device链表中的所有设备:
185 int snd_device_register_all(struct snd_card *card)
186 {
187 struct snd_device *dev;
188 int err;
189
190 if (snd_BUG_ON(!card))
191 return -ENXIO;
192 list_for_each_entry(dev, &card->devices, list) {
193 if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
194 if ((err = dev->ops->dev_register(dev)) < 0)
195 return err;
196 dev->state = SNDRV_DEV_REGISTERED;
197 }
198 }
199 return 0;
200 }
我们看看设备是如何挂在card->device链表中的:
snd_card_sun4i_codec_pcm -> snd_pcm_new -> snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)),其中ops结构体为:
720 static struct snd_device_ops ops = {
721 .dev_free = snd_pcm_dev_free,
722 .dev_register = snd_pcm_dev_register,
723 .dev_disconnect = snd_pcm_dev_disconnect,
724 };
snd_pcm_dev_register为:
976 static int snd_pcm_dev_register(struct snd_device *device)
977 {
978 int cidx, err;
979 struct snd_pcm_substream *substream;
980 struct snd_pcm_notify *notify;
981 char str[16];
982 struct snd_pcm *pcm;
983 struct device *dev;
984
985 if (snd_BUG_ON(!device || !device->device_data))
986 return -ENXIO;
987 pcm = device->device_data;
988 mutex_lock(®ister_mutex);
989 err = snd_pcm_add(pcm);
990 if (err) {
991 mutex_unlock(®ister_mutex);
992 return err;
993 }
994 for (cidx = 0; cidx < 2; cidx++) {
995 int devtype = -1;
996 if (pcm->streams[cidx].substream == NULL)
997 continue;
998 switch (cidx) {
999 case SNDRV_PCM_STREAM_PLAYBACK:
1000 sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);//这里就是设备节点的名字
1001 devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
1002 break;
1003 case SNDRV_PCM_STREAM_CAPTURE:
1004 sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);//这里就是设备节点的名字
1005 devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
1006 break;
1007 }
1008 /* device pointer to use, pcm->dev takes precedence if
1009 * it is assigned, otherwise fall back to card's device
1010 * if possible */
1011 dev = pcm->dev;
1012 if (!dev)
1013 dev = snd_card_get_device_link(pcm->card);
1014 /* register pcm */
1015 err = snd_register_device_for_dev(devtype, pcm->card,
1016 pcm->device,
1017 &snd_pcm_f_ops[cidx],
1018 pcm, str, dev);//在这个函数中,最终调用device_create(sound_class, device, MKDEV(major, minor),private_data,
//"%s", name);来创建设备
1019 if (err < 0) {
1020 list_del(&pcm->list);
1021 mutex_unlock(®ister_mutex);
1022 return err;
1023 }
1024 snd_add_device_sysfs_file(devtype, pcm->card, pcm->device,
1025 &pcm_attrs);
看看我的设备节点名称:
$ cd /dev/snd
$ ls -l
crw-rw----+ 1 root audio 116, 8 2011-02-23 21:38 controlC0
crw-rw----+ 1 root audio 116, 4 2011-02-23 21:38 midiC0D0
crw-rw----+ 1 root audio 116, 7 2011-02-23 21:39 pcmC0D0c
crw-rw----+ 1 root audio 116, 6 2011-02-23 21:56 pcmC0D0p
crw-rw----+ 1 root audio 116, 5 2011-02-23 21:38 pcmC0D1p
crw-rw----+ 1 root audio 116, 3 2011-02-23 21:38 seq
crw-rw----+ 1 root audio 116, 2 2011-02-23 21:38 timer
controlC0 --> 用于声卡的控制,例如通道选择,混音,麦克风的控制等
midiC0D0 --> 用于播放midi音频
pcmC0D0c --> 用于录音的pcm设备
pcmC0D0p --> 用于播放的pcm设备
seq --> 音序器
timer --> 定时器
其中,C0D0代表的是声卡0中的设备0,pcmC0D0c最后一个c代表capture,pcmC0D0p最后一个p代表playback,这些都是alsa-driver中的命名规则。从上面的列表可以看出,我
的声卡下挂了6个设备,根据声卡的实际能力,驱动实际上可以挂上更多种类的设备,在include/sound/core.h中,定义了以下设备类型,通常,我们更关心的是pcm和control
这两种设备。
对于sound/core/control.c文件
#ifdef CONFIG_COMPAT
#include "control_compat.c"
#else
#define snd_ctl_ioctl_compat NULL
#endif
下面的"controlC%i"声卡对应的控制节点fops的compat_ioctl,当没有定义CONFIG_COMPAT时,将被置为NULL
hal层的IOCTRL会对应KERNEL层的core/control.c文件
frameworks/base/services/java/com/android/server/WiredAccessoryObserver.java会监听耳机拔插事件
而打开hal层audio_hw.c的JNI层代码在frameworks/base/services/audioflinger/AudioFlinger.cpp中
audio_hw.c是按照hardware/libhardware/include/hardware/audio.h定义的接口实现就行了
5. getprop 命令可以查看系统属性状态
6.运行JAVA代码:
javac xxx.java(xxx为类的名字)
java xxx.class
7.编译时候提示,You have tried to change the API from what has been previously approved.
To make these errors go away, you have two choices:
1) You can add "@hide" javadoc comments to the methods, etc. listed in the
errors above.
2) You can update current.txt by executing the following command:
make update-api
To submit the revised current.txt to the main Android repository,
you will need approval.
******************************
如果你是想要让这个新增的API只能内部使用,则加上 /** {@hide} */,如我的代码:frameworks/base/core/java/android/os中新增了IHelloService.aidl这个服务,如下
为其中的内容:
1 package android.os;
2
3 /** {@hide} */
4 interface IHelloService {
5 void setVal(int val, String path);
6 int getVal(String path);
7 }
还有新增JNI层的一些用法:
66 {"init_native", "()Z", (void*)hello_init}, //无型参,Z表示返回值为boolean型
67 {"setVal_native", "(ILjava/lang/String;)V", (void*)hello_setVal},// I表示第一个型参为int,Ljava/lang/String表示第二个型参为String,
68 {"getVal_native", "(Ljava/lang/String;)I", (void*)hello_getVal},
由上面可以知道hello_setVal对应的HAL层原型为hello_setVal(int, char *), 在JNI中还要将String转换为char*才能使用,语法如下:
28 /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/
29 static jint hello_getVal(JNIEnv* env, jobject clazz, jstring path) {
30 const char *extraInfoStr = env->GetStringUTFChars(path, NULL);//将String转换为char*
31 int val = 0;
32 if(!hello_device) {
33 LOGI("Hello JNI: device is not open.");
34 return val;
35 }
36 hello_device->get_val(hello_device, &val, extraInfoStr);
37
38 LOGI("Hello JNI: get value %d from device.", val);
39 env->ReleaseStringUTFChars(path, extraInfoStr);//用完后要释放
40
41 return val;
42 }
8. 系统build.prop文件属性的读取文件在base/core/java/android/os/SystemProperties.java,属性接口在frameworks/base/core/java/android/os/Build.java中
9.A10申请外部中断的步骤:
中断号的定义在drivers/input/touchscreen/ctp_platform_ops.h中:
#define PIO_BASE_ADDRESS (0xf1c20800)//这是外部所有IO口中断的入口
#define PIOA_CFG1_REG (PIO_BASE_ADDRESS+0x4)
#define PIOA_DATA (PIO_BASE_ADDRESS+0x10)
#define DELAY_PERIOD (5)
#define SW_INT_IRQNO_PIO 28
#define PIO_INT_STAT_OFFSET (0x214)
#define CTP_IRQ_NO (IRQ_EINT21)
309 static int ctp_judge_int_occur(void)
310 {
311 //int reg_val[3];
312 int reg_val;
313 int ret = -1;
314
315 reg_val = readl(gpio_addr + PIO_INT_STAT_OFFSET);//偏移PIO_INT_STAT_OFFSET处的地址就是外部IO口中断的状态寄存器
316 if(reg_val&(1<<(CTP_IRQ_NO))){//CTP_IRQ_NO=IRQ_EINT21,就是TP的中断脚EINT21,配置脚本中有 ctp_int_port = port:PH21<6><default>
317 ret = 0;
318 }
319 return ret;
320 }
1681 static irqreturn_t ft5x_ts_interrupt(int irq, void *dev_id)
1682 {
1683 struct ft5x_ts_data *ft5x_ts = dev_id;
1684
1685 // print_int_info("==========------ft5x_ts TS Interrupt-----============\n");
1686 if(!ctp_ops.judge_int_occur()){ //要判断是外部哪一个IO口所引起的中断
1687 // print_int_info("==IRQ_EINT21=\n");
1688 ctp_ops.clear_penirq();
1689 if (!work_pending(&ft5x_ts->pen_event_work))
1690 {
1691 // print_int_info("Enter work\n");
1692 queue_work(ft5x_ts->ts_workqueue, &ft5x_ts->pen_event_work);
1693 }
1694 }else{
1695 // print_int_info("Other Interrupt\n");
1696 return IRQ_NONE;
1697 }
1698
1699 return IRQ_HANDLED;
1700 }
1895 err = request_irq(SW_INT_IRQNO_PIO, ft5x_ts_interrupt, IRQF_TRIGGER_FALLING | IRQF_SHARED, "ft5x_ts", ft5x_ts);
10.格式化userdata分区名字的方法在init.sun4i.rc中修改即可,如代码:format_userdata /dev/block/nandi IPND5,IPND5即为电脑中看到的盘符名字
11.全志平台的关机代码在drivers/power/axp_power/axp-mfd.c中:
311 /* PM hookup */
312 if(!pm_power_off)
313 pm_power_off = axp_power_off;axp_power_off定义如下:
static void axp_power_off(void)
{
uint8_t val;
#if defined (CONFIG_AW_AXP18)
axp_set_bits(&axp->dev, POWER18_ONOFF, 0x80);
#endif
#if defined (CONFIG_AW_AXP19)
axp_set_bits(&axp->dev, POWER19_OFF_CTL, 0x80);
#endif
#if defined (CONFIG_AW_AXP20)
if(pmu_pwroff_vol >= 2600 && pmu_pwroff_vol <= 3300){
if (pmu_pwroff_vol > 3200){
val = 0x7;
}
else if (pmu_pwroff_vol > 3100){
val = 0x6;
}
else if (pmu_pwroff_vol > 3000){
val = 0x5;
}
else if (pmu_pwroff_vol > 2900){
val = 0x4;
}
else if (pmu_pwroff_vol > 2800){
val = 0x3;
}
else if (pmu_pwroff_vol > 2700){
val = 0x2;
}
else if (pmu_pwroff_vol > 2600){
val = 0x1;
}
else
val = 0x0;
axp_update(&axp->dev, POWER20_VOFF_SET, val, 0x7);
}
val = 0xff;
if (!use_cou){
axp_read(&axp->dev, POWER20_COULOMB_CTL, &val);
val &= 0x3f;
axp_write(&axp->dev, POWER20_COULOMB_CTL, val);
val |= 0x80;
val &= 0xbf;
axp_write(&axp->dev, POWER20_COULOMB_CTL, val);
}
//led auto
axp_clr_bits(&axp->dev,0x32,0x38);
axp_clr_bits(&axp->dev,0xb9,0x80);
printk("[axp] send power-off command!\n");
mdelay(20);
if(power_start != 1){
axp_read(&axp->dev, POWER20_STATUS, &val);//读取是否处于充电状态,如果是,则reset,进入uboot充电
if(val & 0xF0){
axp_read(&axp->dev, POWER20_MODE_CHGSTATUS, &val);
if(val & 0x20){//判断电池在的话才进入充电
printk("[axp] set flag!\n");
axp_write(&axp->dev, POWER20_DATA_BUFFERC, 0x0f);
mdelay(20);
printk("[axp] reboot!\n");
arch_reset(0,NULL);
printk("[axp] warning!!! arch can't ,reboot, maybe some error happend!\n");
}
}
}
axp_write(&axp->dev, POWER20_DATA_BUFFERC, 0x00);
mdelay(20);
axp_set_bits(&axp->dev, POWER20_OFF_CTL, 0x80);//就是写1到寄存器32H,表示关闭除LDO1外的所有电源,请看AXP209手册P34
mdelay(20);
printk("[axp] warning!!! axp can't power-off, maybe some error happend!\n");
#endif
}
而arch_reset(0,NULL);的代码位于arch/arm/mach-sun4i/include/mach/system.h中,利用的是看门狗复位:
39 static inline void arch_reset(char mode, const char *cmd)
40 {
41 /* use watch-dog to reset system */
42 #define WATCH_DOG_CTRL_REG (SW_VA_TIMERC_IO_BASE + 0x0094)//SW_VA_TIMERC_IO_BASE是虚拟地址
43 *(volatile unsigned int *)WATCH_DOG_CTRL_REG = 0;
44 __delay(100000);
45 *(volatile unsigned int *)WATCH_DOG_CTRL_REG = 3;
46 while(1);
47 }
12.codec控制设置:
Number of controls: 32
ctl typenumname value
0 INT1Master Playback Volume 59 //音量大小设置
1 BOOL1Playback PAMUTE SWITCH On//声音输出总开关,打开才有声音输出,看手册P258 PAMUTE
2 BOOL1Playback MIXPAS Off//输入的声音或者经过混音器输出的声音输出的开关,如3G的语音就是要打开,看手册
// P258 MIXPAS
3 BOOL1Playback DACPAS On//输入的声音不经混音器直接输出,如播放音乐时要打开,看手册P258 DACPAS
// 但也可以选择声音从混音器输出,关掉3,使能2、5、6、7和15即可
4 INT1Mic Output Mix 0//MIC1、2输入的左右声道是否打开到混音器中一起输出到外音
5 BOOL1Ldac Right Mixer Off//输入的声音经过混音器混音时(对应手册DACMISX开关),左声道混音,右没声音
6 BOOL1Rdac Right Mixer Off//输入的声音经过混音器混音时(对应手册DACMISX开关),右声道混音,左没声音
7 BOOL1Ldac Left Mixer Off//输入的声音经过混音器混音时(对应手册DACMISX开关),左声道、左声道的混音
8 BOOL1FmR Switch Off//FM到混音器是否打开,如收音时要打开,但这样上层无法控制音量
9 BOOL1FmL Switch Off//FM到混音器是否打开,如收音时要打开,但这样上层无法控制音量
10 BOOL1LineR Switch Off//线路输入到混音器是否打开,如3G通话要打开,而播放音乐不是线路输入,不用打开
11 BOOL1LineL Switch Off//线路输入到混音器是否打开,如3G通话要打开,而播放音乐不是线路输入,不用打开
12 INT1MIC output volume 3//MIC到混音器输出的增益,
13 INT1Fm output Volume 3//FM到混音器输出的增益,
14 BOOL1Line output Volume On//线路输入到混音器的增益,只有两个等级,-1.5db和0db
15 BOOL1MIX Enable Off//混音器使能
16 BOOL1DACALEN Enable On//数字到模拟的输出是否是能,如音乐要打开,但3G通话是直接旁路输出不用打开
17 BOOL1DACAREN Enable On//数字到模拟的输出是否是能,如音乐要打开,但3G通话是直接旁路输出不用打开
18 BOOL1PA Enable On//PA使能,只有PA打开,才有声音输出
19 BOOL1dither enable Off//手册没有说明
20 BOOL1Mic1outn Enable Off//MIC是否直接输出,如3G通话MIC直接输出到3G模块中
21 INT1LINEIN APM Volume 7//线路模拟输入的增益,有7个增益等级,只是线路的增益,不会影响去他输入源的增益
22 BOOL1Line-in-r function define Off//输入信号差分是能,如3G通话时候要使能,否则2G卡会受到干扰,有噪音
23 INT1ADC Input source 0//模拟到数字转换的输入源选择,可以有3G线路,FM输入,MIC输入等选择
24 INT1Capture Volume 3//模拟到数字转换的增益,有8个等级,0-7(这是总的线路增益,影响到FM,MIC,
// 线路等输入源)
25 INT1Mic2 gain Volume 2//MIC2增益打开的情况下,输入增益的等级设置,没有用到这一路
26 INT1Mic1 gain Volume 2//MIC2增益打开的情况下,输入增益的设置,有4个等级,3G通话时候有增益的话会有噪音
27 BOOL1VMic enable On//MIC电源,用MIC时候就要打开
28 BOOL1Mic2 amplifier enable Off//MIC2输入增益是否打开
29 BOOL1Mic1 amplifier enable On//MIC2输入增益是否打开
30 BOOL1ADCL enable Off//模拟到数字的左声道是否打开,如录音时候有耳麦或则没有耳麦都就要打开
31 BOOL1ADCR enable Off//模拟到数字的左声道是否打开,如录音时候有耳麦或则没有耳麦都就要打开
13. camera的设置:
drivers/media/video/sun4i_csi目录下对应有csi0 、csi1两个文件夹,分别是两个摄像头对应的平台代码,他们对应的节点为/dev/video0前置ov5640, /dev/video1
后置ov2655或者ov2643,sun4i_drv_csi.c中控制camera的主要是csi_power_en脚和csi_stby脚,其中两个camera的csi_power_en相同,在csi_open函数中会打开电源上电,
但打开后马上用 v4l2_subdev_call(dev->sd,core, s_power, CSI_SUBDEV_STBY_ON);来进入standby 模式,只有在摄像头切换中,启用它后调用
static int internal_s_input(struct csi_dev *dev, unsigned int i)函数,在该函数中使用v4l2_subdev_call(dev->sd,core, s_power, CSI_SUBDEV_STBY_OFF);
才真正工作,所以两个摄像头同时只有一个工作,另一个处于standby模式
14. property_get/property_set会从以下文件读取属性:
1: /default.prop
2: /system/build.prop
3: /system/default.prop
4: /data/local.prop
15.android的电量警告和严重电量警告的设置在/frameworks/base/core/res/res/values/config.xml中,在frameworks/base/services/java/com/android/server/
BatteryService.java中读取这些值,而关机电量是在BatteryService.java文件中判断,在update函数中被调用,如下:
208 private final void shutdownIfNoPower()
{
209 // shut down gracefully if our battery is critically low and we are not powered.
210 // wait until the system has booted before attempting to display the shutdown dialog.
211 if (mBatteryLevel == 0 && !isPowered() && ActivityManagerNative.isSystemReady()) {//mBatteryLevel为0就关机
212 Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
213 intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
214 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
215 mContext.startActivity(intent);
216 }
217 }
16.APK签名机制:
<uses-sdk android:minSdkVersion="7" android:sharedUserId="android.uid.system"/>
java -jar signapk.jar platform.x509.pem platform.pk8 old.apk new.apk
17. 按键事件的上报,如果要上报某一个键值,要用set_bit来设置,否则不上报该键值,如:
for (i = 0; i < KEY_MAX_CNT; i++)
set_bit(sun4i_scankeycodes[i], sun4ikbd_dev->keybit);
18.camera拍照的各种声音播放在frameworks/base/core/java/android/hardware/CameraSound.java中实现
19. JNI_OnLoad函数是在android VM执行*so中的System.loadLibrary函数时候执行的,所以一般在该函数中做一些初始化设置和返回JNI版本,
20. u-boot流程:
头文件在include/configs/sun4i.h中
从arch/arm/cpu/armv7/start.S开始
跳到arch/arm/lib/board.c,
21. android源代码中编译jar包的方法:
在需要导出jar包的目录下新建android,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE_TAGS := optionalLOCAL_MODULE :=my_fmradio
include $(BUILD_JAVA_LIBRARY)
22. android背光调节代码路线:
packages/apps/Settings/src/com/android/settings/BrightnessPreference.java -> setBrightness(myState.progress + mScreenBrightnessDim);
private void setBrightness(int brightness)
{
try {
IPowerManager power = IPowerManager.Stub.asInterface(
ServiceManager.getService("power"));
if (power != null) {
power.setBacklightBrightness(brightness);
}
} catch (RemoteException doe) {
}
}
调用IPowerManager类接口,实现在frameworks/base/services/java/com/android/server/PowerManagerService.java
brightness = Math.max(brightness, mScreenBrightnessDim);
mLcdLight.setBrightness(brightness);
mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
mButtonLight.setBrightness(brightness);
可以看到,不但是设置了LCD的背光,如果有,键盘,按键的背光设置了,其中的private LightsService.Light mLcdLight;所以看到目录下的LightsService.java
public void setBrightness(int brightness, int brightnessMode) -> setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode) ->
setLight_native(mNativePointer, mId, color, mode, onMS, offMS, brightnessMode);
看看JNI层的实现,进入frameworks/base/services/jni/com_android_server_LightsService.cpp
这里看看JNI是如何找到HAL层的 hw_module_t结构体的:
hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);//这里传进去的是二维指针,才能返回HAL层的指针哦,关于这个不多说
看看hw_get_module的定义,在hardware/libhardware/hardware.c中:
hw_get_module -> hw_get_module_by_class:
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_PATH2, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1,name,prop);
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);
if (access(path, R_OK) == 0) break;
}
}
查找并加载hal层的so库,最后load(class_id, path, module);用dlopen动态加载so库,这里会比较打开的so库中id的名字和传进来的是否一样,如果都是"lights",才能加
载成功。
看看so库的实现,进入HAL层,在device/softwinner/crane-common/hardware/libhardware/lights/lights.c中:
这里打开的是dev->fd = open("/dev/disp", O_RDONLY);
他在kernel中对应的文件为:drivers/video/sun4i/disp/dev_disp.c
23. 编译,分析uboot:
./build.sh -p sun4i_crane
或者 make sun4i
board_init_r 从汇编跳到C入口,入口在文件arch/arm/lib/board.c中
启动用到的三个设置环境命令:
include/configs/sun4i.h中:
bootcmd=run setargs boot_normal;
board/allwinner/a10-evb/a10-evb.c -> check_android_misc()中
setenv("bootcmd", "run setargs boot_recovery");
setenv("bootcmd", "run setargs boot_fastboot");
他们分别为:
boot_normal=nand read 50000000 boot; boota 50000000//nand对应cmd_nand命令,会查找boot分区,把它读到RAM地址0x50000000中
boot_recovery=nand read 50000000 recovery; boota 50000000//nand对应cmd_nand命令,会查找recovery分区,把它读到RAM地址0x50000000中
boot_fastboot=fastboot//启动cmd_fastboot命令,等待USB发送fastboot命令到来
24. 编译kernel
./build.sh -p sun4i_crane
25. binder通讯机制的理解:
1. rocessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
这里打开的可以是service的fd,也是和servicemanager通讯的FD,和进程相关,一个进程映射一个FD就可以了,service要把自己添加到servicemanager中,就是打开该
fd,但也传进了另外一个参数mHandle(0),表示自己是要和servicemanager通讯,并且把自己的binder实体也传进去,以便挂在servicemanager端,然后service也是利用该FD
等待和client的通讯,整个系统一共有20多处打开FD的LOG。而service等待client数据并且处理数据的地方是下面这两句:
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
就是启动线程等待client的请求
2. 每个进程都有自己的defaultServiceManager(),如frameworks/base/media/mediaserver/main_mediaserver.cpp这个编译出来的执行文件就是一个单独的进程:
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
其他的进程会有自己独立的defaultServiceManager(),这一点从加入的log打印出来有20多个就可以证明:
34 sp<IServiceManager> defaultServiceManager()
35 {
36 if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
37
38 {
39 AutoMutex _l(gDefaultServiceManagerLock);
40 if (gDefaultServiceManager == NULL) {
41 LOGI("luis:go to here");//打印出来有20多个
42 gDefaultServiceManager = interface_cast<IServiceManager>(
43 ProcessState::self()->getContextObject(NULL));
44 }
45 }
3. service传输的数据要拷贝到内核空间的MMAP共享的空间,servicemaneger和client则通过指针就可以保存可操作MMAP空间这些数据,所以MMAP只有一次数据拷贝,一就是
binder进程的通讯只有一次数据拷贝
4. client要从servicemanager获得service接口,也要打开一个FD才能与servicemanager通讯,它也调用IPCThreadState::talkWithDriver这个与binder驱动交互,但打开
的FD是这个进程打开defaultServiceManager时候,函数创建ProcessState对象时,在ProcessState构造函数通过open文件操作函数打开设备文件/dev/binder时设置好的FD,
而且传进来的handle值为0,表示目标Binder对象是ServiceManager,但它自己并不像service一样有binder传给servicemanager,而相反,要从servicemanager中取得一个
binder实体的handle
26. init.sun4i.rc中format_userdata /dev/block/nandi IPND5格式化UMS分区,他对应的命令在system/core/init/builtins.c中:
int do_format_userdata(int argc, char **argv)
{
const char *devicePath = argv[1];
char bootsector[512];
char lable[32];
int fd;
int num;
pid_t child;
int status;
fd = open(devicePath, O_RDONLY);
if( fd <= 0 ) {
ERROR("open device error :%s", strerror(errno));
return 1;
}
memset(bootsector, 0, 512);
read(fd, bootsector, 512);
close(fd);
if( (bootsector[510]==0x55) && (bootsector[511]==0xaa) )
{
ERROR("dont need format %s", devicePath);
return 1;
}
else // 格式化
{
ERROR("start format %s", devicePath);
child = fork();
if (child == 0) {
ERROR("fork to format %s", devicePath);
execl("/system/bin/logwrapper","/system/bin/logwrapper","/system/bin/newfs_msdos","-F","32","-O","android","-c","8", "-L",argv[2],argv
[1], NULL);
exit(-1);
}
ERROR("wait for format %s", devicePath);
while (waitpid(-1, &status, 0) != child) ;
ERROR("format %s ok", devicePath);
return 1;
}
}
27. sensor的代码结构:
frameworks/base/services/sensorservice/SensorService.cpp中
void SensorService::onFirstRef()
67 {
68 LOGD("nuSensorService starting...");
69
70 SensorDevice& dev(SensorDevice::getInstance());//取得sensor列表,就是调用hw_get_module加载so库,
switch (list[i].type) {
87 case SENSOR_TYPE_ORIENTATION:
88 orientationIndex = i;
89 break;
90 case SENSOR_TYPE_GYROSCOPE:
91 hasGyro = true;
92 break;
93 case SENSOR_TYPE_GRAVITY:
94 case SENSOR_TYPE_LINEAR_ACCELERATION://根据type来判断是那种类型的sensor,所以我们在device下的so库中要注意该类型的赋值
95 case SENSOR_TYPE_ROTATION_VECTOR:
96 virtualSensorsNeeds &= ~(1<<list[i].type);
97 break;
28. 上层读取input事件时,一般是通过约定的名字来确定到底和/dev/input下的哪一个设备关联,如imapx15的gsensor,hardware/bosch_sensors/sensors.cpp中,
打开/dev/input目录后,遍历所有设备,根据约定的字符名字匹配:
539 if(ioctl(d06_read_fd, EVIOCGNAME(sizeof(name)),name) > 0)
540 {
541 ALOGD("devname=%s\n",devname);
542 ALOGD("name=%s\n",name);
543 if(!strcmp(name,INPUT_NAME_ACC))//"DMT_Gsensor"))
544 {
545 ALOGD("%s:name=%s,fd=%d\n",__func__,name,d06_read_fd);
546 break;
547 }
而在底层的driver中有:
291 /* Set InputDevice Name */
292 input->name = INPUT_NAME_ACC;
这样就能匹配成功啦
29. infotmic的LCD配置:
路径在drivers/InfotmMedia/lcd_api/source中,新增自己的c配置文件,填写手册中的配置在结构体lcdc_config_t中
在drivers/InfotmMedia/lcd_api/source/lcd_cfg.h中增加新增的文件
而在drivers/InfotmMedia/external/project/ids_drv_i800/ids.c中,会对item文件进行解析,以确认到底用那个LCD配置
28. javah生成JNI文件,其他一切都是浮云
在eclipse中编译好apk后,我的package为 com.example.javajni,class为HellojniActivity,看看生成的bin目录:
├── bin
│ ├── AndroidManifest.xml
│ ├── classes
│ │ ├── com
│ │ │ └── example
│ │ │ └── javajni
│ │ │ ├── BuildConfig.class
│ │ │ ├── HellojniActivity.class
│ │ │ ├── R$attr.class
│ │ │ ├── R.class
│ │ │ ├── R$drawable.class
│ │ │ ├── R$id.class
│ │ │ ├── R$layout.class
│ │ │ ├── R$menu.class
│ │ │ ├── R$string.class
│ │ │ └── R$style.class
│ │ └── com_example_javajni_HellojniActivity.h
我们要在bin/classs目录下运行javah命令,如下javah -classpath ./ -jni com.example.javajni.HellojniActivity,这样才能根据后面的参数找到com/example/
javajni目录下的HellojniActivity.class文件
29. kernel的makefile中链接.a库的写法:
1 obj-$(CONFIG_TOUCHSCREEN_AW5306) += aw5306_ts.o
2 aw5306_ts-objs := AW5306_ts.o AW5306_userpara.o [email protected]
libAW5306.a就是该目录下的一个库
30. allwiner的touch I2C注册过程:
主要是在i2c_driver 中定义了 AW5306_ts_driver.detect = ctp_ops.ts_detect,这样在注册时候会回掉detect函数,该函数做的事情就是判断I2C挂在那条线上
495 int ctp_detect(struct i2c_client *client, struct i2c_board_info *info)
496 {
497 struct i2c_adapter *adapter = client->adapter;
498
499 if(twi_id == adapter->nr)
500 {
501 pr_info("%s: Detected chip %s at adapter %d, address 0x%02x\n",
502 __func__, CTP_NAME, i2c_adapter_id(adapter), client->addr);
503
504 strlcpy(info->type, CTP_NAME, I2C_NAME_SIZE);
505 return 0;
506 }else{
507 return -ENODEV;
508 }
509 }
如果和config中定义的是同一组I2C,则把名字拷贝,这样就能match了
31. 让机器永不休眠并且没有锁屏界面:
frameworks/base/packages/SettingsProvider/res/values/defaults.xml中修改def_screen_off_timeout为-1
frameworks/base/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java中mExternallyEnabled设置为false
32.ND6的以太网服务分析frameworks/base/目录下:
首先在ethernet/java/android/net/ethernet中定义了aidl文件:
EthernetDevInfo.aidl //定义Parcelable传输对象流
EthernetDevInfo.java
EthernetManager.java
EthernetMonitor.java
EthernetNative.java
EthernetStateTracker.java
IEthernetManager.aidl //定义服务接口函数interface IEthernetManager
看到IEthernetManager.aidl就知道有服务要实现这写接口函数,它在frameworks/base/services/java/com/android/server/EthernetService.java中:
public class EthernetService<syncronized> extends IEthernetManager.Stub{........}
而这个服务在services/java/com/android/server/ConnectivityService.java中注册添加:
521 ServiceManager.addService(Context.ETHERNET_SERVICE, ethService);
这样以后我们就可以用getService的方法来获得该服务了。
回来看EthernetManager.java中的函数,它定义了对外提供访问的共有函数:
95 public EthernetDevInfo getSavedConfig() {
96 try {
97 return mService.getSavedConfig();
98 } catch (RemoteException e) {
99 Slog.i(TAG, "Can not get eth config");
100 }
101 return null;
102 }
可以看到都是同过调用mService的方法,而mService正是我们上面的ETHERNET_SERVICE,它在那里获得呢?看文件:
core/java/android/app/ContextImpl.java
487 if (Items.ItemExist("eth.model") == 1) {
488 registerService(ETHERNET_SERVICE, new ServiceFetcher() {
489 public Object createService(ContextImpl ctx) {
490 IBinder b = ServiceManager.getService(ETHERNET_SERVICE);
491 if (b == null)
492 {
493 Log.w(TAG, "Error getting service name:" + ETHERNET_SERVICE);
494 }
495 IEthernetManager service = IEthernetManager.Stub.asInterface(b);
496 return new EthernetManager(service, ctx.mMainThread.getHandler());
497 }});
498 }
果然是通过ServiceManager.getService(ETHERNET_SERVICE)来获得的,而且注册了EthernetManager服务,这样我们的应用中用getSystemService方法即可获得一个
EthernetManager.java中的对象了,当然还要把EthernetManager.java中的函数等声明为公开,应用程序才能调用得到,api/current.txt中:
12765 public class EthernetManager {
12766 ctor public EthernetManager(android.net.ethernet.IEthernetManager, android.os.Handler);
12767 method public java.lang.String[] getDeviceNameList();
12768 method public android.net.ethernet.EthernetDevInfo getSavedConfig();
12769 method public int getState();
12770 method public int getTotalInterface();
12771 method public boolean isConfigured();
12772 method public void updateDevInfo(android.net.ethernet.EthernetDevInfo);
12773 field public static final int ETHERNET_DEVICE_SCAN_RESULT_READY = 0; // 0x0
12774 field public static final java.lang.String ETHERNET_STATE_CHANGED_ACTION = "android.net.ethernet.ETHERNET_STATE_CHANGED";
12775 field public static final int ETHERNET_STATE_DISABLED = 1; // 0x1
12776 field public static final int ETHERNET_STATE_ENABLED = 2; // 0x2
12777 field public static final int ETHERNET_STATE_UNKNOWN = 0; // 0x0
12778 field public static final java.lang.String EXTRA_ETHERNET_STATE = "ETHERNET_state";
12779 field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
12780 field public static final java.lang.String EXTRA_PREVIOUS_ETHERNET_STATE = "previous_ETHERNET_state";
12781 field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.ethernet.STATE_CHANGE";
12782 field public static final java.lang.String TAG = "EthernetManager";
12783 }
这样,应用中getSystemService(Context.ETHERNET_SERVICE)即可获得服务
33.frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java中power key的处理分析:
2994 case KeyEvent.KEYCODE_POWER: {
...........
3023 interceptPowerKeyDown(!isScreenOn || hungUp //处理按键按下去的动作
3024 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
interceptPowerKeyDown函数如下:
605 private void interceptPowerKeyDown(boolean handled) {
606 mPowerKeyHandled = handled;
607 if (!handled) {
608 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());//表示长按多久后弹出关机确认对话框
609 }
610 }
接着:
3028 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {//处理按键抬起的动作
3029 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
3030 }
interceptPowerKeyUp函数如下:
612 private boolean interceptPowerKeyUp(boolean canceled) {
613 if (!mPowerKeyHandled) {
614 mHandler.removeCallbacks(mPowerLongPress);//如果还没有弹出关机确认对话框,取消掉它
615 return !canceled;
616 }
617 return false;
618 }
34. Audio java部分代码流程(4.1.2 version):
在frameworks/base/media/java/android/media中:
IAudioService.aidl提供了所有对外的接口函数,如下:
interface IAudioService {
void adjustVolume(int direction, int flags);
void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags);
void adjustStreamVolume(int streamType, int direction, int flags);
void setStreamVolume(int streamType, int index, int flags);
void setStreamSolo(int streamType, boolean state, IBinder cb);
void setStreamMute(int streamType, boolean state, IBinder cb);
boolean isStreamMute(int streamType);
int getStreamVolume(int streamType);
int getStreamMaxVolume(int streamType);
int getLastAudibleStreamVolume(int streamType);
void setRingerMode(int ringerMode);
.......................
}
这些函数的实现在服务AudioService.java中:
public class AudioService extends IAudioService.Stub {
........
}
该服务在services/java/com/android/server/SystemServer.java中注册进servicemanager中:
492 try {
493 Slog.i(TAG, "Audio Service");
494 ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
495 } catch (Throwable e) {
496 reportWtf("starting Audio Service", e);
497 }
这样在frameworks中可以通过ServiceManager.getService(Context.AUDIO_SERVICE)来获得该服务。
而AudioManager.java则实现这些函数了对外应用的接口,比如:
496 public void adjustVolume(int direction, int flags) {
497 IAudioService service = getService(); //
498 try {
499 service.adjustVolume(direction, flags);
500 } catch (RemoteException e) {
501 Log.e(TAG, "Dead object in adjustVolume", e);
502 }
503 }
这里的getService()获得的是前面的AudioService,如下:
365 private static IAudioService getService()
366 {
367 if (sService != null) {
368 return sService;
369 }
370 IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
371 sService = IAudioService.Stub.asInterface(b);
372 return sService;
373 }
要把AudioManager.java中的对外公开,则要在 core/java/android/app/ContextImpl.java中注册:
281 registerService(AUDIO_SERVICE, new ServiceFetcher() {
282 public Object createService(ContextImpl ctx) {
283 return new AudioManager(ctx);
284 }});
而且,还要把这些函数变量等在api/current.txt中声明:
10353 public class AudioManager {
10354 method public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
10355 method public void adjustStreamVolume(int, int, int);
10356 method public void adjustSuggestedStreamVolume(int, int, int);
10357 method public void adjustVolume(int, int);
10358 method public int getMode();
10359 method public java.lang.String getParameters(java.lang.String);
10360 method public int getRingerMode();
10361 method public deprecated int getRouting(int);
10362 method public int getStreamMaxVolume(int);
10363 method public int getStreamVolume(int);
10364 method public int getVibrateSetting(int);
10365 method public boolean isBluetoothA2dpOn();
这样在应用中用(AudioManager) getSystemService(Context.AUDIO_SERVICE);即可获得服务,从而使用AudioManager.java中的方法
然后看看比如setStreamVolume是如何从java调用到底层的:
1、应用调用比如mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
2、AudioManager.java调用public void setStreamVolume(int streamType, int index, int flags){};
3、AudioService.java调用public void setStreamVolume(int streamType, int index, int flags){},在该函数中调用
setStreamVolumeInt(mStreamVolumeAlias[streamType],
831 index,
832 device,
833 false,
834 true);
--------->
1002 sendMsg(mAudioHandler,
1003 MSG_PERSIST_VOLUME,
1004 SENDMSG_QUEUE,
1005 PERSIST_LAST_AUDIBLE,
1006 device,
1007 streamState,
1008 PERSIST_DELAY);
而mAudioHandler = new AudioHandler(),看看这个AudioHandler类:private class AudioHandler extends Handler {};-------->
所以调用该类重写的handleMessage方法--------->
2940 @Override
2941 public void handleMessage(Message msg) {
2942
2943 switch (msg.what) {
2944
2945 case MSG_SET_DEVICE_VOLUME:
2946 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
2947 break;
setDeviceVolume---------> mStreamStates[streamType].applyDeviceVolume(getDeviceForStream(streamType));---------->
AudioSystem.setStreamVolumeIndex--------->
setStreamVolumeIndex的定义在AudioSystem.java中-------->public static native int setStreamVolumeIndex(int stream, int index, int device);
setStreamVolumeIndex的JNI实现在base/core/jni/android_media_AudioSystem.cpp中---------->
178 static int
179 android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
180 jobject thiz,
181 jint stream,
182 jint index,
183 jint device)
184 {
185 return check_AudioSystem_Command(
186 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
187 index,
188 (audio_devices_t)device));
189 }
AudioSystem类在av/media/libmedia/AudioSystem.cpp中--------->
666 status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
667 int index,
668 audio_devices_t device)
669 {
670 const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
671 if (aps == 0) return PERMISSION_DENIED;
672 return aps->setStreamVolumeIndex(stream, index, device);
673 }
到这里就要涉及到进程间通讯binder的使用了,我们看AudioSystem::get_audio_policy_service()的实现:
514 const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
515 {
516 gLock.lock();
517 if (gAudioPolicyService == 0) {
518 sp<IServiceManager> sm = defaultServiceManager();//取得BpServiceManager,通过这个代理可以调用BnServiceManager::onTransact,最后和
//ServiceManager通讯
519 sp<IBinder> binder;
520 do {
521 binder = sm->getService(String16("media.audio_policy"));//从ServiceManager获得远程AudioPolicyService的句柄
522 if (binder != 0)
523 break;
524 ALOGW("AudioPolicyService not published, waiting...");
525 usleep(500000); // 0.5 s
526 } while (true);
527 if (gAudioPolicyServiceClient == NULL) {
528 gAudioPolicyServiceClient = new AudioPolicyServiceClient();
529 }
530 binder->linkToDeath(gAudioPolicyServiceClient);
531 gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
532 gLock.unlock();
533 } else {
534 gLock.unlock();
535 }
536 return gAudioPolicyService;
537 }
上面531行interface_cast<IAudioPolicyService>(binder),interface_cast是一个模版,在frameworks/native/include/binder/IInterface.h中定义如下:
42 inline sp<INTERFACE> interface_cast(const sp<IBinder>&obj)
43 {
44 return INTERFACE::asInterface(obj);
45 }
展开后是IAudioPolicyService::asInterface(obj);而IAudioPolicyService::asInterface的实现在frameworks/av/include/media/IAudioPolicyService.h中,通过宏
DECLARE_META_INTERFACE(AudioPolicyService)展开后得到的,DECLARE_META_INTERFACE定义在IInterface.h中:
74 #define DECLARE_META_INTERFACE(INTERFACE) \
75 static const android::String16 descriptor; \
76 static android::sp<I##INTERFACE> asInterface( \
77 const android::sp<android::IBinder>& obj); \
78 virtual const android::String16& getInterfaceDescriptor() const; \
79 I##INTERFACE(); \
80 virtual ~I##INTERFACE();
76行展开即可得到IAudioPolicyService::asInterface的定义,而这个定义的实现也是在IInterface.h,通过宏来定义的:
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
........................
89 android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
90 const android::sp<android::IBinder>& obj) \
91 { \
92 android::sp<I##INTERFACE> intr; \
93 if (obj != NULL) { \
94 intr = static_cast<I##INTERFACE*>( \
95 obj->queryLocalInterface( \
96 I##INTERFACE::descriptor).get()); \
97 if (intr == NULL) { \
98 intr = new Bp##INTERFACE(obj); \
99 } \
100 } \
101 return intr; \
102 }
展开后最终是生成调用new BpAudioPolicyService(new BpBinder(handle)),这里的handle是一个句柄;这样我们最终得到了AudioPolicyService的代理BpAudioPolicyService,通过它就可以和
AudioPolicyService的本地接口BnAudioPolicyService通讯了
回到前面的AudioSystem.cpp,取得代理BpAudioPolicyService后调用aps->setStreamVolumeIndex,所以进入IAudioPolicyService.cpp:
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>:
233 virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
234 int index,
235 audio_devices_t device)
236 {
237 Parcel data, reply;
238 data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
239 data.writeInt32(static_cast <uint32_t>(stream));
240 data.writeInt32(index);
241 data.writeInt32(static_cast <uint32_t>(device));
242 remote()->transact(SET_STREAM_VOLUME, data, &reply);
243 return static_cast <status_t> (reply.readInt32());
244 }
242行的remote是通过继承关系BpAudioPolicyService -> BpInterface -> BpRefBase,在类BpRefBase中定义的:
inline IBinder* remote() { return mRemote; }
IBinder* const mRemote;
这里mRemote声明为const,可见它是静态不变,只赋值一次,它是在前面获取远程服务AudioPolicyService时候创建的BpBinder对象(主要是打开了binder驱动,获得FD描述符,并且内
存映射了空间),所以调用BpBinder.cpp的transact函数:
159 status_t BpBinder::transact(
160 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
161 {
162 // Once a binder has died, it will never come back to life.
163 if (mAlive) {
164 status_t status = IPCThreadState::self()->transact(
165 mHandle, code, data, reply, flags);
166 if (status == DEAD_OBJECT) mAlive = 0;
167 return status;
168 }
169
170 return DEAD_OBJECT;
171 }
从164行,调用IPCThreadState.cpp的transact,这里就是最终和binder驱动打交道的地方了,165行通过的mHandle,底层binder驱动知道了传输数据的目标地址为mediaserver进
程,并且调整远程mediaserver用户空间buffer在内核中指向的位置,最终指向客户端内存映射的数据的位置,远程服务端就可以不用再次拷贝数据,直接从用户空间就可以读取客户端
的数据了, 这样remote()->transact(SET_STREAM_VOLUME, data, &reply)就通过binder传递到BnAudioPolicyService中了,这样就调用IAudioPolicyService.cpp的
BnAudioPolicyService::onTransact函数来处理该请求(但由于继承关系最终是派发到Bn的派生类AudioPolicyService::onTransact来处理,不过我们后面也会发现派生类又调回Bn类
的onTransact去处理,很有意思啊),我们看看BnAudioPolicyService是如何获得remote()->transact(SET_STREAM_VOLUME, data, &reply)的请求的,这样要从
AudioPolicyService是如何将自己的服务添加到servicemanager中的说起,在frameworks/av/media/mediaserver/main_mediaserver.cpp中:
34 int main(int argc, char** argv)
35 {
36 sp<ProcessState> proc(ProcessState::self());
37 sp<IServiceManager> sm = defaultServiceManager();
38 ALOGI("ServiceManager: %p", sm.get());
39 AudioFlinger::instantiate();
40 MediaPlayerService::instantiate();
41 CameraService::instantiate();
42 AudioPolicyService::instantiate();
43 ProcessState::self()->startThreadPool();
44 IPCThreadState::self()->joinThreadPool();
45 }
36行,由于main_mediaserver.cpp是编译成一个可执行文件,就是它的启动是作为服务在一个独立的进程中运行了,Main_MediaServer主函数由init.rc在启动时调用,先明白这点,
然后看:
frameworks/native/libs/binder/ProcessState.cpp:
74 sp<ProcessState> ProcessState::self()
75 {
76 Mutex::Autolock _l(gProcessMutex);
77 if (gProcess != NULL) {
78 return gProcess;
79 }
80 gProcess = new ProcessState;
81 return gProcess;
82 }
从77行可知,这是一个单例模式,在这个进程中以后再调用这个函数的话,就直接返回78行,这里我们第一次进来,所以跑到80行,进入ProcessState构造函数:
335 ProcessState::ProcessState()
336 : mDriverFD(open_driver())
337 , mVMStart(MAP_FAILED)
338 , mManagesContexts(false)
339 , mBinderContextCheckFunc(NULL)
340 , mBinderContextUserData(NULL)
341 , mThreadPoolStarted(false)
342 , mThreadPoolSeq(1)
343 {
344 if (mDriverFD >= 0) {
345 // XXX Ideally, there should be a specific define for whether we
346 // have mmap (or whether we could possibly have the kernel module
347 // availabla).
348 #if !defined(HAVE_WIN32_IPC)
349 // mmap the binder, providing a chunk of virtual address space to receive transactions.
350 mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
.................................
}
336行打开Binder设备文件/dev/binder,并将打开设备文件描述符保存在成员变量mDriverFD中;350行mmap来把设备文件/dev/binder映射到内存中,这样我们就有了一块共享内存。
回到main_mediaserver.cpp,37行defaultServiceManager(),在frameworks/native/libs/binder/IServiceManager.cpp中:
34 sp<IServiceManager> defaultServiceManager()
35 {
36 if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
37
38 {
39 AutoMutex _l(gDefaultServiceManagerLock);
40 if (gDefaultServiceManager == NULL) {
41 gDefaultServiceManager = interface_cast<IServiceManager>(
42 ProcessState::self()->getContextObject(NULL));
43 }
44 }
45
46 return gDefaultServiceManager;
47 }
和前面一样,也是一个单例模式,第一次进来肯定为NULL,所以进入41行,ProcessState::self()前面已经运行过一次,直接调用getContextObject(NULL),注意传进来的是NULL
参数,表示和ServiceManager通讯:
89 sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
90 {
91 return getStrongProxyForHandle(0);
92 }
getStrongProxyForHandle(0)最终会调用new BpBinder(0),这样我们就得到了ServiceManager的代理BpBinder,回到IServiceManager.cpp的41行,就变成了
interface_cast<IServiceManager>(new BpBinder(0)),interface_cast在前面已经分析过,所以最后变成new BpServiceManager(new BpBinder(0))。
接着进入main_mediaserver.cpp42行AudioPolicyService::instantiate(),先看看frameworks/av/services/audioflinger/AudioPolicyService.h中的继承关系:
37 class AudioPolicyService :
38 public BinderService<AudioPolicyService>,
39 public BnAudioPolicyService,
40 // public AudioPolicyClientInterface,
41 public IBinder::DeathRecipient
AudioPolicyService并没有实现instantiate方法,而是继承BinderService得到的,该类在frameworks/native/include/binder/BinderService.h中:
33 template<typename SERVICE>
34 class BinderService
35 {
36 public:
37 static status_t publish(bool allowIsolated = false) {
38 sp<IServiceManager> sm(defaultServiceManager());
39 return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
40 }
41
42 static void publishAndJoinThreadPool(bool allowIsolated = false) {
43 sp<IServiceManager> sm(defaultServiceManager());
44 sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
45 ProcessState::self()->startThreadPool();
46 IPCThreadState::self()->joinThreadPool();
47 }
48
49 static void instantiate() { publish(); }
50
51 static status_t shutdown() {
52 return NO_ERROR;
53 }
54 };
这是一个类模版,最终调用39行,得到sm->addService(String16(AudioPolicyService::getServiceName()), new AudioPolicyService(), false)即:
BpServiceManager(new BpBinder(0))->addService(String16("media.audio_policy", new AudioPolicyService(), false),进入BpServiceManger::addService的实现,这个
函数实现在frameworks/native/libs/binder/IServiceManager.cpp:
154 virtual status_t addService(const String16& name, const sp<IBinder>&service, bool allowIsolated)
156 {
157 Parcel data, reply;
158 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
159 data.writeString16(name);
160 data.writeStrongBinder(service);
161 data.writeInt32(allowIsolated ? 1 : 0);
162 status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
163 return err == NO_ERROR ? reply.readExceptionCode() : err;
164 }
这里162行remote流程和前面分析的差不多,最终调用IPCThreadState.cpp的transact,这里就是最终和binder驱动打交道的地方了,binder即为前面main_mediaserver.cpp中36行
ProcessState::ProcessState打开的驱动,用这块共享内存和servicemanager打交道,在底层的内核空间binder驱动会根据传进来的mHandle值判断目标服务地址,这里的
mHandle为0,所以调整servermanager的buffer指向本地内存共享空间,接着往下看main_mediaserver.cpp的43行ProcessState::self()-
>startThreadPool(),
在frameworks/native/libs/binder/ProcessState.cpp中:
136 void ProcessState::startThreadPool()
137 {
138 AutoMutex _l(mLock);
139 if (!mThreadPoolStarted) {
140 mThreadPoolStarted = true;
141 spawnPooledThread(true);
142 }
143 }
看141行:
286 void ProcessState::spawnPooledThread(bool isMain)
287 {
288 if (mThreadPoolStarted) {
289 int32_t s = android_atomic_add(1, &mThreadPoolSeq);
290 char buf[16];
291 snprintf(buf, sizeof(buf), "Binder_%X", s);
292 ALOGV("Spawning new pooled thread, name=%s\n", buf);
293 sp<Thread> t = new PoolThread(isMain);
294 t->run(buf);
295 }
296 }
293行创建了线程,PoolThread类继承列thread类,ProcessState.cpp中::
56 class PoolThread : public Thread
57 {
58 public:
59 PoolThread(bool isMain)
60 : mIsMain(isMain)
61 {
62 }
63
64 protected:
65 virtual bool threadLoop()
66 {
67 IPCThreadState::self()->joinThreadPool(mIsMain);
68 return false;
69 }
70
71 const bool mIsMain;
72 };
294行执行线程,thread在frameworks/native/libs/utils/Threads.cpp中,这样run函数最终调用子类的threadLoop函数,看67行,调用的和main_mediaserver.cpp的44行一样,
进入IPCThreadState.cpp中,result = talkWithDriver()等待client请求,最终会调用 executeCommand(cmd)函数来处理请求,而在executeCommand函数
中,最终会调用BBinder::transact来真正处理Client的请求,接下来再看一下BBinder::transact的实现,frameworks/native/libs/binder/Binder.cpp中:
97 status_t BBinder::transact(
98 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
99 {
100 data.setDataPosition(0);
101
102 status_t err = NO_ERROR;
103 switch (code) {
104 case PING_TRANSACTION:
105 reply->writeInt32(pingBinder());
106 break;
107 default:
108 err = onTransact(code, data, reply, flags);
109 break;
110 }
111
112 if (reply != NULL) {
113 reply->setDataPosition(0);
114 }
115
116 return err;
117 }
108行,调用onTransact方法,由于这里的继承关系,在前面分析main_mediaserver.cpp的42行AudioPolicyService::instantiate()就知道,这里创建的是AudioPolicyService类,
这样由于虚函数onTransact的继承关系,最终调用了AudioPolicyService的onTransact方法,AudioPolicyService.cpp中:
610 status_t AudioPolicyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
612 {
613 return BnAudioPolicyService::onTransact(code, data, reply, flags);
614 }
613行调用的还是基类BnAudioPolicyService的方法.
到这里BpAudioPolicyService和BnAudioPolicyService的binder通讯关系就完成了,回到前面IAudioPolicyService.cpp中的242行
remote()->transact(SET_STREAM_VOLUME, data, &reply);这里传进来的是SET_STREAM_VOLUME,所以调用BnAudioPolicyService::onTransact:
512 case SET_STREAM_VOLUME:{
513 CHECK_INTERFACE(IAudioPolicyService, data, reply);
514 audio_stream_type_t stream =
515 static_cast <audio_stream_type_t>(data.readInt32());
516 int index = data.readInt32();
517 audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
518 reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream,
519 index,
520 device)));
521 return NO_ERROR;
522 } break;
518行AudioPolicyService覆盖了BpAudioPolicyService的setStreamVolumeIndex方法,所以最终调用了AudioPolicyService.cpp的setStreamVolumeIndex方法:
380 status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
381 int index,
382 audio_devices_t device)
383 {
384 if (mpAudioPolicy == NULL) {
385 return NO_INIT;
386 }
387 if (!settingsAllowed()) {
388 return PERMISSION_DENIED;
389 }
390 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
391 return BAD_VALUE;
392 }
393
394 if (mpAudioPolicy->set_stream_volume_index_for_device) {
395 return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
396 stream,
397 index,
398 device);
399 } else {
400 return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
401 }
402 }
总结上面binder的通讯机制,理解了类之间的继承派生关系,也就能把来龙去脉弄清楚,主要还是熟悉C++才行,还有要理解binder通讯的设计原理,即每个服务或者想要获得服务的进
程都会打开binder节点,并且内存映射有一块空间,binder驱动根据传进来的handle判断数据要传送的目的地,从而调整目的地用户空间buffer指针在内核中的位置指向要传送的数据,
目的地读取buffer即可得到数据了,通过这样的浅拷贝即可实现进程间传输数据只用拷贝一次即可的原理。继续从AudioPolicyService.cpp往下走。先看它的构造函数:
58 AudioPolicyService::AudioPolicyService()
59 : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
60 {
61 char value[PROPERTY_VALUE_MAX];
62 const struct hw_module_t *module;
63 int forced_val;
64 int rc;
65
66 Mutex::Autolock _l(mLock);
67
68 // start tone playback thread
69 mTonePlaybackThread = new AudioCommandThread(String8(""));
70 // start audio commands thread
71 mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));
72
73 /* instantiate the audio policy manager */
74 rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
75 if(rc)
76 return;
77
78 rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
79 ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
80 if (rc)
81 return;
82
83 rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
84 &mpAudioPolicy);
85 ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
86 if (rc)
87 return;
88
89 rc = mpAudioPolicy->init_check(mpAudioPolicy);
90 ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
91 if (rc)
92 return;
.......................
}
74行AUDIO_POLICY_HARDWARE_MODULE_ID定义在libhardware/include/hardware/audio_policy.h中,
#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy"
根据hw_get_module的判断关系,看hardware/libhardware_legacy/audio/Android.mk可知,最终调用的是audio_policy.default.so,通过hw_get_module函数的
load(class_id, path, module)打开audio_policy.default.so并返回句柄,接着78行audio_policy_dev_open,在libhardware/include/hardware/audio_policy.h
424 static inline int audio_policy_dev_open(const hw_module_t* module,
425 struct audio_policy_device** device)
426 {
427 return module->methods->open(module, AUDIO_POLICY_INTERFACE,
428 (hw_device_t**)device);
429 }
这样就调用了hardware/libhardware_legacy/audio/audio_policy_hal.cpp的open方法:
406 static int legacy_ap_dev_open(const hw_module_t* module, const char* name, hw_device_t** device)
408 {
409 struct legacy_ap_device *dev;
411 if (strcmp(name, AUDIO_POLICY_INTERFACE) != 0)
412 return -EINVAL;
414 dev = (struct legacy_ap_device *)calloc(1, sizeof(*dev));
415 if (!dev)
416 return -ENOMEM;
418 dev->device.common.tag = HARDWARE_DEVICE_TAG;
419 dev->device.common.version = 0;
420 dev->device.common.module = const_cast<hw_module_t*>(module);
421 dev->device.common.close = legacy_ap_dev_close;
422 dev->device.create_audio_policy = create_legacy_ap;
423 dev->device.destroy_audio_policy = destroy_legacy_ap;
425 *device = &dev->device.common;
427 return 0;
428 }
结构体legacy_ap_device定义:
40 struct legacy_ap_device {
41 struct audio_policy_device device;
42 };
结构体audio_policy_device定义:
410 struct audio_policy_device {
411 struct hw_device_t common;
412
413 int (*create_audio_policy)(const struct audio_policy_device *device,
414 struct audio_policy_service_ops *aps_ops,
415 void *service,
416 struct audio_policy **ap);
417
418 int (*destroy_audio_policy)(const struct audio_policy_device *device,
419 struct audio_policy *ap);
420 };
所以这里open的425行*device = &dev->device.common赋值的虽然是结构体audio_policy_device的成员common的地址,但是common位于结构体首地址,也就是相当于返回了
audio_policy_device结构体的地址。所以接着AudioPolicyService.cpp的83行调用的是audio_policy_device的create_audio_policy,它指向create_legacy_ap函数:
311 static int create_legacy_ap(const struct audio_policy_device *device,
312 struct audio_policy_service_ops *aps_ops,
313 void *service,
314 struct audio_policy **ap)
315 {
316 struct legacy_audio_policy *lap;
317 int ret;
318
319 if (!service || !aps_ops)
320 return -EINVAL;
321
322 lap = (struct legacy_audio_policy *)calloc(1, sizeof(*lap));
323 if (!lap)
324 return -ENOMEM;
325
326 lap->policy.set_device_connection_state = ap_set_device_connection_state;
327 lap->policy.get_device_connection_state = ap_get_device_connection_state;
328 lap->policy.set_phone_state = ap_set_phone_state;
329 lap->policy.set_ringer_mode = ap_set_ringer_mode;
330 lap->policy.set_force_use = ap_set_force_use;
331 lap->policy.get_force_use = ap_get_force_use;
332 lap->policy.set_can_mute_enforced_audible = ap_set_can_mute_enforced_audible;
334 lap->policy.init_check = ap_init_check;
335 lap->policy.get_output = ap_get_output;
336 lap->policy.start_output = ap_start_output;
337 lap->policy.stop_output = ap_stop_output;
338 lap->policy.release_output = ap_release_output;
339 lap->policy.get_input = ap_get_input;
340 lap->policy.start_input = ap_start_input;
341 lap->policy.stop_input = ap_stop_input;
342 lap->policy.release_input = ap_release_input;
343 lap->policy.init_stream_volume = ap_init_stream_volume;
344 lap->policy.set_stream_volume_index = ap_set_stream_volume_index;
345 lap->policy.get_stream_volume_index = ap_get_stream_volume_index;
346 lap->policy.set_stream_volume_index_for_device = ap_set_stream_volume_index_for_device;
347 lap->policy.get_stream_volume_index_for_device = ap_get_stream_volume_index_for_device;
348 lap->policy.get_strategy_for_stream = ap_get_strategy_for_stream;
349 lap->policy.get_devices_for_stream = ap_get_devices_for_stream;
350 lap->policy.get_output_for_effect = ap_get_output_for_effect;
351 lap->policy.register_effect = ap_register_effect;
352 lap->policy.unregister_effect = ap_unregister_effect;
353 lap->policy.set_effect_enabled = ap_set_effect_enabled;
354 lap->policy.is_stream_active = ap_is_stream_active;
355 lap->policy.dump = ap_dump;
356
357 lap->service = service;
358 lap->aps_ops = aps_ops;
359 lap->service_client =
360 new AudioPolicyCompatClient(aps_ops, service);
361 if (!lap->service_client) {
362 ret = -ENOMEM;
363 goto err_new_compat_client;
364 }
365
366 lap->apm = createAudioPolicyManager(lap->service_client);
367 if (!lap->apm) {
368 ret = -ENOMEM;
369 goto err_create_apm;
370 }
371
372 *ap = &lap->policy;
373 return 0;
374
375 err_create_apm:
376 delete lap->service_client;
377 err_new_compat_client:
378 free(lap);
379 *ap = NULL;
380 return ret;
381 }
372行可知,这样mpAudioPolicy指针就指向了lap->policy方法。回到前面AudioPolicyService::setStreamVolumeIndex的394行调用audio_policy_hal.cpp方法:
232 static int ap_set_stream_volume_index_for_device(struct audio_policy *pol,
233 audio_stream_type_t stream,
234 int index,
235 audio_devices_t device)
236 {
237 struct legacy_audio_policy *lap = to_lap(pol);
238 return lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream,
239 index,
240 device);
241 }
237行结构体legacy_audio_policy定义:
44 struct legacy_audio_policy {
45 struct audio_policy policy;//即为mpAudioPolicy
46
47 void *service;
48 struct audio_policy_service_ops *aps_ops;
49 AudioPolicyCompatClient *service_client;
50 AudioPolicyInterface *apm;
51 };
lap->apm的赋值在前面create_legacy_ap函数的366行,看createAudioPolicyManager,hardware/libhardware_legacy/audio/AudioPolicyManagerDefault.cpp中:
24 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
25 {
26 return new AudioPolicyManagerDefault(clientInterface);
27 }
----->hardware/libhardware_legacy/audio/AudioPolicyManagerDefault.h:
25 class AudioPolicyManagerDefault: public AudioPolicyManagerBase
26 {
28 public:
29 AudioPolicyManagerDefault(AudioPolicyClientInterface *clientInterface)
30 : AudioPolicyManagerBase(clientInterface) {}
31
32 virtual ~AudioPolicyManagerDefault() {}
33
34 };
看基类AudioPolicyManagerBase,hardware/libhardware_legacy/include/hardware_legacy/AudioPolicyManagerBase.h的定义,终于找到了setStreamVolumeIndex方法,
在AudioPolicyManagerBase.cpp中:
953 status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index, audio_devices_t device)
956 {
958 if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
959 return BAD_VALUE;
960 }
961 if (!audio_is_output_device(device)) {
962 return BAD_VALUE;
963 }
965 // Force max volume if stream cannot be muted
966 if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
971 // if device is AUDIO_DEVICE_OUT_DEFAULT set default value and
972 // clear all device specific values
973 if (device == AUDIO_DEVICE_OUT_DEFAULT) {
974 mStreams[stream].mIndexCur.clear();
975 }
976 mStreams[stream].mIndexCur.add(device, index);
978 // compute and apply stream volume on all outputs according to connected device
979 status_t status = NO_ERROR;
980 for (size_t i = 0; i < mOutputs.size(); i++) {
981 audio_devices_t curDevice =
982 getDeviceForVolume((audio_devices_t)mOutputs.valueAt(i)->device());
983 if (device == curDevice) {
984 status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), curDevice);
985 if (volStatus != NO_ERROR) {
986 status = volStatus;
987 }
988 }
989 }
990 return status;
991 }
看984行checkAndSetVolume函数:
2683 status_t AudioPolicyManagerBase::checkAndSetVolume(int stream,
2684 int index,
2685 audio_io_handle_t output,
2686 audio_devices_t device,
2687 int delayMs,
2688 bool force)
2689 {
....................
2722 if (stream == AudioSystem::BLUETOOTH_SCO) {
2723 mpClientInterface->setStreamVolume(AudioSystem::VOICE_CALL, volume, output, delayMs);
2724 }
2725 }
2726
2727 mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
...................
2747 }
这里mpClientInterface是在AudioPolicyManagerBase构造函数中赋值的,就是create_legacy_ap函数360行AudioPolicyCompatClient,方法在AudioPolicyCompatClient.cpp:
120 status_t AudioPolicyCompatClient::setStreamVolume(
121 AudioSystem::stream_type stream,
122 float volume,
123 audio_io_handle_t output,
124 int delayMs)
125 {
126 return mServiceOps->set_stream_volume(mService, (audio_stream_type_t)stream,
127 volume, output, delayMs);
128 }
这里是在构造函数中赋值的,看AudioPolicyCompatClient.h:
32 class AudioPolicyCompatClient : public AudioPolicyClientInterface {
33 public:
34 AudioPolicyCompatClient(struct audio_policy_service_ops *serviceOps,
35 void *service) :
36 mServiceOps(serviceOps) ,
mService(service) {}
从36行可知,构造时候就已经赋值了,所以调用的是create_legacy_ap函数312行传进来的的型参aps_ops的set_stream_volume,它的赋值在
frameworks/av/services/audioflinger/AudioPolicyService.cpp中:
1538 struct audio_policy_service_ops aps_ops = {
1539 open_output : aps_open_output,
1540 open_duplicate_output : aps_open_dup_output,
1541 close_output : aps_close_output,
1542 suspend_output : aps_suspend_output,
1543 restore_output : aps_restore_output,
1544 open_input : aps_open_input,
1545 close_input : aps_close_input,
1546 set_stream_volume : aps_set_stream_volume,
1547 set_stream_output : aps_set_stream_output,
1548 set_parameters : aps_set_parameters,
1549 get_parameters : aps_get_parameters,
1550 start_tone : aps_start_tone,
1551 stop_tone : aps_stop_tone,
1552 set_voice_volume : aps_set_voice_volume,
1553 move_effects : aps_move_effects,
1554 load_hw_module : aps_load_hw_module,
1555 open_output_on_module : aps_open_output_on_module,
1556 open_input_on_module : aps_open_input_on_module,
1557 };
------------>
1503 static int aps_set_stream_volume(void *service, audio_stream_type_t stream,
1504 float volume, audio_io_handle_t output,
1505 int delay_ms)
1506 {
1507 AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1508
1509 return audioPolicyService->setStreamVolume(stream, volume, output,
1510 delay_ms);
1511 }
这里1507行的service即create_legacy_ap 360行传进来的service,也就是AudioPolicyService.cpp构造函数中83行的this指针,饶了半天居然还是调用了AudioPolicyService.cpp
的setStreamVolume,噢,My Lady GaGa!
看看setStreamVolume的实现:
1006 int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
1007 float volume,
1008 audio_io_handle_t output,
1009 int delayMs)
1010 {
1011 return (int)mAudioCommandThread->volumeCommand(stream, volume,
1012 output, delayMs);
1013 }
一看就知道是个线程之类的东西了,AudioCommandThread继承了Thread类,看看volumeCommand的实现:
800 status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
801 float volume,
802 audio_io_handle_t output,
803 int delayMs)
804 {
805 status_t status = NO_ERROR;
806
807 AudioCommand *command = new AudioCommand();
808 command->mCommand = SET_VOLUME;
809 VolumeData *data = new VolumeData();
810 data->mStream = stream;
811 data->mVolume = volume;
812 data->mIO = output;
813 command->mParam = data;
814 if (delayMs == 0) {
815 command->mWaitStatus = true;
816 } else {
817 command->mWaitStatus = false;
818 }
819 Mutex::Autolock _l(mLock);
820 insertCommand_l(command, delayMs);
821 ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
822 stream, volume, output);
823 mWaitWorkCV.signal();
824 if (command->mWaitStatus) {
825 command->mCond.wait(mLock);
826 status = command->mStatus;
827 mWaitWorkCV.signal();
828 }
829 return status;
830 }
820行insertCommand_l,加入线程队列中,看看线程的执行函数threadLoop:
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
681 case SET_VOLUME: {
682 VolumeData *data = (VolumeData *)command->mParam;
683 ALOGV("AudioCommandThread() processing set volume stream %d, \
684 volume %f, output %d", data->mStream, data->mVolume, data->mIO);
685 command->mStatus = AudioSystem::setStreamVolume(data->mStream,
686 data->mVolume,
687 data->mIO);
688 if (command->mWaitStatus) {
689 command->mCond.signal();
690 mWaitWorkCV.wait(mLock);
691 }
692 delete data;
693 }break;
}
685行,我们又回到AudioSystem.cpp中来啦:
123 status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,
124 audio_io_handle_t output)
125 {
126 if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
127 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
128 if (af == 0) return PERMISSION_DENIED;
129 af->setStreamVolume(stream, value, output);
130 return NO_ERROR;
131 }
129行,我们终于要进入AudioFlinger.cpp中啦,先看126行,get_audio_flinger:
49 const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
50 {
51 Mutex::Autolock _l(gLock);
52 if (gAudioFlinger == 0) {
53 sp<IServiceManager> sm = defaultServiceManager();
54 sp<IBinder> binder;
55 do {
56 binder = sm->getService(String16("media.audio_flinger"));
57 if (binder != 0)
58 break;
59 ALOGW("AudioFlinger not published, waiting...");
60 usleep(500000); // 0.5 s
61 } while (true);
62 if (gAudioFlingerClient == NULL) {
63 gAudioFlingerClient = new AudioFlingerClient();
64 } else {
65 if (gAudioErrorCallback) {
66 gAudioErrorCallback(NO_ERROR);
67 }
68 }
69 binder->linkToDeath(gAudioFlingerClient);
70 gAudioFlinger = interface_cast<IAudioFlinger>(binder);
71 gAudioFlinger->registerClient(gAudioFlingerClient);
72 }
73 ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
74
75 return gAudioFlinger;
76 }
分析完前面的binder通讯,再看这个函数的代码,太简单了!70行最终得到一个BpAudioFlinger代理,以便和BnAudioFlinger通讯,他们在IAudioFlinger.cpp中:
255 virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
256 audio_io_handle_t output)
257 {
258 Parcel data, reply;
259 data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
260 data.writeInt32((int32_t) stream);
261 data.writeFloat(value);
262 data.writeInt32((int32_t) output);
263 remote()->transact(SET_STREAM_VOLUME, data, &reply);
264 return reply.readInt32();
265 }
263行,,类型为SET_STREAM_VOLUME,由于AudioFlinger继承BnAudioFlinger,调用AudioFlinger的onTransact,但该函数还是回调BnAudioFlinger的onTransact,进入
BnAudioFlinger::onTransact函数:
780 case SET_STREAM_VOLUME: {
781 CHECK_INTERFACE(IAudioFlinger, data, reply);
782 int stream = data.readInt32();
783 float volume = data.readFloat();
784 audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
785 reply->writeInt32( setStreamVolume((audio_stream_type_t) stream, volume, output) );
786 return NO_ERROR;
785行,进入AudioFlinger.cpp:
761 status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
762 audio_io_handle_t output)
763 {
764 // check calling permissions
765 if (!settingsAllowed()) {
766 return PERMISSION_DENIED;
767 }
769 if (uint32_t(stream) >= AUDIO_STREAM_CNT) {//定义在system/core/include/system/audio.h
771 return BAD_VALUE;
772 }
774 AutoMutex lock(mLock);
775 PlaybackThread *thread = NULL;
776 if (output) {
777 thread = checkPlaybackThread_l(output);
778 if (thread == NULL) {
779 return BAD_VALUE;
780 }
781 }
783 mStreamTypes[stream].volume = value;
785 if (thread == NULL) {
786 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
787 mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
788 }
789 } else {
790 thread->setStreamVolume(stream, value);
791 }
793 return NO_ERROR;
794 }
35. camera打开device/infotm/imapx800/etc/media_profiles.xml配置的位置:
apps/Camera/src/com/android/camera/VideoCamera.java中mMediaRecorder.setProfile(mProfile); //mMediaRecorder为打开录像的录音功能
其中mProfile为 mProfile = CamcorderProfile.get(mCameraId, quality);它是通过调用JNI -> HAL层来解析media_profiles.xml文件的
36. infotmic factroy reset流程:
1. packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java------>
getActivity().sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
2. frameworks/base/core/res/AndroidManifest.xml------>
1748 <receiverandroid:name="com.android.server.MasterClearReceiver"//这里的名字即为activity的路径
1749 android:permission="android.permission.MASTER_CLEAR"
1750 android:priority="100" >
3. frameworks/base/services/java/com/android/server/MasterClearReceiver.java------->
RecoverySystem.rebootWipeUserData(context);
4. frameworks/base/core/java/android/os/RecoverySystem.java------->
bootCommand(context, "--wipe_data");
378 public static void bootCommand(Context context, String arg) throws IOException {
379 RECOVERY_DIR.mkdirs(); // In case we need it
380 COMMAND_FILE.delete(); // In case it's not writable
381 LOG_FILE.delete();
382
383 FileWriter command = new FileWriter(COMMAND_FILE);
384 try {
385 command.write(arg);
386 command.write("\n");
387 } finally {
388 command.close();
389 }
390
391 // Having written the command file, go ahead and reboot
392 PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
393 pm.reboot("recovery");
394
395 throw new IOException("Reboot failed (no permissions?)");
396 }
其中383行COMMAND_FILE定义:
71 private static File RECOVERY_DIR = new File("/cache/recovery");
72 private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
385行将字符串--wipe_data写到/chache/recovery分区,接着看393行。
5. frameworks/base/services/java/com/android/server/PowerManagerService.java------->
ShutdownThread.reboot(mContext, finalReason, false);
6. frameworks/base/services/java/com/android/server/pm/ShutdownThread.java------->
reboot() -> shutdownInner() -> beginShutdownSequence() -> sInstance.start() -> run() -> rebootOrShutdown() ->
PowerManagerService.lowLevelShutdown() -> 到PowerManagerService.java中 -> nativeShutdown()
7. JNI frameworks/base/services/jni/com_android_server_PowerManagerService.cpp ------>
android_reboot(ANDROID_RB_POWEROFF, 0, 0);
8. system/core/libcutils/android_reboot.c //adb等命令也是通过该函数来reboot的
__reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,LINUX_REBOOT_CMD_RESTART2, arg);//系统调用,进入kernel
9. kernel/kernel/sys.c -------->
case LINUX_REBOOT_CMD_RESTART2:
if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
ret = -EFAULT;
break;
}
buffer[sizeof(buffer) - 1] = '\0';
//kernel_restart(buffer);
imap_reset(!strncmp(buffer, "recover", 7));
10. arch/arm/mach-imapx800/cpu.c ------->
void imap_reset(int type)
{
imapfb_shutdown();
writel(type, IO_ADDRESS(SYSMGR_RTC_BASE + 0x3c));
printk(KERN_EMERG "sysreboot: %s\n", (type == 2)?
"charger": ((type == 1)? "recovery":
"normal")); //这里肯定是recovery了
writel(0x1, IO_ADDRESS(SYSMGR_RTC_BASE + 0x2c));
writel(0x1, IO_ADDRESS(SYSMGR_RTC_BASE + 0x44));
imap_set_retry_param_default();
writel(0x3, IO_ADDRESS(SYSMGR_RTC_BASE));
while(1);
}