Cảm biến AIDL HAL

Lớp trừu tượng phần cứng cảm biến (HAL) là giao diện giữa khung cảm biến Android và các cảm biến của thiết bị, chẳng hạn như gia tốc kế hoặc con quay hồi chuyển. HAL cảm biến xác định các hàm phải được triển khai để cho phép khung điều khiển cảm biến.

AIDL HAL của cảm biến có trong Android 13 trở lên đối với các thiết bị mới và thiết bị đã nâng cấp. Cảm biến AIDL HAL (dựa trên Cảm biến HAL 2.1) sử dụng giao diện AIDL HAL, cho thấy thiết bị 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.

Giao diện AIDL HAL

Nguồn tài liệu chính cho HAL AIDL của cảm biến nằm trong định nghĩa HAL tại hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Triển khai HAL AIDL của cảm biến

Để triển khai HAL AIDL của cảm biến, một đối tượng phải mở rộng giao diện ISensors và triển khai tất cả các hàm được xác định trong hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Khởi chạy HAL

Khung cảm biến Android phải khởi chạy HAL cảm biến thì mới có thể sử dụng được. Khung này gọi hàm initialize() để cung cấp 3 tham số cho HAL cảm biến: 2 chỉ số mô tả FMQ và 1 con trỏ trỏ đến đối tượng ISensorsCallback.

HAL sử dụng chỉ số mô tả đầu tiên để tạo FMQ sự kiện dùng để ghi các sự kiện cảm biến vào khung. HAL sử dụng chỉ số mô tả thứ hai để tạo FMQ của Khoá chế độ thức dùng để đồng bộ hoá khi HAL mở khoá chế độ thức cho các sự kiện của cảm biến WAKE_UP. HAL phải lưu con trỏ đến đối tượng ISensorsCallback để có thể gọi bất kỳ hàm gọi lại nào cần thiết.

Hàm initialize() phải là hàm đầu tiên được gọi khi khởi chạy HAL cảm biến.

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

Để xem danh sách tất cả cảm biến tĩnh có sẵn trong thiết bị, hãy sử dụng hàm getSensorsList(). Hàm này trả về danh sách cảm biến, mỗi cảm biến được xác định riêng bằng tên. Bạn không được thay đổi tên người dùng của một cảm biến nhất định khi quá trình lưu trữ HAL của cảm biến khởi động lại. Tên người dùng có thể thay đổi khi thiết bị khởi động lại và khi máy chủ hệ thống khởi động lại.

Nếu một số cảm biến có cùng một loại cảm biến và thuộc tính đánh thức, thì cảm biến đầu tiên trong danh sách được gọi là cảm biến mặc định và được trả về các ứng dụng dùng hàm getDefaultSensor(int sensorType, bool wakeUp).

Độ ổn định của danh sách cảm biến

Sau khi khởi động lại HAL của cảm biến, nếu dữ liệu do getSensorsList() trả về cho thấy sự thay đổi đáng kể so với danh sách cảm biến được truy xuất trước khi khởi động lại, thì khung sẽ kích hoạt quá trình khởi động lại môi trường thời gian chạy Android. Những thay đổi đáng kể đối với danh sách cảm biến bao gồm các trường hợp cảm biến có một tay điều khiển nhất định bị thiếu hoặc đã thay đổi thuộc tính hoặc khi cảm biến mới được giới thiệu. Mặc dù việc khởi động lại môi trường thời gian chạy Android gây gián đoạn cho người dùng, nhưng điều này là cần thiết vì khung Android không thể đáp ứng được hợp đồng API Android nữa, theo đó, các cảm biến tĩnh (không động) không thay đổi trong suốt thời gian hoạt động của ứng dụng. Điều này cũng có thể ngăn khung thiết lập lại các yêu cầu cảm biến đang hoạt động do ứng dụng đưa ra. Do đó, nhà cung cấp HAL (Lớp trừu tượng phần cứng) nên ngăn chặn những thay đổi có thể tránh được đối với danh sách cảm biến.

