4.29.2009

add external jar file as part of a system library

FWIW, it appears that if you add the external jar file as part of a user library, specify that the user library is a system library, and add the user library to the Java Build Path then it will work.


For completeness to do this you can do the following:
1. Right-click the project in Eclipse and select "Build Path -> Add Libraries...".
2. Select User Library from the list and click Next.
3. Click the "User Libraries..." button.
4. Click "New..." in the User Libraries dialog.
5. Give the user library a name and select the System library checkbox and click OK.
6. Highlight the newly added user library in the list and click the "Add JARs..." button and add the desired jar files.
7. Click OK on the User Libraries dialog.
8. Make sure the new user library is checked in the Add Library dialog and click Finish.

4.28.2009

AVD(Android Viutual Device)的注意事項

當你正在選擇system image target for 你的AVD時,請心存下列三項

Keep these points in mind when you are selecting a system image target for your AVD:

1. target 的 API level 很重要,因為你的應用程式沒辦法在比它的 API Level 還少的 system image 上跑,在應用程式的 manifest 檔的 attribute 裡的 minSdkVersion 有定義.想知道更多資訊有關 system API Level 跟應用程式 minSdkVersion 之間的關系,請看Specifying Minimum System API Version

The API Level of the target is important, because your application will not be able to run on a system image whose API Level is less than that required by your application, as specified in the minSdkVersion attribute of the application's manifest file. For more information about the relationship between system API Level and application minSdkVersion, see Specifying Minimum System API Version.

2. 強烈鼓勵,建立至少一個AVD, 它的 API Level 大於你的應用程式, 因為這可以讓你測試你的應用程式的forward-compatibility. forward-compatibility 的測試可用來保證,使用者透過system update download 你的應用程式之後,可以運作正常。

Creating at least one AVD that uses a target whose API Level is greater than that required by your application is strongly encouraged, because it allows you to test the forward-compatibility of your application. Forward-compatibility testing ensures that, when users who have downloaded your application receive a system update, your application will continue to function normally.

3. 如果你的應用程式宣告了一個 user-library 元件在它的 manifest 檔,那這個應用程式只能跑在有外部 library 的 system image.如果你要你的應用程試跑在你建立的 AVD 上, 請確定應用程式的 uses-library element 還有所選的 system image target 有無 includes 那個 library.

If your application declares a uses-library element in its manifest file, the application can only run on a system image in which that external library is present. If you want your application to run on the AVD you are creating, check the application's uses-library element and select a system image target that includes that library.

4.27.2009

實作一個假的 character driver 在emulator 上跑

大致上的做法就是將自己 build 的 kernel 放到 emulator, 然後再將自製假的 driver 放進 emulator 裡跑

1. 將 .config 從模擬器裡抓出來
因為模擬器裡的 kernel 的 CONFIG_MODULE 是關掉的。所以我們需要將它打開,否則不能 insmod 。
開了之後就要重 build 出 kernel image (zImage). 而要 build kernel 就需要模擬器裡的 kernel 的 .config。

先下載 Android 的 sdk , 因為 emulator 就在 SDK 裡,可到下面網址 download(註:我是以SDK 1.1為例子,SDK 1.5 還沒試過)


http://developer.android.com/sdk/1.1_r1/index.html



a. 解壓之後,執行 emulator


D:\workplace\android-sdk-windows-1.1_r1\tools>emulator


b. 在 emulator 執行的狀況下抓/proc/config.gz ,放到 \pulldata下


D:\workplace\android-sdk-windows-1.1_r1\tools>adb pull /proc/config.gz



2. 改 CONFIG_MODULES
將 config.gz 解壓之後放到 /mydroid/kernel 下, 然後找 CONFIG_MODULES ,並改為


CONFIG_MODULES=y



3. 改 kernel 的 Makefile
因為我們是跑 arm archtecture ,所以要改 tool chain
在 /mydroid/kernel/Makefile 裡,將 ARCH 跟 CROSS_COMPILE 改為下面


