Tái cấu trúc RIL

Android 7.0 đã tái cấu trúc Lớp giao diện vô tuyến (RIL) bằng cách sử dụng một nhóm tính năng để cải thiện chức năng của RIL. Bạn bắt buộc phải thay đổi mã đối tác để triển khai các tính năng này. Tuy không bắt buộc nhưng bạn nên thực hiện việc này. Các thay đổi tái cấu trúc tương thích ngược, vì vậy, các phương thức triển khai trước đó của các tính năng được tái cấu trúc sẽ tiếp tục hoạt động.

Việc tái cấu trúc RIL bao gồm các điểm cải tiến sau:

  • Mã lỗi RIL. Bật các mã lỗi cụ thể ngoài mã GENERIC_FAILURE hiện có. Điều này hỗ trợ việc khắc phục sự cố bằng cách cung cấp thông tin cụ thể hơn về nguyên nhân gây ra sự cố.
  • Định phiên bản RIL. Cung cấp thông tin phiên bản chính xác và dễ định cấu hình hơn.
  • Giao tiếp RIL bằng khoá chế độ thức. Cải thiện hiệu suất pin của thiết bị.

Bạn có thể triển khai bất kỳ hoặc tất cả các điểm cải tiến nêu trên. Để biết thêm thông tin chi tiết, hãy tham khảo các chú thích mã về việc tạo phiên bản RIL trong https://android.googlesource.com/platform/hardware/ril/+/main/include/telephony/ril.h.

Triển khai mã lỗi RIL nâng cao

Hầu hết các lệnh gọi yêu cầu RIL đều có thể trả về mã lỗi GENERIC_FAILURE khi phản hồi lỗi. Đây là vấn đề với tất cả các phản hồi được yêu cầu mà OEM trả về. Điều này có thể khiến bạn khó gỡ lỗi vấn đề trong báo cáo lỗi nếu cùng một mã lỗi GENERIC_FAILURE được trả về bởi các lệnh gọi RIL vì nhiều lý do. Các nhà cung cấp có thể mất nhiều thời gian để xác định phần mã nào có thể trả về mã GENERIC_FAILURE.

Trong Android 7.x trở lên, nhà sản xuất thiết bị gốc (OEM) có thể trả về một giá trị mã lỗi riêng biệt liên kết với từng lỗi khác nhau hiện được phân loại là GENERIC_FAILURE. Các OEM không muốn công khai mã lỗi tuỳ chỉnh có thể trả về lỗi dưới dạng một tập hợp số nguyên riêng biệt (chẳng hạn như 1 đến x) được liên kết dưới dạng OEM_ERROR_1 đến OEM_ERROR_X. Nhà cung cấp phải đảm bảo rằng mỗi mã lỗi được che giấu như vậy được trả về sẽ liên kết với một lý do lỗi duy nhất trong mã. Việc sử dụng mã lỗi cụ thể có thể giúp tăng tốc quá trình gỡ lỗi RIL bất cứ khi nào OEM trả về lỗi chung, vì thường mất quá nhiều thời gian để xác định nguyên nhân chính xác của mã lỗi GENERIC_FAILURE (và đôi khi không thể tìm ra).

Ngoài ra, ril.h thêm các mã lỗi khác cho enums RIL_LastCallFailCauseRIL_DataCallFailCause để mã của nhà cung cấp có thể tránh trả về các lỗi chung như CALL_FAIL_ERROR_UNSPECIFIEDPDP_FAIL_ERROR_UNSPECIFIED.

Xác thực mã lỗi RIL nâng cao

Sau khi thêm mã lỗi mới để thay thế mã GENERIC_FAILURE, hãy xác minh rằng lệnh gọi RIL trả về mã lỗi mới thay vì GENERIC_FAILURE.

Triển khai tính năng tạo phiên bản RIL nâng cao

Việc tạo phiên bản RIL trong các bản phát hành Android cũ gặp vấn đề: bản thân phiên bản không chính xác, cơ chế báo cáo phiên bản RIL không rõ ràng (khiến một số nhà cung cấp báo cáo phiên bản không chính xác) và giải pháp để ước tính phiên bản dễ bị không chính xác.

