Sensors HAL 1.0

sensors.h 中宣告的感應器 HAL 介面,代表 Android 架構與硬體專屬軟體之間的介面。HAL 實作項目必須定義 sensors.h 中宣告的每個函式。主要函式如下:

  • get_sensors_list - 傳回所有感應器的清單。
  • activate - 啟動或停止感應器。
  • batch - 設定感應器的參數,例如取樣頻率和回報延遲時間上限。
  • setDelay - Used only in HAL version 1.0. 為指定感應器設定取樣頻率。
  • flush - 清除指定感應器的 FIFO,並在完成時回報清除完成事件。
  • poll - Returns available sensor events.

實作內容必須確保執行緒安全,並允許從不同執行緒呼叫這些函式。

介面也會定義這些函式使用的幾種型別。主要類型如下:

  • sensors_module_t
  • sensors_poll_device_t
  • sensor_t
  • sensors_event_t

除了下方的章節,如要進一步瞭解這些型別,請參閱 sensors.h

get_sensors_list(list)

int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t
  const** list);

提供 HAL 實作的感應器清單。如要瞭解感應器的定義方式,請參閱 sensor_t

感應器在清單中的顯示順序,就是感應器向應用程式回報的順序。通常會先顯示基礎感應器,接著是複合感應器。

如果多個感應器共用相同的感應器類型和喚醒屬性,清單中的第一個感應器會稱為「預設」感應器。這是 getDefaultSensor(int sensorType, bool wakeUp) 傳回的項目。

這個函式會傳回清單中的感應器數量。

activate(sensor, true/false)

int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int
  enabled);

啟用或停用感應器。

sensor_handle 是感應器的控制代碼,用於啟用/停用感應器。感應器的控制代碼是由 sensor_t 結構體的 handle 欄位定義。

enabled 設為 1 可啟用感應器,設為 0 則可停用感應器。

單次感應器會在收到事件時自動停用,但仍須接受透過呼叫 activate(..., enabled=0) 停用。

非喚醒感應器絕不會阻止 SoC 進入暫停模式;也就是說,HAL 不得代表應用程式保留部分 Wake Lock。

持續傳送事件時,喚醒感應器可能會阻止 SoC 進入暫停模式,但如果不需要傳送任何事件,就必須釋出部分喚醒鎖定。

如果 enabled 為 1 且感應器已啟用,這項函式會是無運算,且會成功。

如果 enabled 為 0,且感應器已停用,這項函式會成為無運算,並成功執行。

如果成功,這個函式會傳回 0,否則會傳回負數錯誤編號。

batch(sensor, flags, sampling period, maximum report latency)

int (*batch)(
     struct sensors_poll_device_1* dev,
     int sensor_handle,
     int flags,
     int64_t sampling_period_ns,
     int64_t max_report_latency_ns);

設定感應器的參數,包括取樣頻率最長回報延遲時間。感應器啟動時可以呼叫此函式,但不得因此遺失任何感應器測量結果:從一個取樣率轉換到另一個取樣率時,不得遺失事件;從高最大回報延遲時間轉換到低最大回報延遲時間時,也不得遺失事件。

sensor_handle 是要設定的感應器控制代碼。

目前未使用 flags

sampling_period_ns 是感應器應執行的取樣週期,以奈秒為單位。詳情請參閱 sampling_period_ns

max_report_latency_ns 是事件透過 HAL 回報前可延遲的最大時間 (以奈秒為單位)。詳情請參閱 max_report_latency_ns 段落。

如果成功,這個函式會傳回 0,否則會傳回負數錯誤編號。

setDelay(sensor, sampling period)

int (*setDelay)(
     struct sensors_poll_device_t *dev,
     int sensor_handle,
     int64_t sampling_period_ns);

HAL 1.0 版之後,這個函式已淘汰,且不會再呼叫。 而是呼叫 batch 函式來設定 sampling_period_ns 參數。

在 HAL 1.0 版中,系統會使用 setDelay (而非批次) 設定 sampling_period_ns

flush(sensor)

int (*flush)(struct sensors_poll_device_1* dev, int sensor_handle);

在指定感應器的硬體 FIFO 結尾新增清除完成事件,並清除 FIFO;這些事件會照常傳送 (也就是說,如同最大回報延遲時間已過期),並從 FIFO 中移除。

清除作業會以非同步方式進行 (也就是說,這個函式必須立即傳回)。 如果實作方式是為多個感應器使用單一 FIFO,系統只會針對指定感應器排空該 FIFO,並新增排空完成事件。

