精华内容
下载资源
问答
  • 研究导向:open camera过程中有些初始化设置参数需要从vendor层获取,而vendor与hal隶属于不同进程,通过ION机制设置共享内存来实现不同进程间数据共享,下面简要介绍流程:在初始化过程中hal层会通过socket将消息...

    研究导向:

    open camera过程中有些初始化设置参数需要从vendor层获取,而vendor与hal隶属于不同进程,通过ION机制设置共享内存来实现不同进程间数据共享,下面简要介绍流程:

    在初始化过程中hal层会通过socket将消息发送至vendor层-通知vendor map共享内存。

    ION初始化过程:

    vim hardware/qcom/camera/QCamera2/HAL/QCamera2HWI.cpp

    int QCamera2HardwareInterface::openCamera()

    {

    ……

    if (NULL == gCamCapability[mCameraId]) {

    if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) {//会初始化ION

    ......

    }

    }

    mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,

    camEvtHandle,

    (void *) this);

    ……

    pthread_mutex_lock(&m_parm_lock);/* MM-MC-FixString8HeapCorrupt-00+ */

    //初始化m_pCapability-从vendor层拿到的camera相关初始化数据

    mParameters.init(gCamCapability[mCameraId], mCameraHandle, this, this);

    pthread_mutex_unlock(&m_parm_lock);/* MM-MC-FixString8HeapCorrupt-00+ */

    mParameters.m_parm_lock_ptr = &m_parm_lock;/* MM-MC-FixString8HeapCorrupt-00+ */

    ALOGI("openCamera: m_parm_lock_ptr = 0x%x", mParameters.m_parm_lock_ptr);/* MM-MC-FixString8HeapCorrupt-00+ */

    mCameraOpened = true;

    gCameraOpened = true;/* MM-CL-CTS-testMultiCameraRelease-00+ */

    #ifdef USE_ARCSOFT_FEATURE

    if ((NULL != mArcSoft_Feature)&&(mCameraId == 0))/* MM-MC-FixOpenCameraCrash-00+ */

    mArcSoft_Feature->imx214_module_source = gCamCapability[0]->fih_imx214_module_source;//MM-YW-Get module source for HAL-00

    #endif

    return NO_ERROR;

    }

    int QCamera2HardwareInterface::initCapabilities(uint32_t cameraId,

    mm_camera_vtbl_t *cameraHandle)

    {

    ATRACE_CALL();

    int rc = NO_ERROR;

    QCameraHeapMemory *capabilityHeap = NULL;

    /* Allocate memory for capability buffer */

    capabilityHeap = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE);

    rc =capabilityHeap->allocate(1, sizeof(cam_capability_t)); //1、设置ION共享内存

    ......

    /* Map memory for capability buffer */

    memset(DATA_PTR(capabilityHeap,0), 0, sizeof(cam_capability_t));

    //2、通过socket通知vendor映射共享内存用于进程间通信

    rc =cameraHandle->ops->map_buf(cameraHandle->camera_handle,

    CAM_MAPPING_BUF_TYPE_CAPABILITY,

    capabilityHeap->getFd(0),

    sizeof(cam_capability_t));

    if(rc < 0) {

    ALOGE("%s: failed to map capability buffer", __func__);

    goto map_failed;

    }

    /* Query Capability */

    rc = cameraHandle->ops->query_capability(cameraHandle->camera_handle);

    if(rc < 0) {

    ALOGE("%s: failed to query capability",__func__);

    goto query_failed;

    }

    gCamCapability[cameraId] = (cam_capability_t *)malloc(sizeof(cam_capability_t));

    if (!gCamCapability[cameraId]) {

    ALOGE("%s: out of memory", __func__);

    goto query_failed;

    }

    memcpy(gCamCapability[cameraId], DATA_PTR(capabilityHeap,0),

    sizeof(cam_capability_t));

    //copy the preview sizes and video sizes lists because they

    //might be changed later

    copyList(gCamCapability[cameraId]->preview_sizes_tbl, savedSizes[cameraId].all_preview_sizes,

    gCamCapability[cameraId]->preview_sizes_tbl_cnt);

    savedSizes[cameraId].all_preview_sizes_cnt = gCamCapability[cameraId]->preview_sizes_tbl_cnt;

    copyList(gCamCapability[cameraId]->video_sizes_tbl, savedSizes[cameraId].all_video_sizes,

    gCamCapability[cameraId]->video_sizes_tbl_cnt);

    savedSizes[cameraId].all_video_sizes_cnt = gCamCapability[cameraId]->video_sizes_tbl_cnt;

    rc = NO_ERROR;

    query_failed:

    cameraHandle->ops->unmap_buf(cameraHandle->camera_handle,

    CAM_MAPPING_BUF_TYPE_CAPABILITY);

    ……

    }

    1、设置ION共享内存:

    vim hardware/qcom/camera/QCamera2/HAL/QCameraMem.cpp

    int QCameraHeapMemory::allocate(uint8_t count, size_t size)

    {

    traceLogAllocStart(size, count, "HeapMemsize");

    unsigned int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;

    int rc = alloc(count, size, heap_mask); //主要填充mMemInfo

    if (rc < 0)

    return rc;

    for (int i = 0; i < count; i ++) {

    void *vaddr= mmap(NULL,   //映射共享内存

    mMemInfo[i].size,

    PROT_READ | PROT_WRITE,

    MAP_SHARED,

    mMemInfo[i].fd, 0);

    if (vaddr == MAP_FAILED) {

    for (int j = i-1; j >= 0; j --) {

    munmap(mPtr[j], mMemInfo[j].size);

    mPtr[j] = NULL;

    deallocOneBuffer(mMemInfo[j]);

    }

    return NO_MEMORY;

    } else

    mPtr[i] = vaddr;

    }

    if (rc == 0)

    mBufferCount = count;

    traceLogAllocEnd((size * count));

    return OK;

    }

    int QCameraMemory::alloc(int count, size_t size, unsigned int heap_id)

    {

    ……s

    int new_bufCnt = mBufferCount + count;

    traceLogAllocStart(size, count, "Memsize");

    ……

    for (int i = mBufferCount; i < new_bufCnt; i ++) {

    if ( NULL == mMemoryPool ) {

    CDBG_HIGH("%s : No memory pool available and So allocate new buffer", __func__);

    rc = allocOneBuffer(mMemInfo[i], heap_id, size, m_bCached);

    if (rc < 0) {

    ALOGE("%s: AllocateIonMemory failed", __func__);

    for (int j = i-1; j >= 0; j--)

    deallocOneBuffer(mMemInfo[j]);

    break;

    }

    } else {

    rc = mMemoryPool->allocateBuffer(mMemInfo[i],

    heap_id,

    size,

    m_bCached,

    mStreamType);

    if (rc < 0) {

    ALOGE("%s: Memory pool allocation failed", __func__);

    for (int j = i-1; j >= 0; j--)

    mMemoryPool->releaseBuffer(mMemInfo[j],

    mStreamType);

    break;

    }

    }

    }

    traceLogAllocEnd (size * (size_t)count);

    return rc;

    }

    int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo,

    unsigned int heap_id, size_t size, bool cached)

    {

    int rc = OK;

    struct ion_handle_data handle_data;

    struct ion_allocation_data alloc;

    struct ion_fd_data ion_info_fd;

    int main_ion_fd = 0;

    main_ion_fd= open("/dev/ion", O_RDONLY);

    if (main_ion_fd < 0) {

    ALOGE("Ion dev open failed: %s\n", strerror(errno));

    goto ION_OPEN_FAILED;

    }

    memset(&alloc, 0, sizeof(alloc));

    memset(&ion_info_fd, 0, sizeof(ion_info_fd));/* MM-MC-ModifyIonFdInitFlow-00+ */

    alloc.len = size;

    /* to make it page size aligned */

    alloc.len = (alloc.len + 4095U) & (~4095U);

    alloc.align = 4096;

    if (cached) {

    alloc.flags = ION_FLAG_CACHED;

    }

    alloc.heap_id_mask = heap_id;

    rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);

    if (rc < 0) {

    ALOGE("ION allocation failed: %s\n", strerror(errno));

    goto ION_ALLOC_FAILED;

    }

    //memset(&ion_info_fd, 0, sizeof(ion_info_fd));/* MM-MC-ModifyIonFdInitFlow-00- */

    ion_info_fd.handle = alloc.handle;

    rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);

    if (rc < 0) {

    ALOGE("ION map failed %s\n", strerror(errno));

    goto ION_MAP_FAILED;

    }

    memInfo.main_ion_fd = main_ion_fd;

    memInfo.fd = ion_info_fd.fd;

    memInfo.handle = ion_info_fd.handle;

    memInfo.size = alloc.len;

    memInfo.cached = cached;

    memInfo.heap_id = heap_id;

    CDBG_HIGH("%s : ION buffer %lx with size %d allocated",

    __func__, (unsigned long)memInfo.handle, memInfo.size);

    return OK;

    ION_MAP_FAILED:

    memset(&handle_data, 0, sizeof(handle_data));

    handle_data.handle = ion_info_fd.handle;

    ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);

    ION_ALLOC_FAILED:

    close(main_ion_fd);

    ION_OPEN_FAILED:

    return NO_MEMORY;

    }

    2、通过socket通知vendor映射相应共享内存用于进程间通信:

    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c

    static int32_t mm_camera_intf_map_buf(uint32_t camera_handle,

    uint8_t buf_type,

    int fd,

    size_t size)

    {

    int32_t rc = -1;

    mm_camera_obj_t * my_obj = NULL;

    pthread_mutex_lock(&g_intf_lock);

    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);

    if(my_obj) {

    pthread_mutex_lock(&my_obj->cam_lock);

    pthread_mutex_unlock(&g_intf_lock);

    rc = mm_camera_map_buf(my_obj, buf_type, fd, size);

    } else {

    pthread_mutex_unlock(&g_intf_lock);

    }

    return rc;

    }

    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c

    int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,

    uint8_t buf_type,

    int fd,

    size_t size)

    {

    int32_t rc = 0;

    cam_sock_packet_t packet;

    memset(&packet, 0, sizeof(cam_sock_packet_t));

    packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;

    packet.payload.buf_map.type = buf_type;

    packet.payload.buf_map.fd = fd;

    packet.payload.buf_map.size = size;

    rc = mm_camera_util_sendmsg(my_obj,

    &packet,

    sizeof(cam_sock_packet_t),

    fd);

    pthread_mutex_unlock(&my_obj->cam_lock);

    return rc;

    }

    int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,

    void *msg,

    size_t buf_size,

    int sendfd)

    {

    int32_t rc = -1;

    uint32_t status;

    /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/

    pthread_mutex_lock(&my_obj->msg_lock);

    if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {

    /* wait for event that mapping/unmapping is done */

    mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);

    if (MSM_CAMERA_STATUS_SUCCESS == status) {

    rc = 0;

    }

    }

    pthread_mutex_unlock(&my_obj->msg_lock);

    return rc;

    }

    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_sock.c

    int mm_camera_socket_sendmsg(

    int fd,  //socket fd

    void *msg,

    size_t buf_size,

    int sendfd)

    {

    struct msghdr msgh;

    struct iovec iov[1];

    struct cmsghdr * cmsghp = NULL;

    char control[CMSG_SPACE(sizeof(int))];

    if (msg == NULL) {

    CDBG("%s: msg is NULL", __func__);

    return -1;

    }

    memset(&msgh, 0, sizeof(msgh));

    msgh.msg_name = NULL;

    msgh.msg_namelen = 0;

    iov[0].iov_base = msg;

    iov[0].iov_len = buf_size;

    msgh.msg_iov = iov;

    msgh.msg_iovlen = 1;

    CDBG("%s: iov_len=%llu", __func__,

    (unsigned long long int)iov[0].iov_len);

    msgh.msg_control = NULL;

    msgh.msg_controllen = 0;

    /* if sendfd is valid, we need to pass it through control msg */

    if( sendfd > 0) {

    msgh.msg_control = control;

    msgh.msg_controllen = sizeof(control);

    cmsghp = CMSG_FIRSTHDR(&msgh);

    if (cmsghp != NULL) {

    CDBG("%s: Got ctrl msg pointer", __func__);

    cmsghp->cmsg_level = SOL_SOCKET;

    cmsghp->cmsg_type = SCM_RIGHTS;

    cmsghp->cmsg_len = CMSG_LEN(sizeof(int));

    *((int *)CMSG_DATA(cmsghp)) = sendfd;

    CDBG("%s: cmsg data=%d", __func__, *((int *) CMSG_DATA(cmsghp)));

    } else {

    CDBG("%s: ctrl msg NULL", __func__);

    return -1;

    }

    }

    return sendmsg(fd, &(msgh), 0);//socket发送数据到vendor通知映射共享内存

    }

    refer: ION机制介绍

    http://blog.csdn.net/cosmoslhf/article/details/41209925

    展开全文
  • android8.1和之前的版本有一个很大的不同,那就是8.1以后的版本将hal层和framework... 之前我这边有个模块,在android6.0上时,需要在hal层通过ashmem_create_region来创建一块共享内存。然后将创建的共享内存句柄,...

            android8.1和之前的版本有一个很大的不同,那就是8.1以后的版本将hal层和framework层分隔开来,不在同一个进程,不能直接通信。如果framework层需要和hal层通信,需要用到hidl接口。 

            之前我这边有个模块,在android6.0上时,需要在hal层通过ashmem_create_region来创建一块共享内存。然后将创建的共享内存句柄,通过binder,传送给framework层和app层。在android6.0上,一切都很顺利,framework层通过binder获取到hal层创建的共享内存后,mmap一下,就可以得到这块共享内存,并进行读写。

            后来需要将这个模块移植到8.1上,将代码移过去后,发现之前能正常运行的binder,无法将hal层创建的共享内存fd传给framewrok层。结研究发现,这就是8.1上将hal和framework层分隔开来引起的。需要解决这个问题,只能引进hidl接口了。

            hidl接口中,共享内存是通过IAllocator来创建的,然后再通过hidl_memory接收分配的对象,然后通过mapMemory到本进程中的IMemory对象中。hidl_memory类型会映射到 libhidlbase 中的 hidl_memory 类,该类表示未映射的共享内存。这是要在 HIDL 中共享内存而必须在进程之间传递的对象。使用IAllocator分配内存代码如下:
     

            native_handle_t* mHidlHandle = nullptr;
            hidl_memory      mHidlHeap;
            void*            mHidlHeapMemData;
            sp<IMemory>      mHidlHeapMemory; // munmap happens in ~IMemory()
    
            sp<IAllocator> mAshmemAllocator = IAllocator::getService("ashmem");   
            mAshmemAllocator->allocate(len,
                [&](bool success, const hidl_memory& mem) {
                    if (!success) {
                        ALOGI("allocating ashmem of %zu bytes failed!", len);
                        return;
                    }
                    mHidlHandle = native_handle_clone(mem.handle());
                    mHidlHeap = hidl_memory("ashmem", mHidlHandle, len);
                    mHidlHeapMemory = mapMemory(mHidlHeap);
                    if (mHidlHeapMemory == nullptr) {
                        ALOGE("memory map failed!");
                        native_handle_close(mHidlHandle); // close FD for the shared memory
                        native_handle_delete(mHidlHandle);
                        mHidlHeap = hidl_memory();
                        mHidlHandle = nullptr;
                        return;
                    }        
                    mHidlHeapMemData = mHidlHeapMemory->getPointer(); 
                    fd(mHidlHandle);
                })

            上面演示了怎么去分配一块共享内存,下面再完整的讲一下怎么使用hidl接口来传递共享内存。

            1.)在hardware\interfaces目录下新建一个文件夹my_memory,里面新建一个Android.bp,内容如下 

    
    subdirs = [
        "1.0",
        "1.0/default",
    ]

           再创建一个名为“1.0”的文件夹。里面包含Android.bp、IMy_memory.hal文件,以及default文件夹。其中Android.bp在运行./hardware/interfaces/update-makefiles.sh时会自动生成,运行这条命令时,会同时检查你的hal文件以及对应的实现文件是否符合hidl的接口规范,如果不符合,则会提示你。

            IMy_memory.hal内容如下:

    package android.hardware.my_memory@1.0;
     
    interface IMy_memory
    {
        createMemory()generates(handle memory_ptr);
        getMemory()generates(handle memory_ptr);
        getMemoryFd()generates(uint8_t ret);
        getMemorySize()generates(uint32_t ret);
    };

     

    对应的default下有Android.bp、android.hardware.my_memory@1.0-service.rc、service.cpp、my_memory.h、my_memory.cpp这几个文件。其中Android.bp文件内容如下:

    cc_library_shared {
    name: "android.hardware.my_memory@1.0-impl",
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
    srcs: ["my_memory.cpp"],
    cflags: ["-Werror", "-Wno-unused-parameter"],
    shared_libs: [
    "libhidlbase",
    "libhidltransport",
    "libhardware",
    "liblog",
    "libutils",
    "libcutils",
    "android.hardware.my_memory@1.0",
    "libbinder",
    "android.hidl.allocator@1.0",
    "android.hidl.memory@1.0",
    "libhwbinder",
     "libhidlmemory",
    ], 
    }
     
    cc_binary {
    name: "android.hardware.my_memory@1.0-service",
    init_rc: ["android.hardware.mymemory@1.0-service.rc"],
    defaults: ["hidl_defaults"],
    proprietary: true,
    relative_install_path: "hw",
    srcs: ["service.cpp",
    "my_memory.cpp"],
    cflags: ["-Werror", "-Wno-unused-parameter"],
    shared_libs: [
    "liblog",
    "libhardware",
    "libhidlbase",
    "libhidltransport",
    "libutils",
    "libcutils",
    "android.hardware.my_memory@1.0",
    "libbinder",
    "android.hidl.allocator@1.0",
    "android.hidl.memory@1.0",
    "libhwbinder",
     "libhidlmemory",
    ], 
    }
    

    service.cpp内容如下:

     
     #define LOG_TAG "android.hardware.my_memory@1.0-service"
     
    #include <android/hardware/my_memory/1.0/IMy_memory.h>
    #include <hidl/LegacySupport.h>
    #include <binder/ProcessState.h>
    
    #include "my_memory.h"
    using android::hardware::my_memory::V1_0::IMy_memory;
    using android::hardware::my_memory::V1_0::implementation::my_memory;
    using android::hardware::defaultPassthroughServiceImplementation;
    using android::hardware::configureRpcThreadpool;
    using android::hardware::joinRpcThreadpool;
    using android::sp;
     
     
    int main() {
        android::ProcessState::initWithDriver("/dev/vndbinder");
        return defaultPassthroughServiceImplementation<IMy_memory>("my_memory", /*maxThreads*/ 6);
    }
    
    

    my_memory.h内容如下:

    #ifndef ANDROID_HARDWARE_MY_MEMORY_V1_0_H
    #define ANDROID_HARDWARE_MY_MEMORY_V1_0_H
    #include <android/hardware/my_memory/1.0/IMy_memory.h>
    #include <unordered_map> 
    #include <hidl/Status.h>
    #include <hidl/MQDescriptor.h>
    #include <hidlmemory/mapping.h>
    #include <android/hidl/allocator/1.0/IAllocator.h>
    #include <android/hidl/memory/1.0/IMemory.h>
    #include <hidl/MQDescriptor.h>
    
    namespace android {
    namespace hardware {
    namespace my_memory {
    namespace V1_0 {
    namespace implementation {
    using ::android::hardware::my_memory::V1_0::IMy_memory;
    using ::android::hardware::hidl_array;
    using ::android::hardware::hidl_string;
    using ::android::hardware::hidl_vec;
    using ::android::hardware::Return;
    using ::android::hardware::Void;
    using ::android::sp;
    using ::android::hardware::hidl_memory;
    using ::android::hidl::allocator::V1_0::IAllocator;
    using ::android::hidl::base::V1_0::IBase;
    using ::android::hidl::memory::V1_0::IMemory;
    	
    	
    struct my_memory : public IMy_memory {
    	public:
    		my_memory();
            ~my_memory();        
            Return<void>createMemory(createMemory_cb fd) override;
            Return<uint32_t>getMemorySize()override;  
    	private:
            native_handle_t* mHidlHandle = nullptr;
            sp<IAllocator> mAshmemAllocator = nullptr;
    
            hidl_memory      mHidlHeap;
            void*            mHidlHeapMemData;
            sp<IMemory>      mHidlHeapMemory; // munmap happens in ~IMemory()
            
            int32_t mSize = 0;
    };
    	
    extern "C" IMy_memory* HIDL_FETCH_IMy_memory(const char* name);
    }  // namespace implementation
    }  // namespace V1_0
    }  // namespace led
    }  // namespace hardware
    }  // namespace android
     
    #endif //ANDROID_HARDWARE_MY_MEMORY_V1_0_H
    #define LOG_TAG "my_memory.cpp"
     
    #include <log/log.h>
    #include "my_memory.h"
     
    namespace android {
    namespace hardware {
    namespace my_memory {
    namespace V1_0 {
    namespace implementation {
     
    my_memory::my_memory() {
    	ALOGI("my_memory Init");
    } 
    
    my_memory::~my_memory() {
    	ALOGI("my_memory ~my_memory()");
        if (mHidlHeapMemory != nullptr) {
            mHidlHeapMemData = nullptr;
            mHidlHeapMemory.clear(); // The destructor will trigger munmap
        }
    
        if (mHidlHandle) {
            native_handle_close(mHidlHandle); // close FD for the shared memory
            native_handle_delete(mHidlHandle);
        }    
    }
    
    Return<void> my_memory::createMemory(createMemory_cb fd, int32_t size)
    {
        ALOGI("yovtimestamps_memory::createMemory start");
        int32_t pageSize = getpagesize();
        
        if((mHidlHandle == nullptr) || size > mSize)
        {
            //mHidlHandle不为NULL,且size != mSize,表明已经创建过共享内存,但是现在的内存,比之前的
            //要大,要重新分配。
            if (mHidlHeapMemory != nullptr) {
                mHidlHeapMemData = nullptr;
                mHidlHeapMemory.clear(); // The destructor will trigger munmap
            }
            
            if(mHidlHandle != nullptr)
            {
                ALOGI("new size %d, > old size %d, need reallocate", size, mSize);
                native_handle_close(mHidlHandle); // close FD for the shared memory
                native_handle_delete(mHidlHandle);            
            }
            else
            {
                ALOGI("createMemory, first allocation ");
            }
            if(mAshmemAllocator == nullptr)
            {
                mAshmemAllocator = IAllocator::getService("ashmem");
            }
            if (mAshmemAllocator == nullptr) {
                ALOGI("%s: cannot get ashmemAllocator", __FUNCTION__);
                return Void();
            }    
    
            int32_t len = ((size  + pageSize-1) & ~(pageSize-1));   
            mAshmemAllocator->allocate(len,
                [&](bool success, const hidl_memory& mem) {
                    if (!success) {
                        ALOGI("allocating ashmem of %zu bytes failed!", len);
                        return;
                    }
                    mHidlHandle = native_handle_clone(mem.handle());
                    mHidlHeap = hidl_memory("ashmem", mHidlHandle, len);
                    mHidlHeapMemory = mapMemory(mHidlHeap);
                    if (mHidlHeapMemory == nullptr) {
                        ALOGE("memory map failed!");
                        native_handle_close(mHidlHandle); // close FD for the shared memory
                        native_handle_delete(mHidlHandle);
                        mHidlHeap = hidl_memory();
                        mHidlHandle = nullptr;
                        return;
                    }        
                    mHidlHeapMemData = mHidlHeapMemory->getPointer(); 
    
                    fd(mHidlHandle);
                });
        }
        else
        {
            //如果现在申请的内存,小于等于之前的内存,那么就不用重新分配,直接反回。
            ALOGI("mHidlHandle has already exist");
            fd(mHidlHandle);
        }
        mSize = size;
        return Void();
    }
    
    
    Return<uint32_t> my_memory::getMemorySize()
    {
        return mSize;
    }
    
    IMy_memory* HIDL_FETCH_IMy_memory(const char * /*name*/) {
    	ALOGI("my_memory HIDL_FETCH_IMy_memory ");	
        return new my_memory();
    }
     
    }  // namespace implementation
    }  // namespace V1_0
    }  // namespace led
    }  // namespace hardware
    }  // namespace android

           其中参数“createMemory_cb fd”的类型createMemory_cb,是编译时自动生成的,我们的要传回给framework层的内容是一个native_handle_t型的指针mHidlHandle。native_handle_t这个类型定义在system\core\include\cutils\native_handle.h

    typedef struct native_handle
    {
        int version;        /* sizeof(native_handle_t) */
        int numFds;       /* number of file-descriptors at &data[0] */
        int numInts;      /* number of ints at &data[numFds] */
        int data[0];        /* numFds + numInts ints */
    } native_handle_t;

    其中, data[0]存的就是我们刚刚allocate出来的共享内存的文件句柄,我们需要通过这个类型,在hidl里以回调参数的方式传回给调用方。

    android.hardware.my_memory@1.0-service.rc的内容如下:

    service my_memory_server /vendor/bin/hw/android.hardware.my_memory@1.0-service
        class hal
        user system
        group system 
    

            写好上面的代码,编译完成后会在system/lib下生成android.hardware.my_memory@1.0.so,在vendor/lib/hw下生成android.hardware.my_memory@1.0-impl.so, 在vendor/bin/hw下生成android.hardware.yovtimestamps_memory@1.0-service。

           当然,如果仅仅这样,开机后,我们的android.hardware.my_memory@1.0-service这个服务,不会自动启动,因为我们还没有给它配置selinux权限,注意,这个权限,哪怕是selinux关闭了,也要配置。配置过程如下:

            1、)在prebuilts/api/26.0/public/attributes里新增如下代码:

    attribute hal_my_memory;
    attribute hal_my_memory_client;
    attribute hal_my_memory_server;

            2、)在prebuilts/api/26.0/public/hwservice.te 新增如下代码:

    type hal_my_memory_hwservice, hwservice_manager_type;

            3、)在prebuilts/api/26.0/public/下新增hal_my_memory.te文件,内容如下:

    # HwBinder IPC from client to server, and callbacks
    binder_call(hal_my_memory_client, hal_my_memory_server)
    binder_call(hal_my_memory_server, hal_my_memory_client)
    
    add_hwservice(hal_my_memory_server, hal_my_memory_hwservice)
    allow hal_my_memory_client hal_my_memory_hwservice:hwservice_manager find;

     

            4、)在private/compat/26.0/26.0.ignore.cil新增一行代码

        hal_my_memory_hwservice))

     

            5、)在private/hwservice_contexts里新加一行代码:

    android.hardware.my_memory::IMy_memory             u:object_r:hal_my_memory_hwservice:s0

           6、)在public/attributes里新增几行代码:

    attribute hal_my_memory;
    attribute hal_my_memory_client;
    attribute hal_my_memory_server;

            7、)在public里新增一个文件hal_my_memory.te

    # HwBinder IPC from client to server, and callbacks
    binder_call(hal_my_memory_client, hal_my_memory_server)
    binder_call(hal_my_memory_server, hal_my_memory_client)
    
    add_hwservice(hal_my_memory_server, hal_my_memory_hwservice)
    allow hal_my_memory_client hal_my_memory_hwservice:hwservice_manager find;

            8、)在public/hwservice.te里新增一行代码

    type hal_my_memory_hwservice, hwservice_manager_type;

            9、)在vendor/file_contexts里新增一行代码:

    (vendor|system/vendor)/bin/hw/android\.hardware\.my_memory@1\.0-service          u:object_r:hal_my_memory_default_exec:s0

            10、)在vendor下新增一文件hal_my_memory_default.te

    type hal_my_memory_default, domain;
    hal_server_domain(hal_my_memory_default, hal_my_memory)
    
    type hal_my_memory_default_exec, exec_type, vendor_file_type, file_type;
    init_daemon_domain(hal_my_memory_default)

            上面权限加上后,开机时,就会自动启动我们在android.hardware.my_memory@1.0-service.rc里定义的服务my_memory_server了,它会调用到我们的hidl接口HIDL_FETCH_IMy_memory.

             下面再讲下在hal层,是怎么调用到我们接口去创建共享内存的。hal层的调用代码如下:

    sp<IMy_memory> mMy_memoryService = NULL;
    size_t mPageSize = 0;
    hidl_memory      mHidlHeap; 
    sp<::android::hidl::memory::V1_0::IMemory>      mHidlHeapMemory; 
    void* mHidlHeapMemData = NULL;    
        
    if(mMy_memoryService == NULL)
    {
        mMy_memoryService = IMy_memory::getService("my_memory");
    }
    if(mMy_memoryService != NULL)
    {
        mTimestamps_memoryService->createMemory([&](hidl_handle handle, size){
            mHidlHeap = hidl_memory("ashmem", handle, size);
            mHidlHeapMemory = mapMemory(mHidlHeap);
            if (mHidlHeapMemory == nullptr) {
                ALOGE("memory map failed!");
                native_handle_close(handle); // close FD for the shared memory
                native_handle_delete(handle);
                mHidlHeap = hidl_memory();
                handle = nullptr;
                return NO_ERROR;
            }
            mHidlHeapMemData = mHidlHeapMemory->getPointer();
            return NO_ERROR;
        });
        ALOGI("DisplayClient::init 8");
    }

           在framework层获取共享内存的句柄的代码如下:

    sp<IMy_memory> mClient = IMy_memory::getService("my_memory");
    if(mClient != NULL)
    {
        mClient->getMemory([&](hidl_handle handle){
            //在这里必须dup一下,因为handle->data[0]这个值,出了这个函数的作用域,就被释放掉了.
            //mFD的值是一个无效的文件句柄. 必须先dup一下,将它复制出来.这样才可以在出了这个函
            //数的作用域后,仍可以使用
            mFD = dup(handle->data[0]);   
            return NO_ERROR;
        });
    }
    else
    {
        ALOGI("AutotimestampService::get IYovtimestamps_memory == NULL\n");    
    }

            好了,到这里就讲完了,如何从hal层传共享内存到framework层。

    展开全文
  •  open camera过程中有些初始化设置参数需要从vendor层获取,而vendor与hal隶属于不同进程,通过ION机制设置共享内存来实现不同进程间数据共享,下面简要介绍流程: 在初始化过程中hal层会通过socket将消息发送至...

    研究导向:

         open camera过程中有些初始化设置参数需要从vendor层获取,而vendor与hal隶属于不同进程,通过ION机制设置共享内存来实现不同进程间数据共享,下面简要介绍流程:

    在初始化过程中hal层会通过socket将消息发送至vendor层-通知vendor map共享内存。

    ION初始化过程:

       vim hardware/qcom/camera/QCamera2/HAL/QCamera2HWI.cpp
    int QCamera2HardwareInterface::openCamera()
    {
        ……
        if (NULL == gCamCapability[mCameraId]) {
            if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) {  //会初始化ION
                ......
            }
        }
        mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
                                                  camEvtHandle,
                                                  (void *) this);
        ……
        pthread_mutex_lock(&m_parm_lock);/* MM-MC-FixString8HeapCorrupt-00+ */
         //初始化m_pCapability-从vendor层拿到的camera相关初始化数据
        mParameters.init(gCamCapability[mCameraId], mCameraHandle, this, this);
        pthread_mutex_unlock(&m_parm_lock);/* MM-MC-FixString8HeapCorrupt-00+ */
        mParameters.m_parm_lock_ptr = &m_parm_lock;/* MM-MC-FixString8HeapCorrupt-00+ */
        ALOGI("openCamera: m_parm_lock_ptr = 0x%x", mParameters.m_parm_lock_ptr);/* MM-MC-FixString8HeapCorrupt-00+ */
        mCameraOpened = true;
        gCameraOpened = true;/* MM-CL-CTS-testMultiCameraRelease-00+ */
    #ifdef USE_ARCSOFT_FEATURE
        if ((NULL != mArcSoft_Feature)&&(mCameraId == 0))/* MM-MC-FixOpenCameraCrash-00+ */
            mArcSoft_Feature->imx214_module_source = gCamCapability[0]->fih_imx214_module_source;//MM-YW-Get module source for HAL-00
    #endif
        return NO_ERROR;
    }
    int QCamera2HardwareInterface::initCapabilities(uint32_t cameraId,
            mm_camera_vtbl_t *cameraHandle)
    {
        ATRACE_CALL();
        int rc = NO_ERROR;
        QCameraHeapMemory *capabilityHeap = NULL;
        /* Allocate memory for capability buffer */
        capabilityHeap = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE);
        rc = capabilityHeap->allocate(1, sizeof(cam_capability_t)); //1、设置ION共享内存
        ......
        /* Map memory for capability buffer */
    memset(DATA_PTR(capabilityHeap,0), 0, sizeof(cam_capability_t));
    //2、通过socket通知vendor映射共享内存用于进程间通信
        rc = cameraHandle->ops->map_buf(cameraHandle->camera_handle, 
                                    CAM_MAPPING_BUF_TYPE_CAPABILITY,
                                    capabilityHeap->getFd(0),
                                    sizeof(cam_capability_t));
        if(rc < 0) {
            ALOGE("%s: failed to map capability buffer", __func__);
            goto map_failed;
        }
        /* Query Capability */
        rc = cameraHandle->ops->query_capability(cameraHandle->camera_handle);
        if(rc < 0) {
            ALOGE("%s: failed to query capability",__func__);
            goto query_failed;
        }
        gCamCapability[cameraId] = (cam_capability_t *)malloc(sizeof(cam_capability_t));
        if (!gCamCapability[cameraId]) {
            ALOGE("%s: out of memory", __func__);
            goto query_failed;
        }
        memcpy(gCamCapability[cameraId], DATA_PTR(capabilityHeap,0),
                                            sizeof(cam_capability_t));
        //copy the preview sizes and video sizes lists because they
        //might be changed later
        copyList(gCamCapability[cameraId]->preview_sizes_tbl, savedSizes[cameraId].all_preview_sizes,
                 gCamCapability[cameraId]->preview_sizes_tbl_cnt);
        savedSizes[cameraId].all_preview_sizes_cnt = gCamCapability[cameraId]->preview_sizes_tbl_cnt;
        copyList(gCamCapability[cameraId]->video_sizes_tbl, savedSizes[cameraId].all_video_sizes,
                 gCamCapability[cameraId]->video_sizes_tbl_cnt);
        savedSizes[cameraId].all_video_sizes_cnt = gCamCapability[cameraId]->video_sizes_tbl_cnt;
        rc = NO_ERROR;
    query_failed:
        cameraHandle->ops->unmap_buf(cameraHandle->camera_handle,
                                CAM_MAPPING_BUF_TYPE_CAPABILITY);
    ……
    }
    1、设置ION共享内存:
    vim hardware/qcom/camera/QCamera2/HAL/QCameraMem.cpp
    int QCameraHeapMemory::allocate(uint8_t count, size_t size)
    {
        traceLogAllocStart(size, count, "HeapMemsize");
        unsigned int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
        int rc = alloc(count, size, heap_mask);  //主要填充mMemInfo
        if (rc < 0)
            return rc;
        for (int i = 0; i < count; i ++) {
            void *vaddr = mmap(NULL,   //映射共享内存
                        mMemInfo[i].size,
                        PROT_READ | PROT_WRITE,
                        MAP_SHARED,
                        mMemInfo[i].fd, 0);
            if (vaddr == MAP_FAILED) {
                for (int j = i-1; j >= 0; j --) {
                    munmap(mPtr[j], mMemInfo[j].size);
                    mPtr[j] = NULL;
                    deallocOneBuffer(mMemInfo[j]);
                }
                return NO_MEMORY;
            } else
                mPtr[i] = vaddr;
        }
        if (rc == 0)
            mBufferCount = count;
        traceLogAllocEnd((size * count));
        return OK;
    }
    int QCameraMemory::alloc(int count, size_t size, unsigned int heap_id)
    {
        ……s
        int new_bufCnt = mBufferCount + count;
        traceLogAllocStart(size, count, "Memsize");
        ……
        for (int i = mBufferCount; i < new_bufCnt; i ++) {
            if ( NULL == mMemoryPool ) {
                CDBG_HIGH("%s : No memory pool available and So allocate new buffer", __func__);
                rc = allocOneBuffer(mMemInfo[i], heap_id, size, m_bCached);
                if (rc < 0) {
                    ALOGE("%s: AllocateIonMemory failed", __func__);
                    for (int j = i-1; j >= 0; j--)
                        deallocOneBuffer(mMemInfo[j]);
                    break;
                }
            } else {
                rc = mMemoryPool->allocateBuffer(mMemInfo[i],
                                                 heap_id,
                                                 size,
                                                 m_bCached,
                                                 mStreamType);
                if (rc < 0) {
                    ALOGE("%s: Memory pool allocation failed", __func__);
                    for (int j = i-1; j >= 0; j--)
                        mMemoryPool->releaseBuffer(mMemInfo[j],
                                                   mStreamType);
                    break;
                }
            }
        }
        traceLogAllocEnd (size * (size_t)count);
        return rc;
    }
    int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo,
            unsigned int heap_id, size_t size, bool cached)
    {
        int rc = OK;
        struct ion_handle_data handle_data;
        struct ion_allocation_data alloc;
        struct ion_fd_data ion_info_fd;
        int main_ion_fd = 0;
        main_ion_fd = open("/dev/ion", O_RDONLY);
        if (main_ion_fd < 0) {
            ALOGE("Ion dev open failed: %s\n", strerror(errno));
            goto ION_OPEN_FAILED;
        }
        memset(&alloc, 0, sizeof(alloc));
        memset(&ion_info_fd, 0, sizeof(ion_info_fd));/* MM-MC-ModifyIonFdInitFlow-00+ */
        
        alloc.len = size;
        /* to make it page size aligned */
        alloc.len = (alloc.len + 4095U) & (~4095U);
        alloc.align = 4096;
        if (cached) {
            alloc.flags = ION_FLAG_CACHED;
        }
        alloc.heap_id_mask = heap_id;
        rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
        if (rc < 0) {
            ALOGE("ION allocation failed: %s\n", strerror(errno));
            goto ION_ALLOC_FAILED;
        }
        //memset(&ion_info_fd, 0, sizeof(ion_info_fd));/* MM-MC-ModifyIonFdInitFlow-00- */
        ion_info_fd.handle = alloc.handle;
        rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
        if (rc < 0) {
            ALOGE("ION map failed %s\n", strerror(errno));
            goto ION_MAP_FAILED;
        }
        memInfo.main_ion_fd = main_ion_fd;
        memInfo.fd = ion_info_fd.fd;
        memInfo.handle = ion_info_fd.handle;
        memInfo.size = alloc.len;
        memInfo.cached = cached;
        memInfo.heap_id = heap_id;
        CDBG_HIGH("%s : ION buffer %lx with size %d allocated",
                __func__, (unsigned long)memInfo.handle, memInfo.size);
        return OK;
    ION_MAP_FAILED:
        memset(&handle_data, 0, sizeof(handle_data));
        handle_data.handle = ion_info_fd.handle;
        ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
    ION_ALLOC_FAILED:
        close(main_ion_fd);
    ION_OPEN_FAILED:
        return NO_MEMORY;
    }
    2、通过socket通知vendor映射相应共享内存用于进程间通信:
    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
    static int32_t mm_camera_intf_map_buf(uint32_t camera_handle,
                                          uint8_t buf_type,
                                          int fd,
                                          size_t size)
    {
        int32_t rc = -1;
        mm_camera_obj_t * my_obj = NULL;
        pthread_mutex_lock(&g_intf_lock);
        my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
        if(my_obj) {
            pthread_mutex_lock(&my_obj->cam_lock);
            pthread_mutex_unlock(&g_intf_lock);
            rc = mm_camera_map_buf(my_obj, buf_type, fd, size);
        } else {
            pthread_mutex_unlock(&g_intf_lock);
        }
        return rc;
    }
    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c
    int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
                              uint8_t buf_type,
                              int fd,
                              size_t size)
    {
        int32_t rc = 0;
        cam_sock_packet_t packet;
        memset(&packet, 0, sizeof(cam_sock_packet_t));
        packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
        packet.payload.buf_map.type = buf_type;
        packet.payload.buf_map.fd = fd;
        packet.payload.buf_map.size = size;
        rc = mm_camera_util_sendmsg(my_obj,
                                    &packet,
                                    sizeof(cam_sock_packet_t),
                                    fd);
        pthread_mutex_unlock(&my_obj->cam_lock);
        return rc;
    }
    int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
                                   void *msg,
                                   size_t buf_size,
                                   int sendfd)
    {
        int32_t rc = -1;
        uint32_t status;
        /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/
        pthread_mutex_lock(&my_obj->msg_lock);
        if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {
            /* wait for event that mapping/unmapping is done */
            mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
            if (MSM_CAMERA_STATUS_SUCCESS == status) {
                rc = 0;
            }
        }
        pthread_mutex_unlock(&my_obj->msg_lock);
        return rc;
    }
    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_sock.c
    int mm_camera_socket_sendmsg(
      int fd,  //socket fd
      void *msg,
      size_t buf_size,
      int sendfd)
    {
        struct msghdr msgh;
        struct iovec iov[1];
        struct cmsghdr * cmsghp = NULL;
        char control[CMSG_SPACE(sizeof(int))];
        if (msg == NULL) {
          CDBG("%s: msg is NULL", __func__);
          return -1;
        }
        memset(&msgh, 0, sizeof(msgh));
        msgh.msg_name = NULL;
        msgh.msg_namelen = 0;
        iov[0].iov_base = msg;
        iov[0].iov_len = buf_size;
        msgh.msg_iov = iov;
        msgh.msg_iovlen = 1;
        CDBG("%s: iov_len=%llu", __func__,
                (unsigned long long int)iov[0].iov_len);
        msgh.msg_control = NULL;
        msgh.msg_controllen = 0;
        /* if sendfd is valid, we need to pass it through control msg */
        if( sendfd > 0) {
          msgh.msg_control = control;
          msgh.msg_controllen = sizeof(control);
          cmsghp = CMSG_FIRSTHDR(&msgh);
          if (cmsghp != NULL) {
            CDBG("%s: Got ctrl msg pointer", __func__);
            cmsghp->cmsg_level = SOL_SOCKET;
            cmsghp->cmsg_type = SCM_RIGHTS;
            cmsghp->cmsg_len = CMSG_LEN(sizeof(int));
            *((int *)CMSG_DATA(cmsghp)) = sendfd;
            CDBG("%s: cmsg data=%d", __func__, *((int *) CMSG_DATA(cmsghp)));
          } else {
            CDBG("%s: ctrl msg NULL", __func__);
            return -1;
          }
        }
        return sendmsg(fd, &(msgh), 0);  //socket发送数据到vendor通知映射共享内存
    }

    refer: ION机制介绍

    http://blog.csdn.net/cosmoslhf/article/details/41209925

    展开全文
  • 抄的 Hal Vendor 共享

    2017-12-13 13:14:12
     open camera过程中有些初始化设置参数需要从vendor层获取,而vendor与hal隶属于不同进程,通过ION机制设置共享内存来实现不同进程间数据共享,下面简要介绍流程: 在初始化过程中hal层会通过socket将消息发送至...

    研究导向:

         open camera过程中有些初始化设置参数需要从vendor层获取,而vendor与hal隶属于不同进程,通过ION机制设置共享内存来实现不同进程间数据共享,下面简要介绍流程:

    在初始化过程中hal层会通过socket将消息发送至vendor层-通知vendor map共享内存。

    ION初始化过程:

       vim hardware/qcom/camera/QCamera2/HAL/QCamera2HWI.cpp
    int QCamera2HardwareInterface::openCamera()
    {
        ……
        if (NULL == gCamCapability[mCameraId]) {
            if(NO_ERROR != initCapabilities(mCameraId,mCameraHandle)) {  //会初始化ION
                ......
            }
        }
        mCameraHandle->ops->register_event_notify(mCameraHandle->camera_handle,
                                                  camEvtHandle,
                                                  (void *) this);
        ……
        pthread_mutex_lock(&m_parm_lock);/* MM-MC-FixString8HeapCorrupt-00+ */
         //初始化m_pCapability-从vendor层拿到的camera相关初始化数据
        mParameters.init(gCamCapability[mCameraId], mCameraHandle, this, this);
        pthread_mutex_unlock(&m_parm_lock);/* MM-MC-FixString8HeapCorrupt-00+ */
        mParameters.m_parm_lock_ptr = &m_parm_lock;/* MM-MC-FixString8HeapCorrupt-00+ */
        ALOGI("openCamera: m_parm_lock_ptr = 0x%x", mParameters.m_parm_lock_ptr);/* MM-MC-FixString8HeapCorrupt-00+ */
        mCameraOpened = true;
        gCameraOpened = true;/* MM-CL-CTS-testMultiCameraRelease-00+ */
    #ifdef USE_ARCSOFT_FEATURE
        if ((NULL != mArcSoft_Feature)&&(mCameraId == 0))/* MM-MC-FixOpenCameraCrash-00+ */
            mArcSoft_Feature->imx214_module_source = gCamCapability[0]->fih_imx214_module_source;//MM-YW-Get module source for HAL-00
    #endif
        return NO_ERROR;
    }
    int QCamera2HardwareInterface::initCapabilities(uint32_t cameraId,
            mm_camera_vtbl_t *cameraHandle)
    {
        ATRACE_CALL();
        int rc = NO_ERROR;
        QCameraHeapMemory *capabilityHeap = NULL;
        /* Allocate memory for capability buffer */
        capabilityHeap = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE);
        rc = capabilityHeap->allocate(1, sizeof(cam_capability_t)); //1、设置ION共享内存
        ......
        /* Map memory for capability buffer */
    memset(DATA_PTR(capabilityHeap,0), 0, sizeof(cam_capability_t));
    //2、通过socket通知vendor映射共享内存用于进程间通信
        rc = cameraHandle->ops->map_buf(cameraHandle->camera_handle, 
                                    CAM_MAPPING_BUF_TYPE_CAPABILITY,
                                    capabilityHeap->getFd(0),
                                    sizeof(cam_capability_t));
        if(rc < 0) {
            ALOGE("%s: failed to map capability buffer", __func__);
            goto map_failed;
        }
        /* Query Capability */
        rc = cameraHandle->ops->query_capability(cameraHandle->camera_handle);
        if(rc < 0) {
            ALOGE("%s: failed to query capability",__func__);
            goto query_failed;
        }
        gCamCapability[cameraId] = (cam_capability_t *)malloc(sizeof(cam_capability_t));
        if (!gCamCapability[cameraId]) {
            ALOGE("%s: out of memory", __func__);
            goto query_failed;
        }
        memcpy(gCamCapability[cameraId], DATA_PTR(capabilityHeap,0),
                                            sizeof(cam_capability_t));
        //copy the preview sizes and video sizes lists because they
        //might be changed later
        copyList(gCamCapability[cameraId]->preview_sizes_tbl, savedSizes[cameraId].all_preview_sizes,
                 gCamCapability[cameraId]->preview_sizes_tbl_cnt);
        savedSizes[cameraId].all_preview_sizes_cnt = gCamCapability[cameraId]->preview_sizes_tbl_cnt;
        copyList(gCamCapability[cameraId]->video_sizes_tbl, savedSizes[cameraId].all_video_sizes,
                 gCamCapability[cameraId]->video_sizes_tbl_cnt);
        savedSizes[cameraId].all_video_sizes_cnt = gCamCapability[cameraId]->video_sizes_tbl_cnt;
        rc = NO_ERROR;
    query_failed:
        cameraHandle->ops->unmap_buf(cameraHandle->camera_handle,
                                CAM_MAPPING_BUF_TYPE_CAPABILITY);
    ……
    }
    1、设置ION共享内存:
    vim hardware/qcom/camera/QCamera2/HAL/QCameraMem.cpp
    int QCameraHeapMemory::allocate(uint8_t count, size_t size)
    {
        traceLogAllocStart(size, count, "HeapMemsize");
        unsigned int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
        int rc = alloc(count, size, heap_mask);  //主要填充mMemInfo
        if (rc < 0)
            return rc;
        for (int i = 0; i < count; i ++) {
            void *vaddr = mmap(NULL,   //映射共享内存
                        mMemInfo[i].size,
                        PROT_READ | PROT_WRITE,
                        MAP_SHARED,
                        mMemInfo[i].fd, 0);
            if (vaddr == MAP_FAILED) {
                for (int j = i-1; j >= 0; j --) {
                    munmap(mPtr[j], mMemInfo[j].size);
                    mPtr[j] = NULL;
                    deallocOneBuffer(mMemInfo[j]);
                }
                return NO_MEMORY;
            } else
                mPtr[i] = vaddr;
        }
        if (rc == 0)
            mBufferCount = count;
        traceLogAllocEnd((size * count));
        return OK;
    }
    int QCameraMemory::alloc(int count, size_t size, unsigned int heap_id)
    {
        ……s
        int new_bufCnt = mBufferCount + count;
        traceLogAllocStart(size, count, "Memsize");
        ……
        for (int i = mBufferCount; i < new_bufCnt; i ++) {
            if ( NULL == mMemoryPool ) {
                CDBG_HIGH("%s : No memory pool available and So allocate new buffer", __func__);
                rc = allocOneBuffer(mMemInfo[i], heap_id, size, m_bCached);
                if (rc < 0) {
                    ALOGE("%s: AllocateIonMemory failed", __func__);
                    for (int j = i-1; j >= 0; j--)
                        deallocOneBuffer(mMemInfo[j]);
                    break;
                }
            } else {
                rc = mMemoryPool->allocateBuffer(mMemInfo[i],
                                                 heap_id,
                                                 size,
                                                 m_bCached,
                                                 mStreamType);
                if (rc < 0) {
                    ALOGE("%s: Memory pool allocation failed", __func__);
                    for (int j = i-1; j >= 0; j--)
                        mMemoryPool->releaseBuffer(mMemInfo[j],
                                                   mStreamType);
                    break;
                }
            }
        }
        traceLogAllocEnd (size * (size_t)count);
        return rc;
    }
    int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo,
            unsigned int heap_id, size_t size, bool cached)
    {
        int rc = OK;
        struct ion_handle_data handle_data;
        struct ion_allocation_data alloc;
        struct ion_fd_data ion_info_fd;
        int main_ion_fd = 0;
        main_ion_fd = open("/dev/ion", O_RDONLY);
        if (main_ion_fd < 0) {
            ALOGE("Ion dev open failed: %s\n", strerror(errno));
            goto ION_OPEN_FAILED;
        }
        memset(&alloc, 0, sizeof(alloc));
        memset(&ion_info_fd, 0, sizeof(ion_info_fd));/* MM-MC-ModifyIonFdInitFlow-00+ */
        
        alloc.len = size;
        /* to make it page size aligned */
        alloc.len = (alloc.len + 4095U) & (~4095U);
        alloc.align = 4096;
        if (cached) {
            alloc.flags = ION_FLAG_CACHED;
        }
        alloc.heap_id_mask = heap_id;
        rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
        if (rc < 0) {
            ALOGE("ION allocation failed: %s\n", strerror(errno));
            goto ION_ALLOC_FAILED;
        }
        //memset(&ion_info_fd, 0, sizeof(ion_info_fd));/* MM-MC-ModifyIonFdInitFlow-00- */
        ion_info_fd.handle = alloc.handle;
        rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
        if (rc < 0) {
            ALOGE("ION map failed %s\n", strerror(errno));
            goto ION_MAP_FAILED;
        }
        memInfo.main_ion_fd = main_ion_fd;
        memInfo.fd = ion_info_fd.fd;
        memInfo.handle = ion_info_fd.handle;
        memInfo.size = alloc.len;
        memInfo.cached = cached;
        memInfo.heap_id = heap_id;
        CDBG_HIGH("%s : ION buffer %lx with size %d allocated",
                __func__, (unsigned long)memInfo.handle, memInfo.size);
        return OK;
    ION_MAP_FAILED:
        memset(&handle_data, 0, sizeof(handle_data));
        handle_data.handle = ion_info_fd.handle;
        ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
    ION_ALLOC_FAILED:
        close(main_ion_fd);
    ION_OPEN_FAILED:
        return NO_MEMORY;
    }
    2、通过socket通知vendor映射相应共享内存用于进程间通信:
    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
    static int32_t mm_camera_intf_map_buf(uint32_t camera_handle,
                                          uint8_t buf_type,
                                          int fd,
                                          size_t size)
    {
        int32_t rc = -1;
        mm_camera_obj_t * my_obj = NULL;
        pthread_mutex_lock(&g_intf_lock);
        my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
        if(my_obj) {
            pthread_mutex_lock(&my_obj->cam_lock);
            pthread_mutex_unlock(&g_intf_lock);
            rc = mm_camera_map_buf(my_obj, buf_type, fd, size);
        } else {
            pthread_mutex_unlock(&g_intf_lock);
        }
        return rc;
    }
    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c
    int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
                              uint8_t buf_type,
                              int fd,
                              size_t size)
    {
        int32_t rc = 0;
        cam_sock_packet_t packet;
        memset(&packet, 0, sizeof(cam_sock_packet_t));
        packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
        packet.payload.buf_map.type = buf_type;
        packet.payload.buf_map.fd = fd;
        packet.payload.buf_map.size = size;
        rc = mm_camera_util_sendmsg(my_obj,
                                    &packet,
                                    sizeof(cam_sock_packet_t),
                                    fd);
        pthread_mutex_unlock(&my_obj->cam_lock);
        return rc;
    }
    int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
                                   void *msg,
                                   size_t buf_size,
                                   int sendfd)
    {
        int32_t rc = -1;
        uint32_t status;
        /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/
        pthread_mutex_lock(&my_obj->msg_lock);
        if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {
            /* wait for event that mapping/unmapping is done */
            mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
            if (MSM_CAMERA_STATUS_SUCCESS == status) {
                rc = 0;
            }
        }
        pthread_mutex_unlock(&my_obj->msg_lock);
        return rc;
    }
    vim hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_sock.c
    int mm_camera_socket_sendmsg(
      int fd,  //socket fd
      void *msg,
      size_t buf_size,
      int sendfd)
    {
        struct msghdr msgh;
        struct iovec iov[1];
        struct cmsghdr * cmsghp = NULL;
        char control[CMSG_SPACE(sizeof(int))];
        if (msg == NULL) {
          CDBG("%s: msg is NULL", __func__);
          return -1;
        }
        memset(&msgh, 0, sizeof(msgh));
        msgh.msg_name = NULL;
        msgh.msg_namelen = 0;
        iov[0].iov_base = msg;
        iov[0].iov_len = buf_size;
        msgh.msg_iov = iov;
        msgh.msg_iovlen = 1;
        CDBG("%s: iov_len=%llu", __func__,
                (unsigned long long int)iov[0].iov_len);
        msgh.msg_control = NULL;
        msgh.msg_controllen = 0;
        /* if sendfd is valid, we need to pass it through control msg */
        if( sendfd > 0) {
          msgh.msg_control = control;
          msgh.msg_controllen = sizeof(control);
          cmsghp = CMSG_FIRSTHDR(&msgh);
          if (cmsghp != NULL) {
            CDBG("%s: Got ctrl msg pointer", __func__);
            cmsghp->cmsg_level = SOL_SOCKET;
            cmsghp->cmsg_type = SCM_RIGHTS;
            cmsghp->cmsg_len = CMSG_LEN(sizeof(int));
            *((int *)CMSG_DATA(cmsghp)) = sendfd;
            CDBG("%s: cmsg data=%d", __func__, *((int *) CMSG_DATA(cmsghp)));
          } else {
            CDBG("%s: ctrl msg NULL", __func__);
            return -1;
          }
        }
        return sendmsg(fd, &(msgh), 0);  //socket发送数据到vendor通知映射共享内存
    }

    refer: ION机制介绍

    http://blog.csdn.net/cosmoslhf/article/details/41209925

    展开全文
  • 安卓共享内存

    千次阅读 2020-05-19 19:34:36
    在Android平台上,提供了一种共享内存的机制——Ashmem。该机制内部其实复用了Linux的共享内存机制。Ashmem机制使用linux的mmap系统调用,可以将同一段物理内存映射到不同进程各自的虚拟地址空间,从而实现高效的...
  •  //打开和共享内存驱动  fd = open("/dev/map",O_RDWR);  if (fd )  {  return FALSE;  }    comAddr = (unsigned long*)mmap(NULL, sizeof(unsigned long), PROT_READ | PROT_WRITE | PROT_EXEC, ...
  • Android C++ 共享内存MemoryHeapBase实现IPC进程通信实际案列,SensorService
  • Android 进程间通信之匿名共享内存Ashmem源码分析
  • 将读写锁和读写锁的属性以及一个用于存储共享内存的地址的int型变量三者封装成一个struct结构 将这个结构体放到共享内存中,以及将读写锁的属性设置成全局性质,然后使用这个属性初始化锁,以及将锁的地址关联到...
  • Kmdtut 9---共享内存

    2009-08-01 17:07:00
    共享内存董岩 译 9.1 SharingMemory驱动程序源代码9.1.1 DriverEntry函数9.1.2 DispatchControl函数9.1.3 Memory Descriptor List9.1.4 Cleanup函数9.2 SharingMemory应用程序源代码 源代码:KmdKit/examples/basic...
  • #include <asm/arch/sep4020_hal.h> #define DRIVE_MAJOR 165 #define DRIVE_NAME "Test drv" typedef struct { dev_t dev_num ; struct cdev cdev ; }code_dev ; static code_dev test_dev ; ...
  • kmd--9共享内存(Share memory)

    千次阅读 2008-04-17 18:25:00
    在前一个例子SharedSection中,我们共享内存区通讯。这个驱动紧紧关联到用户模式进程的地址空间,也就是驱动所用的虚拟地址在进程空间地址中。这个例子中我们用的这个方法,没有这个缺点,对于驱动来说这个方法更...
  • 代码 #include #include #include #include #include #include #include #include #include #include #include /** * 返回一片共享内存标识符,用于后续获取该共享内存,以及销毁该共享内存 * file_name * md5 */ ...
  • ByteBuffer内存共享分为两种:1、java栈内存共享 2、native堆申请内存。 我这里使用的是第二种方式,也即DirectByteBuffer。第一种,我的理解是java层,不同线程间方便 内存共享。由于native和java的内存不在 一个...
  • HAL学习笔记

    2018-10-22 19:39:48
    一、HAL架构 HAL(硬件抽象层,Hardware Abstraction Layer)是为了保护一些硬件提供商的知识产权而提出的,是为了避免Linux的GPL束缚。把控制硬件的动作都放到了HAL中。 新架构、调整为 HAL stub 的观念 主要包含...
  • STM32 之 HAL

    万次阅读 多人点赞 2019-05-12 11:27:08
    一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配置寄存器进行开发。网上关于标准库、HAL库的描述相信是数不胜数。可是一个对于很多刚入门的朋友还是没法很直观的去真正了解这些不同开发发方式彼此之间的...
  • Android HAL概述

    2017-09-26 03:56:55
    Android HAL(Hardware Abstract Layer)硬件抽象层,从字面意思可以看出是对硬件设备的抽象和封装,为Android在不同硬件设备提供统一的访问接口。HAL处于Android framework和Linux kernel driver之间,HAL存在的意义...
  • 从 Android10 开始,camera 系统加入了一个可选地 buffer 管理方式,可以在 Vendor HAL 这边灵活使用这个选项进行 buffer 管理,以此达到减少 buffer 使用峰值,改变 request 执行速度等优点。具体的来说就是对于 ...
  • Android HAL架构

    千次阅读 2018-01-17 18:09:51
    现有HAL架构由Patrick Brady (Google) 在2008 Google I/O演讲中提出的。Android HAL模块实现- https://my.oschina.net/haomcu/blog/473919> HAL是为了隔离Android Framework和Linux内核;内核空间和用户空间。...
  • HAL(hardware abstract layer)是位于操作系统与硬件之间的接口层,目的在于硬件抽象化。它存在于linux的应用层,它在Android系统中的位置是:向下连接驱动,向上给JNI提供接口。 源码的位置: msm8x12\hardware\...
  • Android Camera HAL3-metadata

    千次阅读 2020-03-28 11:31:47
    Metadata 是整个 Android camera 中类似于高楼大厦中的管道系统一样,贯穿了整个 Camera 的 Framework 和 vendor HAL,Metadata 里面几乎包含了所有的控制、参数、返回值等等,总线型的设计使得这个玩意儿承担的任务...
  • HAL dlopen dlsym

    2013-03-01 00:23:38
    在读HAL相关源码的时候发现这两个函数  简而言之,共享对象通过dlopen动态打开动态库的加载完成后,返回一个句柄,通过dlsym定位到你需要执行的函数指针然后可以在程序中使用   dlopen -- open a dynamically ...
  • Android HAL Android Hal 是用来隔离linux内核和Android用户空间的一个中间库,它主要是为了让一些硬件厂商不用根据linux内核的gpl协议放出全部的linux驱动代码。有了hal硬件厂商就可以只在内核驱动中实现基本的...
  • android camera HAL

    千次阅读 2012-11-21 18:20:12
    一 编译HAL 1 修改BoardConfig.mk device/wolf/smdk6410/BoardConfig.mk USE_CAMERA_STUB := false hardware建立Camera HAL目录 hardware/wolf/libcamera CannedJpeg.h Ov965xCamera.cpp Ov965...
  • HAL库文件结构: HAL驱动文件: 外设驱动API文件和头文件:包含了常见主要的通用API,其中ppp表示外设名称,如adc、usart、gpio、irda等; stm32f0xx_hal_ppp.c stm32f0xx_hal_ppp.h 外设驱动扩展API文件...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,822
精华内容 1,928
关键字:

hal共享内存