Trong Android 7.x trở lên, ril.h ghi lại tất cả giá trị phiên bản RIL, mô tả phiên bản RIL tương ứng và liệt kê tất cả thay đổi đối với phiên bản đó. Khi thực hiện các thay đổi tương ứng với một phiên bản RIL, nhà cung cấp phải cập nhật phiên bản của họ trong mã và trả về phiên bản đó trong RIL_REGISTER.

Xác thực tính năng tạo phiên bản RIL nâng cao

Xác minh rằng phiên bản RIL tương ứng với mã RIL của bạn được trả về trong RIL_REGISTER (thay vì RIL_VERSION được xác định trong ril.h).

Triển khai giao tiếp RIL bằng cách sử dụng khoá chế độ thức

Khóa chế độ thức theo thời gian được sử dụng trong quá trình giao tiếp RIL theo cách không chính xác, ảnh hưởng tiêu cực đến hiệu suất pin. Trong Android 7.x trở lên, bạn có thể cải thiện hiệu suất bằng cách phân loại các yêu cầu RIL và cập nhật mã để xử lý các loại yêu cầu khác nhau theo cách khác nhau.

Phân loại yêu cầu RIL

Yêu cầu RIL có thể là yêu cầu được yêu cầu hoặc không được yêu cầu. Nhà cung cấp nên phân loại thêm các yêu cầu được yêu cầu theo một trong các cách sau:

  • đồng bộ. Các yêu cầu không mất nhiều thời gian để phản hồi. Ví dụ: RIL_REQUEST_GET_SIM_STATUS.
  • không đồng bộ. Các yêu cầu mất nhiều thời gian để phản hồi. Ví dụ: RIL_REQUEST_QUERY_AVAILABLE_NETWORKS.

Các yêu cầu RIL được yêu cầu không đồng bộ có thể mất nhiều thời gian. Sau khi nhận được thông báo xác nhận từ mã của nhà cung cấp, RIL Java sẽ phát hành khoá chế độ thức. Điều này có thể khiến trình xử lý ứng dụng chuyển từ trạng thái rảnh sang trạng thái tạm ngưng. Khi có phản hồi từ mã của nhà cung cấp, RIL Java (bộ xử lý ứng dụng) sẽ thu nạp lại khoá chế độ thức, xử lý phản hồi rồi quay lại trạng thái rảnh. Việc chuyển từ trạng thái rảnh sang trạng thái tạm ngưng rồi lại chuyển về trạng thái rảnh như vậy có thể tiêu tốn nhiều năng lượng.

Nếu thời gian phản hồi không đủ dài, thì việc giữ khoá chế độ thức và ở trạng thái rảnh trong toàn bộ thời gian cần thiết để phản hồi có thể tiết kiệm pin hơn so với việc chuyển sang trạng thái tạm ngưng bằng cách nhả khoá chế độ thức và đánh thức khi nhận được phản hồi. Nhà cung cấp nên sử dụng các phép đo năng lượng dành riêng cho nền tảng để xác định giá trị ngưỡng thời gian T khi mức tiêu thụ năng lượng khi ở trạng thái rảnh trong toàn bộ thời gian T lớn hơn mức tiêu thụ năng lượng khi chuyển từ trạng thái rảnh sang trạng thái tạm ngưng và trạng thái rảnh trong cùng một thời gian T. Khi biết thời gian T, các lệnh RIL mất nhiều thời gian hơn T có thể được phân loại là không đồng bộ và các lệnh còn lại được phân loại là đồng bộ.

Kịch bản giao tiếp RIL

Các sơ đồ sau đây minh hoạ các trường hợp giao tiếp RIL phổ biến và cung cấp giải pháp để sửa đổi mã nhằm xử lý các yêu cầu được yêu cầu và không được yêu cầu của RIL.

