Cảm biến sử dụng nhiều lớp trừu tượng (HAL)

Lớp HAL (HAL) cho cảm biến là một khung cho phép HAL cảm biến chạy cùng với các HAL cảm biến khác. Tính năng Multi-HAL của cảm biến tải động các lớp HAL của cảm biến được lưu trữ dưới dạng thư viện động trên phân vùng nhà cung cấp và cung cấp cho chúng một đối tượng gọi lại có thể xử lý việc đăng sự kiện cũng như thu nạp và giải phóng khoá chế độ thức. HAL phụ của cảm biến là một HAL cảm biến được tích hợp vào một đối tượng dùng chung trên phân vùng của nhà cung cấp và được sử dụng bởi khung đa HAL. Các HAL phụ này không phụ thuộc lẫn nhau hoặc phụ thuộc vào mã nhiều HAL chứa chức năng chính cho quy trình.

Cảm biến Multi-HAL 2.1 có trên các thiết bị chạy Android 11 trở lên là một phiên bản lặp lại của Cảm biến Multi-HAL 2.0 hỗ trợ việc tải các lớp trừu tượng phụ (HAL có thể hiển thị loại cảm biến góc bản lề). Để hỗ trợ loại cảm biến này, HAL phụ phải sử dụng các API HAL phụ được xác định trong tiêu đề 2.1 SubHal.

Đối với các thiết bị chạy Android 13 trở lên sử dụng Cảm biến AIDL HAL, bạn có thể sử dụng lớp đệm nhiều HAL để cho phép tính năng nhiều HAL. Để biết thông tin chi tiết về cách triển khai, vui lòng xem phần Sử dụng nhiều lớp HAL của cảm biến với lớp trừu tượng phần cứng (HAL) cho cảm biến.

Sự khác biệt giữa cảm biến Multi-HAL 2 và Cảm biến HAL 2

Cảm biến Multi-HAL 2 (có trên các thiết bị chạy Android 10 trở lên) ra mắt một số thành phần trừu tượng ở trên Cảm biến HAL 2 để giúp bạn dễ dàng tương tác với các API HAL. Cảm biến Multi-HAL 2 giới thiệu lớp HalProxy để xử lý việc triển khai giao diện HAL 2 cho Cảm biến và giao diện V2_1/SubHal (hoặc V2_0/SubHal) nhằm cho phép HalProxy tương tác với các HAL phụ.

Giao diện ISensorsSubHal khác với giao diện 2.1/ISensors.hal (hoặc 2.0/ISensors.hal) ở những điểm sau:

  • Phương thức khởi tạo truyền một lớp IHalProxyCallback thay vì 2 FMQ và ISensorsCallback.
  • Các lớp trừu tượng phụ (HAL phụ) phải triển khai chức năng gỡ lỗi để cung cấp thông tin gỡ lỗi trong báo cáo lỗi.
  • Các lớp trừu tượng phụ (HAL phụ) phải triển khai hàm tên để có thể phân biệt được lớp HAL phụ đã tải với các lớp HAL phụ khác.

Sự khác biệt chính giữa Cảm biến đa HAL 2 và Cảm biến HAL 2 nằm ở các hàm khởi động. Thay vì cung cấp FMQ, giao diện IHalProxyCallback cung cấp 2 phương thức, trong đó một phương thức để đăng sự kiện cảm biến lên khung cảm biến và một phương thức để tạo khoá chế độ thức. Trong trường hợp này, Cảm biến nhiều lớp HAL quản lý tất cả các hoạt động tương tác với FMQ để đảm bảo phân phối kịp thời các sự kiện cảm biến cho tất cả các lớp trừu tượng phần cứng phụ. Chúng tôi đặc biệt khuyến khích các HAL phụ sử dụng phương thức createScopedWakelock để uỷ quyền chịu trách nhiệm về thời gian tắt khoá chế độ thức cho Multi-HAL cảm biến và để tập trung việc sử dụng khoá chế độ thức thành một khoá chế độ thức chung cho toàn bộ Cảm biến đa khoá, giúp giảm thiểu việc khoá và mở khoá cuộc gọi.