ARCH ?=arm
CROSS_COMPILE ?=../prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-


然後將 LDFLAGS_BUILD_ID mark 掉,如下


# LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,$(call ld-option, -Wl$(comma)--build-id,))


4. build kernel
(1) 先清乾淨


$make mrproper


(2) 將第二步驟的 config 改名為 .config ,放到 /mydroid/kernel 下
(3) make


$make


一開始會問你一些問題,一律都答N
build 完之後,會在 /mydroid/kernel/arch/arm/boot 找到 image, 叫 zImage

5. build fake driver
(1) 從 Linux Device Driver Programming 一書裡,copy 個範例 driver, source C 如下


/*
* devone.c
*
*/
#include linux/init.h
#include linux/module.h
#include linux/types.h
#include linux/kernel.h
#include linux/fs.h
#include linux/cdev.h
#include asm/uaccess.h

MODULE_LICENSE("Dual BSD/GPL");

static int devone_devs = 1; /* device count */
static int devone_major = 0; /* dynamic allocation */
static int devone_minor = 0;
static struct cdev devone_cdev;

ssize_t devone_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
int i;
unsigned char val = 0xff;
int retval;

for (i = 0 ; i < count ; i++) {
if (copy_to_user(&buf[i], &val, 1)) {
retval = -EFAULT;
goto out;
}
}

retval = count;
out:
return (retval);
}

struct file_operations devone_fops = {
.read = devone_read,
};

static int devone_init(void)
{
dev_t dev = MKDEV(devone_major, 0);
int alloc_ret = 0;
int major;
int cdev_err = 0;

alloc_ret = alloc_chrdev_region(&dev, 0, devone_devs, "devone");
if (alloc_ret)
goto error;
devone_major = major = MAJOR(dev);

cdev_init(&devone_cdev, &devone_fops);
devone_cdev.owner = THIS_MODULE;
devone_cdev.ops = &devone_fops;
cdev_err = cdev_add(&devone_cdev, MKDEV(devone_major, devone_minor), 1);
if (cdev_err)
goto error;

printk(KERN_ALERT "devone driver(major %d) installed.\n", major);

return 0;

error:
if (cdev_err == 0)
cdev_del(&devone_cdev);

if (alloc_ret == 0)
unregister_chrdev_region(dev, devone_devs);

return -1;
}

static void devone_exit(void)
{
dev_t dev = MKDEV(devone_major, 0);

cdev_del(&devone_cdev);
unregister_chrdev_region(dev, devone_devs);

printk(KERN_ALERT "devone driver removed.\n");

}

module_init(devone_init);
module_exit(devone_exit);





Makefile 如下,你需要改 KERNELDIR ,這需要指到已經好的kernel,還有命令之前一定要是"tab"


KERNELDIR=/home/arik/Workspace/aydroid/kernel/
PWD := $(shell pwd)

obj-m := devone.o

modules:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules


clean:
rm -rf *.o *~ core.depend .*.cmd *.ko *.mod.c .tmp_versions




6. 將我們 build 的 zImage 放進 emulator 上跑


D:\workplace\android-sdk-windows-1.1_r1\tools>emulator.exe -kernel D:\workplace\
android-sdk-windows-1.1_r1\tools\lib\images\zImage


-kernel 後面的參數就是指到之前 build 出來的 kernel image

7. 把 busybox 放進 emulator
因為待會要用 busybox 的 mknod 指令( emulator 好像沒有), 所以要將 busybox 放進 emulator
(1) 讓 emulator 的 /system 這個目錄變成可 read/write. 開另一個 cmd 下


D:\workplace\android-sdk-windows-1.1_r1\tools>adb remount
* daemon not running. starting it now *
* daemon started successfully *
remount succeeded


(2) 下載 busybox


http://benno.id.au/android/busybox


(3) 把 busybox 放進 emulator