如果指定的感應器沒有 FIFO (無法緩衝),或 FIFO 在呼叫時為空,flush 仍須成功,並傳送該感應器的清除完成事件。這項設定適用於所有感應器,但單次感應器除外。

呼叫 flush 時,即使該感應器的 FIFO 中已有清除事件,仍須建立額外事件並新增至 FIFO 結尾,且必須清除 FIFO。flush 呼叫次數必須等於建立的排清完成事件數。

flush 不適用於單次感應器;如果 sensor_handle 是指單次感應器,flush 必須傳回 -EINVAL,且不得產生任何清除完成中繼資料事件。

如果成功,這個函式會傳回 0;如果指定的感應器是單次感應器或未啟用,則會傳回 -EINVAL;否則會傳回負數錯誤號碼。

poll()

int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int
  count);

填入 data 引數,即可傳回感應器資料陣列。這項函式必須封鎖,直到事件可用為止。如果成功,函式會傳回讀取的事件數,如果發生錯誤,則會傳回負數錯誤代碼。

data 中傳回的事件數量必須小於或等於 count 引數。這個函式絕不會傳回 0 (沒有事件)。

通話順序

裝置啟動時,系統會呼叫 get_sensors_list

感應器啟動時,系統會使用要求的參數呼叫 batch 函式,然後呼叫 activate(..., enable=1)

請注意,在 HAL 1_0 版中,呼叫順序相反:先呼叫 activate,再呼叫 set_delay

當感應器處於啟用狀態,且要求的感應器特徵發生變化時,系統會呼叫 batch 函式。

flush 可隨時呼叫,即使是在未啟用的感應器上 (在這種情況下,必須傳回 -EINVAL)

感應器停用時,系統會呼叫 activate(..., enable=0)

在這些呼叫的同時,系統會重複呼叫 poll 函式來要求資料。即使沒有啟動任何感應器,也可以呼叫 poll

sensors_module_t

sensors_module_t 是用於建立感應器 Android 硬體模組的型別。HAL 的實作項目必須定義這個型別的物件 HAL_MODULE_INFO_SYM,才能公開 get_sensors_list 函式。詳情請參閱 sensors.h 中的 sensors_module_t 定義,以及 hw_module_t 的定義。

sensors_poll_device_t / sensors_poll_device_1_t

sensors_poll_device_1_t 包含上述其餘方法:activatebatchflushpoll。其 common 欄位 (屬於 hw_device_t 型別) 定義了 HAL 的版本號碼。

sensor_t

sensor_t 代表 Android 感應器。以下列舉幾個重要欄位:

名稱:代表感應器的使用者可見字串。這個字串通常包含基礎感應器的零件名稱、感應器類型,以及是否為喚醒感應器。例如「LIS2HH12 Accelerometer」、「MAX21000 Uncalibrated Gyroscope」、「BMP280 Wake-up Barometer」、「MPU6515 Game Rotation Vector」

handle:註冊感應器或從感應器產生事件時,用來參照感應器的整數。

type:感應器類型。詳情請參閱「什麼是 Android 感應器?」一文中的感應器類型說明,並參閱「感應器類型」一文瞭解官方感應器類型。如為非官方感應器類型,type 必須以 SENSOR_TYPE_DEVICE_PRIVATE_BASE 開頭

stringType:感應器類型 (字串)。如果感應器有官方類型,請設為 SENSOR_STRING_TYPE_*。如果感應器具有製造商專屬類型,stringType 必須以製造商反向網域名稱開頭。舉例來說,Fictional-Company 的 Cool-product 團隊定義的感應器 (例如獨角獸偵測器) 可以使用 stringType=”com.fictional_company.cool_product.unicorn_detector”stringType 用於識別非官方感應器類型。如要進一步瞭解型別和字串型別,請參閱 sensors.h

requiredPermission:代表權限的字串,應用程式必須具備這項權限,才能查看感應器、向感應器註冊及接收感應器資料。空字串表示應用程式不需要任何權限即可存取這個感應器。部分感應器類型 (例如心率監測器) 必須具備 requiredPermission。所有提供私密使用者資訊 (例如心率) 的感應器都必須受到權限保護。

flags:這個感應器的旗標,定義感應器的回報模式,以及感應器是否為喚醒感應器。舉例來說,單次喚醒感應器會具有 flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP。目前 HAL 版本未使用的旗標位元必須保持為 0。

maxRange:感應器可回報的最大值,單位與回報值相同。感應器必須能在 [-maxRange; maxRange] 內回報值,且不會飽和。請注意,這表示感應器的一般總範圍為 2*maxRange。如果感應器回報多個軸的值,則範圍會套用至每個軸。舉例來說,如果加速計的範圍是「+/- 2g」,則會回報 maxRange = 2*9.81 = 2g