Các cảm biến Multi-HAL 2 cũng được tích hợp sẵn một số tính năng an toàn. Thư viện này xử lý các tình huống FMQ của cảm biến đã đầy hoặc khi khung cảm biến Android khởi động lại và cần đặt lại trạng thái cảm biến. Ngoài ra, khi các sự kiện được đăng lên lớp HalProxy nhưng khung cảm biến không thể chấp nhận các sự kiện đó ngay lập tức, Multi-HAL của cảm biến có thể di chuyển các sự kiện đó sang một luồng trong nền để cho phép thao tác tiếp tục trên tất cả các HAL phụ trong khi chờ sự kiện được đăng.

Triển khai mã nguồn và tham chiếu

Tất cả mã Multi-HAL của cảm biến đều có trong hardware/interfaces/sensors/common/default/2.X/multihal/. Dưới đây là gợi ý về một số tài nguyên.

  • HalProxy.h: Đối tượng HalProxy được tạo thực thể bằng nhiều lớp HAL (HAL) cho Cảm biến và xử lý việc truyền dữ liệu từ các lớp trừu tượng phụ (HAL) đến khung cảm biến.
  • HalProxy.cpp: Quá trình triển khai HalProxy chứa tất cả logic cần thiết để ghép nối hoạt động giao tiếp giữa các HAL phụ và khung cảm biến.
  • SubHal.h: Giao diện ISensorsSubHal xác định giao diện mà các lớp trừu tượng phụ (HAL) phải tuân thủ để tương thích với HalProxy. Lớp trừu tượng phụ (HAL) triển khai phương thức khởi tạo để có thể sử dụng đối tượng HalProxyCallback cho postEventscreateScopedWakelock.

    Để triển khai Multi-HAL 2.0, hãy sử dụng phiên bản 2.0 của SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: Các bài kiểm thử đơn vị này xác minh việc triển khai HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: Ví dụ về cách triển khai HAL phụ này sử dụng các cảm biến giả để tạo dữ liệu giả. Được dùng để kiểm thử cách nhiều lớp HAL phụ tương tác trên một thiết bị.

Triển khai

Phần này mô tả cách triển khai Multi-HAL của cảm biến trong các trường hợp sau:

Sử dụng lớp HAL (HAL) cho cảm biến với cảm biến AIDL HAL

Để cho phép tính năng đa HAL với HAL của Cảm biến AIDL, hãy nhập mô-đun lớp đệm AIDL nhiều lớp có trong phần phần cứng/giao diện/cảm biến/aidl/default/multihal/. Mô-đun này xử lý việc chuyển đổi giữa các loại định nghĩa HAL của cảm biến AIDL và HIDL, đồng thời xác định một trình bao bọc xung quanh giao diện đa HAL được mô tả trong bài viết Triển khai cảm biến Multi-HAL 2.1. Lớp đệm đa HAL AIDL tương thích với các thiết bị triển khai Cảm biến Multi-HAL 2.1.

Lớp đệm chèn AIDL đa HAL cho phép bạn hiển thị trình theo dõi chuyển động của đầu và các loại cảm biến IMU trục giới hạn trong HAL của Cảm biến. Để sử dụng các loại cảm biến này được xác định bằng giao diện AIDL HAL, hãy đặt trường type trong cấu trúc SensorInfo trong quá trình triển khai getSensorsList_2_1(). Đây là điều kiện an toàn vì các trường loại cảm biến dựa trên số nguyên của HAL (HAL) cho cảm biến AIDL và HID không trùng lặp.

Triển khai cảm biến Multi-HAL 2.1

