تاريخ الإصدار:
Android 11 (المستوى 30) - Thermal API
Android 12 (المستوى 31) - NDK API
(معاينة) Android 15 (DP1) - getThermalHeadroomThresholds()
يعتمد الأداء المحتمل لتطبيقك على الحالة الحرارية والذي قد يختلف بناءً على خصائص مثل الطقس والاستخدام الأخير والتصميم الحراري للجهاز. يمكن للأجهزة الحفاظ على مستوى عالٍ من لفترة محدودة من الوقت قبل أن يتم تقييدها حراريًا. المفتاح يجب أن يكون الهدف من التنفيذ هو تحقيق أهداف الأداء بدون وتجاوز القيود الحرارية. تتيح واجهة برمجة التطبيقات Thermal API إمكانية استخدامها بدون الحاجة إلى لإجراء تحسينات خاصة بالجهاز. علاوةً على ذلك، عند تصحيح أخطاء الأداء فمعرفة ما إذا كانت الحالة الحرارية للجهاز تحدّ من الأداء التحليل.
تتضمن محركات الألعاب عادةً معلَمات لأداء وقت التشغيل يمكنها ضبط حجم العمل الذي يضعه المحرك على الجهاز. على سبيل المثال، يمكن لهذه المعاملات تحديد عدد خيوط العمال، وتقارب خيوط العاملين مع النوى الكبيرة والصغيرة، خيارات الدقة في وحدة معالجة الرسومات ودرجات دقة المخزن المؤقت للإطارات في Unity Engine، يتم تشغيل لعبة للمطوّرين تعديل أعباء العمل من خلال تغيير جدول الجودة الإعدادات باستخدام المكوّن الإضافي "الأداء التكيُّفي". في Unreal Engine، استخدِم إعدادات قابلية التوسيع لضبط ومستويات الجودة بشكل ديناميكي.
عندما يقترب أحد الأجهزة من حالة حرارية غير آمنة، يمكن أن تتجنّب لعبتك الحد من خلال خفض عبء العمل من خلال هذه المعاملات. لتجنُّب تقييد البيانات، يجب مراقبة الحالة الحرارية للجهاز بشكل استباقي، ضبط عبء عمل محرك اللعبة. عندما ترتفع درجة حرارة الجهاز أكثر من اللازم، يجب أن تنخفض إلى أقل من مستوى الأداء المستدام بهدف تشتت الحرارة. بعد ينخفض الارتفاع الحراري إلى مستويات أكثر أمانًا، ويمكن أن تزيد اللعبة إعدادات الجودة مرة أخرى، ولكن احرص على إيجاد مستوى جودة مستدام للحصول على أفضل وقت للّعب
يمكنك مراقبة الحالة الحرارية للجهاز من خلال استطلاع
getThermalHeadroom
. تتنبأ هذه الطريقة بالمدة التي يمكن أن يحافظ فيها الجهاز على
مستوى الأداء بدون ارتفاع درجة الحرارة. إذا كان الوقت أقل من مقدار الوقت
اللازم لأداء أعباء العمل، يجب أن تقلّل لعبتك عبء العمل إلى
مستدامًا. على سبيل المثال، يمكن أن تنتقل اللعبة إلى أنوية أصغر، ثم تقلل
أو عدد اللقطات في الثانية، أو بدقة منخفضة.
الحصول على مدير الحرارة
لاستخدام Thermal API، عليك أولاً الحصول على تطبيق Thermal Manager
C++
AThermalManager* thermal_manager = AThermal_acquireManager();
Java
PowerManager powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
توقَّع أن تكون المساحة المستخدَمة للارتفاع بمقدار x ثانية لتحقيق مزيد من التحكّم.
يمكنك أن تطلب من النظام توقُّع درجة الحرارة قبل الحدث بـ 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 غير مرغوب فيه تلقائيًا جمعتها لك. ولكن إذا كنت تستخدم واجهة برمجة تطبيقات Java من خلال JNI وكان لديك احتفظت بمرجع، تذكر تنظيف المرجع!
C++
AThermal_releaseManager(thermal_manager);
للحصول على دليل كامل حول كيفية تنفيذ Thermal API على لعبة C++ أصلية باستخدام كل من واجهة برمجة تطبيقات C++ (NDK API) وJava API (من خلال JNI)، اطلع على دمج قسم Thermal API ضمن الدرس التطبيقي حول الترميز Adaptability .
إرشادات الارتفاع الحراري
يمكنك مراقبة الحالة الحرارية للجهاز من خلال استطلاع
getThermalHeadroom
. تتنبأ هذه الطريقة بالمدة التي يمكن أن يحافظ فيها الجهاز على
مستوى الأداء قبل الوصول إلى THERMAL_STATUS_SEVERE
.
على سبيل المثال، إذا عرضت getThermalHeadroom(30)
القيمة 0.8، فإنها تشير إلى أنّها في 30.
ثانية، ومن المتوقع أن يصل الارتفاع إلى 0.8، حيث توجد مسافة 0.2
من التقييد الشديد، أو 1.0. إذا كان الوقت أقل من المبلغ المطلوب
من أعباء العمل، فمن المفترض أن تخفِّض لعبتك أعباء العمل إلى
المستوى. على سبيل المثال، يمكن للعبة تقليل عدد اللقطات في الثانية أو تقليل الدقّة أو
وتقليل عمل اتصال الشبكة.
الحالات الحرارية والمعنى
- في حال عدم تقييد الجهاز حراريًا:
- بعض القيود، ولكن ليس لها تأثير كبير في الأداء:
- تقييد كبير يؤثر في الأداء:
قيود الأجهزة في Thermal API
هناك بعض القيود المعروفة أو المتطلبات الإضافية لواجهة Thermal API، بسبب إلى تنفيذ واجهة برمجة التطبيقات الحرارية على الأجهزة القديمة. القيود وكيف لحلّها هي:
- عدم طلب واجهة برمجة التطبيقات
GetThermalHeadroom()
بشكل متكرّر سيؤدي القيام بذلك إلى إلى واجهة برمجة التطبيقات التي تعرض NaN. يجب الاتصال به مرة واحدة في الثانية كحد أقصى. - إذا كانت القيمة الأولية لـ
GetThermalHeadroom()
هي NaN، لن تكون واجهة برمجة التطبيقات متوفّر على الجهاز - إذا كانت الدالة
GetThermalHeadroom()
تعرض قيمة عالية (مثل 0.85 أو أكثر) لا تزال تعرضGetCurrentThermalStatus()
عملية إرجاع بقيمةTHERMAL_STATUS_NONE
، والحالة هي من المحتمل ألا يتم تحديثها. استخدام الأساليب الإرشادية لتقدير التقييد الحراري الصحيح أو استخدامgetThermalHeadroom()
بدونgetCurrentThermalStatus()
.
مثال على الأساليب الإرشادية:
- تحقَّق من توافق واجهة برمجة التطبيقات Thermal API. يتحقق
isAPISupported()
من قيمة الاستدعاء الأول إلىgetThermalHeadroom
للتأكد من أنه ليس 0 أو NaN باستخدام واجهة برمجة التطبيقات إذا كانت القيمة الأولى هي 0 أو NaN. - إذا كانت
getCurrentThermalStatus()
تُرجع قيمة أخرى غيرTHERMAL_STATUS_NONE
، يتم تقييد الجهاز حراريًا. - إذا استمر عرض
getCurrentThermalStatus()
فيTHERMAL_STATUS_NONE
، سيتم هذا لا يعني بالضرورة أن الجهاز لا يتم تقييده حراريًا. يمكنه يعني أنّgetCurrentThermalStatus()
غير متاح على الجهاز. تحقّق من القيمة المعروضةgetThermalHeadroom()
للتأكّد من حالة الجهاز. - إذا كانت
getThermalHeadroom()
تعرض القيمة > 1.0، فإن الحالة يمكن تكون في الواقعTHERMAL_STATUS_SEVERE
أو أعلى، قلّل عبء العمل على الفور الحفاظ على عبء عمل أقل حتى يعرضgetThermalHeadroom()
قيمة أقل - إذا عرضت
getThermalHeadroom()
القيمة 0.95، فإن الحالة يمكن أن تكون في الواقعTHERMAL_STATUS_MODERATE
أو أعلى، وعليك تقليل عبء العمل على الفور. ومواصلة الانتباه لمنع القراءة الأعلى - إذا عرضت
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.
}
}
}
مخطط: