Thermal API

發布日期

Android 11 (API 級別 30) - Thermal API

Android 12 (API 級別 31) - NDK API

(預先發布版) Android 15 (DP1) - getThermalHeadroomThresholds()

應用程式的潛在效能會受限於 細分功能,切身相關的特性包括天氣、近期使用情況 和裝置的熱力設計裝置只能維持最高等級 執行效能有限的時間,然後才開始調節溫度。一把鑰匙 導入目標,應該在沒有提示的情況下達成成效目標 。使用 Thermal API 即可讓 用於裝置專屬的最佳化設定此外,執行效能偵錯時 瞭解裝置的熱力狀態是否限制效能 非常重要

遊戲引擎通常會提供執行階段效能參數,可調整 執行工作負載舉例來說,您可以將這些參數 工作站執行緒的數量、大型與小型核心的工作站執行緒相依性, GPU 擬真度選項和 framebuffer 解析度。在 Unity Engine 中 開發人員可以調整工作負載品質, 設定 使用 Adaptive Performance 外掛程式。 如果是 Unreal Engine,請使用擴充性設定進行調整 以動態方式評估品質等級

當裝置靠近不安全的熱力狀態時,遊戲就能避免 藉此減少工作負載量。為了避免 此時,您應該監控裝置的熱力狀態,並主動監控 調整遊戲引擎工作負載裝置過熱後,工作負載必須 降溫低於永續性等級以消滅熱。更新後 當熱力上升空間進入安全等級時,遊戲就能 請務必調整畫質設定,並確保畫質穩定 以獲得最佳的播放時間

您可以藉由輪詢 getThermalHeadroom敬上 方法。這個方法可預測裝置可維持目前狀態的時間長度 效能等級,避免過熱如果時間少於 遊戲應該將工作負載減少為 實踐永續發展理念舉例來說,遊戲可以改用較小的核心, 或低擬真度

ADPF Thermal API 預先整合
圖 1.未主動監控 getThermalHeadroom 的熱力上升空間
ADPF 熱線 API 整合後 API
圖 2.熱力上升空間,且主動監控「getThermalHeadroom」

取得熱力管理員

如要使用 Thermal API,請先取得 Thermal Manager

C++

AThermalManager* thermal_manager = AThermal_acquireManager();

Java

PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);

預測熱力上升空間 x 秒,進一步控制

您可以使用 目前工作負載這樣您就能更精細地控管設定 並有更多時間 便是減少工作負載來防止 實施熱節流

結果範圍從 0.0f (無調節,THERMAL_STATUS_NONE) 至 1.0f (大幅節流,THERMAL_STATUS_SEVERE)。 如果遊戲的影像品質等級不同,可以遵照我們的 熱力上升空間準則

C++

float thermal_headroom = AThermal_getThermalHeadroom(10);
ALOGI("ThermalHeadroom in 10 sec: %f", thermal_headroom);

Java

float thermalHeadroom = powerManager.getThermalHeadroom(10);
Log.d("ADPF", "ThermalHeadroom in 10 sec: " + thermalHeadroom);

或者,參考熱力狀態來取得說明

每個裝置型號的設計可能不同。部分裝置或許可以 分散暖氣,以便承受較高溫上升空間 然後受到限制如果想要閱讀經過簡化的 熱力上升空間,可以檢查熱力狀態 目前裝置的熱力上升空間值。

C++

AThermalStatus thermal_status = AThermal_getCurrentThermalStatus(thermal_manager);
ALOGI("ThermalStatus is: %d", thermal_status);

Java

int thermalStatus = powerManager.getCurrentThermalStatus();
Log.d("ADPF", "ThermalStatus is: " + thermalStatus);

在熱力狀態變更時收到通知

您也可以避免輪詢 thermalHeadroom,直到 thermalStatus 命中為止 特定等級 (例如:THERMAL_STATUS_LIGHT)。 如要這麼做,您可以註冊回呼,讓系統在 狀態已變更。

C++

int result = AThermal_registerThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
  // failed, check whether you have previously registered callback that
  // hasn’t been unregistered
}

Java

// PowerManager.OnThermalStatusChangedListener is an interface, thus you can
// also define a class that implements the methods
PowerManager.OnThermalStatusChangedListener listener = new
  PowerManager.OnThermalStatusChangedListener() {
    @Override
    public void onThermalStatusChanged(int status) {
        Log.d("ADPF", "ThermalStatus changed: " + status);
        // check the status and flip the flag to start/stop pooling when
        // applicable
    }
};
powerManager.addThermalStatusListener(listener);

請記得在完成後移除事件監聽器

C++

int result = AThermal_unregisterThermalStatusListener(thermal_manager, callback);
if ( result != 0 ) {
  // failed, check whether the callback has been registered previously
}