Để triển khai Cảm biến Multi-HAL 2.1 trên thiết bị mới, hãy làm theo các bước sau:

  1. Triển khai giao diện ISensorsSubHal như mô tả trong SubHal.h.
  2. Triển khai phương thức sensorsHalGetSubHal_2_1 trong SubHal.h.
  3. Thêm mục tiêu cc_library_shared để tạo HAL phụ mới được triển khai. Khi thêm mục tiêu:

    1. Đảm bảo mục tiêu được đẩy đến vị trí nào đó trên phân vùng nhà cung cấp của thiết bị.
    2. Trong tệp cấu hình nằm tại /vendor/etc/sensors/hals.conf, hãy thêm đường dẫn vào thư viện trên một dòng mới. Nếu cần, hãy tạo tệp hals.conf.

    Để xem ví dụ về mục Android.bp để tạo thư viện HAL phụ, hãy xem hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Xoá mọi mục nhập android.hardware.sensors khỏi tệp manifest.xml, tệp này chứa danh sách các lớp trừu tượng phần cứng (HAL) được hỗ trợ trên thiết bị.

  5. Xoá tất cả dịch vụ android.hardware.sensors và tệp service.rc khỏi tệp device.mk rồi thêm android.hardware.sensors@2.1-service.multihalandroid.hardware.sensors@2.1-service.multihal.rc vào PRODUCT_PACKAGES.

Khi khởi động, HalProxy sẽ bắt đầu, tìm lớp HAL phụ mới được triển khai và khởi động lớp đó bằng cách gọi sensorsHalGetSubHal_2_1.

Cổng từ Cảm biến Multi-HAL 2.0 sang Multi-HAL 2.1

Để chuyển từ Multi-HAL 2.0 sang Multi-HAL 2.1, hãy triển khai giao diện SubHal và biên dịch lại lớp trừu tượng phụ (HAL).

Dưới đây là sự khác biệt giữa giao diện SubHal 2.0 và 2.1:

  • IHalProxyCallback sử dụng các kiểu được tạo trong phiên bản 2.1 của thông số kỹ thuật ISensors.hal.
  • Hàm initialize() truyền một IHalProxyCallback mới thay vì mã từ giao diện SubHal 2.0
  • Các lớp trừu tượng phụ (HAL phụ) phải triển khai getSensorsList_2_1injectSensorData_2_1 thay vì getSensorsListinjectSensorData, vì các phương thức này sử dụng các kiểu mới được thêm vào phiên bản 2.1 của quy cách ISensors.hal.
  • Các lớp trừu tượng phụ (HAL phụ) phải hiển thị sensorsHalGetSubHal_2_1 thay vì sensorsHalGetSubHal để lớp này được coi là lớp HAL phụ phiên bản 2.1.

Cổng từ Cảm biến HAL 2.0

Khi nâng cấp lên Cảm biến đa HAL 2.0 từ Cảm biến HAL 2.0, hãy đảm bảo việc triển khai HAL đáp ứng các yêu cầu sau.

Khởi chạy HAL

Cảm biến HAL 2.0 có chức năng khởi động cho phép dịch vụ cảm biến truyền FMQ và lệnh gọi lại cảm biến động. Trong Cảm biến Multi-HAL 2.0, hàm initialize() truyền một lệnh gọi lại duy nhất phải dùng để đăng các sự kiện cảm biến, lấy khoá chế độ thức cũng như thông báo về kết nối và ngắt kết nối cảm biến động.

Đăng các sự kiện cảm biến lên quy trình triển khai Multi-HAL

Thay vì đăng các sự kiện cảm biến thông qua FMQ, lớp trừu tượng phụ (HAL) phải ghi các sự kiện cảm biến vào IHalProxyCallback khi có các sự kiện cảm biến.

Sự kiện WAKE_UP

Trong Cảm biến HAL 2.0, HAL có thể quản lý khóa chế độ thức để thực hiện. Trong Cảm biến Multi-HAL 2.0, các HAL phụ cho phép triển khai Multi-HAL để quản lý khoá chế độ thức và có thể yêu cầu thu thập khoá chế độ thức bằng cách gọi createScopedWakelock. Bạn phải thu nạp và truyền khoá chế độ thức có phạm vi bị khoá đến postEvents khi đăng các sự kiện đánh thức lên quy trình triển khai Multi-HAL.

