AndroidQ 打通應用層到HAL層---(應用層實現)

前幾篇文章陸陸續續實現了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,來測試一下:

  1. 關閉SELinux權限,adb shell setenforce 0
  2. 啓動HIDL service
    在這裏插入圖片描述
  3. 殺掉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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章