Android HAL 徹底探求 (1): アーキテクチャの概要

この記事では、Android HAL のさまざまな方法とアーキテクチャ、およびそれらの間の違いと関係について詳しく学びます。最初は最も初期のレガシー HAL から始まり、Android 8.0 (Oreo) から始まる新しい HAL 定義方法である HIDL (ハードウェア インターフェイス定義言語) が導入されます。HIDL の 2 つのモード (パススルー モードとバインダ化モード) を比較し、それぞれの長所と短所を分析します。最後に、HAL の役割と重要性をまとめ、今後の開発の方向性を展望します。コード構造はカスタム SystemGpio サンプル (レガシー HAL) に基づいています。

一連の記事:
Android HAL の詳細な調査 (1): アーキテクチャの概要
Android HAL の詳細な調査 (2): 従来の HAL とファイルの暗号化および復号化のシミュレーション
Android HAL の詳細な調査 (3): HIDL パススルー モードとシリアル ポートデータ コールバック シミュレーション
Android HAL の詳細な調査 (4): HIDL バインド化モードと CAN データ コールバック シミュレーション
Android HAL の詳細な調査 (5): HAL エラー レポートと解決策のデバッグ

0.参考学習

ハードウェア抽象化層 (HAL) 概要
HIDL C++ | Android オープンソース プロジェクト
HAL タイプ | Android オープンソース プロジェクト
HIDL 詳細解説 - Android10.0 HwBinder 通信原理 (2)
Rockchip シリーズ カスタマイズ GPIO インターフェイス ハードウェア編 (3)

ここに画像の説明を挿入します

1. レガシー HAL

HIDL が登場する前、Android は C 言語で書かれた従来の HAL を使用していました。この HAL は一連の構造体と関数ポインターを定義し、その 1 つがhw_module_tハードウェア モジュールを表します。/hardware/libhardware/include/hardware/このスタイルの HAL は通常、ディレクトリにあります。

インタラクティブモード

従来の HAL は、ハードウェア関連の機能とサービスを提供するために Android フレームワークと対話する必要があります。これを実現するには、従来の HAL は次のレベルを通過する必要があります。

  • Java フレームワーク インターフェイス: これは、Android フレームワークで定義された Java クラスまたはインターフェイスであり、アプリケーションまたはサービスに API を提供するために使用されます。たとえば、android.os.SystemGpioこれは GPIO (汎用入力/出力) ポートを制御するために使用される Java クラスです。
  • AIDL インターフェイス: これは Android フレームワークで定義された AIDL (Android インターフェイス定義言語) ファイルであり、クロスプロセス通信中に受け渡しまたは返す必要があるデータ型とメソッド シグネチャを記述するために使用されます。android.os.IGpioService.aidlこれは、GPIO サービスが実装する必要があるインターフェイスを定義するために使用される AIDL ファイルです。
  • Java でのサービス実装: AIDL インターフェイスを実装する Android フレームワークの Java クラスで、サービスとしてバックグラウンドで実行し、他のプロセスやアプリケーションからのリクエストを処理するために使用されます。com.android.server.GpioServiceこれは、GPIO サービスを実装するために使用される Java クラスです。
  • JNI レイヤー: これは、JNI (Java Native Interface) を使用して Java レイヤーと C レイヤー間の対話をブリッジする Android フレームワークの C/C++ コードです。JNI 層は、Java 層によって渡されたパラメータを C 層が認識できるデータ型に変換し、対応する C 関数を呼び出す役割を果たします。逆に。com_android_server_GpioService.cppGPIO HAL 関連関数を呼び出すために使用される JNI レイヤー ファイルです。
  • HAL ヘッダー: これは、構造体や関数ポインターなどのインターフェイス仕様を定義する、従来の HAL の C ヘッダー ファイルです。hardware/libhardware/include/hardware/これらのヘッダー ファイルは通常、ディレクトリにあり、_hal.h末尾が . gpio_hal.hこれは、GPIO HAL 関連のインターフェイスを定義するために使用される HAL ヘッダー ファイルです。
  • HAL 実装: 従来の HAL の HAL ヘッダー ファイルで定義されたインターフェイス仕様を実装する C コードです。これらのコードは通常hardware/libhardware/modules/、ディレクトリにあり、_hal.cで終わります。gpio_hal.cGPIO HAL関連機能を実装するために使用されるHAL実装ファイルです。
  • カーネル ドライバー: これはハードウェアと直接対話するドライバー層コードであり、通常はオペレーティング システム カーネルの一部です。これらのコードは通常、kernel/drivers/ディレクトリにあり、.cまたはで終わります.hgpio.cこれは、GPIO ポートの入出力ステータスを制御するために使用されるドライバー層ファイルです。

コードアーキテクチャ

従来の HAL は、Android システムの初期のハードウェア抽象化レイヤー設計です。その主な目的は、Android フレームワークに統合インターフェイスを提供し、フレームワークがハードウェアの特定の実装を気にせずに基盤となるハードウェアと対話できるようにすることです。

  • Java フレームワーク インターフェイス:

    • frameworks/base/core/java/android/os/SystemGpio.java: これは、アプリケーションおよびシステム サービスが GPIO ハードウェアと対話する Android フレームワークの Java インターフェイスです。
  • AIDLインターフェース:

    • frameworks/base/core/java/android/os/IGpioService.aidl: AIDL (Android Interface Definition Language) は、アプリケーションが別のプロセスで実行されている GPIO サービスと通信できるようにするクロスプロセス インターフェイスを定義します。
  • Java でのサービスの実装:

    • frameworks/base/services/core/java/com/android/server/GpioService.java: これは、アプリケーションからのリクエストを処理し、JNI を介して基礎となるハードウェアと対話する GPIO サービスの Java 実装です。
  • JNI レイヤー:

    • frameworks/base/services/core/jni/com_android_server_GpioService.cpp: JNI (Java Native Interface) レイヤーにより、Java コードがネイティブ C/C++ コードと対話できるようになります。ここでの JNI コードは、Java サービスと HAL の間の通信を橋渡しするものです。
  • HALヘッダー:

    • hardware/libhardware/include/hardware/gpio_hal.h: これは HAL のヘッダー ファイルであり、ハードウェアと対話するために必要なインターフェイスとデータ構造を定義します。
  • HALの実装:

    • hardware/libhardware/modules/gpio/gpio_hal.c: これは HAL の C 実装であり、基礎となるハードウェア ドライバーと対話します。
  • カーネルドライバー:

    • kernel/drivers/misc/gpio/gpio.c: これは Linux カーネルの GPIO ドライバーであり、ハードウェアと直接対話します。

アーキテクチャ図

従来の HAL アーキテクチャを次の図に示します。
ここに画像の説明を挿入します

従来の HAL の利点は、シンプルかつ直接的で、理解と実装が簡単であることです。しかし、主に次のようないくつかの欠点もあります。

  • バージョン管理と下位互換性の欠如: 従来の HAL には、明確なバージョン番号とインターフェイス変更メカニズムがありません。ハードウェア サプライヤーまたは Android システムが HAL インターフェイスを変更または拡張する必要がある場合は、JNI レイヤー、フレームワーク レイヤー、アプリケーション レイヤーを含むすべての関連コードを同時に変更する必要がありますこのため、コードの保守とアップグレードが困難になり、時間がかかります。
  • セキュリティと安定性の欠如: 従来の HAL は、ライブラリとしてクライアント プロセスに直接リンクされています。つまり、クライアントと HAL 間の呼び出しはプロセス内で行われ、プロセス間通信のオーバーヘッドはありません。しかしこれは、HAL でエラーやクラッシュが発生した場合、クライアント プロセスに影響を与え、さらにはシステム全体のクラッシュを引き起こす可能性があることも意味します。従来の HAL にはサンドボックス機構や権限制御がなく、どのプロセスでもどの HALモジュールに、セキュリティ上のリスクが生じる可能性があります。

従来の HAL の欠点を解決するために、Android では新しい HAL 定義方法である HIDL が 8.0 (Oreo) から導入されました。

HIDL (Hardware Interface Definition Language) は、HAL のインターフェースを定義するために使用される言語です。HIDL は、従来の HAL よりも優れたバージョン管理と下位互換性を提供します。HIDL は、パススルー モードとバインダ化モードという 2 つの異なるモードもサポートします。これら 2 つのモードは、異なる通信方式とアーキテクチャに対応します。

2. HIDLパススルーモード

インタラクティブモード