D:\workplace\android-sdk-windows-1.1_r1\tools>adb push busybox /system/bin
1703 KB/s (0 bytes in 1745016.001s)


(4) 更改 busybox 權限,否則不能用


D:\workplace\android-sdk-windows-1.1_r1\tools>adb shell
# chmod 566 /system/bin/busybox
chmod 566 /system/bin/busybox
#_



8. 把 ko 檔放進 emulator
跟放 busybox 一樣, 把假 driver 放進, 注意 emulator 裡只有 /system 目錄才可對外讀寫, 這裡我是放在 /system/bin


D:\workplace\android-sdk-windows-1.1_r1\tools>adb push devone.ko /system/bin
117 KB/s (0 bytes in 3763.000s)



9. 載入 module
跟在 linux 下做的一樣


D:\workplace\android-sdk-windows-1.1_r1\tools>adb shell
# busybox insmod /system/bin/devone.ko
busybox insmod /system/bin/devone.ko
# busybox lsmod
busybox lsmod
Module Size Used by Not tainted
devone 2624 0
#


10. 將 driver 掛上
掛上之前,要先知道它的 major id


# busybox cat /proc/devices
busybox cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
5 /dev/tty
5 /dev/console
5 /dev/ptmx
7 vcs
10 misc
13 input
29 fb
90 mtd
128 ptm
136 pts
252 devone
253 ttyS
254 rtc

Block devices:
1 ramdisk
7 loop
31 mtdblock
43 nbd
179 mmc
#


知道是 252 之後,就 mknod 上去


# busybox mknod /dev/devone c 252 0
busybox mknod /dev/devone c 252 0
# busybox ls -l /dev/devone
busybox ls -l /dev/devone
crw-rw-rw- 1 0 0 252, 0 Apr 30 02:26 /dev/devone
#


4.23.2009

compile android & kernel

* build android
If you just want to force the generation of the systemimage without
rebuilding anything, you should just be able to do
make snod
(snod == systemimage-nodeps)

清除之前make 習
make clean

*build kernel
(1)
.config 要從模擬器上的kernel 拿

cd \tools
adb pull /proc/config.gz pulldata\config.gz

下完config.gz 就會在\tools\pulldata\裡
config.gz 就是.config,將它解壓並copy 到你要 build 的kernel 目錄下
其中有個flag CONFIG_MODULE 要設成y ,才可手動載入module

(2)
make mrproper (clean)
make msm_defconfig ARCH=arm
make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-

(3)載入映像檔到模擬器中:
映像檔位置: (1) 依照android官方網頁的說明,映像檔是放在lib/images下,在我的電腦(os: xp)上是位於

C:\WT\SoftWare\eclipse\android-sdk-windows-1.1_r1\tools\lib\images。

用指令來指定image的方式如下:

emulator -image system.img -data userdata.img -ramdisk ramdisk.img

如果要重載kernel的image則如下:

emulator -kernel /zImage


如果直接把image檔覆蓋掉在lib/images的檔案也能正常執行。如果使用指令則會啟動模擬器並載入參數路徑所指的映像檔,如下,其實上原本存在於lib/images的映像檔並沒有被參數載入的覆蓋掉!

emulator -image backup\system.img




這裡有講到如何build image for emulator

編譯android原始碼到模擬器上執行
http://www.cookbus.com/show-85-1.html

4.22.2009

android permission

我試著建立一個假的character device.
然後想讓它可以被使用在 Android emulator上。

首先, 我在.config 檔加了CONFIG_MODULES,並重編譯了Android Kernel
然後, 我寫了個module 來控制"/dev/mydev"(它扮演著一個 80char 的buffer),並跨平台組譯成arm 架構。

我ran了emulator ,然後將 busybox 放進去(用來建立/dev/mydev 透過 mknod),並用insmod 載入module

目前,透過使用 open/close/write/等.. shell 和 common activities 都可以對它互動

我想要建一個特別的permission給這個device,然後人不能透過 common Activities 來讀取它。
有任何的文件/提醒/連結嘛?