Lưu ý: Để biết thông tin chi tiết về cách triển khai các hàm được sử dụng trong các sơ đồ sau, hãy tham khảo các phương thức acquireWakeLock(), decrementWakeLock()clearWakeLock( trong ril.cpp.

Tình huống: Yêu cầu RIL và phản hồi không đồng bộ được yêu cầu

Trong trường hợp này, nếu phản hồi được yêu cầu của RIL dự kiến sẽ mất khá nhiều thời gian (tức là phản hồi cho RIL_REQUEST_GET_AVAILABLE_NETWORKS), thì khoá chế độ thức sẽ được giữ trong thời gian dài ở phía bộ xử lý ứng dụng. Các vấn đề về modem cũng có thể khiến bạn phải chờ lâu.

Hình 1. RIL đã yêu cầu phản hồi không đồng bộ.

Giải pháp 1: Mô-đun modem giữ khoá chế độ thức cho yêu cầu RIL và phản hồi không đồng bộ.

Hình 2. Wakelock do modem giữ.
  1. Yêu cầu RIL được gửi và modem sẽ mua khoá chế độ thức để xử lý yêu cầu đó.
  2. Modem gửi thông báo xác nhận khiến phía Java giảm bộ đếm khoá chế độ thức và giải phóng bộ đếm đó khi giá trị bộ đếm là 0.

    Lưu ý: Thời gian chờ khoá chế độ thức cho trình tự yêu cầu-thông báo xác nhận sẽ nhỏ hơn thời gian chờ hiện đang được sử dụng vì thông báo xác nhận sẽ được nhận khá nhanh.

  3. Sau khi xử lý yêu cầu, modem sẽ gửi một tín hiệu ngắt đến mã của nhà cung cấp để lấy khoá chế độ thức và gửi phản hồi đến ril.cpp. Tiếp theo, ril.cpp sẽ lấy khoá chế độ thức và gửi phản hồi đến phía Java.
  4. Khi phản hồi đến phía Java, chế độ khoá chế độ thức sẽ được lấy và phản hồi sẽ được trả về cho phương thức gọi.
  5. Sau khi tất cả các mô-đun xử lý phản hồi, thông báo xác nhận sẽ được gửi (thông qua ổ cắm) trở lại ril.cpp, sau đó giải phóng khoá chế độ thức đã thu được ở bước 3.

Giải pháp 2: Mô-đun không giữ khoá chế độ thức và phản hồi nhanh (yêu cầu và phản hồi RIL đồng bộ). Hành vi đồng bộ so với không đồng bộ được mã hoá cứng cho một lệnh RIL cụ thể và được quyết định trên cơ sở lệnh gọi theo lệnh gọi.

Hình 3. Wakelock không do modem giữ.
  1. Yêu cầu RIL được gửi bằng cách gọi acquireWakeLock() ở phía Java.
  2. Mã của nhà cung cấp không cần phải mua khoá chế độ thức và có thể xử lý yêu cầu cũng như phản hồi nhanh chóng.
  3. Khi phía Java nhận được phản hồi, decrementWakeLock() sẽ được gọi, làm giảm bộ đếm khoá chế độ thức và giải phóng khoá chế độ thức nếu giá trị bộ đếm là 0.

Tình huống: Phản hồi không mong muốn của RIL

Trong trường hợp này, các phản hồi không mong muốn của RIL có một cờ loại khoá chế độ thức trong đó cho biết liệu cần phải mua khoá chế độ thức cho phản hồi của nhà cung cấp hay không. Nếu cờ được đặt, chế độ khoá chế độ thức theo thời gian sẽ được đặt và phản hồi sẽ được gửi qua một ổ cắm đến phía Java. Khi hết thời gian, khoá chế độ thức sẽ được giải phóng. Khoá chế độ thức theo thời gian có thể quá dài hoặc quá ngắn đối với các phản hồi không mong muốn khác nhau của RIL.

Hình 4. Phản hồi không mong muốn của RIL.

Giải pháp: Thông báo xác nhận được gửi từ mã Java đến bên gốc (ril.cpp) thay vì giữ khoá chế độ thức theo thời gian ở bên gốc trong khi gửi phản hồi không mong muốn.

Hình 5. Sử dụng ack thay vì khoá chế độ thức theo thời gian.

Xác thực các chế độ khoá chế độ thức được thiết kế lại

Xác minh rằng các lệnh gọi RIL được xác định là đồng bộ hay không đồng bộ. Vì mức tiêu thụ pin có thể phụ thuộc vào phần cứng/nền tảng, nên nhà cung cấp nên thực hiện một số thử nghiệm nội bộ để tìm hiểu xem việc sử dụng ngữ nghĩa khoá chế độ thức mới cho các lệnh gọi không đồng bộ có giúp tiết kiệm pin hay không.