Để đảm bảo tay điều khiển cảm biến ổn định, HAL phải ánh xạ một cảm biến vật lý nhất định trong thiết bị với tay điều khiển của cảm biến đó một cách xác định. Mặc dù giao diện HAL của cảm biến không yêu cầu phương thức triển khai cụ thể nào, nhưng nhà phát triển có một số lựa chọn để đáp ứng yêu cầu này.

Ví dụ: bạn có thể sắp xếp danh sách cảm biến bằng cách kết hợp các thuộc tính cố định của từng cảm biến, chẳng hạn như nhà cung cấp, kiểu máy và loại cảm biến. Một lựa chọn khác dựa trên thực tế là bộ cảm biến tĩnh của thiết bị được cố định trong phần cứng, vì vậy, HAL cần biết thời điểm tất cả các cảm biến dự kiến đã hoàn tất quá trình khởi chạy trước khi trở về từ getSensorsList(). Danh sách cảm biến dự kiến này có thể được biên dịch thành tệp nhị phân HAL hoặc lưu trữ trong tệp cấu hình trong hệ thống tệp và thứ tự xuất hiện có thể được dùng để lấy các tay điều khiển ổn định. Mặc dù giải pháp tốt nhất phụ thuộc vào thông tin triển khai cụ thể của HAL, nhưng yêu cầu chính là tay điều khiển cảm biến không thay đổi trong quá trình khởi động lại HAL.

Định cấu hình cảm biến

Trước khi kích hoạt cảm biến, bạn phải định cấu hình cảm biến bằng một khoảng thời gian lấy mẫu và độ trễ báo cáo tối đa bằng cách sử dụng hàm batch().

Bạn phải có thể định cấu hình lại cảm biến bất cứ lúc nào bằng batch() mà không mất dữ liệu cảm biến.

Khoảng thời gian lấy mẫu

Khoảng thời gian lấy mẫu có ý nghĩa khác nhau tuỳ theo loại cảm biến đang được định cấu hình:

  • Liên tục: Các sự kiện cảm biến được tạo với tốc độ liên tục.
  • Khi thay đổi: Sự kiện được tạo không nhanh hơn khoảng thời gian lấy mẫu và có thể được tạo với tốc độ chậm hơn khoảng thời gian lấy mẫu nếu giá trị được đo không thay đổi.
  • Một lần: Khoảng thời gian lấy mẫu bị bỏ qua.
  • Đặc biệt: Để biết thêm thông tin chi tiết, hãy xem phần Các loại cảm biến.

Để tìm hiểu về sự tương tác giữa khoảng thời gian lấy mẫu và các chế độ báo cáo của cảm biến, hãy xem bài viết Chế độ báo cáo.

Độ trễ báo cáo tối đa

Độ trễ báo cáo tối đa đặt thời gian tối đa tính bằng nano giây mà các sự kiện có thể bị trì hoãn và lưu trữ trong FIFO phần cứng trước khi được ghi vào FMQ sự kiện thông qua HAL trong khi SoC đang thức.

Giá trị 0 có nghĩa là các sự kiện phải được báo cáo ngay khi được đo lường, bỏ qua hoàn toàn FIFO hoặc làm trống FIFO ngay khi một sự kiện từ cảm biến xuất hiện trong FIFO.

Ví dụ: một gia tốc kế được kích hoạt ở tần số 50 Hz với độ trễ báo cáo tối đa là 0 sẽ kích hoạt các ngắt 50 lần mỗi giây khi SoC ở trạng thái thức.

Khi độ trễ báo cáo tối đa lớn hơn 0, bạn không cần báo cáo các sự kiện cảm biến ngay khi phát hiện thấy. Các sự kiện có thể được tạm thời lưu trữ trong FIFO phần cứng và báo cáo theo lô, miễn là không có sự kiện nào bị trễ quá độ trễ báo cáo tối đa. Tất cả sự kiện kể từ lô trước sẽ được ghi lại và trả về cùng một lúc. Điều này làm giảm số lần gián đoạn được gửi đến SoC và cho phép SoC chuyển sang chế độ tiết kiệm pin hơn trong khi cảm biến đang thu thập và phân lô dữ liệu.

