Sensors HAL 2.0

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ả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.

Sensors HAL 2.0 có trong Android 10 trở lên cho các thiết bị mới và được nâng cấp. Sensors HAL 2.0 dựa trên Sensors HAL 1.0 nhưng có một số điểm khác biệt chính khiến phiên bản này không tương thích ngược. Sensors HAL 2.0 sử dụng Fast Message Queues (FMQs) (hàng đợi thông báo nhanh) để gửi các sự kiện cảm biến từ HAL vào khung cảm biến Android.

Sensors HAL 2.1 có trong Android 11 trở lên cho các thiết bị mới và được nâng cấp. Sensors HAL 2.1 là một phiên bản lặp lại của Sensors HAL 2.0, hiển thị loại cảm biến HINGE_ANGLE và cập nhật nhiều phương thức để chấp nhận loại HINGE_ANGLE.

Giao diện HAL 2.1

Nguồn tài liệu chính cho Sensors HAL 2.1 nằm trong định nghĩa HAL tại hardware/interfaces/sensors/2.1/ISensors.hal. Nếu có xung đột về yêu cầu giữa trang này và ISensors.hal, hãy sử dụng yêu cầu trong ISensors.hal.

Giao diện HAL 2.0

Nguồn tài liệu chính cho Sensors HAL 2.0 nằm trong định nghĩa HAL tại hardware/interfaces/sensors/2.0/ISensors.hal. Nếu có xung đột về yêu cầu giữa trang này và ISensors.hal, hãy sử dụng yêu cầu trong ISensors.hal.

Triển khai Sensors HAL 2.0 và HAL 2.1

Để triển khai Sensors HAL 2.0 hoặc 2.1, 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 2.0/ISensors.hal hoặc 2.1/ISensors.hal.

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() cho HAL 2.0 và hàm initialize_2_1() cho HAL 2.1 để cung cấp 3 tham số cho HAL cảm biến: 2 chỉ số mô tả FMQ và 1 con 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 Wake Lock FMQ dùng để đồng bộ hoá khi HAL giải phóng khoá chế độ thức cho các sự kiện cảm biến WAKE_UP. HAL phải lưu con trỏ vào đối tượng ISensorsCallback để có thể gọi mọi hàm gọi lại cần thiết.

Hàm initialize() hoặc initialize_2_1() 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() trên HAL 2.0 và hàm getSensorsList_2_1() trên HAL 2.1. 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. Tay cầm cho một cảm biến nhất định không được thay đổi khi quá trình lưu trữ HAL cảm biến khởi động lại. Tên người dùng có thể thay đổi trong các lần khởi động lại thiết bị và trong các lần khởi động lại máy chủ hệ thống.

