0%

  Android日志系统详解
  How to debug with Android logging
  怎么抓取Android日志文件

  Android logging system为logging系统提供了一个Java类android.util.Log,也提供了一个c/c++的log库,在kernel中有四个设备节点,详细见:Android日志系统详解。其系统架构如下:
   image by simon

此图与4.0以上的系统有些差异,新版Android增加了log_system

Read more »

  Android日志系统详解
  How to debug with Android logging
  怎么抓取Android日志文件

  不管是做Android应用还是做Android中间层和底层,Logging系统都是必须要了解的;因为Android不像单片机程序UCOS那么简单,可以很方便的单步调试。所以,就准备用一篇blog来分析一下logging system。

##概览
  Android提供了一个灵活的logging系统,允许应用程序和系统组件等整个系统记录logging信息,它是独立于Linux Kernel的一个logging系统,kernel是通过”pr_info”、”printk”等存储,通过“dmesg”或“cat /proc/kmsg”获取。不过,Android logging 系统也是将信息存在内核缓存区。其结构如下: 
 
    image by Tetsuyuki Kobabayshi

Read more »

  Android编译过程详解之一
  Android编译过程详解之二
  Android编译过程详解之三
  Android.mk解析

  前两个篇基本完全涉及到了整个编译过程,接下来着重分析一下和公司产品相关的mk文件。有两个路径前面没有怎么提到过,如下:

1
2
build/target/product # 当前产品配置的mk文件,如:需要包含哪些apk在此产品中
build/target/board # 硬件芯片配置的mk文件,如:GPU、是否支持浮点运算等

  除以上两个路径外,对产品定义的文件通常位于device目录下,还可以定义在vender目录下(不过Google已不建议如此做了),device目录下根据公司名和产品名分为两级目录,这个上文已经介绍过。通常一个产品定义如下四个文件:

  • AndroidProducts.mk
  • 产品版本定义文件(一般针对不同应用环境存在多个,如:msm8916_32.mk)
  • BoardConfig.mk
  • verndorsetup.sh

AndroidProducts.mk

Read more »

  Android编译过程详解之一
  Android编译过程详解之二
  Android编译过程详解之三
  Android.mk解析
 
  配置好环境变量后,接下来要做的就是build了。为了提高编译速度,我们自定义了一个go.sh的脚本文件,详细下面解释。另,编译的时候一般会在后面加一个-j8来实现多线程编译,如:

1
   ./go.sh -j8 or make -j8/--jobs  

参数“-j“ 和”–jobs ”指定了同时编译的线程数量,通常是编译主机 CPU 支持的并发线程总数的 1 倍或 2 倍(如:在一个 4 核,每个核支持两个线程的 CPU 上,可以使用 make -j8 或 make -j16)。在调用 make 命令时,如果没有指定任何目标,则将编译默认目标“droid”(下面详解),然后将会编译出完整的 Android 系统镜像。

build系统分类

  整个build系统的Make文件可以分为三类:

  1. build系统核心文件:定义整个build系统的框架,其他所有make文件都是在这个框架的基础上写出来的。
  2. 产品的make文件:位于device目录,通常以公司名和产品名分为两级目录,如:\device\qcom\msm8916_32。
  3. 模块的make文件:每个模块专用的make文件,kernel中统一名字为Makefile,其他为Android.mk。 

build结果

所有的编译产物都将位于 /out 目录下,该目录下主要有以下几个子目录:

  • /out/host/:该目录下包含了针对主机的 Android 开发工具的产物。即 SDK 中的各种工具,例如:emulator,adb,aapt 等。
  • /out/target/common/:该目录下包含了针对设备的共通的编译产物,主要是 Java 应用代码和 Java 库。
  • /out/target/product//:包含了针对特定设备的编译结果以及平台相关的 C/C++ 库和二进制文件。其中,是具体目标设备的名称。
  • /out/dist/:包含了为多种分发而准备的包,通过“make disttarget”将文件拷贝到该目录,默认的编译目标不会产生该目录。
    Read more »

  Android编译过程详解之一
  Android编译过程详解之二
  Android编译过程详解之三
  Android.mk解析

ActivityNotFoundException

  最近将Android从4.4移植到5.1时,添加一个从拨号界面输入*#360*#进入battery info查看界面的功能时(如感兴趣,详情见Android电池监控系统(bms)之一电池系统架构),activity跳转部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
else if(input.equals(BATTERY_INFO))
{//added by lihuaqian
try {
ComponentName Component = new ComponentName("com.android.settings","com.android.settings.BatteryOemInfo");
Intent intent = new Intent();
intent.setComponent(Component);
intent.setAction(Intent.ACTION_VIEW);
context.startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
Log.d(TAG, "no activity to battery cmd.");
//e.printStackTrace();
}
}

  遇到如下问题:

1
  ActivityNotFoundException : Unable to find explicit activity class; have you declared this activity in your AndroidManifest.xml?
Read more »

**  Platform Information :
   System: Android4.4.4
   Platform: Qualcomm msm8916
   Author: Andy Lee
   Email: huaqianlee@gmail.com**

欢迎指出错误,共同学习,共同进步

  Android编译过程详解之一
  Android编译过程详解之二
  Android编译过程详解之三
  Android.mk解析
 
  Google给出的编译环境和构建方法见:http://source.android.com/source/initializing.html,过程见:http://source.android.com/source/building.html,不过这是解释怎么编译一个通用的系统,没有详细描述细节,而且需要翻墙。接下来我就准备跟着高通平台的编译过程来详细了解一下。

我平时的编译步骤如下:
 1. source setup.sh project-name debug/release 加载命令配置环境 
 2. ./go.sh [target] or make [target] 编译

Read more »

analysis log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<3>[52515.763039] __smb135x_write: Writing 0x41=0x06
<3>[52515.774459] __smb135x_write: Writing 0x41=0x26
函数调用:
static int __smb135x_write(struct smb135x_chg *chip, int reg,u8 val)
->smb135x_write(struct smb135x_chg *chip, int reg,u8 val) / smb135x_masked_write(struct smb135x_chg *chip, int reg, u8 mask, u8 val)


<3>[52515.777868] fast_chg_handler: rt_stat = 0x00
<3>[52515.782184] usbin_uv_handler: chip->usb_present = 1 usb_present = 0
<3>[52515.788369] handle_usb_removal: setting usb psy type = 0
<3>[52515.793689] handle_usb_removal: setting usb psy present = 0
<3>[52515.799241] power_ok_handler: rt_stat = 0x00
<3>[52515.803472] src_detect_handler: chip->usb_present = 0 usb_present = 0
函数调用:
fast_chg_handler(struct smb135x_chg *chip, u8 rt_stat)
usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat)
handle_usb_removal(struct smb135x_chg *chip)
(->usbin_uv_handler(struct smb135x_chg *chip, u8 rt_stat)/usbin_ov_handler(struct smb135x_chg *chip, u8 rt_stat)/determine_initial_status(struct smb135x_chg *chip))
static struct irq_handler_info handlers[]=
{
...
{
.name = "fast_chg",
.smb_irq = fast_chg_handler,
},
{
.name = "usbin_uv",
.smb_irq = usbin_uv_handler,
},
...
}
->smb135x_irq_read(struct smb135x_chg *chip)
/static irqreturn_t smb135x_chg_stat_handler(int irq, void *dev_id)
->smb135x_chg_stat_handler(int irq, void *dev_id)
->smb135x_main_charger_probe(struct i2c_client *client,const struct i2c_device_id *id)

<3>[52515.809926] smb135x_chg_stat_handler: handler count = 4
<3>[52515.815104] smb135x_chg_stat_handler: batt psy changed
<3>[52515.820247] smb135x_chg_stat_handler: usb psy changed
<3>[52515.825260] smb135x_chg_stat_handler: dc psy changed
函数调用:
smb135x_chg_stat_handler(int irq, void *dev_id)
smb135x_external_power_changed(struct power_supply *psy)
-> smb135x_main_charger_probe(struct i2c_client *client,const struct i2c_device_id *id)/(force_irq_set(void *data, u64 val)/smb135x_resume(struct device *dev))

<6>[52515.836445] msm_hsusb msm_hsusb: CI13XXX_CONTROLLER_DISCONNECT_EVENT received
函数调用:
kernel/drivers/usb/chipidea/ci13xxx_msm.c:186: dev_info(dev, "CI13XXX_CONTROLLER_DISCONNECT_EVENT received\n");

<3>[52515.837146] smb135x_get_prop_batt_status: STATUS_4_REG=80
<3>[52515.841747] smb135x_get_prop_batt_status: STATUS_4_REG=80
函数调用:
smb135x_get_prop_batt_status(struct smb135x_chg *chip)
->smb135x_battery_get_property(struct power_supply *psy,enum power_supply_property prop,union power_supply_propval *val)/
smb135x_parallel_get_property(...)

