Cảm biến đa HAL

Sensors Multi-HAL là một khung cho phép các HAL cảm biến chạy cùng với các HAL cảm biến khác. Sensors Multi-HAL tải động các HAL phụ 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 thập và giải phóng khoá chế độ thức. HAL phụ 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 nhà cung cấp và được khung multi-HAL sử dụng. Các HAL phụ này không phụ thuộc vào nhau hoặc vào mã multi-HAL chứa hàm chính cho quy trình.

Sensors 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 Sensors Multi-HAL 2.0 hỗ trợ tải các HAL phụ 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, các HAL phụ phải sử dụng các API HAL phụ được xác định trong tiêu đề SubHal 2.1.

Đối với các thiết bị chạy Android 13 trở lên sử dụng Sensors AIDL HAL, bạn có thể sử dụng lớp shim multi-HAL để cho phép khả năng multi-HAL. Để biết thông tin chi tiết về cách triển khai, hãy xem bài viết Sử dụng Sensors Multi-HAL với Sensors AIDL HAL.

Sự khác biệt giữa Sensors Multi-HAL 2 và Sensors HAL 2

Sensors Multi-HAL 2 (có trên các thiết bị chạy Android 10 trở lên) giới thiệu một số lớp trừu tượng trên Sensors HAL 2 để giúp bạn tương tác dễ dàng hơn với các API HAL. Sensors Multi-HAL 2 giới thiệu lớp HalProxy để xử lý việc triển khai giao diện Sensors HAL 2 và giao diện V2_1/SubHal (hoặc V2_0/SubHal) để 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) theo những cách sau:

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

Sự khác biệt chính giữa Sensors Multi-HAL 2 và Sensors HAL 2 nằm ở các hàm khởi chạy. Thay vì cung cấp FMQ, giao diện IHalProxyCallback cung cấp 2 phương thức: một phương thức để đăng các sự kiện cảm biến lên khung cảm biến và một phương thức để tạo khoá đánh thức. Ở phía sau, Sensors Multi-HAL quản lý tất cả các 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 HAL phụ. Bạn nên sử dụng phương thức createScopedWakelock để uỷ quyền gánh nặng về thời gian chờ khoá chế độ thức cho Sensors Multi-HAL và tập trung việc sử dụng khoá chế độ thức vào một khoá chế độ thức chung cho toàn bộ Sensors Multi-HAL. Nhờ đó, bạn có thể giảm thiểu các lệnh gọi khoá và mở khoá.

Sensors Multi-HAL 2 cũng có một số tính năng an toàn tích hợp sẵn. Khung này xử lý các trường hợp FMQ cảm biến đầy hoặc khung cảm biến Android khởi động lại và trạng thái cảm biến cần được đặt lại. 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 ngay các sự kiện, Sensors Multi-HAL có thể chuyển các sự kiện sang một luồng nền để cho phép tiếp tục hoạt động trên tất cả các HAL phụ trong khi chờ các sự kiện được đăng.

Mã nguồn và cách triển khai tham chiếu

Tất cả mã Sensors Multi-HAL đều có trong hardware/interfaces/sensors/common/default/2.X/multihal/. Sau đây là các con trỏ đến một số tài nguyên.

  • HalProxy.h: Đối tượng HalProxy được Sensors multi-HAL khởi tạo và xử lý việc chuyển dữ liệu từ các HAL phụ sang khung cảm biến.
  • HalProxy.cpp: Việc triển khai HalProxy chứa tất cả logic cần thiết để ghép kênh 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 HAL phụ phải tuân theo để tương thích với HalProxy. HAL phụ triển khai phương thức khởi chạy để có thể sử dụng đối tượng HalProxyCallback cho postEventscreateScopedWakelock.

    Đối với các cách 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/: Cách triển khai HAL phụ mẫu này sử dụng các cảm biến giả để tạo dữ liệu giả. Hữu ích cho việc kiểm thử cách nhiều 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 Sensors Multi-HAL trong các trường hợp sau:

Sử dụng Sensors Multi-HAL với Sensors AIDL HAL

Để cho phép khả năng multi-HAL với Sensors AIDL HAL, hãy nhập mô-đun lớp shim AIDL Multi-HAL có trong hardware/interfaces/sensors/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ảm biến AIDL và HIDL và xác định một trình bao bọc xung quanh giao diện multi-HAL được mô tả trong Triển khai Sensors Multi-HAL 2.1. Lớp shim multi-HAL AIDL tương thích với các thiết bị triển khai Sensors Multi-HAL 2.1.

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

Triển khai Sensors Multi-HAL 2.1

Để triển khai Sensors Multi-HAL 2.1 trên một 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 triển khai. Khi thêm mục tiêu:

    1. Đảm bảo mục tiêu được chuyển đến một 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 đến 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 nhập 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á tất cả mục nhập android.hardware.sensors khỏi tệp manifest.xml chứa danh sách các HAL được hỗ trợ trên thiết bị.

  5. Xoá tất cả tệp dịch vụ android.hardware.sensorsservice.rc khỏi tệp device.mk, đồng thờ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 HAL phụ mới triển khai và khởi chạy HAL đó bằng cách gọi sensorsHalGetSubHal_2_1.

