一.振動器系統結構和移植內容
振動器負責控制引用電話的震動功能,Android中的振動器系統是一個專供這方面功能的小系統,提供根據時間的振動功能。
振動器系統包含瞭驅動程序,硬件抽象層,JNI部分,java框架類等幾個部分,也向java應用程序層提供瞭簡單的API作為平臺接口。
二.振動器部分的結構
Android振動器系統自下而上包含瞭驅動程序,振動器系統硬件抽象層,振動器系統java框架類,java框架中振動器系統使用等幾個部分。
自下而上,Android的振動器系統分成瞭以下部分。
1. 驅動程序:特定硬件平臺振動器的驅動程序,通常基於Android的Timed Output驅動框架實現
2. 硬件抽象層:振動器系統的硬件抽象層在Android中已經具有默認實現,代碼路徑:
Hardware/libhardwar_legacy/vibrator/vibrator.c
振動器的硬件抽象層通常並不重新實現,是libhardware_legacy.so的一部分。
3. JNI部分
這個類是振動器的JNI部分,通過調用硬件抽象層向上提供接口。
4. Java部分VibratorService.java通過調用,VibratorService JNI 來實現 com.android.server包中的VibrattorService類。這個類不是平臺的API,被Android 系統Java框架中的一小部分的調用.Vibrator.java文件實現瞭android.os包中的Vibrator類,這是向java層提供的API
三.移植方法
針對特定的硬件平臺,振動器系統的移植有兩種方法。
第一種方法:由於已經具有硬件抽象層,振動器系統的移植隻需要實現驅動程序即可。這個驅動程序需要給予Android內核中的Timed Output驅動框架。
第二種方法:根據自己實現的驅動程序,重新實現振動器的硬件抽象層定義接口,由於振動器硬件抽象層的接口非常簡單,因此這種實現方式也不會很復雜。
四.移植與調試的要點
1. 驅動程序
Vibrator的驅動程序隻需要實現振動的接口即可,這是一個輸出設備,需要接受振動時間作為參數。由於比較簡單,因此Vibrator驅動程序可以使用多種方式來實現。
在Android中,推薦基於Android內核定義TimedOutput驅動程序框架來實現Vibrator的驅動程序。
Timed Output的含義為定時輸出,用於定時發出某個輸出。實際上,這種驅動程序依然是基於sys文件系統來完成的。
Driver/staging/android/目錄timed_output.h中定義timed_output_dev結構體,其中包含enable和get_time 這兩個函數指針,實現結構體後,使用timed_output_dev_register()和timed_output_dev_unregister()函數註冊和註銷即可。
Timed Output驅動程序框架將為每個設備在/sys/class/timed_output/目錄中創建一個子目錄,設備子目錄中的enable文件就是設備的控制文件。讀enable文件表示獲得剩餘時間,寫這個文件表示根據時間振動。
Timed Output驅動的設備調試,通過sys文件系統即可。
對於Vibrator設備,其實現的TimedOutput驅動程序的名稱應該為“vibrator”。因此Vibrator設備在sys文件系統中的方法如下:
#echo”10000”>/sys/class/timed_output/vibrator/enable
#cat/sys/class/timed_output/vibrator/enable
3290
#echo”0”>/sys/class/timed_output/vibrator/enable
對於enable文件,“寫”表示使能指定的時間,“讀”表示獲取剩餘時間。
2.硬件抽象層的接口
Vibrator硬件抽象層的接口在hardware/libhardware_legacy/include/hardware_legacy/目錄的vibrator.h文件中定義:
int vibrator_on(int timeout_ms);
int vibrator_off();
vibrator.h文件中定義兩個接口,分別表示振動和關閉,振動開始以毫秒作為時間單位。
3. 標準硬件抽象層的實現
Vibrator硬件抽象層具有標準的實現。在hardware/libhardware_legacy/vibrator/目錄的vibrator.c中。
其中實現的核心內容為sendit()函數,這個函數的內容如下:
[java] <span style="font-size:16px;"> #define THE_DEVICE “/sys/class/timed_output/vibrator/enable”
static int sendit(int timeout_ms)
{
int nwr,ret,fd;
char value[20];
ifdef QEMU_HARDWARE
if (qemu_check()){
return qemu_control_command(“vibrator:%d,timeout_ms);
}
#endif
fd=open(THE_DEVICE,O_RDWR);
if(fd<0) return errno;
nwr=sprint(value,”%d\n”,timeout_ms);
ret=write(fd,value,nwr);
close(fd);
return (rnt == nwr) ? 0 : -1;
}
</span>
<span style="font-size:16px;"> #define THE_DEVICE “/sys/class/timed_output/vibrator/enable”
static int sendit(int timeout_ms)
{
int nwr,ret,fd;
char value[20];
ifdef QEMU_HARDWARE
if (qemu_check()){
return qemu_control_command(“vibrator:%d,timeout_ms);
}
#endif
fd=open(THE_DEVICE,O_RDWR);
if(fd<0) return errno;
nwr=sprint(value,”%d\n”,timeout_ms);
ret=write(fd,value,nwr);
close(fd);
return (rnt == nwr) ? 0 : -1;
}
</span>
Sendit()函數負責根據時間“振動”,在真實的硬件中,通過sys文件系統的文件進行控制;如果是模擬器環境則通過QEMU發送命令。
Vibrator_on()調用sendit()以時間作為參數,vibrator_on()調用sendit()以0作為參數。
摘自 北京大學-Google Android實驗室