在Ubuntu上為Android系統的ApplicationFrameworks層增加硬體訪問服務

歐陽鵬發表於2013-03-25

在數字科技日新月異的今天,軟體和硬體的完美結合,造就了智慧移動裝置的流行。今天大家對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介面:

[java] view
plain
copy
  1. package android.os;  
  2.    
  3. interface IHelloService {  
  4.     void setVal(int val);  
  5.     int getVal();  
  6. }  

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介面:
    USER-NAME@MACHINE-NAME:~/Android$ mmm frameworks/base

   這樣,就會根據IHelloService.aidl生成相應的IHelloService.Stub介面。

   五.進入到frameworks/base/services/java/com/android/server目錄,新增HelloService.java檔案:

[java] view
plain
copy
  1. package com.android.server;  
  2. import android.content.Context;  
  3. import android.os.IHelloService;  
  4. import android.util.Slog;  
  5. public class HelloService extends IHelloService.Stub {  
  6.     private static final String TAG = “HelloService”;  
  7.     HelloService() {  
  8.         init_native();  
  9.     }  
  10.     public void setVal(int val) {  
  11.         setVal_native(val);  
  12.     }     
  13.     public int getVal() {  
  14.         return getVal_native();  
  15.     }  
  16.       
  17.     private static native boolean init_native();  
  18.         private static native void setVal_native(int val);  
  19.     private static native int getVal_native();  
  20. };  

   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介面來訪問硬體,敬請期待。


相關文章