我知道Android 有一個特別的HAL,但沒有文件。

I'm trying to create a fake character device.
I want to make it usable within the provided Android emulator.

Firstly, I recompiled the Android Kernel editing the .config file,
adding CONFIG_MODULES.
Then, I wrote a module managing "/dev/mydev" (it acts as a 80 char
buffer) and crosscompiled it for arm architecture.
I ran the emulator and pushed busybox (for creating the /dev/mydev
with mknod) and loaded the module with insmod.


Now, both shell and common activities can interact with it, by using
standard open/close/write/etc...


I would like to create a specific permission for that device and make
it not readable from common Activities.
Is there some documentation/hints/links?


I know Android has a specific HAL but there's no documentation.




就application style permissions來說,你一般要做的就是去define一個新的gid, 就是你的device 會被發布的gid(如此它就不會被讀/寫),
加一個entry 在 \frameworks\base\data\etc\permissions.xml 去對映到 permission string,
然後加一個item在 frameworks/base/core/res/AndroidManifest.xml 來描述這個permission.
gid 的group 是被defined 在user space, 有個 system/init 來defines 這些standard groups.

For application style permissions, what you generally do is define a new gid
that your device is published under (so it is not world readable/writeable),
add an entry to etc/permissions.xml mapping that gid to a permission string,
and add an item in the frameworks AndroidManifest.xml describing that
permission.

The meaning of groups is purely defined by user space. There is a
system/init header that defines the standard groups.

4.19.2009

股票模擬遊戲

最近開始再研究股票

就再想怎麼沒有一個網站模擬台股來弄個線上遊戲,每天life 跟真實台股連線
每個人從20萬台幣開始玩,最後也有融資融卷等工具可用

這樣就有地方可以練習,又可累積經驗,但又不用擔心真的了錢
等練到贏率大於80%時就可真的下場投資了

最好是可以真的摸擬實際的市場機制,也就是說當這個遊戲愈多人玩,表示愈多散戶投入,那也應該要反應在遊戲裡面
或者不要反應,也許會比較準對於練習來說


找了一下,如果要玩美股的話有這個網站

Practice Investing, Stock Market Game


如果不用自己的錢去玩,真的可以學到東西嘛?
如何讓人真的serious 去玩就像真的一樣?

4.13.2009

How Linux kernel Init

要了解kernel 如何init
先了解kernel image 的架構


vmlinux 是kernel 本身再加了一些符號什麼的
然後把那些符號拿掉就成了image 的binary
之後用gzip 壓成piggy.gz
然後用asmbaly build 成piggy.o


*bootstrap loader and bootloader的不同
bootloader 只負責POWER ON

*bootstrap loader(second-stage loader),head.o @bootstrap loader
1.creat the proper environment to decompress,
2.relocate the kernel,
3.pass control to head.o@kernel




*head.o @kernel

1.Checks for valid processor and architecture
2.Creates initial page table entries
3.Enables the processor's memory management unit (MMU)
4.Establishes limited error detection and reporting
5.Jumps to the start of the kernel proper, main.c

在這個時候只有有限的memory maping.. 所以如果想在這加個firmwave 去down load到特定的device,是會crash的
要init driver 就透過device driver model

*start_kernel() @ .../init/main.c

USB 裝置會挑電腦?

常聽人說我的手機接我的電腦不能連 ActiveSync,但接別台電腦就可連
就說這隻手機會挑電腦

其實這只說對了一部份

當連線的時候,如果USB的訊號差,則USB的protocol 一般都可cover 掉,只要重傳就好了,只是效能沒那麼好而已
但如果訊號差都一定的程度,那就會連不起來
所以我們知道USB的protocol 對壞的訊號有一定的容忍度。

而訊號的好壞取決於三個部份,手機端(device), cable/cradle, 電腦端(host)
手機的lay out 是不是符合標準
cable/ cradle 是不是有太多connector 轉接
電腦端是不是也轉接connector (一般桌機,USB port 前面的比後面的訊號差 )
這三個部份加起來,如果訊號壞到超過potocol的容忍度,就連不起來了

