1. 程式人生 > >Android系統篇之----編寫系統服務並且將其編譯到系統原始碼中

Android系統篇之----編寫系統服務並且將其編譯到系統原始碼中

點選頂部藍字"編碼美麗"關注公眾號

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

宣告:本文內容參考羅昇陽的書籍:《Android系統原始碼情景分析》 如果想了解更詳細的內容非常建議購買此書,非常感謝羅神的這本書,給我帶來很多未知的知識,大神的部落格地址:

http://blog.csdn.net/luoshengyang

溫馨提示:昨天網站掛了,搶修了一下,今天恢復了,謝謝熱心使用者反饋問題:http://www.wjdiankong.cn

一、編寫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原始碼。

專案地址下載:

http://download.csdn.net/detail/jiangwei0910410003/9642835

五、總結

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

祝大家國慶節快樂,過完節之後咋們就要繼續iOS的狂暴之路,知識已經準備就緒了,就等過節之後來耍耍了!

手機檢視文章不方便,可以網頁看

http://www.wjdiankong.cn

  

徐宜生(醫生)大神公眾號 "Android群英傳",關注瞭解更多技術內容

相關閱讀:

相關推薦

Android系統----編寫系統服務並且編譯系統原始碼

點選頂部藍字"編碼美麗"關注公眾號 在之前已經介紹了一篇關於如何 編寫簡單的驅動以及訪問該驅動的小程式,最後將程式編譯到Android核心原始碼中通過程式訪問驅動驗證是可以通過的,那麼本文就繼續這個知識點,把這個驅動程式通過JNI連線建立一個系統服務,提供給上層應用訪問改服務功能,可以看到前一篇介

Windows系統程式設計編寫Windows服務(1)

一、Windows服務簡介: Windows服務,也稱NT服務,提供將伺服器轉換為可以用命令或者在啟動時初始化的服務所需的管理能力,初始化發生在任何使用者登入之前,服務可以暫停、恢復、終止、監控。 登錄檔維護與服務的有關資訊。     Windows的所有服務在如下圖所

Android系統----免root實現Hook系統服務攔截方法

一、Binder機制回顧 在之前一篇文章中介紹了 Android中的Binder機制和系統遠端服務呼叫機制,本文將繼續借助上一篇的內容來實現Hook系統服務攔截指定方法的邏輯,瞭解了上一篇文章之後,知道系統的服務其實都是一個遠端Binder物件,而這個物件都是由Se

Android系統-免root實現Hook系統服務攔截方法

第二篇讀書筆記 梳理了下思路,解決了疑惑 我們使用剪下板服務的時候是呼叫了ContextImpl的getSystemService方法 ContextImpl的getSystemService方法 @Override public

Android系統----解讀AMS遠端服務呼叫機制以及Activity的啟動流程

一、為何本文不介紹Hook系統的AMS服務在之前一篇文章中已經講解了 Android中Hook系統服務,以及攔截具體方法的功能了,按照流程本文應該介紹如何Hook系統的AMS服務攔截應用的啟動流程操作,

Hadoop基礎-MapReduce入門編寫簡單的Wordcount測試程式碼

            Hadoop基礎-MapReduce入門篇之編寫簡單的Wordcount測試程式碼                                               作者:尹正傑 版權宣告:原創作品,謝絕轉載!否則將追究法律責任。        

【朝花夕拾】Android效能(一)序言及JVM

序言        筆者從事Anroid開發有些年頭了,深知掌握Anroid效能優化方面的知識的必要性,這是一個程式設計師必須修煉的內功。在面試中,它是面試官的摯愛,在工作中,它是程式碼質量的攔路虎,其重要性可見一斑。在團隊中,效能優化的工作又往往由經驗豐富的老師傅來

Android粒子文字的粒子化運動

零、前言 1.第一次接觸粒子是在html5的canvas,說是html的canvas,倒不如說是JavaScript的canvas,畢竟核心都在js。 2.經過長久的醞釀,感覺Java實現粒子運動好像也不是什麼難事,Android粒子篇將用Android作為視口,帶你領略粒子的炫酷。 3.關於效能方面

【朝花夕拾】Android效能(六)Android程序管理機制

一、Android程序管理的特殊設計        Linux系統對程序的管理方式是一旦程序活動停止,系統就會結束該程序。儘管Android基於Linux Kernel,但在程序管理上,卻採取了另外一種獨特的設計:當程序活動停止時,系統並不會立刻結束它,而是會盡可能地將該程序儲存在記憶體中,在以後的某個時間,

Android基礎Android快速入門--你必須要知道的基礎

1. Activity的理解: 2. Intent的理解 關於IntentFilter 3. Intent的使用:(建立、攜帶資料、讀取資料) 1.建立:      顯式意圖: Intent intent = new Inten

Android面試軟引用和弱引用的區別

軟引用所指向的物件要進行回收,需要滿足兩個條件: ● 沒有任何強引用 指向 軟引用指向的物件(記憶體中的Person物件) ● JVM需要記憶體時,即在丟擲OOM之前 即SoftReference變相

Android面試ArrayList和LinkedList的區別

● 資料結構 ArrayList基於動態陣列;LinkedList基於連結串列 ● 隨機訪問 ArrayList優於LinkedList,因為LinkedList要移動指標來查詢,下面以get方法為例

Android面試Activity與Fragment、Fragment與Fragment之間的通訊

Activity與Fragment Activity向Fragment通訊 ① 拿到Fragment的引用,直接呼叫其public方法。 ② 如果Activity中未儲存任何Fragment的引用,

Android面試IPC機制[程序之間的通訊]

簡介 IPC Inter-Process Communication 跨程序通訊,兩個程序之間進行資料交換的過程 在Android中的多程序一般指一個應用中存在多個程序的情況,下面討論一個應用中多程序

android studio簡單呼叫攝像頭並且獲取照片

1.首先讓我們來理清一下其中的邏輯:拍一張照片,獲取其路徑,根據路徑進行展示。2.好了我們已經理清好邏輯了:那我們就想如何實現,首先我們要實現一個app呼叫拍照功能,很簡單,我們學過用一個活動呼叫另一個活動的intent,很明顯是有的,然後我們要如何讓拍到的照片返回到我們的a

【朝花夕拾】Android效能(七)Android跨程序通訊

前言        Android系統的執行由大量相互獨立的程序相互協助來完成的,所以Android程序間通訊問題,是做好Android開發高階工程師必須要跨過的一道坎,也是面試時經常被問及到的知識點。但是,我們是否真的清楚,Android中都有哪些方式實現跨程序通訊

Android自定義控制元件畫圓,並且修改填充色

畫圓就是簡答呼叫了drawCircle的api public class Dot extends View { public Dot(Context context) { s

Android中級Fresco-載入圖片基礎[詳細圖解Fresco的使用]

常見問題: 初次使用,我們就先簡單書寫我們的 activity_main.xml : <code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing

Android基礎在ListView顯示網路圖片

http://blog.csdn.net/y13872888163/article/details/6434001 最近在做一個天氣預報的例子,想在ListView中新增網路圖片,在翻閱很多文件,在Baidu上Google很久,終於找到了辦法,現在跟大家分享一下解決方

野人學Android基礎初探UI控制元件第一課--TextView動態賦值

除了上節課中講到的TextView靜態賦值,還有一種更加靈活的賦值方法–動態賦值。在app的執行過程中,根據程式的需要可以隨時改變TextView的值。 其實現的基本邏輯可以歸納如下: 1.通過id獲取我們要操作的TextView控制元件 2.使用一些方法