بازسازی RIL

اندروید ۷.۰ لایه رابط رادیویی (RIL) را با استفاده از مجموعه‌ای از ویژگی‌ها برای بهبود عملکرد RIL، بازسازی کرد. برای پیاده‌سازی این ویژگی‌ها، که اختیاری هستند اما توصیه می‌شوند، تغییرات کد همکار الزامی است. تغییرات بازسازی با نسخه‌های قبلی سازگار هستند، بنابراین پیاده‌سازی‌های قبلی ویژگی‌های بازسازی‌شده همچنان کار می‌کنند.

بازسازی RIL شامل بهبودهای زیر است:

  • کدهای خطای RIL. کدهای خطای خاصی را علاوه بر کد GENERIC_FAILURE موجود فعال می‌کند. این امر با ارائه اطلاعات دقیق‌تر در مورد علت خطاها، به عیب‌یابی خطا کمک می‌کند.
  • نسخه‌بندی RIL. اطلاعات نسخه دقیق‌تر و آسان‌تری برای پیکربندی ارائه می‌دهد.
  • ارتباط RIL با استفاده از wakelocks. عملکرد باتری دستگاه را بهبود می‌بخشد.

شما می‌توانید هر یک یا همه بهبودهای فوق را پیاده‌سازی کنید. برای جزئیات بیشتر، به توضیحات کد در مورد نسخه‌بندی RIL در https://android.googlesource.com/platform/hardware/ril/+/android16-qpr1-release/include/telephony/ril.h مراجعه کنید.

کدهای خطای RIL بهبود یافته را پیاده‌سازی کنید

تقریباً همه فراخوانی‌های درخواست RIL می‌توانند در پاسخ به یک خطا، کد خطای GENERIC_FAILURE را برگردانند. این مشکلی است که در تمام پاسخ‌های درخواستی که توسط تولیدکنندگان اصلی تجهیزات (OEM) برگردانده می‌شود، وجود دارد و اگر کد خطای GENERIC_FAILURE یکسانی توسط فراخوانی‌های RIL به دلایل مختلف برگردانده شود، می‌تواند اشکال‌زدایی یک مشکل از گزارش اشکال را دشوار کند. حتی ممکن است زمان قابل توجهی برای فروشندگان طول بکشد تا تشخیص دهند کدام بخش از کد می‌توانسته کد GENERIC_FAILURE را برگردانده باشد.

در اندروید ۷.x و بالاتر، تولیدکنندگان اصلی تجهیزات (OEM) می‌توانند یک مقدار کد خطای متمایز مرتبط با هر خطای مختلف را که در حال حاضر به عنوان GENERIC_FAILURE طبقه‌بندی می‌شود، برگردانند. تولیدکنندگان اصلی تجهیزاتی که نمی‌خواهند کدهای خطای سفارشی خود را به صورت عمومی فاش کنند، می‌توانند خطاها را به صورت مجموعه‌ای متمایز از اعداد صحیح (مانند ۱ تا x) که به صورت OEM_ERROR_1 به OEM_ERROR_X نگاشت شده‌اند، برگردانند. فروشندگان باید اطمینان حاصل کنند که هر یک از این کدهای خطای پنهان شده، به یک دلیل خطای منحصر به فرد در کد نگاشت می‌شوند. استفاده از کدهای خطای خاص می‌تواند اشکال‌زدایی RIL را در زمان بازگشت خطاهای عمومی توسط تولیدکننده اصلی تجهیزات (OEM) سرعت بخشد، زیرا اغلب شناسایی علت دقیق کد خطای GENERIC_FAILURE زمان زیادی می‌برد (و گاهی اوقات تشخیص آن غیرممکن است).

علاوه بر این، ril.h کدهای خطای بیشتری را برای enumهای RIL_LastCallFailCause و RIL_DataCallFailCause اضافه می‌کند تا کد فروشنده بتواند از بازگشت خطاهای عمومی مانند CALL_FAIL_ERROR_UNSPECIFIED و PDP_FAIL_ERROR_UNSPECIFIED جلوگیری کند.