而理論上來說,device 及cable 再出貨時就是要有最佳的匹配,將errors 降到最低,
這樣就有空間,留給電腦的部份,也就比較不會挑電腦了

4.12.2009

用英文,而不是學英文

一直覺得英文只是個工具
而工具,有人用的好,也有人用的不好
重點就是"用"

一個字或片語或句子結構 會不會用就決定你英文的好壞

但沒人規定說要用一個工具就一定要很會用
重點就是看你用它來做什麼


以TOEFL 為例,
就是要了解各個學科的字
及熟練如何表達自己的意思

而TOEIC,
則要多了解商業領域的字
及日常生活的用語


一些有趣的元素可以加入
1. 玩-動機, 新奇好玩
2. 演戲-角色扮演
3.

4.09.2009

工人還是功能

最近同事去巴里島度蜜月,回來帶了些雕刻飾品。
說到,當地的人雕刻東西很厲害,一面石牆不打草稿,就刻出了很漂亮的圖案。

我想這有兩種形況
1. 他已經看到他想要的圖案在石牆上,所以他就刻出他要的東西,而且也可以刻出任何他想要的東西,是藝術家,東西是藝術品。
2. 這個圖案他已經做了很多遍,已經很熟每個需要刻的位置,他只是repeat 出每個動作,可以做的很快,甚至於可以寫出SOP,只是會的圖案有限,這種人是工人,東西是產品。

我相信很多時候,是兩個同時存在在同一個人上,只是比例問題而已。
想想自己,身為工程師,有多少時間是再trace code, debug, try and error, 又有多少時間是真的從無到有做出自己想要的東西出來。

4.07.2009

測USBIF 注意事項

最近再整理筆記,趁這個機會整理一下測USBIF 的部份

1. 還沒插入USB cable 之前,USB充電應關閉,一直到set configured 之後才可開啟。
2. 用電池的產品,USB充電不可超過100mA(會影響test J/K)。
3. D+D- 的訊號線應離PHY愈近愈好,且不可串接或並接任何東西(例如bead),Handy 用coaxial cable 在機子裡跑是一大敗筆, (影響Rx sensitivity)。
4. Connector 如果可以的話,盡量用標準的USB connector,如果不是標準的,Vbus和Ground 也要先touch 在cable 插入時。
5. 有cable 的產品,再測眼圖時用FAR END來測,沒cable 的產品(大母哥) 用NEAR END測。
6. 連線完cable 拔掉之後,D+ D-應為low。
7. 在Ch9裡, default power 應該為 “BUS/SELF POWER” ,而current power 如果是SELF POWER,則Vbus 的電流不可超過100mA,如果是BUS POWER 則不可超過500mA. 但在PC suspend 時,兩者定義都不可超過2.5mA。

4.06.2009

Android HAL

有人問說有沒有一個標準的方法來加一個driver 給上層android AP用,答案是沒有。



如果我要建一個新的device, 符合Android HAL, 我知道, 我應該使用下列方法的其中一個:
1. App - Runtime Service - lib
2. App - Runtime Service - Native Service - lib
3. App - Runtime Service - Native Daemon - lib

If I want to create a new device, conforming to Android HAL, I should
use one of the following approaches:
1. App - Runtime Service - lib
2. App - Runtime Service - Native Service - lib
3. App - Runtime Service - Native Daemon - lib


但是,除了現存的devices 以外, 要改所以需要改的檔案,來增加一個新的device,似乎不容易。

我想要寫一個user-mode 的driver,而不是用kernel-mode driver model.
然後想要讓它可以在enulator 上跑。

Except for the existing devices, it is not easy to identify all the
files which need to be modified for adding a new one.
I am also interested in writing a User-Mode Driver, instead of using a
Kernel-Mode Driver model.
For now, I want to make it work in the emulator.