Mỗi sự kiện đều có một dấu thời gian liên kết với sự kiện đó. Việc trì hoãn thời điểm báo cáo một sự kiện không được ảnh hưởng đến dấu thời gian của sự kiện đó. Dấu thời gian phải chính xác và tương ứng với thời điểm sự kiện thực sự xảy ra, chứ không phải thời điểm sự kiện được báo cáo.

Để biết thêm thông tin và yêu cầu về việc báo cáo sự kiện cảm biến có độ trễ báo cáo tối đa khác 0, hãy xem phần Gói hàng.

Kích hoạt cảm biến

Khung này bật và tắt cảm biến bằng hàm activate(). Trước khi kích hoạt một cảm biến, khung phải định cấu hình cảm biến bằng batch() trước.

Sau khi một cảm biến bị vô hiệu hoá, bạn không được ghi các sự kiện cảm biến bổ sung từ cảm biến đó vào FMQ sự kiện.

Cảm biến xả

Nếu một cảm biến được định cấu hình để xử lý dữ liệu cảm biến theo lô, thì khung có thể buộc thực hiện ngay việc xả các sự kiện cảm biến theo lô bằng cách gọi flush(). Điều này khiến các sự kiện cảm biến theo lô cho tay điều khiển cảm biến được chỉ định sẽ được ghi ngay vào FMQ sự kiện. HAL cảm biến phải thêm một sự kiện hoàn tất xả vào cuối các sự kiện cảm biến được ghi do lệnh gọi đến flush().

Quá trình xả diễn ra không đồng bộ (nghĩa là hàm này phải trả về ngay lập tức). Nếu quá trình triển khai sử dụng một FIFO duy nhất cho một số cảm biến, thì FIFO đó sẽ được làm trống và sự kiện hoàn tất làm trống chỉ được thêm cho cảm biến được chỉ định.

Nếu cảm biến được chỉ định không có FIFO (không có thể lưu vào bộ đệm) hoặc nếu FIFO trống tại thời điểm gọi, thì flush() vẫn phải thành công và gửi một sự kiện hoàn tất xả dữ liệu cho cảm biến đó. Điều này áp dụng cho tất cả cảm biến ngoại trừ cảm biến một lần.

Nếu flush() được gọi cho cảm biến một lần, thì flush() phải trả về BAD_VALUE và không tạo ra một sự kiện hoàn tất xả dữ liệu.

Ghi các sự kiện cảm biến vào FMQ

FMQ của sự kiện được HAL của cảm biến sử dụng để đẩy các sự kiện cảm biến vào khung cảm biến Android.

FMQ sự kiện là một FMQ được đồng bộ hoá, nghĩa là mọi nỗ lực ghi nhiều sự kiện hơn vào FMQ so với không gian có sẵn sẽ dẫn đến việc ghi không thành công. Trong trường hợp đó, HAL sẽ xác định xem có ghi tập hợp sự kiện hiện tại dưới dạng hai nhóm sự kiện nhỏ hơn hay ghi tất cả sự kiện cùng nhau khi có đủ dung lượng hay không.

Khi HAL của cảm biến đã ghi số lượng sự kiện cảm biến mong muốn vào FMQ của sự kiện, HAL của cảm biến phải thông báo cho khung biết rằng các sự kiện đã sẵn sàng bằng cách ghi bit EventQueueFlagBits::READ_AND_PROCESS vào hàm EventFlag::wake của FMQ của sự kiện. Bạn có thể tạo Eventflag từ sự kiện FMQ bằng cách sử dụng EventFlag::createEventFlag và hàm getEventFlagWord() của sự kiện FMQ.

HAL AIDL của cảm biến hỗ trợ cả writewriteBlocking trên FMQ sự kiện. Phương thức triển khai mặc định cung cấp thông tin tham khảo để sử dụng write. Nếu sử dụng hàm writeBlocking, bạn phải đặt cờ readNotification thành EventQueueFlagBits::EVENTS_READ. Cờ này do khung đặt khi đọc các sự kiện từ FMQ sự kiện. Bạn phải đặt cờ thông báo ghi thành EventQueueFlagBits::READ_AND_PROCESS để thông báo cho khung rằng các sự kiện đã được ghi vào FMQ sự kiện.

Sự kiện WAKE_UP

Sự kiện WAKE_UP là các sự kiện cảm biến khiến bộ xử lý ứng dụng (AP) đánh thức và xử lý sự kiện ngay lập tức. Bất cứ khi nào một sự kiện WAKE_UP được ghi vào FMQ sự kiện, HAL cảm biến phải bảo mật khoá chế độ thức để đảm bảo hệ thống luôn thức cho đến khi khung có thể xử lý sự kiện. Khi nhận được một sự kiện WAKE_UP, khung sẽ bảo mật khoá chế độ thức riêng, cho phép HAL Cảm biến mở khoá chế độ thức. Để đồng bộ hoá khi HAL cảm biến giải phóng khoá chế độ thức, hãy sử dụng Wake Lock FMQ.

HAL cảm biến phải đọc FMQ khoá chế độ thức để xác định số lượng sự kiện WAKE_UP mà khung đã xử lý. HAL chỉ nên giải phóng khoá chế độ thức cho các sự kiện WAKE_UP nếu tổng số sự kiện WAKE_UP chưa được xử lý bằng 0. Sau khi xử lý các sự kiện cảm biến, khung này sẽ đếm số lượng sự kiện được đánh dấu là sự kiện WAKE_UP và ghi số này trở lại FMQ của Khóa chế độ thức.

Khung này sẽ đặt thông báo ghi WakeLockQueueFlagBits::DATA_WRITTEN trên FMQ của Khoá chế độ thức bất cứ khi nào khung này ghi dữ liệu vào FMQ của Khoá chế độ thức.

Cảm biến động

Cảm biến động là những cảm biến không phải là một phần của thiết bị nhưng có thể được dùng làm dữ liệu đầu vào cho thiết bị, chẳng hạn như tay điều khiển trò chơi có gia tốc kế.

Khi cảm biến động được kết nối, hàm onDynamicSensorConnected trong ISensorsCallback phải được gọi từ HAL cảm biến. Thao tác này sẽ thông báo cho khung về cảm biến động mới và cho phép kiểm soát cảm biến thông qua khung cũng như để các ứng dụng sử dụng các sự kiện của cảm biến.

Tương tự, khi một cảm biến động bị ngắt kết nối, bạn phải gọi hàm onDynamicSensorDisconnected trong ISensorsCallback để khung có thể xoá mọi cảm biến không còn hoạt động.

Kênh trực tiếp

Kênh trực tiếp là một phương thức hoạt động trong đó các sự kiện cảm biến được ghi vào bộ nhớ cụ thể thay vì vào FMQ sự kiện, bỏ qua Khung cảm biến Android. Ứng dụng đăng ký kênh trực tiếp phải đọc trực tiếp các sự kiện cảm biến từ bộ nhớ dùng để tạo kênh trực tiếp và sẽ không nhận được các sự kiện cảm biến thông qua khung. Hàm configDirectReport() tương tự như batch() để hoạt động bình thường và định cấu hình kênh báo cáo trực tiếp.

Hàm registerDirectChannel()unregisterDirectChannel() tạo hoặc huỷ một kênh trực tiếp mới.

Chế độ hoạt động

Hàm setOperationMode() cho phép khung cấu hình cảm biến để khung có thể chèn dữ liệu cảm biến vào cảm biến. Điều này rất hữu ích cho việc kiểm thử, đặc biệt là đối với các thuật toán nằm bên dưới khung.

Hàm injectSensorData() thường được dùng để đẩy các tham số vận hành vào lớp HAL của cảm biến. Bạn cũng có thể dùng hàm này để chèn sự kiện cảm biến vào một cảm biến cụ thể.

Xác nhận kết quả

Để xác thực việc triển khai HAL cảm biến, hãy chạy các chương trình kiểm thử cảm biến CTS và VTS.