Cảm biến động

Cảm biến Multi-HAL 2.0 yêu cầu gọi onDynamicSensorsConnectedonDynamicSensorsDisconnected trong IHalProxyCallback bất cứ khi nào kết nối cảm biến động thay đổi. Các lệnh gọi lại này có sẵn như một phần của con trỏ IHalProxyCallback được cung cấp thông qua hàm initialize().

Cổng từ Cảm biến HAL 1.0

Khi nâng cấp lên Cảm biến đa HAL 2.0 từ Cảm biến HAL 1.0, hãy đảm bảo việc triển khai HAL đáp ứng các yêu cầu sau.

Khởi chạy HAL

Hàm initialize() phải được hỗ trợ để thiết lập lệnh gọi lại giữa việc triển khai HAL phụ và Multi-HAL.

Hiển thị các cảm biến có sẵn

Trong Cảm biến Multi-HAL 2.0, hàm getSensorsList() phải trả về cùng một giá trị trong một lần khởi động thiết bị, ngay cả khi các cảm biến khởi động lại HAL (Lớp trừu tượng phần cứng). Điều này cho phép khung cố gắng thiết lập lại các kết nối cảm biến nếu máy chủ hệ thống khởi động lại. Giá trị do getSensorsList() trả về có thể thay đổi sau khi thiết bị khởi động lại.

Đăng các sự kiện cảm biến lên quy trình triển khai Multi-HAL

Trong Cảm biến HAL 2.0, thay vì đợi poll() được gọi, HAL phụ phải chủ động ghi các sự kiện cảm biến vào IHalProxyCallback bất cứ khi nào có sự kiện cảm biến.

Sự kiện WAKE_UP

Trong Cảm biến HAL 1.0, HAL có thể quản lý khóa chế độ thức để thực hiện. Trong Cảm biến Multi-HAL 2.0, các HAL phụ cho phép triển khai Multi-HAL để quản lý khoá chế độ thức và có thể yêu cầu thu thập khoá chế độ thức bằng cách gọi createScopedWakelock. Bạn phải thu nạp và truyền khoá chế độ thức có phạm vi bị khoá đến postEvents khi đăng các sự kiện đánh thức lên quy trình triển khai Multi-HAL.

Cảm biến động

Trong Cảm biến HAL 1.0, các cảm biến động được trả về thông qua hàm poll(). Cảm biến Multi-HAL 2.0 yêu cầu gọi onDynamicSensorsConnectedonDynamicSensorsDisconnected trong IHalProxyCallback bất cứ khi nào kết nối cảm biến động thay đổi. Các lệnh gọi lại này có sẵn như một phần của con trỏ IHalProxyCallback được cung cấp thông qua hàm initialize().

Cổng từ Cảm biến Multi-HAL 1.0

Để chuyển một phương thức triển khai hiện có từ Cảm biến Multi-HAL 1.0, hãy làm theo các bước sau.

  1. Đảm bảo rằng cấu hình HAL của cảm biến nằm tại /vendor/etc/sensors/hals.conf. Quá trình này có thể bao gồm việc di chuyển tệp nằm tại /system/etc/sensors/hals.conf.
  2. Xoá mọi tham chiếu đến hardware/hardware.hhardware/sensors.h vì các tham chiếu này không được hỗ trợ cho HAL 2.0.
  3. Chuyển các lớp HAL phụ như mô tả trong bài viết Chuyển từ các cảm biến Hal 1.0.
  4. Thiết lập Cảm biến Multi-HAL 2.0 làm HAL được chỉ định bằng cách làm theo bước 3 và 4 trong phần Triển khai cảm biến Mutli-HAL 2.0.

Xác nhận kết quả

Chạy VTS

Khi bạn đã tích hợp một hoặc nhiều HAL phụ với cảm biến Multi-Hal 2.1, hãy sử dụng Bộ kiểm thử nhà cung cấp (VTS) để đảm bảo việc triển khai HAL phụ đáp ứng tất cả các yêu cầu do giao diện HAL của cảm biến đặt ra.

