การเปลี่ยนโครงสร้างภายในระบบ RIL

Android 7.0 ปรับโครงสร้าง Radio Interface Layer (RIL) โดยใช้ชุดฟีเจอร์เพื่อปรับปรุงฟังก์ชันการทำงานของ RIL พาร์ทเนอร์ต้องเปลี่ยนแปลงโค้ดเพื่อใช้ฟีเจอร์เหล่านี้ ซึ่งไม่บังคับแต่แนะนําให้ใช้ การเปลี่ยนแปลงการแยกส่วนโค้ดจะใช้งานย้อนหลังได้ ดังนั้นการใช้งานฟีเจอร์ที่แยกส่วนโค้ดก่อนหน้านี้จะยังคงใช้งานได้ต่อไป

การแยกส่วน RIL มีการปรับปรุงต่อไปนี้

  • รหัสข้อผิดพลาด RIL เปิดใช้รหัสข้อผิดพลาดที่เฉพาะเจาะจงนอกเหนือจากรหัส GENERIC_FAILURE ที่มีอยู่ ซึ่งช่วยในการแก้ปัญหาข้อผิดพลาดโดยให้ข้อมูลที่เฉพาะเจาะจงมากขึ้นเกี่ยวกับสาเหตุของข้อผิดพลาด
  • การกำหนดเวอร์ชัน RIL กำหนดค่าข้อมูลเวอร์ชันได้ง่ายขึ้นและแม่นยำมากขึ้น
  • การสื่อสาร RIL โดยใช้ Wakelock ปรับปรุงประสิทธิภาพแบตเตอรี่ของอุปกรณ์

คุณสามารถใช้การปรับปรุงข้างต้นอย่างใดอย่างหนึ่งหรือทั้งหมดก็ได้ ดูรายละเอียดเพิ่มเติมได้ที่ความคิดเห็นโค้ดเกี่ยวกับการกำหนดเวอร์ชัน RIL ใน https://android.googlesource.com/platform/hardware/ril/+/main/include/telephony/ril.h

ใช้รหัสข้อผิดพลาด RIL ที่ปรับปรุงแล้ว

การเรียกคําขอ RIL เกือบทั้งหมดสามารถแสดงรหัสข้อผิดพลาด GENERIC_FAILURE เพื่อตอบสนองต่อข้อผิดพลาด ปัญหานี้เกี่ยวข้องกับคําตอบทั้งหมดที่ OEM ส่งกลับ ซึ่งอาจทําให้การแก้ไขข้อบกพร่องจากรายงานข้อบกพร่องนั้นยากขึ้นหากการเรียก RIL แสดงรหัสข้อผิดพลาด GENERIC_FAILURE เดียวกันเนื่องจากสาเหตุที่แตกต่างกัน ผู้ให้บริการอาจใช้เวลานานในการระบุส่วนใดของโค้ดที่อาจแสดงรหัส GENERIC_FAILURE

ใน Android 7.x ขึ้นไป OEM สามารถแสดงผลค่ารหัสข้อผิดพลาดที่แตกต่างกันซึ่งเชื่อมโยงกับข้อผิดพลาดแต่ละรายการที่จัดหมวดหมู่เป็นGENERIC_FAILUREในปัจจุบัน OEM ที่ไม่ต้องการเปิดเผยรหัสข้อผิดพลาดที่กำหนดเองต่อสาธารณะสามารถแสดงข้อผิดพลาดเป็นชุดจำนวนเต็มที่แตกต่างกัน (เช่น 1 ถึง x) ที่แมปเป็น OEM_ERROR_1 ถึง OEM_ERROR_X ผู้ให้บริการควรตรวจสอบว่ารหัสข้อผิดพลาดที่มีการมาสก์แต่ละรายการที่แสดงผลนั้นแมปกับเหตุผลของข้อผิดพลาดที่ไม่ซ้ำกันในโค้ด การใช้รหัสข้อผิดพลาดที่เฉพาะเจาะจงจะช่วยเร่งการแก้ไขข้อบกพร่อง RIL ได้ทุกครั้งที่มีการแสดงข้อผิดพลาดทั่วไปจาก OEM เนื่องจากบางครั้งอาจใช้เวลานานเกินไปในการระบุสาเหตุที่แน่ชัดของรหัสข้อผิดพลาด GENERIC_FAILURE (และบางครั้งก็ไม่สามารถระบุได้)