اعتبارسنجی کدهای خطای RIL بهبود یافته

پس از افزودن کدهای خطای جدید برای جایگزینی کد GENERIC_FAILURE ، بررسی کنید که کدهای خطای جدید به جای GENERIC_FAILURE توسط فراخوانی RIL بازگردانده می‌شوند.

پیاده‌سازی نسخه‌بندی بهبود یافته RIL

نسخه‌بندی RIL در نسخه‌های قدیمی‌تر اندروید مشکل‌ساز بود: خود نسخه دقیق نبود، مکانیسم گزارش نسخه RIL نامشخص بود (که باعث می‌شد برخی از فروشندگان نسخه نادرستی را گزارش دهند) و راه‌حل تخمین نسخه مستعد عدم دقت بود.

در اندروید ۷.x و بالاتر، ril.h تمام مقادیر نسخه RIL را مستند می‌کند، نسخه RIL مربوطه را توصیف می‌کند و تمام تغییرات مربوط به آن نسخه را فهرست می‌کند. هنگام ایجاد تغییراتی که مربوط به یک نسخه RIL است، فروشندگان باید نسخه خود را در کد به‌روزرسانی کرده و آن نسخه را در RIL_REGISTER برگردانند.

اعتبارسنجی نسخه‌بندی بهبود یافته RIL

تأیید کنید که نسخه RIL مربوط به کد RIL شما در طول RIL_REGISTER برگردانده می‌شود (به جای RIL_VERSION تعریف شده در ril.h ).

پیاده‌سازی ارتباط RIL با استفاده از wakelocks

قفل‌های بیدارباش زمان‌بندی‌شده در ارتباطات RIL به شیوه‌ای غیردقیق استفاده می‌شوند که بر عملکرد باتری تأثیر منفی می‌گذارد. در اندروید ۷.x و بالاتر، می‌توانید با طبقه‌بندی درخواست‌های RIL و به‌روزرسانی کد برای مدیریت متفاوت قفل‌های بیدارباش برای انواع مختلف درخواست، عملکرد را بهبود بخشید.

طبقه‌بندی درخواست‌های RIL

درخواست‌های RIL می‌توانند درخواستی یا ناخواسته باشند. فروشندگان باید درخواست‌های درخواستی را به عنوان یکی از موارد زیر طبقه‌بندی کنند:

  • همزمان . درخواست‌هایی که زمان زیادی برای پاسخ دادن نیاز ندارند. برای مثال، RIL_REQUEST_GET_SIM_STATUS .
  • ناهمزمان . درخواست‌هایی که زمان قابل توجهی برای پاسخ دادن نیاز دارند. برای مثال، RIL_REQUEST_QUERY_AVAILABLE_NETWORKS .

درخواست‌های ناهمزمان RIL می‌توانند زمان قابل توجهی طول بکشند. پس از دریافت تایید از کد فروشنده، RIL Java قفل بیدارباش را آزاد می‌کند که ممکن است باعث شود پردازنده برنامه از حالت بیکار به حالت تعلیق برود. هنگامی که پاسخ از کد فروشنده در دسترس باشد، RIL Java (پردازنده برنامه) قفل بیدارباش را دوباره دریافت می‌کند، پاسخ را پردازش می‌کند و سپس به حالت بیکار برمی‌گردد. چنین حرکتی از بیکار به حالت تعلیق به بیکار می‌تواند انرژی زیادی مصرف کند.

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

سناریوهای ارتباطی RIL

نمودارهای زیر سناریوهای رایج ارتباطی RIL را نشان می‌دهند و راه‌حل‌هایی برای اصلاح کد جهت مدیریت درخواست‌های درخواستی و ناخواسته RIL ارائه می‌دهند.

نکته: برای جزئیات پیاده‌سازی توابع مورد استفاده در نمودارهای زیر، به متدهای acquireWakeLock() ، decrementWakeLock() و clearWakeLock( ) در ril.cpp مراجعه کنید.

سناریو: درخواست RIL و پاسخ ناهمزمان درخواستی

