為提升裝置安全性,Android 7.0 將單一 mediaserver
程序分割成多個程序,並將權限和功能限制在各程序所需的範圍內。這些變更可透過以下方式降低媒體架構的安全漏洞:
- 將 AV 管道元件分割為應用程式專屬的沙箱程序。
- 啟用可更新的媒體元件 (擷取器、編解碼器等)。
這些異動也大幅降低了大部分媒體相關安全漏洞的嚴重程度,進而提升使用者安全性,確保使用者裝置和資料安全無虞。
OEM 和 SoC 供應商需要更新 HAL 和架構變更,使其與新架構相容。具體來說,由於供應商提供的 Android 程式碼通常會假設所有內容都會在同一個程序中執行,因此供應商必須更新程式碼,以便在各程序中傳遞具有意義的原生句柄 (native_handle
)。如需媒體強化相關變更的參考導入方式,請參閱 frameworks/av
和 frameworks/native
。
架構變更
先前版本的 Android 使用單一巨型 mediaserver
程序,且具有許多權限 (相機存取權、音訊存取權、視訊驅動程式存取權、檔案存取權、網路存取權等)。Android 7.0 將 mediaserver
程序分割為多個新程序,每個程序都只需要較少的權限:
圖 1. 強化媒體伺服器的架構變更
這項全新架構可確保即使程序遭到入侵,惡意程式碼也無法存取先前由 mediaserver
持有的完整權限組合。程序受到 SElinux 和 seccomp 政策的限制。
注意:由於供應商依附元件,某些編解碼器仍會在 mediaserver
中執行,因此會向 mediaserver
授予過多權限。具體來說,Widevine Classic 會繼續在 Android 7.0 的 mediaserver
中執行。
媒體伺服器異動
在 Android 7.0 中,mediaserver
程序會用於驅動播放和錄製作業,例如在元件和程序之間傳遞及同步處理緩衝區。程序會透過標準 Binder 機制進行通訊。
在標準本機檔案播放工作階段中,應用程式會將檔案描述元 (FD) 傳遞至 mediaserver
(通常是透過 MediaPlayer Java API),而 mediaserver
會執行以下操作:
- 將 FD 包裝成傳遞至萃取程序的 Binder DataSource 物件,該程序會使用該物件透過 Binder IPC 讀取檔案。(mediaextractor 不會取得 FD,而是會讓 Binder 回呼至
mediaserver
以取得資料)。 - 檢查檔案,為檔案類型建立適當的擷取器 (例如 MP3Extractor 或 MPEG4Extractor),並將擷取器的 Binder 介面傳回至
mediaserver
程序。 - 向擷取器發出 Binder IPC 呼叫,以判斷檔案中的資料類型 (例如 MP3 或 H.264 資料)。
- 呼叫
mediacodec
程序,以建立所需類型的編解碼;接收這些編解碼的 Binder 介面。 - 重複呼叫 Binder IPC 至擷取器,以便讀取已編碼的樣本,並使用 Binder IPC 將已編碼的資料傳送至
mediacodec
處理程序進行解碼,然後接收解碼後的資料。
在某些用途中,系統不會使用編解碼器 (例如在離線播放時,編碼資料會直接傳送至輸出裝置),或是編解碼器可能會直接轉譯解碼資料,而非傳回解碼資料的緩衝區 (影片播放)。
MediaCodecService 異動
編碼器和解碼器會在編解碼服務中運作。由於供應商依附元件,因此並非所有編解碼都會在編解碼處理程序中運作。在 Android 7.0 中:
- 非安全解碼器和軟體編碼器會在編解碼器程序中執行。
- 安全解碼器和硬體編碼器位於
mediaserver
中 (未變更)。
應用程式 (或 mediaserver
) 會呼叫編解碼器程序,以建立所需類型的編解碼器,然後呼叫該編解碼器,以便傳入已編碼的資料並擷取已解碼的資料 (用於解碼),或傳入已解碼的資料並擷取已編碼的資料 (用於編碼)。從編碼器傳送至編碼器的資料傳輸作業已使用共用記憶體,因此該程序不會有所變動。
MediaDrmServer 異動
播放受 DRM 保護的內容 (例如 Google Play 電影中的電影) 時,就會使用 DRM 伺服器。它會以安全的方式處理加密資料的解密作業,因此可存取憑證、金鑰儲存空間和其他機密元件。由於供應商依附元件,DRM 程序尚未在所有情況下使用。
AudioServer 異動
AudioServer 程序會代管音訊相關元件,例如音訊輸入和輸出、用於決定音訊轉送的 policymanager 服務,以及 FM 廣播服務。如要進一步瞭解音訊變更和實作指南,請參閱實作音訊。
CameraServer 異動
CameraServer 會控制攝影機,並在錄製影片時用於從攝影機取得影像框,然後將這些框架傳遞給 mediaserver
進一步處理。如要進一步瞭解 CameraServer 變更的內容和實作指南,請參閱「攝影機架構強化措施」。
ExtractorService 異動
Extractor Service 會代管extractor,也就是用於剖析媒體架構支援的各種檔案格式的元件。Extractor 服務是所有服務中權限最低的服務,因為它無法讀取 FD,因此會改為對 Binder 介面 (由 mediaserver for
在每個播放工作階段提供) 發出呼叫,以便存取檔案。
應用程式 (或 mediaserver
) 會呼叫擷取器程序來取得 IMediaExtractor
,然後呼叫該 IMediaExtractor
來取得檔案中包含的曲目 IMediaSources
,接著呼叫 IMediaSources
來讀取這些資料。
為了在程序之間傳輸資料,應用程式 (或 mediaserver
) 會將資料納入回覆包裹中,做為 Binder 交易的一部分,或使用共用記憶體:
- 使用共用記憶體需要額外的 Binder 呼叫來釋放共用記憶體,但對於大型緩衝區,這麼做速度更快,且耗電量更低。
- 使用in-Parcel 需要額外複製作業,但速度更快,且對於小於 64 KB 的緩衝區,耗電量也較低。
實作
如要支援將 MediaDrm
和 MediaCrypto
元件移至新的 mediadrmserver
程序,供應商必須變更安全緩衝區的配置方法,以便在程序之間共用緩衝區。
在先前的 Android 版本中,安全緩衝區會由 OMX::allocateBuffer
在 mediaserver
中分配,並在相同程序的解密期間使用,如下所示:
圖 2. Android 6.0 以下版本的媒體伺服器緩衝區配置。
在 Android 7.0 中,緩衝區配置程序已變更為新機制,可提供彈性,同時盡量降低對現有實作項目的影響。在新的 mediadrmserver
程序中,MediaDrm
和 MediaCrypto
堆疊會以不同的方式分配緩衝區,且廠商必須更新安全緩衝區句柄,以便在 MediaCodec
對 MediaCrypto
叫用解密作業時,透過繫結器傳輸緩衝區。
圖 3. Android 7.0 以上版本的媒體伺服器緩衝區配置。
使用原生控制項
OMX::allocateBuffer
必須傳回 native_handle
結構體的指標,其中包含檔案描述符 (FD) 和其他整數資料。native_handle
具備使用 FD 的所有優點,包括現有的繫結器支援序列化/反序列化,同時讓目前未使用 FD 的供應商享有更大的彈性。
使用 native_handle_create()
分配原生控制項。架構程式碼會取得已分配 native_handle
結構體的擁有權,並負責在 native_handle
原先分配的程序和序列化程序中釋放資源。架構會使用 native_handle_close()
釋放原生句柄,接著使用 native_handle_delete()
序列化/反序列化 native_handle
,Parcel::writeNativeHandle()/readNativeHandle()
使用 FD 代表安全緩衝區的 SoC 廠商,可以使用自己的 FD 填入 native_handle
中的 FD。不使用 FD 的供應商可以在 native_buffer
中使用其他欄位來表示安全緩衝區。
設定解密位置
供應商必須更新在 native_handle
上運作的 OEMCrypto 解密方法,以便執行任何必要的供應商專屬作業,讓 native_handle
可在新的程序空間中使用 (變更通常包括 OEMCrypto 程式庫的更新)。
由於 allocateBuffer
是標準的 OMX 作業,Android 7.0 包含新的 OMX 擴充功能 (OMX.google.android.index.allocateNativeHandle
),可用於查詢這項支援功能,以及 OMX_SetParameter
呼叫,可通知 OMX 實作應使用原生句柄。