นอกจากนี้ ril.h ยังเพิ่มรหัสข้อผิดพลาดอื่นๆ สําหรับ enums RIL_LastCallFailCause และ RIL_DataCallFailCause เพื่อให้โค้ดของผู้ให้บริการหลีกเลี่ยงการแสดงผลข้อผิดพลาดทั่วไป เช่น CALL_FAIL_ERROR_UNSPECIFIED และ PDP_FAIL_ERROR_UNSPECIFIED

ตรวจสอบรหัสข้อผิดพลาด RIL ที่ปรับปรุงแล้ว

หลังจากเพิ่มรหัสข้อผิดพลาดใหม่เพื่อแทนที่รหัส GENERIC_FAILURE แล้ว ให้ตรวจสอบว่ารหัสข้อผิดพลาดใหม่แสดงขึ้นจากการเรียก RIL แทน GENERIC_FAILURE

ใช้การกำหนดเวอร์ชัน RIL ที่ปรับปรุงแล้ว

เวอร์ชัน RIL ใน Android เวอร์ชันเก่ามีปัญหา เนื่องจากเวอร์ชันนั้นไม่แม่นยำ กลไกการรายงานเวอร์ชัน RIL ไม่ชัดเจน (ทำให้ผู้ให้บริการบางรายรายงานเวอร์ชันที่ไม่ถูกต้อง) และวิธีแก้ปัญหาในการประมาณเวอร์ชันมีแนวโน้มที่จะไม่ถูกต้อง

ใน Android 7.x ขึ้นไป ril.h จะบันทึกค่าเวอร์ชัน RIL ทั้งหมด อธิบายเวอร์ชัน RIL ที่เกี่ยวข้อง และแสดงรายการการเปลี่ยนแปลงทั้งหมดของเวอร์ชันนั้น เมื่อทำการเปลี่ยนแปลงที่เกี่ยวข้องกับเวอร์ชัน RIL เวนเดอร์ต้องอัปเดตเวอร์ชันในโค้ดและส่งเวอร์ชันนั้นใน RIL_REGISTER

ตรวจสอบการกำหนดเวอร์ชัน RIL ที่ปรับปรุงแล้ว

ตรวจสอบว่าระบบแสดงผลเวอร์ชัน RIL ที่สอดคล้องกับรหัส RIL ของคุณในระหว่าง RIL_REGISTER (แทนที่จะเป็น RIL_VERSION ที่ระบุไว้ใน ril.h)

ใช้การสื่อสาร RIL โดยใช้ Wakelock

ระบบใช้ Wakelock แบบตั้งเวลาในการสื่อสาร RIL ในลักษณะที่ไม่แม่นยำ ซึ่งส่งผลเสียต่อประสิทธิภาพของแบตเตอรี่ ใน Android 7.x ขึ้นไป คุณสามารถปรับปรุงประสิทธิภาพได้โดยการจัดประเภทคำขอ RIL และการอัปเดตโค้ดเพื่อจัดการ Wakelock ที่แตกต่างกันสำหรับคำขอประเภทต่างๆ

จัดประเภทคำขอ RIL

คำขอ RIL อาจเป็นคำขอที่ขอหรือไม่ได้ขอก็ได้ ผู้ให้บริการควรจัดประเภทคำขอที่ขอเข้ามาใหม่เป็นประเภทใดประเภทหนึ่งต่อไปนี้

  • แบบเรียลไทม์ คำขอที่ใช้เวลาไม่นานในการตอบกลับ เช่น RIL_REQUEST_GET_SIM_STATUS
  • แบบไม่เรียลไทม์ คำขอที่ใช้เวลาในการตอบกลับนาน เช่น RIL_REQUEST_QUERY_AVAILABLE_NETWORKS

คำขอ RIL ที่ส่งมาแบบอะซิงโครนัสอาจใช้เวลานาน หลังจากได้รับ ACK จากโค้ดของผู้ให้บริการแล้ว 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) ระบบจะล็อกให้อุปกรณ์ตื่นเป็นเวลานานในฝั่งตัวประมวลผลของแอป ปัญหาเกี่ยวกับโมเด็มอาจส่งผลให้คุณต้องรอนาน

รูปที่ 1 RIL ขอการตอบกลับแบบอะซิงโครนัส

วิธีแก้ปัญหาที่ 1: โมเด็มจะล็อกให้ตื่นอยู่เพื่อรับคำขอ RIL และการตอบกลับแบบไม่พร้อมกัน

รูปที่ 2 Wakelock ค้างอยู่ในโมเด็ม
  1. ระบบจะส่งคำขอ RIL และโมเด็มจะรับการล็อกการปลุกเพื่อประมวลผลคำขอนั้น
  2. โมเด็มส่งการตอบกลับที่ทำให้ฝั่ง Java ลดลง ตัวนับการตื่นล็อกและปล่อยเมื่อค่าตัวนับเป็น 0

    หมายเหตุ: ระยะเวลาการหมดเวลาของ Wakelock สําหรับลําดับคําขอ-การตอบกลับจะสั้นกว่าระยะเวลาการหมดเวลาที่ใช้งานอยู่ในปัจจุบัน เนื่องจากควรจะได้รับการตอบกลับอย่างรวดเร็ว

  3. หลังจากประมวลผลคําขอแล้ว โมเด็มจะส่งการขัดจังหวะไปยังโค้ดของผู้ให้บริการที่รับ Wakelock และส่งการตอบกลับไปยัง ril.cpp ซึ่งจะรับ Wakelock และส่งการตอบกลับไปยังฝั่ง Java
  4. เมื่อการตอบกลับมาถึงฝั่ง Java ระบบจะรับ Wakelock และส่งการตอบกลับกลับไปยังผู้เรียกใช้
  5. หลังจากโมดูลทั้งหมดประมวลผลการตอบกลับแล้ว ระบบจะส่งการตอบกลับ (ผ่านซ็อกเก็ต) กลับไปยัง ril.cpp ซึ่งจะปล่อยการล็อกที่ตื่นอยู่ซึ่งได้มาจากขั้นตอนที่ 3

วิธีแก้ปัญหาที่ 2: โมเด็มไม่ได้ล็อกการตื่นไว้และการตอบกลับรวดเร็ว (คำขอและคำตอบ RIL แบบซิงค์) ลักษณะการทำงานแบบซิงค์กับแบบแอซิงค์จะกำหนดไว้ล่วงหน้าสำหรับคําสั่ง RIL ที่เฉพาะเจาะจงและตัดสินใจในแต่ละการเรียก

รูปที่ 3 โมเด็มไม่ได้ทำให้อุปกรณ์อยู่ในสถานะตื่น
  1. ระบบจะส่งคําขอ RIL โดยการเรียกใช้ acquireWakeLock() ฝั่ง Java
  2. โค้ดของผู้ให้บริการไม่จำเป็นต้องใช้ Wakelock และสามารถประมวลผลคำขอและตอบกลับได้อย่างรวดเร็ว
  3. เมื่อฝั่ง Java ได้รับคำตอบ ระบบจะเรียกใช้ decrementWakeLock() ซึ่งจะลดตัวนับการตื่นอยู่ และปล่อยการตื่นอยู่หากค่าตัวนับเป็น 0

สถานการณ์: การตอบกลับที่ไม่พึงประสงค์ของ RIL

ในกรณีนี้ การตอบกลับที่ไม่พึงประสงค์ของ RIL จะมี Flag ประเภท Wakelock ในการบ่งชี้ว่าจำเป็นต้องใช้ Wakelock สำหรับการตอบกลับของผู้ให้บริการหรือไม่ หากตั้งค่า Flag ระบบจะตั้งค่า Wakelock แบบกำหนดเวลาและส่งการตอบกลับผ่านซ็อกเก็ตไปยังฝั่ง Java เมื่อตัวจับเวลาหมดอายุ ระบบจะยกเลิกการล็อกการปลุก การล็อกที่ทำงานตามเวลาอาจนานหรือสั้นเกินไปสำหรับการตอบกลับที่ไม่พึงประสงค์ของ RIL

รูปที่ 4 การตอบกลับที่ไม่พึงประสงค์ของ RIL

วิธีแก้ไข: ระบบจะส่งการตอบกลับจากโค้ด Java ไปยังฝั่งเนทีฟ (ril.cpp) แทนการล็อกให้ตื่นตามเวลาในฝั่งเนทีฟขณะส่งการตอบกลับที่ไม่พึงประสงค์

รูปที่ 5 ใช้การตอบกลับแทนการล็อกที่ทำงานตามเวลา

ตรวจสอบ Wakelock ที่ออกแบบใหม่

ยืนยันว่าการเรียก RIL ได้รับการระบุว่าเป็นแบบเรียลไทม์หรือไม่เรียลไทม์ เนื่องจากปริมาณการใช้พลังงานแบตเตอรี่อาจขึ้นอยู่กับฮาร์ดแวร์/แพลตฟอร์ม ผู้ให้บริการจึงควรทำการทดสอบภายในเพื่อดูว่าการใช้เซมาติกส์ Wakelock ใหม่สำหรับการเรียกแบบไม่พร้อมกันช่วยประหยัดพลังงานแบตเตอรี่ได้หรือไม่