所以,我加了一個假的device ,有點像是sensor device。然後,我試著建立一個library (就叫fake)來處理所有必要的功能。然後把它放在 /hardware/libhardware/fake, /hardware/libhardware/include/fake, 另外還有Android.mk 放在裡面,Android.mk相關連到/dev/fak 和 /dev/input/fake(第一個for data, 第二個for 控制)

My fake device will be similar to "sensor" device.
I tried to create a library calling it "fake" and managing all
necessary features.
I put them into /hardware/libhardware/fake, /hardware/libhardware/
include/fake, with its Android.mk.
It relies on /dev/fake and /dev/input/fake (one for data, the second
one for control).


第一個問題,在Android Project Group裡有標準的方式加一個新的device嘛(kernel and/or user mode)?(檔案該放的目錄,如何加makefiles, 等等? device /dev/input/compass 是哪個driver再管理的?)有沒有一個stub 是專門再加新的dvice 及相關的Manager/Services,給上層的Application?

First question. There's a standard way in Android Project Group for
adding a new device (kernel and/or user model)? (Folders where files
should be placed, tips for makefiles, etc? The device /dev/input/
compass is managed by which driver?)
There's a stub for implementing a new device and related Manager/
Services, to higher levels up to Application?




The abstraction layers in Android are admittedly inconsistent. Audio
and camera both use a C++ pure virtual interface (e.g.
AudioHardwareInterface.h), while other places like LED's and blitter
functions have a C struct of function pointers.
Android 的抽像層不可否任地是前後茅盾的。Audio 和camera 都是C++純虛擬介面,但其它地方像LED 和blitter 就有function pointers 的 C 結構.

Because we run the actual device image in the emulator, any devices
that aren't backed by a kernel driver in the emulator need a fake
device (such as camera). For audio, we have a kernel driver for the
emulator, but other devices like the G1 have a user space layer on top
of the kernel driver. In this case, for the emulator, there is a shim
that translates AudioHardwareInterface calls to kernel calls.
因為我們是在模擬器上跑一個實體device 的image,任何在模擬器背後沒有kernel driver 的devices 都需要一個假的device(像是camera)。對audoi來說,我們有kernel driver在模擬器上,但是其它的device 像是G1 在kernel driver 的上方有個user space 層。
就這個case 來說,就有個小程式轉換AudioHardwareInterface 到呼叫kernel calls.


How you surface the driver features to the application will depend on
what you are trying to do. Most hardware features are abstracted by a
native service, for example Surfaceflinger for 2D graphics,
AudioFlinger for audio, CameraService (because CameraFlinger just
sounded wrong) for the camera. This allows us to enforce security
using the binder interface and to abstract away a lot of differences
so that applications don't have to be written to work with specific
hardware.
要如何寫driver 功能的介面給application ,取決於你打算怎麼做。大部份的硬體功能都有抽象層在現有的service裡。例如 2D graphics 有 SurfaceFlinger,audio 有AudioFlinger, camera有CameraService(因為CameraFlinger聽起來很奇怪)。在這樣的架構下,讓我們在用binder interface 時有一定的安全性,並將大部份的不同性抽象化,好讓applications 不用管硬體


I haven't looked at the compass code, but I can take you through the
camera as an example.
我還沒實際去看這個部份的code, 但是我可以給你一個以camera 為例子的例子,來說明


At the top of the stack is android.hardware.Camera, which is the Java
object that the application instantiates when it wants to take a
picture. This is a thin wrapper around android_hardware_Camera.cpp
which is the JNI interface. This in turn is a wrapper around libs/ui/
Camera.cpp which is the proxy for the remote object in the camera
service. And yes, libs/ui is a strange place for it, but it has some
circular dependencies on Surfaceflinger, so that's where it ended up.