パススルー モードでは、HAL サービスはクライアント プロセスのライブラリとして実行されます。これは、クライアントと HAL 間の呼び出しがプロセス内で行われ、プロセス間通信のオーバーヘッドがないことを意味します。このモードは従来の HAL に似ていますが、次のような違いがあります。

  • C の代わりに C++ を使用する: パススルー モードの HIDL HAL は C++ で書かれています。これにより、HAL はクラス、継承、ポリモーフィズムなどの C++ 機能を使用できるようになります。
  • .h の代わりに .hal を使用する: パススルー モードの HIDL HAL は、ファイル.halではなくファイルを使用してインターフェイス仕様を定義します.h.halファイルは、HAL インターフェイスで受け渡すか返す必要があるデータ型とメソッド シグネチャを記述するために使用される特別な構文です。通常、ファイルはディレクトリ内に.halあり、末尾は . たとえば、 GPIO HAL 関連のインターフェイスを定義するために使用されるファイルですhardware/interfaces/.halIGpio.hal.hal
  • コードを手動で記述する代わりに hidl-gen を使用します。パススルー モードの HIDL HAL は、ファイルhidl-genから.halC++ および Java コードを生成するツールを使用します。これらのコードには、インターフェイスの実装、クライアント プロキシ、サービス登録、その他の機能が含まれます。これにより、反復的で退屈なコードを手動で記述することがなくなり、コードがインターフェイス仕様と一致していることが保証されます。
  • Android.mk の代わりに Android.bp を使用します。パススルー モードの HIDL HAL は、新しいビルド システム Soong を使用してコードをコンパイルします。Soong は.bpファイルを使用して、HAL インターフェイスで受け渡すか返す必要があるデータ型とメソッド シグネチャを記述します。通常、ファイルはディレクトリ内に.halあり、末尾は . GPIO HAL 関連のインターフェースを定義するために使用されるファイルです。hardware/interfaces/.halIGpio.hal.hal
  • Android.mk の代わりに Android.bp を使用します。パススルー モードの HIDL HAL は、新しいビルド システム Soong を使用してコードをコンパイルします。Soong は、.bpファイルの代わりにファイルを使用して、ビルド ルールと依存関係を記述します.mk.bpファイルは通常、HAL 実装コードと同じディレクトリにあり、.bpで終わります。Gpio.bpGPIO HAL 関連のコードをコンパイルするために使用されるファイルです.bp

パススルー モードの利点は、パフォーマンスが高く、プロセス間通信のオーバーヘッドがないことです。しかし、主に次のようないくつかの欠点もあります。

  • セキュリティと安定性の欠如: パススルー モードには、従来の HAL のセキュリティと安定性の問題が依然として存在します。HAL サービスはクライアント プロセスのライブラリとして実行されるため、HAL でエラーやクラッシュが発生すると、クライアント プロセスに影響を与え、場合によってはシステム全体がクラッシュすることがあります。また、パススルー モードにはサンドボックス メカニズムや権限制御がないため、どのプロセスでもどの HAL モジュールにもアクセスできるため、セキュリティ リスクが生じる可能性があります。
  • 柔軟性とスケーラビリティの欠如: パススルー モードの HIDL HAL は、ライブラリとしてクライアント プロセスにのみリンクできます。つまり、クライアントは C++ ネイティブ サービスまたはアプリケーションである必要があります。クライアントが Java 層のアプリケーションまたはサービスの場合でも、Java と C++ の間の対話を橋渡しするために JNI 層が必要です。これにより、コードが複雑になり、メンテナンスのコストが増加します。また、パススルー モードは、同じ HAL サービスに同時にアクセスする複数のクライアントをサポートしないため、HAL サービスのスケーラビリティが制限されます。

パススルー モードの欠点を解決するために、Android は別の HIDL モード、バインダ化モードも提供します。

コードアーキテクチャ

HIDL (ハードウェア インターフェイス定義言語) は、Android Oreo (8.0) で導入された新しいハードウェア抽象化メカニズムです。パススルー モードは、HAL を従来の方法で実行しながら、HIDL インターフェイスを通じて Android フレームワークと対話できるようにするモードの 1 つです。

  • Java フレームワーク インターフェイス:

    • frameworks/base/core/java/android/os/SystemGpio.java: これは、アプリケーションおよびシステム サービスが GPIO ハードウェアと対話する Android フレームワークの Java インターフェイスです。
  • HIDL インターフェイス定義:

    • hardware/interfaces/gpio/1.0/IGpio.hal: これは、GPIO ハードウェアと対話する方法を記述する HIDL によって定義されたインターフェイスです。
  • ネイティブサービスの実装:

    • frameworks/base/services/core/jni/com_android_server_GpioService.cpp: Java レイヤーがハードウェアに直接アクセスする必要がある場合、この JNI レイヤーを通じて HIDL インターフェイスと対話します。
  • HALの実装:

    • hardware/interfaces/gpio/1.0/default/Gpio.cpp: これは HIDL HAL の実装であり、基盤となるハードウェア ドライバーと対話します。
  • カーネルドライバー:

    • kernel/drivers/misc/gpio/gpio.c: これは Linux カーネルの GPIO ドライバーであり、ハードウェアと直接対話します。

アーキテクチャ図

パススルー モードの HIDL HAL のアーキテクチャを次の図に示します。

ここに画像の説明を挿入します

3. HIDL バインダ化モード:

インタラクティブモード

バインダ化モードでは、HAL サービスは独立したプロセスとして実行されます。クライアントと HAL 間の通信は、Binder IPC を介して行われます。このモードはパススルー モードとは異なりますが、次の共通点があります。

  • C の代わりに C++ を使用する: バインダー化モードの HIDL HAL も C++ で記述されます。
  • .h の代わりに .hal を使用します。バインダ化モードの HIDL HAL も.halファイルを使用してインターフェイス仕様を定義します。
  • コードを手動で記述する代わりに hidl-gen を使用します。バインダー化モードの HIDL HAL は、ファイルhidl-genから C++ および Java コードを生成するためにも使用されます.hal
  • Android.mk の代わりに Android.bp を使用します。バインダー化モードの HIDL HAL も Soong を使用してコードをコンパイルします。

Binderized モードの利点は、HAL サービスが独自のサンドボックス環境で実行され、SELinux を通じて許可できるため、高いセキュリティと安定性です。バインダ化モードでは、複数のクライアントが同じ HAL サービスに同時にアクセスすることもサポートされ、HAL サービスのスケーラビリティが向上します。しかし、主に次のようないくつかの欠点もあります。

  • 低パフォーマンス: バインダー化モードの HIDL HAL では、バインダー IPC を介したクロスプロセス通信が必要となり、追加のオーバーヘッドと遅延が発生します。特に、オーディオ、ビデオ、センサーなど、高周波数または低遅延要件を持つ一部のハードウェア サービスの場合、Binder IPC はそのパフォーマンスとエクスペリエンスに影響を与える可能性があります。
  • 高い複雑さ: バインダー化モードの HIDL HAL は独立したサービス プロセスを実装する必要があるため、コードの複雑さとメンテナンス コストが増加します。特に、GPIO、LED などの一部の単純なハードウェア サービスや使用頻度が低いハードウェア サービスの場合、独立したサービス プロセスを実装する必要がない場合があります。

コードアーキテクチャ

バインダー化モードは、HAL が別のプロセスとして実行され、Binder IPC を通じて Android フレームワークと対話する HIDL の別のモードです。

  • Java フレームワーク インターフェイス:

    • frameworks/base/core/java/android/os/SystemGpio.java: これは、アプリケーションおよびシステム サービスが GPIO ハードウェアと対話する Android フレームワークの Java インターフェイスです。
  • HIDL インターフェイス定義:

    • hardware/interfaces/gpio/1.0/IGpio.hal: これは、GPIO ハードウェアと対話する方法を記述する HIDL によって定義されたインターフェイスです。
  • HAL サービスの実装:

    • hardware/interfaces/gpio/1.0/service/GpioService.cpp: これは、Binderized モードでの HAL サービス実装であり、独立したプロセスとして実行され、Binder IPC を通じて Android フレームワークと対話します。
  • カーネルドライバー:

    • kernel/drivers/misc/gpio/gpio.c: これは Linux カーネルの GPIO ドライバーであり、ハードウェアと直接対話します。

アーキテクチャ図

バインダ化モードの HIDL HAL のアーキテクチャを次の図に示します。

ここに画像の説明を挿入します

