การปรับโครงสร้าง RIL

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

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

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

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

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

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

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 ค้างไว้และอยู่ในสถานะไม่ได้ใช้งานตลอดเวลาที่ใช้ในการตอบสนองจะมีประสิทธิภาพในการใช้พลังงานมากกว่าการเข้าสู่สถานะ Suspend โดยการปล่อย 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 สำหรับลำดับการร้องขอ-ack จะน้อยกว่าระยะเวลาการหมดเวลาที่ใช้อยู่ในปัจจุบัน เนื่องจากควรได้รับ ack อย่างรวดเร็ว

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

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

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

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

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

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

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

รูปที่ 5 การใช้ ack แทนการตั้งเวลาปลุก

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

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