在最上層是 android.hardware.Camera, 就是當application 拍照時會跑的Java object。它就是個小的wrapper在 android_hardware_Camera.cpp,也就是JNI介面。接下來,有另一個wrapper 在libs/ui/Camera.cpp,這個cpp是一個代理,專門for camera service 的remote object用。沒錯,放在libs/ui是蠻奇怪的,不過沒辦法,有些環境相依性的問題關於Surfaceflinger, 所以就這麼定了。


Now it gets interesting because there is a binder interface called
ICamera.h (pure virtual) which is implemented in ICamera.cpp which is
the marshalling code for the IPC binder calls. Let's just take it on
faith that the calls from the client result in a marshalled
ICameraClient object appearing on the server side of the interface.
Upon establishing a connection - provided that the application has
permission to use the camera - the camera service instantiates a
CameraHardwareInterface derived object, which is the HAL for the
actual camera hardware. The camera service takes care of preview
display and other low-level house-keeping functions that would be
difficult to do in a Java app.
現在,有趣的是,有個binder interface 叫做ICamera.h (純虛擬的),它被寫在ICamera.cpp裡,而ICamera.cpp 是marshalling code for IPC binder 呼叫的。我們只要相信,從client 來的呼叫,會導致一個marshalled 的ICameraClient object 顯示在server端的介面上。在建立連結上(所謂連結就是application 提到許可來使用camera),camera service會具現化 CameraHardwareInterface 而取得object, 這個object 就是實體camera 硬體用的HAL。而camera service 會處理preview 顯示,還有其它低階的內在功能(Java app會比較困難處理的部份)。


The camera hardware driver can either be implemented as a kernel
driver with a thin user space shim driver, or it can be implemented as
a user space driver with a thin kernel driver (primarily to control
access).
Camera hardware driver 可以寫成一個kernel driver 跟一個小user space 的driver, 或是寫成user space driver 跟一個小kernel dirver(主要是控制存取部份).


This is one of the more complex device models. Other devices (like the
LEDs) have a much simpler model.
這是比較複雜的device models的其中一個。其它的devices(像是LEDs)就有比較簡單model



>如果我要建一個新的device, 符合Android HAL, 我知道, 我應該使用下列方法的其中一個:
> 1. App - Runtime Service - lib
> 2. App - Runtime Service - Native Service - lib
> 3. App - Runtime Service - Native Daemon - lib

這要看形況,大部份的流程會像這樣:
app -> java api (manager) -> java service -> HAL module -> kernel

It depends, most of the time you'll need to do something like:

app -> java api (manager) -> java service -> HAL module -> kernel


有時候,以sensors為case來說,會有一個額外的native daemon, 但是在這個特別的case裡, it's an implementation detail (the sources for that daemon are proprietary).(看不懂什麼意思:p)

Sometimes (it's the case for the sensors), there is an extra native
daemon, but in this particular case, it's an implementation detail
(the sources for that daemon are proprietary).


有時候,native service 可以直接替換到java service,這要歸功於binder interfaces(它在程式語言上是很彈性的,所以service 可以被寫成java to c++,而不會破壞相容性,反之亦然)

Sometimes, the "java service", can be replaced directly by a "native
service", thanks to the binder interfaces (they're agnostic to the
languages involved, so a service can even be rewritten from java to
C++ or vice-versa, without breaking compatibility).


在一些cases 下,也是有可能跳過整個java service,如果HAL module 可以處理多個clients 以及相關的權限。

In some cases, it is also possible to skip the "java service"
entirely, if the HAL module can handle multiple clients and all the
permissions involved.


也有可能兩個方式都混在一起並用,以sensors 的例子來說; service 可以跟硬體建立connection , 但是app 卻可以直接跟HAL module 溝通傳資料。

It is also possible to have a mix and match, this is the case for the
sensors; the service is used to establish a connection with the
hardware, but all the data moving is done by talking directly to the
HAL module from the the app.


所以,結論就是,沒一定的規則。這要看你是想達成什麼樣的結果。

So, in short, there are no rules. It depends on what you're trying to
accomplish.