Cảm biến 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á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 chức năng phải được triển khai để cho phép khung kiểm soát các 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ề các 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 Cảm biến 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ỏ đế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() hoặc initialize_2_1() phải là hàm đầu tiên được gọi khi khởi tạo 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. Không được thay đổi tay điều khiển của một cảm biến nhất định khi quy 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 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 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() hoặc getSensorsList_2_1() trả về cho thấy có 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 Android Runtime. 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 những thay đổi không cần thiết đối với danh sách cảm biến.

Để đảm bảo các tay cầm cảm biến hoạt động ổn định, HAL phải liên kết một cách quyết định 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ặ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 một cảm biến, bạn phải định cấu hình cảm biến theo khoảng thời gian lấy mẫu và độ trễ báo cáo tối đa bằng hàm batch().

Bạn phải có thể định cấu hình lại một cảm biến bất cứ lúc nào bằng cách sử dụng batch() mà không bị 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: Các 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 so với khoảng thời gian lấy mẫu nếu giá trị được đo lường 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ị bằng 0 biểu thị rằng các sự kiện phải được báo cáo ngay sau khi đo lường, bỏ qua hoàn toàn FIFO hoặc xoá FIFO ngay khi một sự kiện của cảm biến có mặt 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 tương ứng. 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à các yêu cầu về cách báo cáo các sự kiện cảm biến có độ trễ báo cáo tối đa khác 0, hãy xem phần Tạo lô.

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 lập tức vào FMQ của 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 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 cho cảm biến đó. Điều này áp dụng cho tất cả các cảm biến không phải cảm biến chụp 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 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 như vậy, HAL sẽ xác định xem nên viết 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 viết tất cả các sự kiện cùng nhau khi có đủ dung lượ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ừ sự kiện FMQ bằng cách sử dụng EventFlag::createEventFlag và hàm getEventFlagWord() của sự kiện 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ủa Cảm biến phát hành khoá chế độ thức, hãy sử dụng FMQ của Khoá chế độ thức.

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 đặ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 một cảm biến động được kết nối, hàm onDynamicSensorConnected trong ISensorsCallback phải được gọi từ Lớp trừu tượng phần cứng (HAL) của 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 các sự kiện cảm biến trực tiếp từ bộ nhớ dùng để tạo kênh trực tiếp và sẽ không nhận 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.

Các hàm registerDirectChannel()unregisterDirectChannel() sẽ 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() 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. Hàm này cũng có thể được dùng để 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ủa cảm biến, hãy chạy các bài kiểm thử CTS và VTS của cảm biến.

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à rất quan trọng để đảm bảo rằng thiết bị kiểm thử đáp ứng mọi yêu cầu của CDD.

Kiểm thử VTS

Các bài kiểm thử VTS cho Sensors HAL 2.0 nằm trong thư mục hardware/interfaces/sensors/2.0/vts. Các kiểm thử VTS cho Sensors HAL 2.1 nằm trong thư mục hardware/interfaces/sensors/2.1/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.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 từ phiên bản 2.0 lên Cảm biến HAL 2.1, việc triển khai HAL (Lớp trừu tượng phần cứng) 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ì HAL phiên bản nhỏ phải hỗ trợ tất cả các chức năng từ các HAL trước đó, nên HAL 2.1 phải hỗ trợ được khởi tạo 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

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

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

Trong Cảm biến 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 HAL cảm biến khởi động lại. 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 một lần khởi động thiết bị, ngay cả khi HAL cảm biến khởi động lại. Đ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 để khiến FMQ đọc được 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). Bởi vì trong Cảm biến HAL 2.0, HAL không còn biết thời điểm 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 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. Cảm biến HAL 2.0 yêu cầu gọi onDynamicSensorsConnectedonDynamicSensorsDisconnected trong ISensorsCallback 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ỏ 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 đổi từ Cảm biến HAL 1.0.