HIDLの学習の概要-ICameraProvider.halインターフェイスを拡張して、メガレベルのデータをプロセス間でCameraProviderプロセスに転送する実装スキームを実現します

CameraAPI2はデータをCamera HALに転送します。カメラパラメータは主にcamera_metadataを介して実現されます。最近のプロジェクトでは、YUVデータをCamera HALに転送する必要があり、サイズは数メガバイトです。これを達成するために既存のcamera_metadataを使用することは困難です(後で調査する必要があります)。実現可能性1)。

この機能を実現し、CameraAPI2がCamera HALにデータを転送する機能をさらに向上させるために、この記事では、ICameraProvider.halインターフェイスを拡張して匿名の共有メモリ(Ashmem)をCameraProviderプロセスに渡すことにより、この機能を実装します。

主な実装は次のとおりです
。ICameraProvider.halファイルを変更します。

//hardware\interfaces\camera\provider\2.4\ICameraProvider.hal
--- a/camera/provider/2.4/ICameraProvider.hal
+++ b/camera/provider/2.4/ICameraProvider.hal
@@ -185,4 +185,7 @@ interface ICameraProvider {
    
    
             (Status status,
              android.hardware.camera.device@3.2::ICameraDevice device);
 //扩展的接口registerMemory
 //descriptor为共享内存句柄
 //bufferSize为共享内存大小
 //bufferCount共享内存个数
 //memId?
+    registerMemory(handle descriptor, uint32_t bufferSize, uint32_t bufferCount)
+            generates (uint32_t memId);
+
 };

