Android native進程間通訊實例-binder篇之——HAL層訪問JAVA層的服務

有一天在羣裏聊天的時候,有人提出一個問題,怎樣才能作到HAL層訪問JAVA層的接口?恰好我不會,因此作了一點研究。html

 

以前的文章末尾部分說過了service call 能夠用來調試系統的binder服務。 傳送門: Android native進程間通訊實例-binder篇之——簡單的單工通訊java

此次能夠用到這個命令了!android

 

1. 隨機選取一個java層的服務。shell

adb shell 中輸入命令 service list,選取一個服務來作研究,此次看中的是 textservices, 注意第一個服務 bysysui 後面的 "[ ]" 裏面沒有內容,不能選取這樣的服務來作此次的研究。數組

 

2. 搜尋這個服務相關的源碼。函數

frameworks/base/services/core/java/com/android/server/TextServicesManagerService.javaui

frameworks/base/core/java/com/android/internal/textservice/ITextServicesManager.aidlthis

out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/textservice/ITextServicesManager.javaspa

 

3. 選擇一個接口用於被 HAL 層的代碼訪問3d

能夠知道TextServicesManagerService.java 中 有一行 public class TextServicesManagerService extends ITextServicesManager.Stub,

因此我從 ITextServicesManager.aidl 來選擇要訪問的接口, 此次選的就是 boolean isSpellCheckerEnabled(); 這個函數應該就是返回一個bool變量而已,越簡單越好。

 

4. 搜尋 binder 中 transact 須要輸入的 code

由於吧啦吧啦的緣由(能夠自行去別的博文搜索原理,本系列博文側重實際操做),因此在out目錄下能夠獲取到每一個服務中各個接口訪問鎖須要傳入的code。

在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/textservice/ITextServicesManager.java中能夠發現熟悉的onTransact接口,

同時發現調用 sSpellCheckerEnabled 的code爲TRANSACTION_isSpellCheckerEnabled,

它的定義是:static final int TRANSACTION_isSpellCheckerEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);

由於android.os.IBinder.FIRST_CALL_TRANSACTION的值是1, 因此可知code爲 8

 

5. 使用service call 來撩一下 isSpellCheckerEnabled 

能夠看到Parcel有兩個值,第一個是00000000,第二個是00000001.

再看看ITextServicesManager.java中TRANSACTION_isSpellCheckerEnabled這個code的處理,果真write了兩次,而第二次writeInt的值就是咱們須要獲取的bool值了!

 

ITextServicesManager.java

case TRANSACTION_isSpellCheckerEnabled:
{
    data.enforceInterface(DESCRIPTOR);
    boolean _result = this.isSpellCheckerEnabled();
    reply.writeNoException();
    reply.writeInt(((_result)?(1):(0)));
    return true;
}

  

按照以前分析的方法,傳送門:Android native進程間通訊實例-binder篇之——用parcel傳輸數組

1. 首先data.enforceInterface 傳進去了一個組字符串 private static final java.lang.String DESCRIPTOR = "com.android.internal.textservice.ITextServicesManager"; 

感受這組字符串是和校驗有關了,查看了Parcel.cpp 源碼, 發現enforceInterface果真是對比字符串用的,在這個接口的上面有個接口名字叫作 writeInterfaceToken,

因此到時候要用 writeInterfaceToken 來寫這組字符串用於比對校驗。

2. writeNoException 和 writeInt 最終調用的是 Parcel.cpp 裏面writeInt32,因此reply部分要 readInt32 兩次。

 

6. HAL層代碼怎麼寫

就直接在以前寫的mybinderclient.cpp 上面貼源碼吧transct 前寫校驗字符串,而後傳入code 值爲8,最後readInt32 兩次,第二次就是要讀取的JAVA 層服務isSpellCheckerEnabled  的值啦!

#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>

#include<stdio.h>

#define LOG_TAG "binderclient"

using namespace android;


int main(int argc, char** argv)
{
    static  int TRANSACTION_isSpellCheckerEnabled = (/*android.os.IBinder.FIRST_CALL_TRANSACTION*/1 + 7);

    sp<IBinder> ITextServicesBinder = defaultServiceManager()->getService(String16("textservices"));

    Parcel ITextServicesData, ITextServicesReply;

    ITextServicesData.writeInterfaceToken(String16("com.android.internal.textservice.ITextServicesManager"));
    
    ITextServicesBinder->transact(TRANSACTION_isSpellCheckerEnabled, ITextServicesData, &ITextServicesReply);

    int ret = ITextServicesReply.readInt32();
    int ret2 = ITextServicesReply.readInt32();

    printf("ret = %d, isSpellCheckerEnabled = %d\n", ret, ret2);

    return 0;
}

  

執行結果:

 

 

 

此次在HAL層經過binder 訪問 JAVA 層服務的簡單例子就講解到這裏,但願你們看完之後可以舉一反三,在這個例子上面獲得啓發。

但願讀者多多吐槽,咱們一塊兒共同進步!!

 

原文出處:https://www.cnblogs.com/songsongman/p/11100760.html

相關文章
相關標籤/搜索