<3>[52515.847405] smb135x_external_power_changed: current_limit = 0
函数调用:
smb135x_external_power_changed(struct power_supply *psy)

.....

driver architecture

the important structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
static struct i2c_driver smb135x_charger_driver = {
.driver = {
.name = "smb135x-charger",
.owner = THIS_MODULE,
.of_match_table = smb135x_match_table, // get the dtsi profile
.pm = &smb135x_pm_ops,
},
.probe = smb135x_charger_probe,
.remove = smb135x_charger_remove,
.id_table = smb135x_charger_id,
};
/*represent an I2C slave device*/
struct i2c_client {
unsigned short flags; /* div., see below */
unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
char name[I2C_NAME_SIZE];
struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */
struct device dev; /* the device structure */
int irq; /* irq issued by device */
struct list_head detected;
};
struct i2c_device_id {
char name[I2C_NAME_SIZE];
kernel_ulong_t driver_data; /* Data private to the driver */
};

struct device_node {
const char *name;
const char *type;
phandle phandle;
const char *full_name;
...
}
struct smb135x_chg {
struct i2c_client *client;
struct device *dev;
struct mutex read_write_lock;
...
/* psy */
struct power_supply *usb_psy;
int usb_psy_ma;
struct power_supply batt_psy;
struct power_supply dc_psy;
struct power_supply parallel_psy;
struct power_supply *bms_psy;
...
}
struct power_supply {
const char *name;
enum power_supply_type type;
enum power_supply_property *properties;
...
int (*get_property)(...)
int (*set_property)(...)
... /* private */ struct device *dev;
...
}

driver analysis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 注册驱动:
if (is_parallel_charger(client))
smb135x_parallel_charger_probe(client, id);
else
smb135x_main_charger_probe(client, id); // 驱动注册入口函数
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
chip->client = client;
chip->dev = &client->dev; // get the dev
smb_parse_dt(chip) // parse DT nodes
usb_psy = power_supply_get_by_name("usb"); // get usb Supply
struct device *dev = class_find_device(power_supply_class, NULL, name,power_supply_match_device_by_name);
dev_get_drvdata(dev)
INIT_DELAYED_WORK(&chip->wireless_insertion_work,wireless_insertion_work);
smb135x_read(chip, CFG_4_REG, &reg) // probe the device to check if its actually connected
i2c_set_clientdata(client, chip); // client->...->driver_datat = chip
smb135x_chip_version_and_revision(chip) // judge the chip version(smb1357/1358....)
dump_regs(chip) // read and display the register's value
smb135x_regulator_init(chip) // initialize regulator(稳压器)
smb135x_hw_init(chip) // initialize hardware(初始化芯片各种参数)
determine_initial_status(chip) //determine init status
.../* initialize Battery power_supply*/
chip->batt_psy.get_property = smb135x_battery_get_property;
chip->batt_psy.set_property = smb135x_battery_set_property;
chip->batt_psy.external_power_changed = smb135x_external_power_changed; // register external power update online function
chip->batt_psy.property_is_writeable = smb135x_battery_is_writeable;
power_supply_register(chip->dev, &chip->batt_psy) // register Battery power Supply
....// get the profile and register the function
power_supply_register(chip->dev, &chip->dc_psy); // register dc psy
devm_request_threaded_irq(struct device *dev, unsigned int irq, irq_handler_t handler, irq_handler_t thread_fn,unsigned long irqflags,
const char *devname, void *dev_id) // allocate(分配) an interrupt line for a managed device
enable_irq_wake(client->irq); // control irq power management wakeup
create_debugfs_entries(chip); // create debug

  Git是Linux撞始人Linus Towards花一周写出来的分布式版本控制系统,大神终究是大神,这么牛逼的东西只需要一周。之前花了一百多刀买了Linus的原版自传《Just for fun》,基本上是他自己写的,很幽默,有兴趣可以看看。Linus很傲,但是傲得有资本,唯一能无视Jobs的现实扭曲力场,对Jobs的盛情邀请say no转身而去的人。 
 
  言归正传,Git十分好用,应用也十分广泛,现在最好的代码托管网站Github就是基于git创建的,而且现在大多数公司及个人都在使用它进行代码管理,要熟练使用还是需要花一些苦功夫的,我现在也还只是会基本的应用,更深层次的使用还不熟悉。为了方便自己以后使用,将自己常用的一些命令加以总结,并Google了一些常用及进阶命令,一并列出,方便查询使用。

最重要的命令: git –help

Read more »