Chuyển từ Sensors 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 HAL phụ.

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

  • IHalProxyCallback sử dụng các loại được tạo trong phiên bản 2.1 của thông số kỹ thuật ISensors.hal.
  • Hàm initialize() chuyển một IHalProxyCallback thay vì hàm từ giao diện SubHal 2.0
  • Các 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 loại mới được thêm vào trong phiên bản 2.1 của thông số kỹ thuật ISensors.hal.
  • Các HAL phụ phải hiển thị sensorsHalGetSubHal_2_1 thay vì sensorsHalGetSubHal để Multi-HAL coi chúng là các HAL phụ phiên bản 2.1.

Chuyển từ Sensors HAL 2.0

Khi nâng cấp lên Sensors Multi-HAL 2.0 từ Sensors HAL 2.0, hãy đảm bảo rằng việc triển khai HAL đáp ứng các yêu cầu sau.

Khởi chạy HAL

Sensors HAL 2.0 có một hàm khởi chạy cho phép dịch vụ cảm biến chuyển FMQ và một lệnh gọi lại cảm biến động. Trong Sensors Multi-HAL 2.0, hàm initialize() chuyển một lệnh gọi lại duy nhất phải được dùng để đăng các sự kiện cảm biến, thu thập khoá đánh thức và thông báo về việc 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 cách triển khai Multi-HAL

Thay vì đăng các sự kiện cảm biến thông qua FMQ, HAL phụ 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 Sensors HAL 2.0, HAL có thể quản lý khoá chế độ thức cho việc triển khai. Trong Sensors Multi-HAL 2.0, các HAL phụ cho phép việc 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 thập và chuyển một khoá chế độ thức có phạm vi bị khoá sang postEvents khi đăng các sự kiện đánh thức lên cách triển khai Multi-HAL.

Cảm biến động

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

Chuyển từ Sensors HAL 1.0

Khi nâng cấp lên Sensors Multi-HAL 2.0 từ Sensors HAL 1.0, hãy đảm bảo rằng việc triển khai HAL đáp ứng các yêu cầu sau.

Khởi chạy HAL

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

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

Trong Sensors 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 khởi động lại HAL cảm biến. Đ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 cách triển khai Multi-HAL

Trong Sensors HAL 2.0, thay vì chờ 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ó các sự kiện cảm biến.

Sự kiện WAKE_UP

Trong Sensors HAL 1.0, HAL có thể quản lý khoá chế độ thức cho việc triển khai. Trong Sensors Multi-HAL 2.0, các HAL phụ cho phép việc 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 thập và chuyển một khoá chế độ thức có phạm vi bị khoá sang postEvents khi đăng các sự kiện đánh thức lên cách triển khai Multi-HAL.

Cảm biến động

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

Chuyển từ Sensors Multi-HAL 1.0

Để chuyển một cách triển khai hiện có từ Sensors 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ảm biến nằm tại /vendor/etc/sensors/hals.conf. Bạn có thể cần 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 HAL phụ như mô tả trong Chuyển từ Sensors Hal 1.0.
  4. Đặt Sensors Multi-HAL 2.0 làm HAL được chỉ định bằng cách làm theo các bước 3 và 4 trong phần Triển khai Sensors 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 Sensors Multi-Hal 2.1, hãy sử dụng Bộ kiểm thử nhà cung cấp (VTS) để đảm bảo các cách triển khai HAL phụ đáp ứng tất cả các yêu cầu do giao diện Sensors HAL đặt ra.

Để chỉ chạy các bài kiểm thử VTS cảm biến khi VTS được thiết lập trên một 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 shim 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ác HAL phụ giả mà được khởi tạo trong bài kiểm thử đơn vị và không được tải động. Khi tạo một HAL phụ mới, các bài kiểm thử này sẽ đóng vai trò là hướng dẫn về cách thêm các bài kiểm thử đơn vị để xác minh rằng HAL phụ mới được triển khai đúng cách.

Để chạy các bài 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 các HAL phụ giả

Các HAL phụ giả là 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ác cảm biến được kích hoạt, chúng 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 thử cách mã Multi-HAL đầy đủ hoạt động với các HAL phụ khác được tải vào hệ thống và để nhấn mạnh các khía cạnh khác nhau của mã Sensors Multi-HAL.

Có 2 HAL phụ giả tại hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Để tạo và chuyển các HAL phụ giả sang một thiết bị, hãy làm theo các bước sau:

  1. Chạy các lệnh sau để tạo và chuyển 3 HAL phụ giả khác nhau sang 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ảm biến tại /vendor/etc/sensors/hals.conf bằng các đườ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 và 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 khung bằng cách sử dụng lệnh lshal. Để yêu cầu kết quả gỡ lỗi của Sensors HAL, 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ụ sẽ được xuất ra thiết bị đầu cuối. Dưới đây là ví dụ về kết quả lệnh cho đối tượng HalProxy và các HAL phụ giả.

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 (1000 trở lên), thì điều này cho biết có nhiều sự kiện đang chờ được ghi vào khung cảm biến. Điều này cho biết dịch vụ cảm biến đang bị bế tắc 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 sự kiện cảm biến lớn gần đây đã được đăng từ một HAL phụ.

Nếu số tham chiếu khoá chế độ thức lớn hơn 0, thì điều này có nghĩa là HalProxy đã thu thập một khoá chế độ thức. Giá trị này chỉ lớn hơn 0 nếu ScopedWakelock đang được giữ một cách có chủ ý 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 được chuyển đến từng HAL phụ, vì vậy, nhà phát triển phải triển khai phương thức gỡ lỗi trong giao diện ISensorsSubHal.