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

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

การปรับโครงสร้าง RIL มีการปรับปรุงต่อไปนี้

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

คุณสามารถใช้การปรับปรุงข้างต้นทั้งหมดหรือบางส่วนก็ได้ ดูรายละเอียดเพิ่มเติมได้ที่ความคิดเห็นในโค้ดเกี่ยวกับการกำหนดเวอร์ชัน RIL ใน https://android.googlesource.com/platform/hardware/ril/+/android16-release/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 ยังเพิ่มรหัสข้อผิดพลาดสำหรับ Enum RIL_LastCallFailCause และ RIL_DataCallFailCause เพื่อให้ รหัสของผู้ให้บริการหลีกเลี่ยงการแสดงข้อผิดพลาดทั่วไป เช่น CALL_FAIL_ERROR_UNSPECIFIED และ PDP_FAIL_ERROR_UNSPECIFIED

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

หลังจากเพิ่มรหัสข้อผิดพลาดใหม่เพื่อแทนที่GENERIC_FAILURE code แล้ว ให้ตรวจสอบว่าการเรียก 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 จะปล่อย Wakelock ซึ่งอาจ ทําให้โปรเซสเซอร์ของแอปเปลี่ยนจากสถานะว่างไปเป็นสถานะระงับ เมื่อมีการตอบกลับจากโค้ดของผู้ให้บริการ RIL Java (ตัวประมวลผลแอป) จะขอรับ WakeLock อีกครั้ง ประมวลผลการตอบกลับ แล้วกลับไปที่สถานะว่าง การเปลี่ยนจากไม่ได้ใช้งานเป็นระงับแล้วกลับมาเป็นไม่ได้ใช้งานอีกครั้งอาจใช้พลังงานมาก

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

สถานการณ์การสื่อสาร RIL

แผนภาพต่อไปนี้แสดงสถานการณ์การสื่อสาร RIL ทั่วไปและ ให้โซลูชันสำหรับการแก้ไขโค้ดเพื่อจัดการคำขอ RIL ที่ขอและไม่ได้ขอ

หมายเหตุ: ดูรายละเอียดการติดตั้งใช้งานฟังก์ชัน ที่ใช้ในไดอะแกรมต่อไปนี้ได้ที่เมธอด acquireWakeLock(), decrementWakeLock() และ clearWakeLock( ใน ril.cpp

สถานการณ์: คำขอ RIL และการตอบกลับแบบอะซิงโครนัสที่ขอ

ในสถานการณ์นี้ หากคาดว่าการตอบกลับที่ RIL ร้องขอจะใช้เวลานานพอสมควร (เช่น การตอบกลับ RIL_REQUEST_GET_AVAILABLE_NETWORKS) ระบบจะถือว่า Wakelock ใช้เวลานานในฝั่งโปรเซสเซอร์ของแอป ปัญหาเกี่ยวกับโมเด็มอาจทำให้คุณต้อง รอนานด้วย

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

วิธีที่ 1: โมเด็มจะถือ Wakelock สำหรับคำขอ RIL และการตอบกลับแบบอะซิงโครนัส

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

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

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

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

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

สถานการณ์: การตอบกลับที่ไม่ได้ร้องขอจาก RIL

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

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

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

รูปที่ 5 ใช้ ACK แทน WakeLock ที่กำหนดเวลา

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

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