Nếu một số cảm biến có cùng 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ề cho các ứng dụng sử 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() hoặc getSensorsList_2_1() 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 này 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 đó, các nhà cung cấp HAL nên ngăn chặn các thay đổi không thể tránh khỏi đố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 tuỳ 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ảm biến dự kiến đã hoàn tất quá trình khởi chạy trước khi quay lại từ getSensorsList() hoặc getSensorsList_2_1(). 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 làm 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à chế độ báo cáo của cảm biến, hãy xem phần 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 cho biết 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ượng 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 cảm biến, trước tiên, khung phải định cấu hình cảm biến bằng batch().

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ả xảy ra không đồng bộ (tức 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 xoá và sự kiện hoàn tất xoá chỉ được thêm cho cảm biến đã chỉ định.

Nếu cảm biến được chỉ định không có FIFO (không 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ả 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 một cảm biến một lần, thì flush() phải trả về BAD_VALUE và không tạo sự kiện hoàn tất xả.

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

FMQ sự kiện được HAL 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 mức dung lượng có sẵn vào FMQ 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ảm biến đã ghi số lượng sự kiện cảm biến mong muốn vào FMQ sự kiện, HAL cảm biến phải thông báo cho khung 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 sự kiện. Bạn có thể tạo EventFlag từ Event FMQ bằng cách sử dụng EventFlag::createEventFlag và hàm getEventFlagWord() của Event FMQ.

Sensors HAL 2.0/2.1 hỗ trợ cả writewriteBlocking trên Event FMQ. 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 sự kiện WAKE_UP, khung này sẽ bảo mật khoá chế độ thức của riêng mình, cho phép HAL cảm biến giải phóng 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ố lượng này trở lại FMQ của Khóa chế độ thức.

Khung này đặt thông báo ghi WakeLockQueueFlagBits::DATA_WRITTEN trên Wake Lock FMQ bất cứ khi nào ghi dữ liệu vào Wake Lock FMQ.

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 Event FMQ, 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 hữu ích cho việc kiểm thử, đặc biệt là đối với các thuật toán tồn tại bên dưới khung.

Hàm injectSensorData() trong HAL 2.0 và hàm injectSensorsData_2_1() trong HAL 2.0 thường được dùng để đẩy các tham số hoạt động vào HAL cảm biến. Bạn cũng có thể dùng hàm này để chèn các 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.

Kiểm thử CTS

Các bài kiểm thử CTS cảm biến tồn tại trong cả bài kiểm thử CTS tự động và ứng dụng Trình xác minh CTS 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ử 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

Các kiểm thử VTS cho Sensors HAL 2.0 nằm trong hardware/interfaces/sensors/2.0/vts. Các kiểm thử VTS cho Sensors HAL 2.1 nằm trong hardware/interfaces/sensors/2.1/vts. Các kiểm thử này đảm bảo rằng HAL cảm biến được triển khai đúng cách và tất cả các yêu cầu trong ISensors.halISensorsCallback.hal đều được đáp ứng đúng cách.

Nâng cấp từ Sensors HAL 2.0 lên 2.1

Khi nâng cấp lên Sensors HAL 2.1 từ 2.0, quá trình triển khai HAL của bạn phải bao gồm các phương thức initialize_2_1(), getSensorsList_2_1()injectSensorsData_2_1() cùng với các loại HAL 2.1. Các phương thức này phải đáp ứng các yêu cầu giống như nêu trên cho HAL 2.0.

Vì các HAL phiên bản nhỏ phải hỗ trợ tất cả các hàm từ các HAL trước đó, nên HAL 2.1 phải hỗ trợ việc khởi chạy dưới dạng HAL 2.0. Để tránh sự phức tạp khi hỗ trợ cả hai phiên bản HAL, bạn nên sử dụng Multi-HAL 2.1.

Để biết ví dụ về cách triển khai HAL Sensors 2.1 của riêng bạn, hãy xem Sensors.h.

Nâng cấp từ Sensors HAL 1.0 lên 2.0

Khi nâng cấp từ Sensors HAL 1.0 lên 2.0, hãy đảm bảo việc triển khai HAL của bạn đá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 FMQ giữa khung và HAL.

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

Trong Sensors 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 Sensors HAL. 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ì chờ poll() được gọi, trong Sensors HAL 2.0, Sensors HAL phải chủ động ghi các sự kiện cảm biến vào Event FMQ 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 để thực hiện việc đọc FMQ trong khung.

Sự kiện WAKE_UP

Trong Sensors HAL 1.0, HAL có thể giải phóng khoá chế độ thức cho bất kỳ sự kiện WAKE_UP nào trong bất kỳ lệnh gọi tiếp theo nào đế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ả sự kiện cảm biến và đã nhận được khoá chế độ thức (nếu cần). Vì trong Sensors HAL 2.0, HAL không còn biết được thời điểm khung xử lý các sự kiện được ghi vào FMQ, nên Wake Lock FMQ cho phép khung giao tiếp với HAL khi đã xử lý các sự kiện WAKE_UP.

Trong Sensors HAL 2.0, khoá chế độ thức do Sensors HAL 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. Sensors HAL 2.0 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 trong con trỏ ISensorsCallback được cung cấp thông qua hàm initialize().

Chế độ hoạt động

Chế độ DATA_INJECTION cho cảm biến WAKE_UP phải được hỗ trợ trong Sensors HAL 2.0.

Hỗ trợ nhiều HAL

Sensors HAL 2.0 và 2.1 hỗ trợ nhiều HAL bằng cách sử dụng khung Sensors Multi-HAL. Để biết thông tin chi tiết về cách triển khai, hãy xem phần Chuyển từ Sensors HAL 1.0.