Java

powerManager.removeThermalStatusListener(listener);

清除

完成後,請清除您取得的 thermal_manager。 如果您使用 Java,則 PowerManager 參照可自動為垃圾檔案進行垃圾處理 系統但如果您是透過 JNI 使用 Java API,且 保留一個參考資料,請記得清除參照!

C++

AThermal_releaseManager(thermal_manager);

如需在原生 C++ 遊戲中實作 Thermal API 的完整指南, C++ API (NDK API) 和 Java API (透過 JNI),請參閱 「適應性程式碼研究室」中的 Thermal API 一節 專區。

熱力上升空間規範

您可以藉由輪詢 getThermalHeadroom敬上 方法。這個方法可預測裝置可維持目前狀態的時間長度 成效等級才會顯示為 THERMAL_STATUS_SEVERE。 舉例來說,如果 getThermalHeadroom(30) 傳回 0.8,就表示在 30 中 進步空間預計會達到 0.8,距離 0.2 防止過度節流,甚至是 1.0如果時間少於 即可讓遊戲達成永續發展 第二,自訂角色只能 套用至專案或機構舉例來說,遊戲可以降低影格速率、低保真度 以減少網路連線能力

過熱狀態與意義

Thermal API 的裝置限制

Thermal API 有一些已知限製或額外規定, 瞭解如何在較舊的裝置上實作 Thermal API。限制和方式 方法如下:

  • 請勿太常呼叫 GetThermalHeadroom() API。這麼做 結果,API 會傳回 NaN呼叫頻率上限為每秒一次。
  • 如果 GetThermalHeadroom() 的初始值為 NaN,則 API 不會 可用的裝置
  • 如果 GetThermalHeadroom() 傳回高價值 (例如:0.85 以上) 且 GetCurrentThermalStatus() 仍會傳回 THERMAL_STATUS_NONE,表示狀態是 可能沒有更新。使用經驗法則估算正確的熱節流 或是只使用 getThermalHeadroom(),而不使用 getCurrentThermalStatus()

經驗法則範例:

  1. 檢查系統是否支援 Thermal API。isAPISupported() 會檢查 第一個呼叫 getThermalHeadroom 以確保其並非 0 或 NN,並且 如果第一個值是 0 或 NaN,就會略過 API。
  2. 如果 getCurrentThermalStatus() 傳回的值不是 THERMAL_STATUS_NONE,裝置目前受到熱節限制。
  3. 如果 getCurrentThermalStatus() 持續傳回 THERMAL_STATUS_NONE,就會 但不一定代表裝置沒有受到熱節限制。 表示裝置不支援 getCurrentThermalStatus()。 檢查 getThermalHeadroom() 的傳回值,確保 裝置。
  4. 如果 getThermalHeadroom() 傳回 > 的值1.0,狀態 但實際上是 THERMAL_STATUS_SEVERE 以上,立即減少工作負載 維持較少工作負載,直到 getThermalHeadroom() 傳回的值較低
  5. 如果 getThermalHeadroom() 傳回 0.95 值,狀態 但實際上是 THERMAL_STATUS_MODERATE 以上,請立即減少工作負載 並隨時留意
  6. 如果 getThermalHeadroom() 傳回 0.85 值,狀態 其實是 THERMAL_STATUS_LIGHT,請密切留意並減少工作負載 可以的話

虛擬程式碼:

  bool isAPISupported() {
    float first_value_of_thermal_headroom = getThermalHeadroom();
    if ( first_value_of_thermal_headroom == 0 ||
      first_value_of_thermal_headroom == NaN ) {
        // Checked the thermal Headroom API's initial return value
        // it is NaN or 0,so, return false (not supported)
        return false;
    }
    return true;
  }
  
  if (!isAPISupported()) {
    // Checked the thermal Headroom API's initial return value, it is NaN or 0
    // Don’t use the API
  } else {
      // Use thermalStatus API to check if it returns valid values.
      if (getCurrentThermalStatus() > THERMAL_STATUS_NONE) {
          // The device IS being thermally throttled
      } else {
      // The device is not being thermally throttled currently. However, it
      // could also be an indicator that the ThermalStatus API may not be
      // supported in the device.
      // Currently this API uses predefined threshold values for thermal status
      // mapping. In the future  you may be able to query this directly.
      float thermal_headroom = getThermalHeadroom();
      if ( thermal_headroom > 1.0) {
            // The device COULD be severely throttled.
      } else  if ( thermal_headroom > 0.95) {
            // The device COULD be moderately throttled.
      } else if ( thermal_headroom > 0.85) {
            // The device COULD be experiencing light throttling.
      }
    }
  }

圖:

ADPF 啟發式範例
圖 3:以下示例說明如何判斷舊裝置是否支援 Thermal API。