RIL 重構

Android 7.0 使用一組功能重建了無線電介面層 (RIL),以改善 RIL 功能。需要更改合作夥伴程式碼才能實現這些功能,這是可選的,但鼓勵這樣做。重構變更是向後相容的,因此重構功能的先前實作仍然有效。

RIL 重構包括以下改進:

  • RIL 錯誤代碼。除了現有的GENERIC_FAILURE代碼之外,還啟用特定的錯誤代碼。這透過提供有關錯誤原因的更具體的資訊來幫助排除錯誤。
  • RIL 版本控制。提供更準確、更易於配置的版本資訊。
  • 使用喚醒鎖定的 RIL 通訊。提高設備電池效能。

您可以實施上述任何或所有改進。有關更多詳細信息,請參閱https://android.googlesource.com/platform/hardware/ril/+/main/include/telephony/ril.h中有關 RIL 版本控制的程式碼註釋。

實作增強的 RIL 錯誤代碼

幾乎所有 RIL 請求呼叫都可以傳回GENERIC_FAILURE錯誤代碼以回應錯誤。這是 OEM 傳回的所有請求回應的問題,如果 RIL 呼叫因不同原因傳回相同的GENERIC_FAILURE錯誤代碼,則可能會很難從錯誤報告中偵錯問題。供應商可能需要相當長的時間才能確定代碼的哪一部分可能會傳回GENERIC_FAILURE代碼。

在 Android 7.x 及更高版本中,OEM 可以傳回與目​​前分類為GENERIC_FAILURE的每個不同錯誤關聯的不同錯誤代碼值。不想公開透露其自訂錯誤代碼的 OEM 可以將錯誤傳回為一組不同的整數(例如 1 到 x),映射為OEM_ERROR_1OEM_ERROR_X 。供應商應確保傳回的每個此類屏蔽錯誤代碼都對應到程式碼中的唯一錯誤原因。每當 OEM 傳回一般錯誤時,使用特定錯誤代碼都可以加快 RIL 偵錯速度,因為通常需要花費太多時間來確定GENERIC_FAILURE錯誤代碼的確切原因(有時甚至無法找出)。

此外, ril.h為枚舉RIL_LastCallFailCauseRIL_DataCallFailCause添加了更多錯誤代碼,因此供應商代碼可以避免返回通用錯誤,例如CALL_FAIL_ERROR_UNSPECIFIEDPDP_FAIL_ERROR_UNSPECIFIED

驗證增強型 RIL 錯誤代碼

新增新的錯誤代碼來替換GENERIC_FAILURE代碼後,驗證 RIL 呼叫傳回新的錯誤代碼而不是GENERIC_FAILURE

實施增強的 RIL 版本控制

舊版 Android 版本中的 RIL 版本控制存在問題:版本本身不精確,報告 RIL 版本的機制不清楚(導致某些供應商報告不正確的版本),並且估計版本的解決方法容易不準確。

在 Android 7.x 及更高版本中, ril.h記錄所有 RIL 版本值、描述對應的 RIL 版本,並列出該版本的所有變更。在進行與 RIL 版本相對應的變更時,供應商必須更新程式碼中的版本並在RIL_REGISTER中傳回該版本。

驗證增強的 RIL 版本控制

驗證在RIL_REGISTER期間傳回與您的 RIL 程式碼相對應的 RIL 版本(而不是ril.h中定義的RIL_VERSION )。

使用喚醒鎖定實現 RIL 通信

定時喚醒鎖在 RIL 通訊中的使用方式並不精確,這會對電池效能產生負面影響。在 Android 7.x 及更高版本中,您可以透過對 RIL 請求進行分類並更新程式碼以針對不同請求類型以不同方式處理喚醒鎖定來提高效能。

對 RIL 請求進行分類

RIL 請求可以是請求的,也可以是主動請求的。供應商應將徵求的請求進一步分類為以下其中之一:

  • 同步。不需要相當長的時間回覆的請求。例如, RIL_REQUEST_GET_SIM_STATUS
  • 異步。需要相當長的時間才能回覆的請求。例如, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS

非同步請求的 RIL 請求可能需要相當長的時間。從供應商程式碼收到確認後,RIL Java 釋放喚醒鎖定,這可能導致應用程式處理器從空閒狀態進入暫停狀態。當供應商程式碼提供回應時,RIL Java(應用程式處理器)會重新取得喚醒鎖定,處理回應,然後返回空閒狀態。這種從空閒到掛起再到空閒的轉變會消耗大量電力。

如果回應時間不夠長,則在回應所需的整個時間內保持喚醒鎖定並保持空閒狀態比透過釋放喚醒鎖定並在回應到達時喚醒而進入掛起狀態更節能。供應商應使用特定於平台的功耗測量來確定時間T的閾值,即在整個時間T內保持空閒狀態所消耗的功耗大於在同一時間T內從空閒狀態轉為掛起狀態再轉為空閒狀態所消耗的功耗。當時間T已知時,花費超過時間T的 RIL 指令可以歸類為非同步,其餘指令歸類為同步。

RIL通訊場景

下圖說明了常見的 RIL 通訊場景,並提供了修改程式碼以處理 RIL 請求和主動請求的解決方案。

注意:有關下圖中使用的函數的實現詳細信息,請參閱ril.cpp中的acquireWakeLock()decrementWakeLock()clearWakeLock( ) 方法。

場景:RIL 請求並請求非同步回應

在這種情況下,如果 RIL 請求的回應預計需要相當長的時間(即對RIL_REQUEST_GET_AVAILABLE_NETWORKS的回應),則喚醒鎖定將在應用程式處理器端保持很長時間。調製解調器問題也可能導致長時間等待。

圖 1. RIL 請求非同步回應。

解決方案 1:數據機持有 RIL 請求和非同步回應的喚醒鎖定。

圖 2.調變解調器保持的喚醒鎖定。
  1. 發送 RIL 請求,數據機取得喚醒鎖定來處理該請求。
  2. 數據機發送確認,導致 Java 端遞減喚醒鎖定計數器,並在計數器值為 0 時釋放它。

    注意:請求-確認序列的喚醒鎖定逾時持續時間將小於目前使用的逾時持續時間,因為應該相當快速地接收到確認。

  3. 處理完請求後,數據機向供應商代碼發送中斷,供應商代碼獲取喚醒鎖定並向 ril.cpp 發送回應,ril.cpp 又會取得喚醒鎖定並向 Java 端發送回應。
  4. 當回應到達 Java 端時,將取得喚醒鎖定並將回應傳回給呼叫者。
  5. 所有模組處理完回應後,會將確認(透過套接字)傳回ril.cpp ,然後釋放在步驟 3 中取得的喚醒鎖定。

解決方案2:調變解調器不會保持喚醒鎖定且回應很快(同步RIL請求和回應)。同步與異步行為是針對特定 RIL 指令進行硬編碼的,並根據逐一呼叫來決定。

圖 3.調變解調器未保持喚醒鎖定。
  1. RIL請求是透過Java端呼叫acquireWakeLock()來傳送的。
  2. 供應商代碼不需要取得喚醒鎖,可以快速處理請求並回應。
  3. 當Java端收到回應時,呼叫decrementWakeLock() ,這會減少喚醒鎖定計數器,如果計數器值為0則釋放喚醒鎖定。

場景:RIL 主動回應

在這種情況下,RIL 主動回應在 中具有喚醒鎖定類型標誌,指示是否需要為供應商回應取得喚醒鎖定。如果設定了該標誌,則會設定定時喚醒鎖定,並透過套接字將回應傳送到 Java 端。當定時器到期時,喚醒鎖定被釋放。對於不同的 RIL 主動回應,定時喚醒鎖定可能太長或太短。

圖 4. RIL 主動響應。

解決方案:從 Java 程式碼向本機端 ( ril.cpp ) 發送確認,而不是在發送未經請求的回應時在本機端保持定時喚醒鎖定。

圖 5.使用 ack 代替定時喚醒鎖定。

驗證重新設計的喚醒鎖

驗證 RIL 呼叫是否被識別為同步或非同步。由於電池功耗可能與硬體/平台相關,因此供應商應進行一些內部測試,以確定對非同步呼叫使用新的喚醒鎖語義是否可以節省電池電量。