161
技術社區[雲棲]
在Ubuntu上為Android係統的Application Frameworks層增加硬件訪問服務
在數字科技日新月異的今天,軟件和硬件的完美結合,造就了智能移動設備的流行。今天大家對iOS和Android係統的趨之若鶩,一定程度上是由於這兩個係統上有著豐富多彩的各種應用軟件。因此,軟件和硬件的關係,在一定程度上可以說,硬件是為軟件服務的。硬件工程師研發出一款硬件設備,自然少了軟件工程師為其編寫驅動程序;而驅動程序的最終目的,是為了使得最上層的應用程序能夠使用這些硬件提供的服務來為用戶提供軟件功能。對Android係統上的應用軟件來說,就是要在係統的Application Frameworks層為其提供硬件服務。在前麵的幾篇文章中,我們著重介紹了Linux內核層、硬件抽象層和運行時庫層提供的自定義硬件服務接口,這些接口都是通過C或者C++語言來實現的。在這一篇文章中,我們將介紹如何在Android係統的Application Frameworks層提供Java接口的硬件服務。
一. 參照在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口一文所示,為硬件抽象層模塊準備好JNI方法調用層。
二. 在Android係統中,硬件服務一般是運行在一個獨立的進程中為各種應用程序提供服務。因此,調用這些硬件服務的應用程序與這些硬件服務之間的通信需要通過代理來進行。為此,我們要先定義好通信接口。進入到frameworks/base/core/java/android/os目錄,新增IHelloService.aidl接口定義文件:
USER-NAME@MACHINE-NAME:~/Android$ cd frameworks/base/core/java/android/os
USER-NAME@MACHINE-NAME:~/Android/frameworks/base/core/java/android/os$ vi IHelloService.aidl
IHelloService.aidl定義了IHelloService接口:
- package android.os;
- interface IHelloService {
- void setVal(int val);
- int getVal();
- }
IHelloService接口主要提供了設備和獲取硬件寄存器val的值的功能,分別通過setVal和getVal兩個函數來實現。
三.返回到frameworks/base目錄,打開Android.mk文件,修改LOCAL_SRC_FILES變量的值,增加IHelloService.aidl源文件:
## READ ME: ########################################################
##
## When updating this list of aidl files, consider if that aidl is
## part of the SDK API. If it is, also add it to the list below that
## is preprocessed and distributed with the SDK. This list should
## not contain any aidl files for parcelables, but the one below should
## if you intend for 3rd parties to be able to send those objects
## across process boundaries.
##
## READ ME: ########################################################
LOCAL_SRC_FILES += /
....................................................................
core/java/android/os/IVibratorService.aidl /
core/java/android/os/IHelloService.aidl /
core/java/android/service/urlrenderer/IUrlRendererService.aidl /
.....................................................................
這樣,就會根據IHelloService.aidl生成相應的IHelloService.Stub接口。
五.進入到frameworks/base/services/java/com/android/server目錄,新增HelloService.java文件:
- package com.android.server;
- import android.content.Context;
- import android.os.IHelloService;
- import android.util.Slog;
- public class HelloService extends IHelloService.Stub {
- private static final String TAG = "HelloService";
- HelloService() {
- init_native();
- }
- public void setVal(int val) {
- setVal_native(val);
- }
- public int getVal() {
- return getVal_native();
- }
- private static native boolean init_native();
- private static native void setVal_native(int val);
- private static native int getVal_native();
- };
HelloService主要是通過調用JNI方法init_native、setVal_native和getVal_native(見在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口一文)來提供硬件服務。
六. 修改同目錄的SystemServer.java文件,在ServerThread::run函數中增加加載HelloService的代碼:
@Override
public void run() {
....................................................................................
try {
Slog.i(TAG, "DiskStats Service");
ServiceManager.addService("diskstats", new DiskStatsService(context));
} catch (Throwable e) {
Slog.e(TAG, "Failure starting DiskStats Service", e);
}
try {
Slog.i(TAG, "Hello Service");
ServiceManager.addService("hello", new HelloService());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Hello Service", e);
}
......................................................................................
}
七. 編譯HelloService和重新打包system.img:
USER-NAME@MACHINE-NAME:~/Android$ mmm frameworks/base/services/java
USER-NAME@MACHINE-NAME:~/Android$ make snod
這樣,重新打包後的system.img係統鏡像文件就在Application Frameworks層中包含了我們自定義的硬件服務HelloService了,並且會在係統啟動的時候,自動加載HelloService。這時,應用程序就可以通過Java接口來訪問Hello硬件服務了。我們將在下一篇文章中描述如何編寫一個Java應用程序來調用這個HelloService接口來訪問硬件,敬請期待。
最後更新:2017-04-03 12:54:58