Để chỉ chạy các cảm biến VTS sẽ kiểm thử khi VTS được thiết lập trên máy chủ lưu trữ, hãy thực thi các lệnh sau:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

Nếu bạn đang chạy lớp đệm lót AIDL Multi-HAL, hãy chạy VtsAidlHalSensorsTargetTest.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

Chạy kiểm thử đơn vị

Các bài kiểm thử đơn vị trong HalProxy_test.cpp kiểm thử HalProxy bằng cách sử dụng các lớp trừu tượng phụ (HAL) giả được tạo thực thể trong bài kiểm thử đơn vị và không được tải động. Khi tạo một lớp HAL phụ mới, các hoạt động kiểm thử này sẽ là hướng dẫn về cách thêm hoạt động kiểm thử đơn vị để xác minh rằng lớp HAL phụ mới được triển khai đúng cách.

Để chạy kiểm thử, hãy thực thi các lệnh sau:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

Kiểm thử bằng lớp trừu tượng phần cứng (HAL) giả

Các lớp trừu tượng phụ (HAL) giả là những cách triển khai giả của giao diện ISensorsSubHal. Các HAL phụ hiển thị các danh sách cảm biến khác nhau. Khi được kích hoạt, cảm biến sẽ định kỳ đăng các sự kiện cảm biến được tạo tự động lên HalProxy dựa trên các khoảng thời gian được chỉ định trong một yêu cầu cảm biến nhất định.

Bạn có thể sử dụng các HAL phụ giả để kiểm tra cách hoạt động của mã Multi-HAL đầy đủ với các HAL phụ khác được tải vào hệ thống, cũng như để kiểm soát các khía cạnh khác nhau của mã Multi-HAL cảm biến.

Có 2 lớp trừu tượng phụ (HAL) giả tại hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Để tạo và đẩy các lớp trừu tượng phụ (HAL) giả vào một thiết bị, hãy thực hiện các bước sau:

  1. Chạy các lệnh sau để tạo và đẩy 3 lớp HAL phụ giả mạo khác nhau vào thiết bị:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  2. Cập nhật cấu hình HAL của cảm biến tại /vendor/etc/sensors/hals.conf bằng đường dẫn cho các HAL phụ giả.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. Khởi động lại HalProxy rồi tải các HAL phụ mới được liệt kê trong cấu hình.

    adb shell stop
    adb shell start
    

Gỡ lỗi

Nhà phát triển có thể gỡ lỗi cho khung này bằng cách dùng lệnh lshal. Để yêu cầu đầu ra gỡ lỗi của HAL Cảm biến, hãy chạy lệnh sau:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

Sau đó, thông tin về trạng thái hiện tại của HalProxy và các HAL phụ của nó sẽ được đưa đến thiết bị đầu cuối. Dưới đây là ví dụ về kết quả của lệnh cho đối tượng HalProxy và các lớp HAL phụ giả mạo.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

Nếu số được chỉ định cho # of events on pending write queue là một số lớn (1.000 trở lên), tức là có nhiều sự kiện đang chờ xử lý được ghi vào khung cảm biến. Điều này cho biết dịch vụ cảm biến bị khoá hoặc đã gặp sự cố và không xử lý các sự kiện cảm biến, hoặc một loạt lớn các sự kiện cảm biến được đăng gần đây từ một HAL phụ.

Nếu số lượng tham chiếu khoá chế độ thức lớn hơn 0, điều này có nghĩa là HalProxy đã có khoá chế độ thức. Giá trị này chỉ được lớn hơn 0 nếu một ScopedWakelock được cố ý giữ lại hoặc nếu các sự kiện đánh thức được gửi đến HalProxy và chưa được khung cảm biến xử lý.

Chỉ số mô tả tệp được chuyển đến phương thức gỡ lỗi của HalProxy sẽ được chuyển đến từng HAL phụ, vì vậy, các nhà phát triển phải triển khai phương thức gỡ lỗi trong giao diện ISensorsSubHal.