CameraProviderを再コンパイルします(2をコンパイルするには、hardware \ interfaces \ current.txtを変更する必要がある場合があります

--- a/current.txt
+++ b/current.txt
@@ -58,7 +58,6 @@ b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardwar
 0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
 030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
 5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
 //删除该行
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider

再生成されたCameraProviderインターフェースは次のとおりです。

struct ICameraProvider : public ::android::hidl::base::V1_0::IBase {
    
    
    virtual bool isRemote() const override {
    
     return false; }
...
    using getCameraDeviceInterface_V3_x_cb = std::function<void(::android::hardware::camera::common::V1_0::Status status, const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device)>;
    virtual ::android::hardware::Return<void> getCameraDeviceInterface_V3_x(const ::android::hardware::hidl_string& cameraDeviceName, getCameraDeviceInterface_V3_x_cb _hidl_cb) = 0;
//新添加的接口
    virtual ::android::hardware::Return<uint32_t> registerMemory(const ::android::hardware::hidl_handle& descriptor, uint32_t bufferSize, uint32_t bufferCount) = 0;
....

ICameraProvider抽象クラスを実装するCameraProviderクラスに新しく定義されたregisterMemoryメソッドを実装
し、CameraProvider.hヘッダーファイルにregisterMemory宣言を追加することも必要です。

//hardware\interfaces\camera\provider\2.4\default\CameraProvider.h
--- a/camera/provider/2.4/default/CameraProvider.h
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -68,7 +68,7 @@ struct CameraProvider : public ICameraProvider, public camera_module_callbacks_t
     Return<void> getCameraDeviceInterface_V3_x(
             const hidl_string& cameraDeviceName,
             getCameraDeviceInterface_V3_x_cb _hidl_cb) override;
//新接口声明声明
+    Return<uint32_t> registerMemory(const hidl_handle& descriptor, uint32_t bufferSize, uint32_t bufferCount) override;
 private:
     Mutex mCbLock;
     sp<ICameraProviderCallback> mCallbacks = nullptr;

CameraProvider.cppにregisterMemoryを実装する

--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -24,6 +24,8 @@
 #include <cutils/properties.h>
 #include <string.h>
 #include <utils/Trace.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
 
 
 namespace android {
    
    
@@ -523,6 +525,60 @@ Return<void> CameraProvider::getCameraDeviceInterface_V3_x(
     return Void();
 }
// 添加局部dumpImage方法,检验数据是否传递正确
+void dumpImage(unsigned char* pData,
+        uint32_t frameid,uint32_t stride,uint32_t height,uint32_t bytePerPixe) {
    
    
+    ALOGE("%s,%d E .", __FUNCTION__,__LINE__);
+
+    char buf[255];
+    memset(buf, 0, sizeof(buf));
+    snprintf(buf, sizeof(buf),  "/data/misc/camera/frame_%dx%d_%d.raw",
+             stride,height,frameid);
+    ALOGE("%s,%d buf : %s", __FUNCTION__,__LINE__,buf);
+    int file_fd = open(buf, O_RDWR | O_CREAT, 0666);
+    uint32_t size = stride*height*bytePerPixe;
+    if (file_fd >= 0)
+    {
    
    
+        ssize_t written_Len    = write(file_fd, pData, size);
+        ALOGE("%s,%d : written number of %zd bytes to file %s", __FUNCTION__,__LINE__,written_Len,buf);
+        close(file_fd);
+    }
+    else
+    {
    
    
+        ALOGE("%s,%d : failed to write data to %s", __FUNCTION__,__LINE__,buf);
+    }
+    ALOGE("%s,%d X .", __FUNCTION__,__LINE__);
+}
+
// registerMemory接口实现
+Return<uint32_t> CameraProvider::registerMemory(const hidl_handle& descriptor, uint32_t bufferSize, uint32_t bufferCount) {
    
    
+    ALOGE("%s:%d,%d,%d", __FUNCTION__,bufferSize,bufferCount,descriptor->data[0]);
+    if (descriptor->numFds != 1) {
    
    
+        ALOGE("%s: camera memory descriptor has numFds %d (expect 1)",
+                __FUNCTION__, descriptor->numFds);
+        return 0;
+    }
+    if (descriptor->data[0] < 0) {
    
    
+        ALOGE("%s: camera memory descriptor has FD %d (expect >= 0)",
+                __FUNCTION__, descriptor->data[0]);
+        return 0;
+    }
+    
+    sp<android::MemoryHeapBase> mHeap;
+    //由hidl_handle descriptor转换生成MemoryHeapBase
+    //MemoryHeapBase是内名共享内存定义的方法,以后会单独研究下MemoryHeapBase MemoryBase
+    mHeap = new android::MemoryHeapBase(descriptor->data[0], bufferSize * bufferCount,0,0);
+    sp<MemoryBase> *mBuffers;
+    mBuffers = new sp<MemoryBase>[bufferCount];
+    for (uint_t i = 0; i < bufferCount; i++) {
    
    
+        mBuffers[i] = new MemoryBase(mHeap,i * bufferSize, bufferSize);
+    }
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mBuffers[0]->getMemory(&offset, &size);
+    void* heapBase = heap->base();
+    //dump传递进CameraProvider的数据,检查数据是否正确
+    dumpImage((unsigned char*)heapBase,1,bufferSize,bufferCount,1);
+    //将由descriptor转换生成的MemoryHeapBase对象的HeapID放回给client用户
+    return mHeap->getHeapID();
+};
+

次に、コンパイルされたファイルを変更します

//hardware\interfaces\camera\provider\2.4\default\Android.bp
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -23,7 +23,8 @@ cc_library_shared {
    
    
         "[email protected]",
         "liblog",
         "libhardware",
-        "libcamera_metadata"
+        "libcamera_metadata",
+        "libbinder"
     ],
     static_libs: [
         "[email protected]"

これまでのところ、CameraProviderの変更は完了しています。

次に、新しく定義されたregisterMemoryの使用方法、つまり、AshmemをユーザーデータとともにCameraProviderに渡す方法を紹介します。
この記事では、CameraServiceでこのメソッドを使用しています。もちろん、カメラアプリケーションなど、CameraProviderサービスエージェントを取得できる任意の場所で使用することもできます。

--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -25,11 +25,20 @@
 #include <hidl/ServiceManagement.h>
 #include <functional>
 #include <camera_metadata_hidden.h>
 //添加必要的头文件
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <hidlmemory/mapping.h>
 
 namespace android {
    
    
 
 using namespace ::android::hardware::camera;
 using namespace ::android::hardware::camera::common::V1_0;
+using ::android::hardware::camera::device::V1_0::MemoryId;
//将必要的名称空间添加到本类中
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::hardware::hidl_memory;

 
 namespace {
    
    
 // Hardcoded name for the passthrough HAL implementation, since it can't be discovered via the
@@ -522,6 +531,35 @@ status_t CameraProviderManager::ProviderInfo::initialize() {
    
    
         return mapToStatusT(status);
     }
 
+    // Shared memory related members
+    size_t buf_size = 1024 * 1024;// 1m
+    uint_t num_bufs = 1;
+    hidl_memory      mHidlHeap;
+    native_handle_t* mHidlHandle; // contains one shared memory FD
+    sp<IAllocator>   ashmemAllocator;
+    sp<IMemory>      mHidlHeapMemory; // munmap happens in ~IMemory()
+    void*            mHidlHeapMemData;
+   //获取IAllocator服务代理,IAllocator需要以后研究下
+    ashmemAllocator = IAllocator::getService("ashmem");
+    const size_t pagesize = getpagesize();
+    //大小对其到pagesize的整数倍
+    size_t size = ((buf_size * num_bufs + pagesize-1) & ~(pagesize-1));
+    //分配匿名共享内存
+    ashmemAllocator->allocate(size,
+        [&](bool success, const hidl_memory& mem) {
    
    
+            mHidlHandle = native_handle_clone(mem.handle());
+            mHidlHeap = hidl_memory("ashmem", mHidlHandle, size);
+            ALOGI("allocate %d", success);
+        });
+    //将内存映射到当前进程,mapMemory需要以后研究下
+    mHidlHeapMemory = mapMemory(mHidlHeap);
+    mHidlHeapMemData = mHidlHeapMemory->getPointer();
+    uint8_t*temp = (uint8_t*)mHidlHeapMemData;
+    //测试内容,如果在CameraProvider dumpImage方法保存的数据全部是0xFE,说明功能实现成功
+    memset(temp,0xFE,size);
+    //将带有用户数据的内名共享内存注册给CameraProvider
+    uint32_t memid = mInterface->registerMemory(mHidlHandle, buf_size, num_bufs);
+    ALOGI("memid %d", memid);
+
+
     sp<StatusListener> listener = mManager->getStatusListener();
     for (auto& device : devices) {
    
    
         std::string id;

コンパイルされたファイルを変更する

//frameworks\av\services\camera\libcameraservice\Android.mk
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -99,9 +99,12 @@ LOCAL_SHARED_LIBRARIES:= \
     android.hardware.camera.device@1.0 \
     vendor.qti.hardware.camera.device@1.0 \
     android.hardware.camera.device@3.2 \
-    android.hardware.camera.device@3.3
+    android.hardware.camera.device@3.3 \
+    android.hidl.allocator@1.0 \
+    android.hidl.memory@1.0\
+    libhidlmemory \
 
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder libcamera_client libfmq
+LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbinder libcamera_client libfmq android.hidl.allocator@1.0 android.hidl.memory@1.0 libhidlmemory
 
 LOCAL_C_INCLUDES += \
     system/media/private/camera/include \

再コンパイルして、生成されたものを電話にプッシュし、電話を再起動して、ファイルが/data/misc/cameraディレクトリに生成されていることを確認し
frame_1048576x1_1.rawます


ここに画像の説明を挿入
内容を開いて次のように表示します。ダンプデータから、CameraServiceによって渡された内容と値は同じです。基本機能実現3


  1. 検証は実行できません。理由について、AndroidフレームワークCameraMetadataとHIDL CameraMetadataの違いと変換 を確認しください↩︎

  2. コンパイル時に、現在のハッシュとhardware \ interfaces \ current.txtが一致するかどうかをチェックします
    コードはsystem \ tools \ hidl \ Coordinator.cpp Coordinator :: enforceHashes(…)にあります。↩︎

  3. ログを見ると、SELinux:avc:denied {find} for interface = android.hidl.memory :: IMapper関連のログが見つかりました。また、SELinux権限の問題を修正する必要があるかもしれません。プロジェクトはSELinuxを閉じました。また、現在は登録方法のみが実装されており、反登録が必要です。↩︎

おすすめ

転載: blog.csdn.net/u010116586/article/details/96431008