Bài kiểm thử CTS

Các kiểm thử CTS cảm biến tồn tại trong cả kiểm thử CTS tự động và ứng dụng CTS Verifier thủ công.

Các chương trình kiểm thử tự động nằm trong thư mục cts/tests/sensor/src/android/hardware/cts. Các kiểm thử này xác minh chức năng tiêu chuẩn của cảm biến, chẳng hạn như kích hoạt cảm biến, tạo lô và tốc độ sự kiện cảm biến.

Các bài kiểm thử của Trình xác minh CTS nằm trong cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Các kiểm thử này yêu cầu người vận hành kiểm thử nhập dữ liệu theo cách thủ công và đảm bảo rằng các cảm biến báo cáo giá trị chính xác.

Việc vượt qua các bài kiểm thử CTS là yếu tố quan trọng để đảm bảo rằng thiết bị đang được kiểm thử đáp ứng tất cả các yêu cầu của CDD.

Kiểm thử VTS

Bài kiểm thử VTS cho Cảm biến AIDL HAL nằm trong phần hardware/Interfaces/sensors/aidl/vts/. Những hoạt động kiểm thử này đảm bảo rằng HAL của cảm biến được triển khai đúng cách và tất cả yêu cầu trong ISensors.aidlISensorsCallback.aidl đều được đáp ứng đúng cách.

Khởi chạy HAL

Bạn phải hỗ trợ hàm initialize() để thiết lập FMQ giữa khung và HAL.

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

Trong HAL AIDL của cảm biến, 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ủa cảm biến. Một yêu cầu mới của hàm getSensorsList() là hàm này phải trả về cùng một giá trị trong quá trình khởi động một thiết bị, ngay cả khi khởi động lại HAL của cảm biến. Điều này cho phép khung cố gắng thiết lập lại 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.

Ghi các sự kiện cảm biến vào FMQ

Thay vì đợi poll() được gọi, trong lớp trừu tượng phần cứng (HAL) của cảm biến AIDL, lớp trừu tượng phần cứng (HAL) của cảm biến phải chủ động ghi các sự kiện cảm biến vào FMQ của sự kiện bất cứ khi nào có sự kiện cảm biến. HAL cũng chịu trách nhiệm ghi các bit chính xác vào EventFlag để khiến FMQ đọc được trong khung.

Sự kiện WAKE_UP

Trong Cảm biến HAL 1.0, HAL có thể mở khoá chế độ thức cho mọi sự kiện WAKE_UP trong mọi lệnh gọi tiếp theo đến poll() sau khi WAKE_UP được đăng lên poll() vì điều này cho biết rằng khung đã xử lý tất cả các sự kiện cảm biến và đã nhận được khoá chế độ thức, nếu cần. Vì trong HAL AIDL của cảm biến, HAL không còn được thông báo khi khung đã xử lý các sự kiện được ghi vào FMQ, nên FMQ của khoá chế độ thức cho phép khung giao tiếp với HAL khi đã xử lý các sự kiện WAKE_UP.

Trong HAL AIDL của cảm biến, khoá chế độ thức do HAL của cảm biến bảo vệ cho các sự kiện WAKE_UP phải bắt đầu bằng SensorsHAL_WAKEUP.

Cảm biến động

Các cảm biến động được trả về bằng hàm poll() trong Sensors HAL 1.0. HAL AIDL của cảm biến yêu cầu onDynamicSensorsConnectedonDynamicSensorsDisconnected trong ISensorsCallback được gọi 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 như một phần của con trỏ ISensorsCallback được cung cấp thông qua hàm initialize().

Chế độ hoạt động

Phải hỗ trợ chế độ DATA_INJECTION cho cảm biến WAKE_UP.

Hỗ trợ nhiều HAL

AIDL HAL của cảm biến hỗ trợ nhiều HAL bằng cách sử dụng khung Multi-HAL của cảm biến. Để biết chi tiết về cách triển khai, hãy xem phần Chuyển từ Sensors HAL 2.1.