Thermal API

تاريخ الإصدار:

‫Android 11 (المستوى 30 لواجهة برمجة التطبيقات) - واجهة برمجة التطبيقات Thermal API

‫Android 12 (المستوى 31 لواجهة برمجة التطبيقات) - واجهة برمجة التطبيقات في NDK

(إصدار تجريبي) Android 15 (DP1) - getThermalHeadroomThresholds()

يتم تحديد الأداء المحتمل لتطبيقك حسب الحالة الحرارية للجهاز، والتي يمكن أن تختلف استنادًا إلى خصائص مثل الطقس والاستخدام الحديث والتصميم الحراري للجهاز. يمكن للأجهزة الحفاظ على مستوى عالٍ من الأداء لفترة زمنية محدودة فقط قبل أن يتم خفض سرعتها بسبب ارتفاع درجة الحرارة. يجب أن يكون أحد الأهداف الرئيسية لعملية التنفيذ هو تحقيق أهداف الأداء بدون تجاوز القيود الحرارية. تتيح واجهة برمجة التطبيقات Thermal API إمكانية ذلك بدون الحاجة إلى إجراء تحسينات خاصة بالجهاز. بالإضافة إلى ذلك، عند تصحيح أخطاء الأداء، من المهم معرفة ما إذا كانت الحالة الحرارية لجهازك تحدّ من الأداء.

تحتوي محركات الألعاب عادةً على مَعلمات أداء وقت التشغيل التي يمكنها ضبط عبء العمل الذي يفرضه المحرك على الجهاز. على سبيل المثال، يمكن أن تحدّد هذه المَعلمات عدد سلاسل عمليات العامل، ومستوى التقارب بين سلاسل عمليات العامل والنوى الكبيرة والصغيرة، وخيارات دقة وحدة معالجة الرسومات، ودقة إطارات المخزن المؤقت. في Unity Engine، يمكن لمطوّري الألعاب تعديل عبء العمل من خلال تغيير إعدادات الجودة باستخدام مكوّن Adaptive Performance الإضافي. في Unreal Engine، استخدِم إعدادات قابلية التوسّع لضبط مستويات الجودة بشكل ديناميكي.

عندما يقترب الجهاز من حالة حرارية غير آمنة، يمكن أن تتجنّب لعبتك خفض الأداء من خلال تقليل حجم المعالجة باستخدام هذه المَعلمات. لتجنُّب خفض السرعة، عليك مراقبة حالة حرارة الجهاز وضبط حجم معالجة محرك اللعبة بشكل استباقي.

وبعد أن يسخن الجهاز بشكل مفرط، يجب أن ينخفض عبء العمل إلى ما دون مستوى الأداء المستدام من أجل تبديد الحرارة. بعد أن ينخفض هامش الحرارة إلى مستويات أكثر أمانًا، يمكن للعبة رفع إعدادات الجودة مرة أخرى، ولكن يجب الحرص على تحديد مستوى جودة مستدام لضمان أفضل وقت ممكن للعب.

يمكنك مراقبة الحالة الحرارية للجهاز من خلال طلب البيانات بشكل متكرّر باستخدام طريقة getThermalHeadroom. تتوقّع هذه الطريقة المدة التي يمكن للجهاز خلالها الحفاظ على مستوى الأداء الحالي بدون ارتفاع درجة حرارته بشكل مفرط. إذا كان الوقت أقل من الوقت المطلوب لتشغيل عبء العمل، يجب أن تقلّل لعبتك عبء العمل إلى مستوى مستدام. على سبيل المثال، يمكن أن تنتقل اللعبة إلى استخدام نوى أصغر أو تخفض عدد اللقطات في الثانية أو تقلّل من دقة العرض.

الدمج المُسبَق لواجهة برمجة التطبيقات الحرارية ADPF
الشكل 1. مساحة الحرارة المتاحة بدون مراقبة نشطة getThermalHeadroom
ADPF Thermal API Post-Integration
الشكل 2. مساحة الحرارة المتاحة مع المراقبة النشطة للدالة `getThermalHeadroom`

الحصول على تطبيق Thermal Manager

لاستخدام 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(0);
ALOGI("ThermalHeadroom: %f", thermal_headroom);

Java

float thermalHeadroom = powerManager.getThermalHeadroom(0);
Log.d("ADPF", "ThermalHeadroom: " + 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 تلقائيًا. ولكن إذا كنت تستخدم واجهة برمجة تطبيقات Java من خلال JNI واحتفظت بمرجع، تذكَّر إزالة المرجع.

C++‎

AThermal_releaseManager(thermal_manager);

للحصول على دليل كامل حول كيفية تنفيذ Thermal API في لعبة C++ أصلية باستخدام كل من واجهة برمجة التطبيقات C++ (واجهة برمجة تطبيقات NDK) وواجهة برمجة تطبيقات Java (من خلال JNI)، يمكنك الاطّلاع على قسم دمج Thermal API في قسم برنامج Adaptability التعليمي.

إرشادات بشأن المساحة المتاحة للتبديد الحراري

يمكنك مراقبة الحالة الحرارية للجهاز من خلال طلب البيانات بشكل متكرر باستخدام طريقة getThermalHeadroom. تتوقّع هذه الطريقة المدة التي يمكن للجهاز خلالها الحفاظ على مستوى الأداء الحالي قبل الوصول إلى THERMAL_STATUS_SEVERE. على سبيل المثال، إذا عرضت getThermalHeadroom(30) القيمة 0.8، يشير ذلك إلى أنّه من المتوقّع أن يصل هامش الأداء إلى 0.8 خلال 30 ثانية، أي أنّ هناك مسافة 0.2 من الحدّ الأقصى للتقييد الشديد، أو 1.0. إذا كان الوقت أقل من الوقت اللازم لتشغيل عبء العمل، يجب أن تقلّل لعبتك عبء العمل إلى مستوى مستدام. على سبيل المثال، يمكن للعبة تقليل عدد اللقطات في الثانية أو خفض الدقة أو تقليل العمل المطلوب لتوفير اتصال الشبكة.

حالات درجة الحرارة ومعانيها

القيود المفروضة على الأجهزة في Thermal API

هناك بعض القيود المعروفة أو المتطلبات الإضافية لواجهة برمجة التطبيقات Thermal API، وذلك بسبب عمليات تنفيذ واجهة برمجة التطبيقات Thermal API على الأجهزة القديمة. في ما يلي القيود وكيفية التغلّب عليها:

  • لا تستدعِ واجهة برمجة التطبيقات GetThermalHeadroom() بشكل متكرّر. وفي حال إجراء ذلك، تعرض واجهة برمجة التطبيقات القيمة NaN. يجب عدم استدعاء هذا الإجراء أكثر من مرة كل 10 ثوانٍ.
  • تجنَّب إجراء مكالمات من سلاسل محادثات متعددة، لأنّه يصعب ضمان تكرار المكالمات وقد يؤدي ذلك إلى أن تعرض واجهة برمجة التطبيقات NaN.
  • إذا كانت القيمة الأولية لـ GetThermalHeadroom() هي NaN، لن تكون واجهة برمجة التطبيقات متاحة على الجهاز.
  • إذا عرضت الدالة GetThermalHeadroom() قيمة عالية (مثل 0.85 أو أكثر) واستمرت الدالة GetCurrentThermalStatus() في عرض THERMAL_STATUS_NONE، من المحتمل ألا يتم تعديل الحالة. استخدِم طرقًا تجريبية لتقدير حالة الحدّ من سرعة المعالجة بسبب الحرارة بشكل صحيح، أو استخدِم getThermalHeadroom() بدون getCurrentThermalStatus().

مثال على الإعدادات الإرشادية:

  1. تأكَّد من أنّ الجهاز يتيح استخدام Thermal API. تتحقّق isAPISupported() من قيمة الطلب الأول إلى getThermalHeadroom للتأكّد من أنّها ليست 0 أو NaN، وتتخطّى استخدام واجهة برمجة التطبيقات إذا كانت القيمة الأولى 0 أو NaN.
  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 متوافقة مع الأجهزة القديمة