新项目的手机需要实现关机状态下的闹钟,早在刚开始接触 android 的时候都在想为什么 android 不支持关机状态下的一些功能呢?像充电或者闹钟什么的,虽然每个平台的驱动不一样但上层应用是可以提供统一接口的呀,果然在 4.0 的时候支持关机充电了,关机闹钟仍然不在默认支持中。市场上的很多品牌手机也都不支持这个功能,让很多用惯了 Feature Phone 以及担心辐射的用户都不习惯。这次做关机闹钟在一些思路上借鉴了关机充电的实现方法。
整体思路如下:
在 uboot 中通过 PMU 判断开机的原因,如果是
1、UI
在 zygote 没有启动之前完成 UI 显示可以参考 charger 的做法,用 android 的 minui 接口,这些接口实现了图形的描绘以及固定大小的文字显示,函数介绍如下:
- int
gr_init(void); - void
gr_exit(void); -
- int
gr_fb_width(void); - int
gr_fb_height(void); - gr_pixel
*gr_fb_data(void); - void
gr_flip(void); - void
gr_fb_blank(bool blank); -
- void
gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); - void
gr_fill(int x, int y, int w, int h); - int
gr_text(int x, int y, const char *s); - int
gr_measure(const char *s); - void
gr_font_size(int *x, int *y); -
- void
gr_blit(gr_surface source, int sx, int sy, int w, int h, int dx, int dy); - unsigned
int gr_get_width(gr_surface surface); - unsigned
int gr_get_height(gr_surface surface); -
- int
res_create_surface(const char* name, gr_surface* pSurface); - void
res_free_surface(gr_surface surface);
2、闹铃
在这个阶段播放闹铃只能选择
3、input evnt
当闹钟开始响后,用户可以通过触摸屏点击选择是否开关机或者进入懒人模式,这里就需要对用户操作做出判断,即在程序中去读取
- static
int event_loop(void) - {
-
int i; -
int ret = 0; -
int nfds = ALARM_MAX_DEVICE; -
struct input_event event; -
const char *device = NULL; -
const char *device_path = "/dev/input"; -
-
ret = scan_dir(device_path); -
if(ret < 0) { -
printf("scan dir failed for %s.\n", device_path); -
return ret; -
} -
-
for(;;) { -
poll(ufds, nfds, -1); -
-
for (i = 0; i < nfds; i++) { -
if(ufds[i].revents) { -
if(ufds[i].revents & POLLIN) { -
ret = read(ufds[i].fd, &event, sizeof(event)); -
if (ret < (int)sizeof(event)) { -
printf("could not get event.\n"); -
continue; -
} -
handle_event(event.type, event.code, event.value); -
} -
} -
} -
} -
-
return 0; - }
附:android 权限管理机制
这次在编译使用 alarm 的时候遇到了一个权限问题:编译出来的 alarm 可执行程序在 out 目录下面是拥有可执行权限的,但是在烧录到机器后发现没有可执行权限了,最后才发现是 android 的权限管理机制引起的。
1、文件系统中的权限设定
在 android 系统编译完成后会生成后缀为 img 的文件如:system.img、boot.img,包含了许多目录和文件。在编译的时候会用到
-
- static
struct fs_path_config android_dirs[] = { -
{ 00770, AID_SYSTEM, AID_CACHE, "cache" }, -
{ 00771, AID_SYSTEM, AID_SYSTEM, "data/app" }, -
{ 00771, AID_SYSTEM, AID_SYSTEM, "data/app-private" }, -
... -
{ 00755, AID_ROOT, AID_ROOT, "system/etc/ppp" }, -
{ 00777, AID_ROOT, AID_ROOT, "sdcard" }, -
{ 00755, AID_ROOT, AID_ROOT, 0 }, - };
-
-
- static
struct fs_path_config android_files[] = { -
{ 00440, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.rc" }, -
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.sh" }, -
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app -
{ 00644, AID_MEDIA_RW, AID_MEDIA_RW, "data/media -
... -
{ 06750, AID_ROOT, AID_SHELL, "system/bin/run-as" }, -
{ 00755, AID_ROOT, AID_SHELL, "system/bin -
{ 00755, AID_ROOT, AID_ROOT, "system/lib/valgrind -
{ 00750, AID_ROOT, AID_SHELL, "alarm*" }, -
{ 00644, AID_ROOT, AID_ROOT, 0 }, - };
2、设备文件的权限
android 系统中,kernel 启动后运行的第一个进程为
其他由 kernel 或 init 及其脚本创建的目录或文件,如果需要修改访问权限,可以通过 init 使用的脚本文件