API حرارتی

منتشر شد :

Android 11 (API Level 30) - Thermal API

Android 12 (API سطح 31) - NDK API

(پیش نمایش) Android 15 (DP1) - getThermalHeadroomThresholds()

عملکرد بالقوه برنامه شما توسط وضعیت حرارتی دستگاه محدود می شود، که می تواند بر اساس ویژگی هایی مانند آب و هوا، استفاده اخیر و طراحی حرارتی دستگاه متفاوت باشد. دستگاه‌ها فقط می‌توانند برای مدت زمان محدودی قبل از دریچه گازگیری حرارتی، سطح بالایی از عملکرد را حفظ کنند. یک هدف کلیدی از پیاده سازی شما باید دستیابی به اهداف عملکردی بدون فراتر از محدودیت های حرارتی باشد. Thermal API این کار را بدون نیاز به بهینه سازی خاص دستگاه ممکن می سازد. علاوه بر این، هنگام اشکال زدایی مشکلات عملکرد، دانستن اینکه آیا وضعیت حرارتی دستگاه شما عملکرد را محدود می کند، مهم است.

موتورهای بازی معمولاً دارای پارامترهای عملکرد زمان اجرا هستند که می توانند بار کاری را که موتور روی دستگاه وارد می کند تنظیم کند. به عنوان مثال، این پارامترها می‌توانند تعداد رشته‌های کارگر، پیوند کارگر-رشته برای هسته‌های بزرگ و کوچک، گزینه‌های وفاداری GPU و وضوح فریم‌بافر را تنظیم کنند. در Unity Engine، توسعه‌دهندگان بازی می‌توانند حجم کار را با تغییر تنظیمات کیفیت با استفاده از افزونه Adaptive Performance تنظیم کنند. برای Unreal Engine، از تنظیمات مقیاس پذیری برای تنظیم پویا سطوح کیفیت استفاده کنید.

هنگامی که دستگاهی به وضعیت حرارتی ناامن نزدیک می‌شود، بازی شما می‌تواند با کاهش بار کاری از طریق این پارامترها، از ضربه خوردن جلوگیری کند. برای جلوگیری از دریچه گاز، باید وضعیت حرارتی دستگاه را کنترل کنید و به طور فعال حجم کاری موتور بازی را تنظیم کنید. هنگامی که دستگاه بیش از حد گرم می شود، حجم کار باید به زیر سطح عملکرد پایدار کاهش یابد تا گرما از بین برود. پس از اینکه فضای سر حرارتی به سطوح ایمن‌تر کاهش یافت، بازی می‌تواند تنظیمات کیفیت را دوباره افزایش دهد، اما مطمئن شوید که یک سطح کیفیت پایدار برای زمان بازی بهینه پیدا می‌کنید.

با نظرسنجی از روش getThermalHeadroom می توانید وضعیت حرارتی دستگاه را کنترل کنید. این روش پیش بینی می کند که دستگاه تا چه مدت می تواند سطح عملکرد فعلی را بدون گرم شدن بیش از حد حفظ کند. اگر زمان کمتر از مقدار مورد نیاز برای اجرای حجم کار باشد، بازی شما باید حجم کار را به سطح پایدار کاهش دهد. برای مثال، بازی می‌تواند به هسته‌های کوچک‌تر تغییر کند، نرخ فریم را کاهش دهد یا وفاداری را کاهش دهد.

ADPF Thermal API Pre-integration
شکل 1. Headroom حرارتی بدون نظارت فعال getThermalHeadroom
ADPF حرارتی API پس از ادغام
شکل 2. Headroom حرارتی با نظارت فعال "getThermalHeadroom".

مدیریت حرارتی را به دست آورید

برای استفاده از Thermal API، ابتدا باید Thermal Manager را خریداری کنید

C++

AThermalManager* thermal_manager = AThermal_acquireManager();

جاوا

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

برای کنترل بیشتر، قسمت Thermal Headroom را 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);

جاوا

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

جاوا

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
}

جاوا

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

جاوا

powerManager.removeThermalStatusListener(listener);

پاکسازی

پس از اتمام کار، باید thermal_manager را که به دست آورده‌اید پاکسازی کنید. اگر از جاوا استفاده می کنید، مرجع PowerManager می تواند به طور خودکار برای شما زباله جمع آوری شود. اما اگر از Java API از طریق JNI استفاده می کنید و یک مرجع را حفظ کرده اید، به یاد داشته باشید که مرجع را پاک کنید!

C++

AThermal_releaseManager(thermal_manager);

برای راهنمایی کامل در مورد نحوه پیاده‌سازی Thermal API در یک بازی C++ بومی با استفاده از C++ API (NDK API) و Java API (از طریق JNI)، بخش Integrate Thermal API را در بخش Adaptability codelab بررسی کنید.

دستورالعمل های اتاق سر حرارتی

با نظرسنجی از روش getThermalHeadroom می توانید وضعیت حرارتی دستگاه را کنترل کنید. این روش پیش بینی می کند که دستگاه تا چه مدت می تواند سطح عملکرد فعلی را قبل از رسیدن به THERMAL_STATUS_SEVERE حفظ کند. به عنوان مثال، اگر getThermalHeadroom(30) 0.8 را برگرداند، نشان می دهد که در 30 ثانیه، انتظار می رود فضای سر به 0.8 برسد، جایی که 0.2 فاصله از throttling شدید یا 1.0 وجود دارد. اگر زمان کمتر از مقدار مورد نیاز برای اجرای حجم کار باشد، بازی شما باید حجم کار را به سطح پایدار کاهش دهد. به عنوان مثال، بازی می تواند نرخ فریم را کاهش دهد، وفاداری را کاهش دهد یا کار اتصال به شبکه را کاهش دهد.

وضعیت های حرارتی و معنی

محدودیت های دستگاه Thermal API

برخی محدودیت‌ها یا الزامات اضافی شناخته شده برای Thermal API وجود دارد که به دلیل اجرای API حرارتی در دستگاه‌های قدیمی‌تر است. محدودیت ها و نحوه رفع آنها به شرح زیر است:

  • API GetThermalHeadroom() را خیلی مکرر صدا نکنید. انجام این کار باعث می شود که API NaN را برگرداند. شما باید حداکثر یک بار در ثانیه با آن تماس بگیرید.
  • اگر مقدار اولیه GetThermalHeadroom() NaN باشد، API در دستگاه موجود نیست
  • اگر GetThermalHeadroom() مقدار بالایی را برگرداند (به عنوان مثال: 0.85 یا بیشتر) و GetCurrentThermalStatus() همچنان THERMAL_STATUS_NONE را برمی گرداند، وضعیت احتمالا به روز نمی شود. از اکتشافی برای تخمین وضعیت صحیح throttling حرارتی استفاده کنید یا فقط از getThermalHeadroom() بدون getCurrentThermalStatus() استفاده کنید.

مثال اکتشافی:

  1. بررسی کنید که Thermal API پشتیبانی می شود. isAPISupported() مقدار اولین تماس را برای getThermalHeadroom بررسی می کند تا مطمئن شود که 0 یا NaN نیست و اگر اولین مقدار 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. نمونه ای از اکتشافی برای تعیین پشتیبانی از API حرارتی در دستگاه های قدیمی تر