前幾篇文章陸陸續續實現了HAL,HIDL,JNI,AIDL服務,現在只差最後一步,應用層的實現我們就可以打通應用層到HAL的整個調用流程了,話不多說,上代碼
應用層的實現相對比較簡單,在Android Studio中進行開發,寫完之後拷貝到源碼packages/apps下進行編譯就行了,在packages/apps下創建HelloDemo目錄,將開發好的文件拷貝過來,看看目錄結構:
很簡單的一個應用,把主要文件源碼貼出來一下:
MainActivity.java
package com.android.hello;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.os.IBinder;
import android.app.IHelloService;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.view.Window;
public class MainActivity extends Activity implements View.OnClickListener {
private Button button;
private EditText editText1;
private EditText editText2;
private EditText editText3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
editText1 = findViewById(R.id.edit_text1);
editText2 = findViewById(R.id.edit_text2);
editText3 = findViewById(R.id.edit_text3);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
IHelloService helloService = getHelloService();
if(helloService == null){
Log.d("dongjiao","onClick...faile to get helloService...");
return;
}
Log.d("dongjiao","onClick...success to get helloService...");
int a = Integer.parseInt(editText1.getText().toString());
int b = Integer.parseInt(editText2.getText().toString());
try{
int total = helloService.add(a,b);
editText3.setText(total+"");
Toast.makeText(this,"total = :"+total,Toast.LENGTH_LONG).show();
}catch(RemoteException e){
Log.d("dongjiao","RemoteException = :"+e);
}
}
private IHelloService getHelloService(){
IBinder b = ServiceManager.getService("helloService");
IHelloService helloService = IHelloService.Stub.asInterface(b);
return helloService;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/edit_text1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="請輸入"
android:inputType="number"
/>
<EditText
android:id="@+id/edit_text2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="請輸入"
android:inputType="number"
/>
<EditText
android:id="@+id/edit_text3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="0"
/>
</LinearLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click"
/>
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.hello">
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="HelloDemo"
android:roundIcon="@drawable/ic_launcher"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Android.bp
android_app {
name: "HelloDemo",
srcs: ["src/**/*.java"],
platform_apis: true,
}
這個應用功能就是點擊Button時,獲取前一篇文章實現的HelloService服務,然後調用HelloService的add方法,這個方法會通過JNI到HIDL服務中
接着進行編譯,mmm packages/apps/HelloDemo
編譯成功後將這個APK push到手機中
adb push out/target/product/TOKYO_TF_arm64/system/app/HelloDemo/HelloDemo.apk /system/app/HelloDemo
重啓手機,這個APK界面就這樣:
功能很簡單,三個EditText和一個Button,前兩個EditText用來接收兩個加數,後一個EditText接收它們的和,通過Button調用HelloService的add方法,HelloService的add方法通過JNI到native層再到HIDL調用addition_hidl函數,最終到HAL中調用additionTest函數實現兩個數相加,然後返回給APP,
我們最終目的就是如此
我在HAL,HIDL,JNI,AIDL,APP各層都添加了log,來測試一下:
- 關閉SELinux權限,adb shell setenforce 0
- 啓動HIDL service
- 殺掉system_server讓AIDL服務HelloService重新啓動,HelloService啓動的同時會通過JNI獲取HIDL服務,HIDL服務中又會獲取HAL
如下是AIDL服務HelloService啓動的log輸出
log中HAL,HIDL,JNI,AIDL每層都已經成功輸出log,說明我們在SystemService中啓動HelloService之後到HAL的流程已經打通了(HAL,HIDL,JNI,AIDL可參考前幾篇文章實現),再測試一下APP的功能,輸入兩個數,點擊CLICK按鈕
沒有報錯,成功計算出total值,看看log輸出:
log也很清晰,從APP的click開始,到AIDL,JNI,HIDL,HAL
功能雖簡單,麻雀雖小,五臟俱全,到這裏我們這個系列的文章已經結束,從應用層到HAL的整體流程已經瞭解,其實Android系統的整體流程就是這樣的,只不過它每一層包含複雜的邏輯,但是架構都類似,上層到底層,層層調用,一個APP就可以簡單操縱硬件,一層一層提供接口
瞭解系統調用流程對我們理解Android系統的幫助是非常大的
這幾篇文章的源碼已經上傳github,執行如下命令即可獲取:
git clone https://github.com/tdj520/-HAL.git