Termal API

Yayınlanma tarihi:

Android 11 (API düzeyi 30) - Termal API

Android 12 (API düzeyi 31) - NDK API

(Önizleme) Android 15 (DP1) - getThermalHeadroomThresholds()

Uygulamanızın potansiyel performansı, cihazın termal durumuyla sınırlıdır. Bu durum hava durumu, son kullanım ve cihazın termal tasarımı gibi özelliklere göre değişiklik gösterebilir. Cihazlar, termal olarak sınırlandırılmadan önce yalnızca sınırlı bir süre boyunca yüksek performans sağlayabilir. Uygulamanızın temel hedeflerinden biri, termal sınırlamaları aşmadan performans hedeflerine ulaşmaktır. Termal API, cihaza özel optimizasyonlara gerek kalmadan bunu mümkün kılar. Ayrıca, performans sorunlarında hata ayıklama yaparken cihazınızın termal durumunun performansı sınırlayıp sınırlamadığını bilmek önemlidir.

Oyun motorlarında genellikle motorun cihaza yüklediği iş yükünü ayarlayabilen çalışma zamanı performans parametreleri bulunur. Örneğin, bu parametreler çalışan iş parçacıklarının sayısını, büyük ve küçük çekirdekler için çalışan iş parçacığı yakınlığını, GPU doğruluk seçeneklerini ve çerçeve önbelleği çözünürlüklerini ayarlayabilir. Unity Engine'de oyun geliştiriciler, Adaptive Performance eklentisini kullanarak Kalite Ayarlarını değiştirerek iş yükünü ayarlayabilir. Unreal Engine için kalite düzeylerini dinamik olarak ayarlamak üzere Ölçeklenebilirlik Ayarları'nı kullanın.

Bir cihaz güvenli olmayan bir termal duruma yaklaştığında, oyununuz bu parametreler aracılığıyla iş yükünü azaltarak tıkanmayı önleyebilir. Yavaşlatmayı önlemek için cihazın termal durumunu izlemeniz ve oyun motoru iş yükünü proaktif olarak ayarlamanız gerekir. Cihaz aşırı ısındığında, ısının dağıtılması için iş yükü sürdürülebilir performans seviyesinin altına düşmelidir. Termal marj daha güvenli seviyelere düştüğünde oyun, kalite ayarlarını tekrar artırabilir. Ancak optimum oyun süresi için sürdürülebilir bir kalite düzeyi bulduğunuzdan emin olun.

getThermalHeadroom yöntemini sorgulayarak cihazın termal durumunu izleyebilirsiniz. Bu yöntem, cihazın aşırı ısınmadan mevcut performans düzeyini ne kadar süre koruyabileceğini tahmin eder. Zaman, iş yükünü çalıştırmak için gerekenden azsa oyununuz iş yükünü sürdürülebilir bir seviyeye düşürmelidir. Örneğin, oyun daha küçük çekirdeklere geçebilir, kare hızını düşürebilir veya doğruluğu azaltabilir.

ADPF Termal API Ön Entegrasyonu
Şekil 1. getThermalHeadroom işlevi etkin olarak izlenmeden termal marj
ADPF Termal API Entegrasyon Sonrası
Şekil 2. `getThermalHeadroom`işlevinin etkin izlenmesi ile termal boşluk

Termal Yönetici'yi edinme

Termal API'yi kullanmak için önce Termal Yöneticisi'ni edinmeniz gerekir.

C++

AThermalManager* thermal_manager = AThermal_acquireManager();

Java

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

Daha fazla kontrol için termal marjı x saniye ileriye tahmin edin

Sistemden mevcut iş yükü ile x saniye ilerideki sıcaklığı tahmin etmesini isteyebilirsiniz. Bu sayede, termal sınırlamanın devreye girmesini önlemek için iş yükünü azaltarak daha ayrıntılı bir kontrol sahibi olur ve daha fazla tepki verme süresi elde edersiniz.

Sonuç 0,0f (daraltma yok, THERMAL_STATUS_NONE) ile 1,0f (ağır daraltma, THERMAL_STATUS_SEVERE) arasında değişir. Oyunlarınızda farklı grafik kalitesi seviyeleri varsa Isıtma Boşluğu Yönergelerimizi uygulayabilirsiniz.

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);

Alternatif olarak, netlik için termal duruma güvenebilirsiniz

Her cihaz modeli farklı şekilde tasarlanmış olabilir. Bazı cihazlar ısıyı daha iyi dağıtabilir ve bu nedenle, ısı sınırına ulaşmadan daha yüksek termal marja dayanabilir. Isıtma marjı aralıkları için basitleştirilmiş bir gruplandırma okumak istiyorsanız mevcut cihazdaki ısıtma marjı değerini anlamak için ısıtma durumunu kontrol edebilirsiniz.

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);

Termal durum değiştiğinde bildirim alın

Ayrıca, thermalStatus belirli bir seviyeye (örneğin: THERMAL_STATUS_LIGHT) ulaşana kadar thermalHeadroom'ü sorgulamak zorunda kalmazsınız. Bunun için, durum değiştiğinde sistemin sizi bilgilendirmesi için geri çağırma işlevi kaydedebilirsiniz.

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);

İşiniz bittiğinde dinleyiciyi kaldırmayı unutmayın.

C++

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

Java

powerManager.removeThermalStatusListener(listener);

Temizle

İşlemi tamamladığınızda, edindiğiniz thermal_manager öğesini temizlemeniz gerekir. Java kullanıyorsanız PowerManager referansı sizin için otomatik olarak çöp toplanabilir. Ancak Java API'yi JNI üzerinden kullanıyorsanız ve bir referans tuttuysanız referansı temizlemeyi unutmayın.

C++

AThermal_releaseManager(thermal_manager);

Hem C++ API'yi (NDK API) hem de Java API'yi (JNI aracılığıyla) kullanarak Thermal API'yi yerel bir C++ oyununa uygulamayla ilgili eksiksiz bir kılavuz için Uyumluluk kod laboratuvarının Thermal API'yi entegre etme bölümüne göz atın.

Isıtma payı yönergeleri

getThermalHeadroom yöntemini sorgulayarak cihazın termal durumunu izleyebilirsiniz. Bu yöntem, cihazın THERMAL_STATUS_SEVERE değerine ulaşmadan önce mevcut performans düzeyini ne kadar süre boyunca koruyabileceğini tahmin eder. Örneğin, getThermalHeadroom(30) 0,8 döndürürse bu, 30 saniye içinde boş alanın 0,8'e ulaşmasının beklendiğini gösterir. Bu durumda, şiddetli daralmadan 0,2 uzaklıkta veya 1,0'dasınız demektir. Zaman, iş yükünü çalıştırmak için gerekenden azsa oyununuz iş yükünü sürdürülebilir bir seviyeye düşürmelidir. Örneğin, oyun kare hızını düşürebilir, doğruluğu azaltabilir veya ağ bağlantısı çalışmasını azaltabilir.

Isıtma durumları ve anlamları

Thermal API'nin cihaz sınırlamaları

Termal API'nin eski cihazlarda uygulanması nedeniyle, Termal API ile ilgili bilinen bazı sınırlamalar veya ek şartlar vardır. Sınırlılıklar ve bu sınırlamaların nasıl aşıldığı aşağıda açıklanmıştır:

  • GetThermalHeadroom() API'yi çok sık çağırmayın. Bunu yaparsanız API NaN değerini döndürür. 10 saniyede bir defadan fazla arama yapmamalısınız.
  • Birden fazla iş parçacığında çağrı yapmaktan kaçının. Bu, çağrı sıklığını kontrol etmeyi zorlaştırır ve API'nin NaN döndürmesine neden olabilir.
  • GetThermalHeadroom() değerinin başlangıç değeri NaN ise API cihazda kullanılamaz
  • GetThermalHeadroom() yüksek bir değer döndürüyorsa (ör. 0, 85 veya daha yüksek) ve GetCurrentThermalStatus() hâlâ THERMAL_STATUS_NONE döndürüyorsa durum büyük olasılıkla güncellenmemiştir. Doğru termal kısıtlama durumunu tahmin etmek için sezgisel yöntemler kullanın veya getCurrentThermalStatus() olmadan yalnızca getThermalHeadroom() kullanın.

Buluşsal yöntemler örneği:

  1. Termal API'nin desteklenip desteklenmediğini kontrol edin. isAPISupported(), getThermalHeadroom'a yapılan ilk çağrının değerinin 0 veya NaN olmadığından emin olmak için değerini kontrol eder ve ilk değer 0 veya NaN ise API'yi kullanmayı atlar.
  2. getCurrentThermalStatus(), THERMAL_STATUS_NONE dışında bir değer döndürüyorsa cihaz termal olarak kısıtlanıyordur.
  3. getCurrentThermalStatus() sürekli olarak THERMAL_STATUS_NONE döndürüyorsa bu, cihazın termal olarak kısıtlanmadığı anlamına gelmez. Bu, getCurrentThermalStatus()'ün cihazda desteklenmediği anlamına gelebilir. Cihazın durumunu kontrol etmek için getThermalHeadroom() değerinin döndürülen değerini kontrol edin.
  4. getThermalHeadroom(), 1, 0'dan büyük bir değer döndürüyorsa durum aslında THERMAL_STATUS_SEVERE veya daha yüksek olabilir. İş yükünü hemen azaltın ve getThermalHeadroom() daha düşük bir değer döndürene kadar düşük iş yükünü koruyun.
  5. getThermalHeadroom() 0,95 değerini döndürüyorsa durum aslında THERMAL_STATUS_MODERATE veya daha yüksek olabilir. İş yükünü hemen azaltın ve daha yüksek okumaları önlemek için dikkatli olun.
  6. getThermalHeadroom() 0,85 değerini döndürüyorsa durum aslında THERMAL_STATUS_LIGHT olabilir.Dikkatli olun ve mümkünse iş yükünü azaltın

Sözde kod:

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

Diyagram:

ADPF Sezgisel Örneği
Şekil 3. Eski cihazlarda Termal API desteğini belirlemek için kullanılan sezgisel yöntem örneği