概要: HIDL は、パススルー モードとバインダ化モードという 2 つの異なるモードを提供します。これら 2 つのモードは、異なる通信方式とアーキテクチャに対応します。パススルー モードはパフォーマンスは高くなりますが、セキュリティと安定性は低くなります。バインダ化モードはセキュリティと安定性が高くなりますが、パフォーマンスは低くなります。特定のハードウェア サービスとニーズに基づいて、適切なモードを選択できます。

HALの役割と意義

HAL は Android システムとハードウェア間のブリッジであり、Android フレームワークの標準インターフェイスを提供し、ハードウェアの特定の実装の詳細を知らなくても Android フレームワークがさまざまなハードウェアと対話できるようにします。HALの機能と意義としては主に以下の点が挙げられます。

  • ハードウェア ベンダーと Android システム間の互換性の向上: HAL を通じて、ハードウェア ベンダーはドライバーや Android システムを変更することなく、Android 仕様を満たすインターフェイスをハードウェアに提供できます。これにより、ハードウェア ベンダーはハードウェアを Android プラットフォームに適応させ、ドライバーをより迅速に更新することが容易になります。
  • Android システムとアプリケーション間の抽象化の向上: HAL を通じて、Android システムとアプリケーションは、ハードウェアの特定の実装の詳細を気にすることなく、統合 API を使用してハードウェア サービスにアクセスできます。これにより、Android システムとアプリケーションが複数のハードウェア プラットフォームとデバイスをサポートし、機能をより柔軟に拡張および最適化することが容易になります。
  • Android システムとアプリケーション間のセキュリティと安定性の向上: HAL を通じて、Android システムとアプリケーションは、サンドボックス メカニズムと権限制御を通じてハードウェア サービスへのアクセスを制限し、悪意のある操作や誤った操作によるハードウェアやシステムへの損傷を防ぐことができます。HAL を通じて、Android システムとアプリケーションは、ハードウェア サービスのエラーやクラッシュによって引き起こされた問題を隔離または回復して、システムとアプリケーションの正常な動作を保証することもできます。

今後の開発の方向性

Android システムとハードウェア プラットフォームが開発と革新を続けるにつれて、HAL もそれに応じて変化し、進化します。考えられる開発の方向性:

  • さらなる HIDL 化: HIDL は HAL を定義する新しい方法であり、より優れたバージョン管理と下位互換性を提供します。現在、HIDL はオーディオ、ビデオ、センサー、カメラなどのほとんどのハードウェア サービスをカバーしています。ただし、電源管理、メモリ管理など、HIDL 化されていない従来の HAL がまだいくつかあります。将来的には、互換性と保守性を向上させるために、より従来の HAL が HIDL 化される可能性があります。
  • さらなるバインダ化: バインダ化モードは、より高いセキュリティと安定性を提供する新しい HAL 通信方式です。現在、バインダ化モードは、オーディオ、ビデオ、センサー、カメラなど、ほとんどの HIDL HAL に適用できます。ただし、GPIO、LED など、バインダ化されていないパススルー モードがまだいくつかあります。セキュリティとスケーラビリティを向上させるために、より多くのパススルー パターンがバインダ化される可能性があります。
  • 詳細 VTS : VTS (Vendor Test Suite) は、HAL の機能、互換性、セキュリティ、パフォーマンスのテストを自動的に実行できる新しい HAL テスト ツールです。現在、VTS はオーディオ、ビデオ、センサー、カメラなど、ほとんどの HIDL HAL をサポートしています。ただし、電源管理、メモリ管理など、VTS 化されていない HAL がまだいくつかあります。品質と信頼性を向上させるために、さらに多くの HAL が VTS 化される可能性があります。

要約する

Android HAL は、Android システムとハードウェア間の標準インターフェイスを提供する重要なコンポーネントです。HAL のさまざまなメソッドとアーキテクチャは、Android システムとハードウェア プラットフォームの継続的な開発と革新を反映しています。この記事では、Android HAL を学習する 3 つの方法 (レガシー HAL、HIDL パススルー モード、HIDL バインダライズド モード) の基本概念を深く掘り下げ、それらの違いと関連性を分析します。また、HAL の役割と意義をまとめ、今後の開発の方向性を展望します。

おすすめ

転載: blog.csdn.net/SHH_1064994894/article/details/132608830