解析度:感應器可測量的最小值差異。 通常是根據 maxRange 和測量值中的位元數計算。

power:啟用感應器的電力成本,以毫安培為單位。 這幾乎總是比基礎感應器規格書中回報的耗電量高。詳情請參閱「基礎感應器 != 實體感應器」,並參閱「電力測量程序」,瞭解如何測量感應器的耗電量。如果感應器的耗電量取決於裝置是否移動,則移動時的耗電量會顯示在 power 欄位中。

minDelay:針對連續感應器,這是以微秒為單位的取樣週期,對應感應器支援的最快速率。如要進一步瞭解這個值的使用方式,請參閱 sampling_period_ns。請注意,minDelay 以微秒為單位,而 sampling_period_ns 以奈秒為單位。如果是變更時和特殊回報模式感應器,除非另有規定,否則 minDelay 必須為 0。如果是單次感應器,則必須為 -1。

maxDelay:針對連續和變更感應器,以微秒為單位的取樣週期,對應於感應器支援的最慢速率。如要進一步瞭解這個值的使用方式,請參閱 sampling_period_ns。請注意,maxDelay 以微秒為單位,而 sampling_period_ns 以奈秒為單位。如果是特殊感應器和單次感應器,maxDelay 必須為 0。

fifoReservedEventCount:硬體 FIFO 中為這個感應器保留的事件數。如果這個感應器有專屬的 FIFO,則 fifoReservedEventCount 是這個專屬 FIFO 的大小。如果 FIFO 與其他感應器共用,fifoReservedEventCount 是指為該感應器保留的 FIFO 部分大小。在大多數共用 FIFO 系統,以及沒有硬體 FIFO 的系統上,這個值為 0。

fifoMaxEventCount:這個感應器 FIFO 中可儲存的事件數量上限。這個值一律大於或等於 fifoReservedEventCount。這個值可用於估算以特定速率向感應器註冊時,FIFO 會多快填滿 (假設沒有其他感應器啟動)。如果系統沒有硬體 FIFO,fifoMaxEventCount 為 0。詳情請參閱「批次處理」。

如果是具有正式感應器類型的感應器,架構會覆寫部分欄位。舉例來說,加速計感應器必須採用連續回報模式,心率監測器則必須受到 SENSOR_PERMISSION_BODY_SENSORS 權限保護。

sensors_event_t

Android 感應器產生的感應器事件,會透過 poll 函式回報,且屬於 type sensors_event_t。以下是 sensors_event_t 的幾個重要欄位:

version:必須為 sizeof(struct sensors_event_t)

感應器:產生事件的感應器控制代碼,由 sensor_t.handle 定義。

type:產生事件的感應器類型,如 sensor_t.type 所定義。

時間戳記:事件的時間戳記 (以奈秒為單位)。這是事件發生的時間 (採取步驟或進行加速度計測量),而非事件回報時間。timestamp 必須與 elapsedRealtimeNano 時鐘同步,如果是連續感應器,抖動必須很小。有時必須進行時間戳記篩選,才能符合 CDD 需求,因為只使用 SoC 中斷時間設定時間戳記會導致抖動過高,而只使用感應器晶片時間設定時間戳記則會導致與 elapsedRealtimeNano 時鐘不同步,因為感應器時鐘會漂移。

資料和重疊欄位:感應器測量的值。這些欄位的意義和單位會因感應器類型而異。如需資料欄位的說明,請參閱 sensors.h 和不同感應器類型的定義。部分感應器也會透過 status 欄位,在資料中回報讀數準確度。這個欄位只會針對特定感應器類型透過管道傳輸,並在 SDK 層顯示為準確度值。對於這些感應器,狀態欄位必須設定的事實會在感應器類型定義中提及。

中繼資料排清完成事件

中繼資料事件的類型與一般感應器事件相同: sensors_event_meta_data_t = sensors_event_t。這些事件會透過輪詢與其他感應器事件一併傳回。這些欄位如下:

version:必須為 META_DATA_VERSION

type:必須是 SENSOR_TYPE_META_DATA

感應器、保留和時間戳記:必須為 0

meta_data.what:包含此事件的中繼資料類型。目前只有一種有效的中繼資料類型:META_DATA_FLUSH_COMPLETE

META_DATA_FLUSH_COMPLETE 事件代表感應器 FIFO 的排清作業已完成。當 meta_data.what=META_DATA_FLUSH_COMPLETE 時,meta_data.sensor 必須設為已清除感應器的控制代碼。只有在感應器上呼叫 flush 時,系統才會產生這些事件。詳情請參閱「清除」函式一節。