Để cải thiện tính bảo mật của thiết bị, Android 7.0 chia quy trình mediaserver
đa phương tiện nguyên khối thành nhiều quy trình với các quyền và khả năng chỉ được giới hạn ở những quy trình được yêu cầu bởi mỗi quy trình. Những thay đổi này giảm thiểu các lỗ hổng bảo mật khung phương tiện bằng cách:
- Tách các thành phần đường dẫn AV thành các quy trình được đóng hộp cát dành riêng cho ứng dụng.
- Kích hoạt các thành phần phương tiện có thể cập nhật (trình trích xuất, codec, v.v.).
Những thay đổi này cũng cải thiện tính bảo mật cho người dùng cuối bằng cách giảm đáng kể mức độ nghiêm trọng của hầu hết các lỗ hổng bảo mật liên quan đến phương tiện truyền thông, giữ an toàn cho thiết bị và dữ liệu của người dùng cuối.
Các nhà cung cấp OEM và SoC cần cập nhật các thay đổi về HAL và khung để làm cho chúng tương thích với kiến trúc mới. Cụ thể, vì mã Android do nhà cung cấp cung cấp thường giả định mọi thứ chạy trong cùng một quy trình, nên nhà cung cấp phải cập nhật mã của họ để chuyển các thẻ điều khiển gốc ( native_handle
) có ý nghĩa trong các quy trình. Để tham khảo việc triển khai các thay đổi liên quan đến việc tăng cường phương tiện, hãy tham khảo frameworks/av
và frameworks/native
.
Thay đổi kiến trúc
Các phiên bản trước của Android sử dụng một quy trình mediaserver
nguyên khối duy nhất với nhiều quyền (truy cập camera, truy cập âm thanh, truy cập trình điều khiển video, truy cập tệp, truy cập mạng, v.v.). Android 7.0 chia quy trình mediaserver
thành nhiều quy trình mới, mỗi quy trình yêu cầu một nhóm quyền nhỏ hơn nhiều:
Kiến trúc mới này đảm bảo rằng ngay cả khi một quy trình bị xâm phạm, mã độc cũng không có quyền truy cập vào toàn bộ quyền mà mediaserver
nắm giữ trước đó. Các quy trình bị hạn chế bởi chính sách SElinux và seccomp.
Lưu ý: Do sự phụ thuộc của nhà cung cấp, một số codec vẫn chạy trong mediaserver
và do đó cấp cho mediaserver
nhiều quyền hơn mức cần thiết. Cụ thể, Widevine Classic tiếp tục chạy trên mediaserver
dành cho Android 7.0.
Thay đổi máy chủ phương tiện
Trong Android 7.0, quy trình mediaserver
tồn tại để điều khiển phát lại và ghi, ví dụ: chuyển và đồng bộ hóa bộ đệm giữa các thành phần và quy trình. Các tiến trình giao tiếp thông qua cơ chế Binder tiêu chuẩn.
Trong phiên phát lại tệp cục bộ tiêu chuẩn, ứng dụng chuyển bộ mô tả tệp (FD) tới mediaserver
(thường thông qua API MediaPlayer Java) và mediaserver
:
- Gói FD vào một đối tượng Binder DataSource được chuyển đến quy trình trích xuất, sử dụng nó để đọc từ tệp bằng Binder IPC. (Trình trích xuất phương tiện không nhận được FD mà thay vào đó thực hiện các cuộc gọi Binder trở lại
mediaserver
để lấy dữ liệu.) - Kiểm tra tệp, tạo trình giải nén thích hợp cho loại tệp (ví dụ: MP3Extractor hoặc MPEG4Extractor) và trả về giao diện Binder cho trình giải nén cho quy trình
mediaserver
. - Thực hiện các cuộc gọi Binder IPC tới trình trích xuất để xác định loại dữ liệu trong tệp (ví dụ: dữ liệu MP3 hoặc H.264).
- Gọi vào quy trình
mediacodec
để tạo codec thuộc loại được yêu cầu; nhận giao diện Binder cho các codec này. - Thực hiện các lệnh gọi Binder IPC lặp đi lặp lại tới trình trích xuất để đọc các mẫu được mã hóa, sử dụng Binder IPC để gửi dữ liệu được mã hóa đến quy trình
mediacodec
để giải mã và nhận dữ liệu đã giải mã.
Trong một số trường hợp sử dụng, không có codec nào được sử dụng (chẳng hạn như phát lại không tải trong đó dữ liệu được mã hóa được gửi trực tiếp đến thiết bị đầu ra) hoặc codec có thể hiển thị trực tiếp dữ liệu được giải mã thay vì trả về bộ đệm dữ liệu được giải mã (phát lại video).
MediaCodecThay đổi dịch vụ
Dịch vụ codec là nơi hoạt động của bộ mã hóa và bộ giải mã. Do sự phụ thuộc của nhà cung cấp, không phải tất cả các codec đều hoạt động trong quy trình codec. Trong Android 7.0:
- Bộ giải mã không an toàn và bộ mã hóa phần mềm nằm trong quy trình codec.
- Bộ giải mã an toàn và bộ mã hóa phần cứng nằm trong
mediaserver
(không thay đổi).
Một ứng dụng (hoặc mediaserver
) gọi quy trình codec để tạo một codec thuộc loại được yêu cầu, sau đó gọi codec đó để truyền dữ liệu được mã hóa và truy xuất dữ liệu đã giải mã (để giải mã) hoặc để truyền dữ liệu đã giải mã và truy xuất dữ liệu được mã hóa (để mã hóa) . Việc truyền dữ liệu đến và đi từ codec đã sử dụng bộ nhớ dùng chung nên quá trình đó không thay đổi.
MediaDrmServer thay đổi
Máy chủ DRM được sử dụng khi phát nội dung được bảo vệ bằng DRM, chẳng hạn như phim trong Google Play Phim. Nó xử lý việc giải mã dữ liệu được mã hóa một cách an toàn và do đó có quyền truy cập vào chứng chỉ, bộ lưu trữ khóa cũng như các thành phần nhạy cảm khác. Do sự phụ thuộc của nhà cung cấp, quy trình DRM chưa được sử dụng trong mọi trường hợp.
Thay đổi máy chủ âm thanh
Quá trình AudioServer lưu trữ các thành phần liên quan đến âm thanh như đầu vào và đầu ra âm thanh, dịch vụ quản lý chính sách xác định định tuyến âm thanh và dịch vụ đài FM. Để biết chi tiết về các thay đổi về Âm thanh và hướng dẫn triển khai, hãy xem Triển khai âm thanh .
Máy ảnhThay đổi máy chủ
CameraServer điều khiển camera và được sử dụng khi quay video để lấy các khung hình video từ camera, sau đó chuyển chúng đến mediaserver
để xử lý thêm. Để biết chi tiết về các thay đổi và hướng dẫn triển khai các thay đổi của CameraServer, hãy tham khảo Tăng cường khung máy ảnh .
ExtractorThay đổi dịch vụ
Dịch vụ trình trích xuất lưu trữ các trình trích xuất , các thành phần phân tích cú pháp các định dạng tệp khác nhau được khung phương tiện hỗ trợ. Dịch vụ giải nén là dịch vụ có ít đặc quyền nhất trong tất cả các dịch vụ—nó không thể đọc FD nên thay vào đó, nó thực hiện lệnh gọi đến giao diện Binder (được mediaserver for
mỗi phiên phát lại) để truy cập các tệp.
Một ứng dụng (hoặc mediaserver
) thực hiện lệnh gọi đến quy trình trích xuất để lấy IMediaExtractor
, gọi IMediaExtractor
đó để lấy IMediaSources
cho bản nhạc có trong tệp và sau đó gọi IMediaSources
để đọc dữ liệu từ chúng.
Để truyền dữ liệu giữa các tiến trình, ứng dụng (hoặc mediaserver
) sẽ bao gồm dữ liệu trong reply-Parcel như một phần của giao dịch Binder hoặc sử dụng bộ nhớ dùng chung:
- Việc sử dụng bộ nhớ dùng chung yêu cầu lệnh gọi Binder bổ sung để giải phóng bộ nhớ dùng chung nhưng nhanh hơn và sử dụng ít năng lượng hơn cho các bộ đệm lớn.
- Việc sử dụng In-Parcel yêu cầu sao chép thêm nhưng nhanh hơn và sử dụng ít năng lượng hơn cho các bộ đệm nhỏ hơn 64KB.
Thực hiện
Để hỗ trợ việc di chuyển các thành phần MediaDrm
và MediaCrypto
vào quy trình mediadrmserver
mới, nhà cung cấp phải thay đổi phương thức phân bổ cho bộ đệm an toàn để cho phép chia sẻ bộ đệm giữa các quy trình.
Trong các bản phát hành Android trước đây, bộ đệm an toàn được phân bổ trong mediaserver
bởi OMX::allocateBuffer
và được sử dụng trong quá trình giải mã trong cùng một quy trình, như minh họa bên dưới:
Trong Android 7.0, quy trình phân bổ bộ đệm đã thay đổi thành cơ chế mới mang lại sự linh hoạt đồng thời giảm thiểu tác động đến việc triển khai hiện có. Với các ngăn xếp MediaDrm
và MediaCrypto
trong quy trình mediadrmserver
mới, các bộ đệm được phân bổ khác nhau và các nhà cung cấp phải cập nhật các bộ xử lý bộ đệm an toàn để chúng có thể được vận chuyển qua chất kết dính khi MediaCodec
gọi thao tác giải mã trên MediaCrypto
.
Sử dụng tay cầm gốc
OMX::allocateBuffer
phải trả về một con trỏ tới cấu trúc native_handle
, cấu trúc này chứa các bộ mô tả tệp (FD) và dữ liệu số nguyên bổ sung. native_handle
có tất cả các ưu điểm của việc sử dụng FD, bao gồm hỗ trợ liên kết hiện có cho việc tuần tự hóa/giải tuần tự hóa, đồng thời cho phép các nhà cung cấp hiện không sử dụng FD linh hoạt hơn.
Sử dụng native_handle_create()
để phân bổ mã điều khiển gốc. Mã khung có quyền sở hữu cấu trúc native_handle
được phân bổ và chịu trách nhiệm giải phóng tài nguyên trong cả quá trình mà native_handle
được phân bổ ban đầu và trong quá trình nó được giải tuần tự hóa. Khung này giải phóng các thẻ điều khiển gốc với native_handle_close()
theo sau là native_handle_delete()
và tuần tự hóa/giải tuần tự hóa native_handle
bằng cách sử dụng Parcel::writeNativeHandle()/readNativeHandle()
.
Các nhà cung cấp SoC sử dụng FD để thể hiện bộ đệm an toàn có thể đưa FD vào native_handle
bằng FD của họ. Các nhà cung cấp không sử dụng FD có thể biểu thị bộ đệm an toàn bằng cách sử dụng các trường bổ sung trong native_buffer
.
Đặt vị trí giải mã
Nhà cung cấp phải cập nhật phương thức giải mã OEMCrypto hoạt động trên native_handle
để thực hiện mọi thao tác cần thiết dành riêng cho nhà cung cấp để làm cho native_handle
có thể sử dụng được trong không gian quy trình mới (các thay đổi thường bao gồm các bản cập nhật cho thư viện OEMCrypto).
Vì allocateBuffer
là một hoạt động OMX tiêu chuẩn nên Android 7.0 bao gồm tiện ích mở rộng OMX mới ( OMX.google.android.index.allocateNativeHandle
) để truy vấn hỗ trợ này và lệnh gọi OMX_SetParameter
để thông báo việc triển khai OMX nên sử dụng các thẻ điều khiển gốc.