Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android系統篇之編寫系統服務

Android系統篇之編寫系統服務

編輯:關於Android編程

在之前已經介紹了一篇關於如何編寫簡單的驅動以及訪問該驅動的小程序,最後將程序編譯到Android內核源碼中通過程序訪問驅動驗證是可以通過的,那麼本文就繼續這個知識點,把這個驅動程序通過JNI連接創建一個系統服務,提供給上層應用訪問改服務功能,可以看到前一篇介紹驅動程序的功能是屬於內核層的,而本文介紹的內容是Framework層的知識。

一、編寫JNI層服務代碼

第一步:創建JNI目錄

進入到系統的JNI目錄中:frameworks/base/services/jni 在這個目錄中包含了系統服務的所有JNI實現的程序:

\

 

第二步:編寫JNI代碼

實現代碼也比較簡單,直接訪問之前編譯好的驅動即可,然後在提供給外部一個讀寫的方法,最後在進行JNI方法的手動注冊:

\

 

第三步:修改編譯腳本

在同一目錄中有一個Android.mk文件,需要添加我們的這個服務,後續要將這個服務編譯到源碼中:

\

 

第四步:添加服務JNI功能的加載配置

上面已經編寫好了我們的系統服務功能,也手動注冊了一些讀寫方法,那麼還需要把這個注冊功能添加到系統的onload.cpp文件中被調用,不然系統編譯之後也是找不到那個JNI方法的,而這個onload.cpp程序,是系統啟動的時候去運行,內部是專門注冊系統服務的JNI方法的:

\

 

第五步:編譯framework層源碼

上面幾步已經完成了代碼編寫和腳本配置,下面就可以直接編譯源碼,把這個服務的JNI功能編譯到源碼中,可以直接使用mmm命令進行單獨模塊的編譯:

mmm frameworks/base/services/jni
make snod

這樣編譯之後的system.img中就包含了我們定義的系統JNI服務實現邏輯,接下來我們就可以編寫Java代碼來訪問這個JNI暴露的讀寫方法了。

 

二、編寫Java層服務代碼

第一步:創建服務的AIDL文件

進入系統服務的AIDL文件目錄:frameworks/base/core/java/android/os 這裡存放了系統所有服務的AIDL定義

\

關於AIDL內容,也是很簡單的,提供讀寫方法:

\

 

第二步:編譯AIDL文件

我們在使用AIDL的時候都知道,定義完文件之後,必須編譯一下,生成對應的Java代碼,這樣後續才能使用類似於XXX.Stub類,才能在遠端服務實現具體功能。這裡也是一樣的,所以我們得先編譯這個aidl文件:

mmm frameworks/base

單獨編譯framework模塊代碼,這樣就會產生對應的IFregService.Stub類了。

 

第三步:實現具體服務功能

上面已經編譯aidl文件,生成了對應的java代碼,下面如果想實現具體的功能,就必須繼承Stub類,這個文件存放的目錄為:frameworks/base/services/java/com/android/server 系統中所有具體服務實現都是在這個目錄中:

\

代碼實現也比較簡單:

\

在這裡會定義讀寫的native方法,和之前的JNI層實現的方法對應:

\

 

第四步:將服務添加到ServiceManager中

為了讓上次訪問到這個服務,和系統其它服務一樣,咋們必須得把服務注冊到ServiceManager中,而這個注冊功能是在SystemServer類中,因為在系統啟動的時候,Zygote進程產生的第一個進程就是system_server,在這個進程中做了系統服務的注冊工作,我們在服務的同一目錄中找到SystemServer.java類,在ServerThread::run函數中注冊:

\

這樣注冊之後,上層應用就可以通過ServiceManager直接獲取到這個服務了,就可以直接訪問具體功能了。

 

第六步:編譯Framework源碼

上面都已經完成了Java層服務代碼的實現了,而到這裡,我們似乎已經看到了熟悉的代碼了,比如服務的AIDL定義,實現和注冊服務功能,和之前介紹的 Binder機制以及遠程服務調用機制的知識 越來越接近了,下面在最後一步,編譯源碼:

mmm frameworks/base/services/java
make snod

編譯之後得到system.img文件就包含了我們在Framework定義的FregService服務了,而這個服務的名稱是freg,下面繼續介紹如何編寫一個程序來訪問這個服務功能。

 

三、編寫系統應用訪問服務功能

前面已經介紹了編寫Framework中的服務功能,在JNI層實現了訪問驅動的native代碼,然後實現了Java層代碼調用這些native方法實現驅動的讀寫功能,並且定義了一個系統服務,包裝這些功能,最後把這個服務注冊到系統中,這裡我們就來編寫一個簡單的Android系統程序,來訪問這個服務功能:

第一步:創建程序項目

創建系統程序項目都是在這個目錄中:packages/experimental,我們定義一個Freg項目:

\

這個項目結構和正常的Android程序結構一樣,沒什麼好說的,因為這裡不是依賴於IDE編譯,所以咋們還得編寫編譯腳本Android.mk文件:

\

關於Android程序代碼也比較簡單,直接通過ServiceManager來訪問這個服務即可:

\

 

第二步:編譯應用程序

上面的程序創建完成之後,接下來再次編譯源碼,把這個應用打包到系統中:

mmm packages/experimental/Freg
make snod

編譯完成之後,生成的system.img文件就包含了這個系統應用程序

 

第三步:啟動模擬器驗證程序

接下來咋們就可以啟動模擬器,來運行這個小程序了:

emulator -kernel kernel/common/arch/arm/boot/zImage &

我們找到這個程序之後,打開的效果:

\

打開這個程序之後,我們可以進行讀寫操作了:

\

 

 

四、流程總結

到這裡我們就成功了完成了手動編寫一個簡單的系統服務並且添加到系統中,結合之前的一篇文章內容,下面就來總結整個過程,先來一張圖壓壓驚:

\

有了這張圖咋們再來總結一下:

1、編寫驅動
1>在 kernel/driver 目錄下創建freg驅動程序
2>make menuconfig 編譯驅動程序到內核源碼中

2、編寫Framework層服務的JNI程序
1>在 frameworks/base/services/jni 目錄下創建了服務的jni代碼
2>在onload.cpp中添加服務jni方法的注冊邏輯
3>mmm frameworks/base/services/jni 編譯jni程序到系統源碼中

3、編寫Framework層服務的Java程序
1>在 frameworks/base/core/java/android/os 目錄下創建了服務的AIDL文件
2>mmm frameworks/base 編譯AIDL文件,生成對應的Java代碼
3>在 frameworks/base/services/java/com/android/server 目錄中編寫具體服務的實現功能
4>最後在同一目錄下找到SystemServer.java文件中注冊該服務(ServiceManager.addService方法)
5>mmm frameworks/base/services/java 編譯java層服務

4、編寫系統Android應用程序
1>在 packages/experimental 目錄下創建Android項目,在程序中直接使用ServiceManager來得到遠端服務即可
2>mmm packages/experimental/Freg 編譯程序到系統中
3>啟動模擬器驗證結果 :emulator -kernel kernel/common/arch/arm/boot/zImage &

 

說到底,其實這個實驗有的同學可能非常感興趣,可能想立馬就實驗一把,但是這裡現在最大的問題就是你得必須先編譯過Android源碼,這個是最核心的也是最基本的,然後在按照這些流程走的話就很簡單了,所以作為一個Android開發者畢生還是要編譯一次Android源碼的。所以感興趣的同學應該趕快動起手來編譯Android源碼。

五、總結

到這裡就結束了如何手動編寫系統服務並且添加到系統中的工作了,同時也暫時結束了這段時間介紹的Android系統篇的系列知識,其實我本來只是想介紹如何Hook掉系統的AMS服務攔截應用啟動的知識,可是誰都想不到引出了這麼一大串的知識出來,沒辦法我也只能慢慢的一篇一篇介紹了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved