カーネル 4.14 以上を搭載したデバイスでは、ION カーネル モジュールが大幅にリファクタリングされています。多くのベンダーで、共有メモリバッファを割り当てる際に呼び出すグラフィックス メモリ アロケータ(gralloc)のハードウェア抽象化レイヤ(HAL)での実装に同モジュールが利用されており、リファクタリングによる影響がおよびます。このページでは、従来のベンダーコードを ION の新しいバージョンに移行する方法を紹介し、将来起こる可能性があるアプリケーション バイナリ インターフェース(ABI)の互換性の問題について説明します。
ION について
ION は、アップストリーム カーネルで開発中のステージング ツリーの一部です。ステージングに際し、カーネルのメジャー バージョンが異なると、ION のユーザー空間とカーネルの間に位置する ABI に互換性の問題が生じる可能性があります。ION ABI で問題が生じたとしても、通常のアプリやリリース済みのデバイスに直接の影響が生じることはありません。しかし、ベンダーがカーネルを新しいメジャー バージョンに移行する際には、変更された内容が ION を呼び出すベンダーコードに影響する可能性があります。また、Android システムチームが ION をステージング ツリーから移行してアップストリームで扱う際にも、ABI の互換性の問題が起こる可能性があります。
Android-4.14 における変更
カーネル 4.12 では、ION カーネルコードが大幅にリファクタリングされ、他のカーネル フレームワークと重複していた部分のクリーンアップと削除が行われました。その結果、従来の ION ioctl の多くが不要となり、削除されました。
ION client と ION handle の削除
カーネル 4.12 より前のバージョンでは、/dev/ion
を open することで ION client が割り当てられていました。ION_IOC_ALLOC
ioctl により新しいバッファが割り当てられ、それを ION handle(opaque 型の整数型で、割り当てられる ION client にのみ有意な値)としてユーザー空間に返していました。バッファをユーザー空間にマッピングする、もしくは他のプロセスと共有する際には、ION_IOC_SHARE
ioctl により、ION handle が dma-buf fd として再エクスポートされていました。
カーネル 4.12 では、ION_IOC_ALLOC
ioctl により dma-buf fd が直接出力されます。中間処理として用意されていた ION handle は、ION handle の使用や生成を行うすべての ioctl と合わせて削除されました。dma-buf fd は特定の ION client には結び付けられていないため、ION_IOC_SHARE
ioctl が不要になり、ION client のインフラストラクチャもすべて削除されています。
cache-coherency ioctl の追加
カーネル 4.12 より前のバージョンでは、ファイル ディスクリプタをメモリと同期させる ION_IOC_SYNC
ioctl が提供されていました。ただ、この ioctl についてはドキュメントが十分に用意されておらず、柔軟性に欠けていたことから、多くのベンダーがキャッシュ メンテナンスを行うためのカスタム ioctl を実装していました。
カーネル 4.12 では、ION_IOC_SYNC
が linux/dma-buf.h
で定義されている DMA_BUF_IOCTL_SYNC ioctl
に置き換えられました。DMA_BUF_IOCTL_SYNC
は CPU へのアクセスの開始と終了のたびに呼び出され、そのアクセスが読み取り、書き込み、両方のどれにあたるかがフラグで示されます。DMA_BUF_IOCTL_SYNC
は ION_IOC_SYNC
よりも複雑ですが、背後で動作するキャッシュ メンテナンス操作について、ユーザー空間でより詳細に管理できるようになります。
DMA_BUF_IOCTL_SYNC
はカーネルの安定版 ABI であり、ION による割り当てかどうかにかかわらず、すべての dma-buf fd で使用できます。
Android-4.12 以上へのベンダーコードの移行
Android システムチームは、ユーザー空間の client について、オープン コーディングで ioctl()
を呼び出すのではなく、libion を使用するように強く推奨しています。Android 9 以降の libion では、ランタイムに ION ABI が自動的に検出され、カーネル間の相違が顕在化しないような処理が行われます。しかし、カーネル 4.12 以降からは、ion_user_handle_t
handle を生成または使用する libion 関数は機能しなくなりました。この関数は、以下の dma-buf fd の同等の操作よって置き換えられており、すべてのカーネル バージョンで利用できます。
従来の ion_user_handle_t 呼び出し | 同等の dma-buf fd 呼び出し |
---|---|
ion_alloc(ion_fd, …, &buf_handle) |
ion_alloc_fd(ion_fd, ..., &buf_fd) |
ion_share(ion_fd, buf_handle, &buf_fd) |
N/A(dma-buf fd ではこの呼び出しは不要です) |
ion_map(ion_fd, buf_handle, ...) |
mmap(buf_fd, ...) |
ion_free(ion_fd, buf_handle) |
close(buf_fd) |
ion_import(ion_fd, buf_fd, &buf_handle) |
N/A(dma-buf fd ではこの呼び出しは不要です) |
ion_sync_fd(ion_fd, buf_fd) |
If (ion_is_legacy(ion_fd)) ion_sync_fd(ion_fd, buf_fd); else ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...); |
カーネル内の client については、カーネル向け API のエクスポートが ION では行われなくなったことから、ion_import_dma_buf_fd()
でカーネル内 ION カーネル API を使用していたドライバを、dma_buf_get()
でカーネル内 dma-buf API を使用するように変換する必要があります。
将来的な ION ABI の互換性の問題
ION がステージング ツリーに移行するまでに、今後リリースされるカーネルで ION ABI の互換性の問題が再び生じる可能性があります。Android システムチームでは、こうした変更が Android の次期バージョンで動作するデバイスに影響するとは想定していません。ただし、次期バージョンより後の Android においては、デバイスに影響をおよぼす可能性があります。
たとえば、アップストリームのコミュニティでは、デバイスが各ヒープに異なる SELinux ポリシーを適用できるように、単一の /dev/ion
ノードをヒープごとの複数のノードに分割します(例: /dev/ion/heap0
)。このような変更が将来のカーネル リリースで実装されると、ION ABI に互換性の問題が生じる恐れがあります。