در این سناریو، اگر انتظار می‌رود پاسخ درخواستی RIL زمان قابل توجهی طول بکشد (یعنی پاسخی به RIL_REQUEST_GET_AVAILABLE_NETWORKS )، قفل بیدارباش برای مدت طولانی در سمت پردازنده برنامه نگه داشته می‌شود. مشکلات مودم نیز می‌توانند منجر به انتظار طولانی شوند.

شکل ۱. RIL پاسخ ناهمزمان درخواست کرد.

راه حل ۱: مودم قفل بیدارباش را برای درخواست RIL و پاسخ ناهمزمان نگه می‌دارد.

شکل ۲. قفل بیدارباش که توسط مودم نگه داشته می‌شود.
  1. درخواست RIL ارسال می‌شود و مودم برای پردازش آن درخواست، قفل بیدارباش (wakelock) را فعال می‌کند.
  2. مودم یک پیام تأیید ارسال می‌کند که باعث می‌شود طرف جاوا شمارنده‌ی wakelock را یک واحد کاهش دهد و وقتی مقدار شمارنده به ۰ رسید، آن را آزاد کند.

    نکته: مدت زمان انقضای wakelock برای توالی request-ack باید کمتر از مدت زمان انقضای فعلی باشد، زیرا ack باید نسبتاً سریع دریافت شود.

  3. پس از پردازش درخواست، مودم یک وقفه به کد فروشنده که wakelock را دریافت می‌کند ارسال می‌کند و پاسخی به ril.cpp ارسال می‌کند که به نوبه خود wakelock را دریافت کرده و پاسخی را به سمت جاوا ارسال می‌کند.
  4. وقتی پاسخ به سمت جاوا می‌رسد، wakelock دریافت می‌شود و پاسخی به فراخواننده بازگردانده می‌شود.
  5. پس از پردازش پاسخ توسط همه ماژول‌ها، پیام تأیید (از طریق سوکت) به ril.cpp ارسال می‌شود، که سپس wakelock به دست آمده در مرحله ۳ را آزاد می‌کند.

راه حل ۲: مودم قفل بیدارباش را نگه نمی‌دارد و پاسخ سریع است (درخواست و پاسخ RIL همزمان). رفتار همزمان در مقابل ناهمزمان برای یک دستور خاص RIL کدگذاری شده و بر اساس فراخوانی به فراخوانی تصمیم‌گیری می‌شود.

شکل ۳. قفل بیداری توسط مودم فعال نیست.
  1. درخواست RIL با فراخوانی تابع acquireWakeLock() در سمت جاوا ارسال می‌شود.
  2. کد فروشنده نیازی به دریافت wakelock ندارد و می‌تواند درخواست را پردازش کرده و به سرعت پاسخ دهد.
  3. وقتی پاسخ توسط سمت جاوا دریافت می‌شود، تابع decrementWakeLock() فراخوانی می‌شود که شمارنده wakelock را کاهش می‌دهد و اگر مقدار شمارنده برابر با ۰ باشد، wakelock را آزاد می‌کند.

سناریو: پاسخ ناخواسته RIL

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

شکل ۴. پاسخ ناخواسته RIL.

راه حل: به جای نگه داشتن wakelock زمان‌بندی شده در سمت بومی هنگام ارسال پاسخ ناخواسته، یک پیام تأیید از کد جاوا به سمت بومی ( ril.cpp ) ارسال می‌شود.

شکل ۵. استفاده از ack به جای wakelock زمان‌بندی‌شده

اعتبارسنجی wakelock های بازطراحی شده

تأیید کنید که فراخوانی‌های RIL به صورت همزمان یا ناهمزمان شناسایی می‌شوند. از آنجا که مصرف انرژی باتری می‌تواند به سخت‌افزار/پلتفرم وابسته باشد، فروشندگان باید آزمایش‌های داخلی انجام دهند تا دریابند که آیا استفاده از معانی جدید wakelock برای فراخوانی‌های ناهمزمان منجر به صرفه‌جویی در مصرف باتری می‌شود یا خیر.