QCameraMem.cpp revision 3de90b6340b8c7dedb86a220f86bc43d372d668e
1/* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#define LOG_TAG "QCameraHWI_Mem"
31
32#include <string.h>
33#include <fcntl.h>
34#include <sys/mman.h>
35#include <utils/Log.h>
36#include <utils/Errors.h>
37#include <genlock.h>
38#include <gralloc_priv.h>
39#include <QComOMXMetadata.h>
40#include "QCameraMem.h"
41
42extern "C" {
43#include <mm_camera_interface.h>
44}
45
46using namespace android;
47
48namespace qcamera {
49
50// QCaemra2Memory base class
51
52QCameraMemory::QCameraMemory()
53{
54    mBufferCount = 0;
55    for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
56        mMemInfo[i].fd = 0;
57        mMemInfo[i].main_ion_fd = 0;
58        mMemInfo[i].handle = NULL;
59        mMemInfo[i].size = 0;
60    }
61}
62
63QCameraMemory::~QCameraMemory()
64{
65}
66
67int QCameraMemory::cacheOpsInternal(int index, unsigned int cmd, void *vaddr)
68{
69    struct ion_flush_data cache_inv_data;
70    struct ion_custom_data custom_data;
71    int ret = OK;
72
73    if (index >= mBufferCount) {
74        ALOGE("%s: index %d out of bound [0, %d)", __func__, index, mBufferCount);
75        return BAD_INDEX;
76    }
77
78    memset(&cache_inv_data, 0, sizeof(cache_inv_data));
79    memset(&custom_data, 0, sizeof(custom_data));
80    cache_inv_data.vaddr = vaddr;
81    cache_inv_data.fd = mMemInfo[index].fd;
82    cache_inv_data.handle = mMemInfo[index].handle;
83    cache_inv_data.length = mMemInfo[index].size;
84    custom_data.cmd = cmd;
85    custom_data.arg = (unsigned long)&cache_inv_data;
86
87    ALOGD("%s: addr = %p, fd = %d, handle = %p length = %d, ION Fd = %d",
88         __func__, cache_inv_data.vaddr, cache_inv_data.fd,
89         cache_inv_data.handle, cache_inv_data.length,
90         mMemInfo[index].main_ion_fd);
91    ret = ioctl(mMemInfo[index].main_ion_fd, ION_IOC_CUSTOM, &custom_data);
92    if (ret < 0)
93        ALOGE("%s: Cache Invalidate failed: %s\n", __func__, strerror(errno));
94
95    return ret;
96}
97
98int QCameraMemory::getFd(int index) const
99{
100    if (index >= mBufferCount)
101        return BAD_INDEX;
102
103    return mMemInfo[index].fd;
104}
105
106int QCameraMemory::getSize(int index) const
107{
108    if (index >= mBufferCount)
109        return BAD_INDEX;
110
111    return (int)mMemInfo[index].size;
112}
113
114int QCameraMemory::getCnt() const
115{
116    return mBufferCount;
117}
118
119void QCameraMemory::getBufDef(const cam_frame_len_offset_t &offset,
120        mm_camera_buf_def_t &bufDef, int index) const
121{
122    if (!mBufferCount) {
123        ALOGE("Memory not allocated");
124        return;
125    }
126    bufDef.fd = mMemInfo[index].fd;
127    bufDef.frame_len = mMemInfo[index].size;
128    bufDef.mem_info = (void *)this;
129    bufDef.num_planes = offset.num_planes;
130	bufDef.buffer = getPtr(index);
131    bufDef.buf_idx = index;
132
133    /* Plane 0 needs to be set separately. Set other planes in a loop */
134    bufDef.planes[0].length = offset.mp[0].len;
135    bufDef.planes[0].m.userptr = mMemInfo[index].fd;
136    bufDef.planes[0].data_offset = offset.mp[0].offset;
137    bufDef.planes[0].reserved[0] = 0;
138    for (int i = 1; i < bufDef.num_planes; i++) {
139         bufDef.planes[i].length = offset.mp[i].len;
140         bufDef.planes[i].m.userptr = mMemInfo[i].fd;
141         bufDef.planes[i].data_offset = offset.mp[i].offset;
142         bufDef.planes[i].reserved[0] =
143                 bufDef.planes[i-1].reserved[0] +
144                 bufDef.planes[i-1].length;
145    }
146}
147
148int QCameraMemory::alloc(int count, int size, int heap_id)
149{
150    int rc = OK;
151    if (count > MM_CAMERA_MAX_NUM_FRAMES) {
152        ALOGE("Buffer count %d out of bound. Max is %d", count, MM_CAMERA_MAX_NUM_FRAMES);
153        return BAD_INDEX;
154    }
155    if (mBufferCount) {
156        ALOGE("Allocating a already allocated heap memory");
157        return INVALID_OPERATION;
158    }
159
160    for (int i = 0; i < count; i ++) {
161        rc = allocOneBuffer(mMemInfo[i], heap_id, size);
162        if (rc < 0) {
163            ALOGE("AllocateIonMemory failed");
164            for (int j = i-1; j >= 0; j--)
165                deallocOneBuffer(mMemInfo[j]);
166            break;
167        }
168    }
169    return rc;
170}
171
172void QCameraMemory::dealloc()
173{
174    for (int i = 0; i < mBufferCount; i++)
175        deallocOneBuffer(mMemInfo[i]);
176}
177
178int QCameraMemory::allocOneBuffer(QCameraMemInfo &memInfo, int heap_id, int size)
179{
180    int rc = OK;
181    struct ion_handle_data handle_data;
182    struct ion_allocation_data alloc;
183    struct ion_fd_data ion_info_fd;
184    int main_ion_fd = 0;
185
186    main_ion_fd = open("/dev/ion", O_RDONLY);
187    if (main_ion_fd <= 0) {
188        ALOGE("Ion dev open failed: %s\n", strerror(errno));
189        goto ION_OPEN_FAILED;
190    }
191
192    memset(&alloc, 0, sizeof(alloc));
193    alloc.len = size;
194    /* to make it page size aligned */
195    alloc.len = (alloc.len + 4095) & (~4095);
196    alloc.align = 4096;
197    alloc.flags = ION_FLAG_CACHED;
198    alloc.heap_mask = heap_id;
199    rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
200    if (rc < 0) {
201        ALOGE("ION allocation failed: %s\n", strerror(errno));
202        goto ION_ALLOC_FAILED;
203    }
204
205    memset(&ion_info_fd, 0, sizeof(ion_info_fd));
206    ion_info_fd.handle = alloc.handle;
207    rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
208    if (rc < 0) {
209        ALOGE("ION map failed %s\n", strerror(errno));
210        goto ION_MAP_FAILED;
211    }
212
213    memInfo.main_ion_fd = main_ion_fd;
214    memInfo.fd = ion_info_fd.fd;
215    memInfo.handle = ion_info_fd.handle;
216    memInfo.size = alloc.len;
217    return OK;
218
219ION_MAP_FAILED:
220    memset(&handle_data, 0, sizeof(handle_data));
221    handle_data.handle = ion_info_fd.handle;
222    ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
223ION_ALLOC_FAILED:
224    close(main_ion_fd);
225ION_OPEN_FAILED:
226    return NO_MEMORY;
227}
228
229void QCameraMemory::deallocOneBuffer(QCameraMemInfo &memInfo)
230{
231    struct ion_handle_data handle_data;
232
233    if (memInfo.fd > 0) {
234        close(memInfo.fd);
235        memInfo.fd = 0;
236    }
237
238    if (memInfo.main_ion_fd > 0) {
239        memset(&handle_data, 0, sizeof(handle_data));
240        handle_data.handle = memInfo.handle;
241        ioctl(memInfo.main_ion_fd, ION_IOC_FREE, &handle_data);
242        close(memInfo.main_ion_fd);
243        memInfo.main_ion_fd = 0;
244    }
245    memInfo.handle = NULL;
246    memInfo.size = 0;
247}
248
249// QCameraHeapMemory for ion memory used internally in HAL.
250QCameraHeapMemory::QCameraHeapMemory()
251    : QCameraMemory()
252{
253    for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
254        mPtr[i] = NULL;
255}
256
257QCameraHeapMemory::~QCameraHeapMemory()
258{
259}
260
261void *QCameraHeapMemory::getPtr(int index) const
262{
263    if (index >= mBufferCount) {
264        ALOGE("index out of bound");
265        return (void *)BAD_INDEX;
266    }
267    return mPtr[index];
268}
269
270int QCameraHeapMemory::allocate(int count, int size)
271{
272    int heap_mask = (0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
273    int rc = alloc(count, size, heap_mask);
274    if (rc < 0)
275        return rc;
276
277    for (int i = 0; i < count; i ++) {
278        void *vaddr = mmap(NULL,
279                    mMemInfo[i].size,
280                    PROT_READ | PROT_WRITE,
281                    MAP_SHARED,
282                    mMemInfo[i].fd, 0);
283        if (vaddr == MAP_FAILED) {
284            for (int j = i-1; j >= 0; j --) {
285                munmap(mPtr[i], mMemInfo[i].size);
286                rc = NO_MEMORY;
287                break;
288            }
289        } else
290            mPtr[i] = vaddr;
291    }
292    if (rc == 0)
293        mBufferCount = count;
294    return OK;
295}
296
297void QCameraHeapMemory::deallocate()
298{
299    for (int i = 0; i < mBufferCount; i++) {
300        munmap(mPtr[i], mMemInfo[i].size);
301        mPtr[i] = NULL;
302    }
303    dealloc();
304    mBufferCount = 0;
305}
306
307int QCameraHeapMemory::cacheOps(int index, unsigned int cmd)
308{
309    if (index >= mBufferCount)
310        return BAD_INDEX;
311    return cacheOpsInternal(index, cmd, mPtr[index]);
312}
313
314int QCameraHeapMemory::getRegFlags(uint8_t * /*regFlags*/) const
315{
316    return INVALID_OPERATION;
317}
318
319camera_memory_t *QCameraHeapMemory::getMemory(
320                int /*index*/, bool /*metadata*/) const
321{
322    return NULL;
323}
324
325int QCameraHeapMemory::getMatchBufIndex(const void *opaque,
326                                        bool metadata) const
327{
328    int index = -1;
329    if (metadata) {
330        return -1;
331    }
332    for (int i = 0; i < mBufferCount; i++) {
333        if (mPtr[i] == opaque) {
334            index = i;
335            break;
336        }
337    }
338    return index;
339}
340
341
342// QCameraStreamMemory for ION memory allocated directly from /dev/ion
343// and shared with framework
344QCameraStreamMemory::QCameraStreamMemory(camera_request_memory getMemory) :
345        mGetMemory(getMemory)
346{
347    for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
348        mCameraMemory[i] = NULL;
349}
350
351QCameraStreamMemory::~QCameraStreamMemory()
352{
353}
354
355int QCameraStreamMemory::allocate(int count, int size)
356{
357    int heap_mask = (0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
358    int rc = alloc(count, size, heap_mask);
359    if (rc < 0)
360        return rc;
361
362    for (int i = 0; i < count; i ++) {
363        mCameraMemory[i] = mGetMemory(mMemInfo[i].fd, mMemInfo[i].size, 1, this);
364    }
365    mBufferCount = count;
366    return NO_ERROR;
367}
368
369void QCameraStreamMemory::deallocate()
370{
371    for (int i = 0; i < mBufferCount; i ++) {
372        mCameraMemory[i]->release(mCameraMemory[i]);
373        mCameraMemory[i] = NULL;
374    }
375    dealloc();
376    mBufferCount = 0;
377}
378
379int QCameraStreamMemory::cacheOps(int index, unsigned int cmd)
380{
381    if (index >= mBufferCount)
382        return BAD_INDEX;
383    return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
384}
385
386int QCameraStreamMemory::getRegFlags(uint8_t *regFlags) const
387{
388    for (int i = 0; i < mBufferCount; i ++)
389        regFlags[i] = 1;
390    return NO_ERROR;
391}
392
393camera_memory_t *QCameraStreamMemory::getMemory(int index, bool metadata) const
394{
395    if (index >= mBufferCount || metadata)
396        return NULL;
397    return mCameraMemory[index];
398}
399
400int QCameraStreamMemory::getMatchBufIndex(const void *opaque,
401                                          bool metadata) const
402{
403    int index = -1;
404    if (metadata) {
405        return -1;
406    }
407    for (int i = 0; i < mBufferCount; i++) {
408        if (mCameraMemory[i]->data == opaque) {
409            index = i;
410            break;
411        }
412    }
413    return index;
414}
415
416void *QCameraStreamMemory::getPtr(int index) const
417{
418    if (index >= mBufferCount) {
419        ALOGE("index out of bound");
420        return (void *)BAD_INDEX;
421    }
422    return mCameraMemory[index]->data;
423}
424
425QCameraVideoMemory::QCameraVideoMemory(camera_request_memory getMemory)
426    : QCameraStreamMemory(getMemory)
427{
428    memset(mMetadata, 0, sizeof(mMetadata));
429}
430
431QCameraVideoMemory::~QCameraVideoMemory()
432{
433}
434
435int QCameraVideoMemory::allocate(int count, int size)
436{
437    int rc = QCameraStreamMemory::allocate(count, size);
438    if (rc < 0)
439        return rc;
440
441    for (int i = 0; i < count; i ++) {
442        mMetadata[i] = mGetMemory(-1,
443                sizeof(struct encoder_media_buffer_type), 1, this);
444        if (!mMetadata[i]) {
445            ALOGE("allocation of video metadata failed.");
446            for (int j = 0; j < i-1; j ++)
447                mMetadata[j]->release(mMetadata[j]);
448            QCameraStreamMemory::deallocate();
449            return NO_MEMORY;
450        }
451        struct encoder_media_buffer_type * packet =
452            (struct encoder_media_buffer_type *)mMetadata[i]->data;
453        packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size
454        packet->buffer_type = kMetadataBufferTypeCameraSource;
455        native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle);
456        nh->data[0] = mMemInfo[i].fd;
457        nh->data[1] = 0;
458        nh->data[2] = mMemInfo[i].size;
459    }
460    mBufferCount = count;
461    return NO_ERROR;
462}
463
464void QCameraVideoMemory::deallocate()
465{
466    for (int i = 0; i < mBufferCount; i ++) {
467        mMetadata[i]->release(mMetadata[i]);
468        mMetadata[i] = NULL;
469    }
470    QCameraStreamMemory::dealloc();
471    mBufferCount = 0;
472}
473
474camera_memory_t *QCameraVideoMemory::getMemory(int index, bool metadata) const
475{
476    if (index >= mBufferCount)
477        return NULL;
478    if (metadata)
479        return mMetadata[index];
480    else
481        return mCameraMemory[index];
482}
483
484int QCameraVideoMemory::getMatchBufIndex(const void *opaque,
485                                         bool metadata) const
486{
487    int index = -1;
488    for (int i = 0; i < mBufferCount; i++) {
489        if (metadata) {
490            if (mMetadata[i]->data == opaque) {
491                index = i;
492                break;
493            }
494        } else {
495            if (mCameraMemory[i]->data == opaque) {
496                index = i;
497                break;
498            }
499        }
500    }
501    return index;
502}
503
504// QCameraGrallocMemory for memory allocated from native_window
505QCameraGrallocMemory::QCameraGrallocMemory(camera_request_memory getMemory)
506        : QCameraMemory()
507{
508    mMinUndequeuedBuffers = 0;
509    mWindow = NULL;
510    mWidth = mHeight = 0;
511    mFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
512    mGetMemory = getMemory;
513    for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++) {
514        mBufferHandle[i] = NULL;
515        mLocalFlag[i] = BUFFER_NOT_OWNED;
516        mPrivateHandle[i] = NULL;
517    }
518}
519
520QCameraGrallocMemory::~QCameraGrallocMemory()
521{
522}
523
524void QCameraGrallocMemory::setWindowInfo(preview_stream_ops_t *window,
525        int width, int height, int format)
526{
527    mWindow = window;
528    mWidth = width;
529    mHeight = height;
530    mFormat = format;
531}
532
533int QCameraGrallocMemory::displayBuffer(int index)
534{
535    int err = NO_ERROR;
536    int dequeuedIdx = BAD_INDEX;
537
538    if (BUFFER_LOCKED == mLocalFlag[index]) {
539        if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t*)
540                        (*mBufferHandle[index]))) {
541            ALOGE("genlock_unlock_buffer failed");
542        } else {
543            mLocalFlag[index] = BUFFER_UNLOCKED;
544        }
545    } else {
546        ALOGE("buffer to be enqueued is not locked");
547    }
548
549    cleanInvalidateCache(index);
550    err = mWindow->enqueue_buffer(mWindow, (buffer_handle_t *)mBufferHandle[index]);
551    if(err != 0) {
552        ALOGE("%s: enqueue_buffer failed, err = %d", __func__, err);
553    } else {
554        ALOGV("%s: enqueue_buffer hdl=%p", __func__, *mBufferHandle[index]);
555        mLocalFlag[index] = BUFFER_NOT_OWNED;
556    }
557
558    buffer_handle_t *buffer_handle = NULL;
559    int stride = 0;
560    err = mWindow->dequeue_buffer(mWindow, &buffer_handle, &stride);
561    if (err == NO_ERROR && buffer_handle != NULL) {
562        int i;
563        ALOGV("%s: dequed buf hdl =%p", __func__, *buffer_handle);
564        for(i = 0; i < mBufferCount; i++) {
565            if(mBufferHandle[i] == buffer_handle) {
566                ALOGV("%s: Found buffer in idx:%d", __func__, i);
567                mLocalFlag[i] = BUFFER_UNLOCKED;
568                break;
569            }
570        }
571        if (i < mBufferCount ) {
572            err = mWindow->lock_buffer(mWindow, buffer_handle);
573            ALOGD("camera call genlock_lock: hdl =%p", *buffer_handle);
574            if (GENLOCK_FAILURE == genlock_lock_buffer((native_handle_t*)
575                    (*buffer_handle), GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) {
576                ALOGE("%s: genlock_lock_buffer(WRITE) failed", __func__);
577            } else  {
578                mLocalFlag[i] = BUFFER_LOCKED;
579                dequeuedIdx = i;
580            }
581        }
582    } else {
583        ALOGD("%s: dequeue_buffer, no free buffer from display now", __func__);
584    }
585    return dequeuedIdx;
586}
587
588int QCameraGrallocMemory::allocate(int count, int /*size*/)
589{
590    int err = 0;
591    status_t ret = NO_ERROR;
592    int gralloc_usage;
593    struct ion_fd_data ion_info_fd;
594
595    ALOGI(" %s : E ", __FUNCTION__);
596
597    if (!mWindow) {
598        ALOGE("Invalid native window");
599        return INVALID_OPERATION;
600    }
601
602    // Increment buffer count by min undequeued buffer.
603    err = mWindow->get_min_undequeued_buffer_count(mWindow,&mMinUndequeuedBuffers);
604    if (err != 0) {
605        ALOGE("get_min_undequeued_buffer_count  failed: %s (%d)",
606                strerror(-err), -err);
607        ret = UNKNOWN_ERROR;
608        goto end;
609    }
610    count += mMinUndequeuedBuffers;
611
612    err = mWindow->set_buffer_count(mWindow, count);
613    if (err != 0) {
614         ALOGE("set_buffer_count failed: %s (%d)",
615                    strerror(-err), -err);
616         ret = UNKNOWN_ERROR;
617         goto end;
618    }
619
620    err = mWindow->set_buffers_geometry(mWindow, mWidth, mHeight, mFormat);
621    if (err != 0) {
622         ALOGE("%s: set_buffers_geometry failed: %s (%d)",
623               __func__, strerror(-err), -err);
624         ret = UNKNOWN_ERROR;
625         goto end;
626    }
627
628    gralloc_usage = GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
629    err = mWindow->set_usage(mWindow, gralloc_usage);
630    if(err != 0) {
631        /* set_usage error out */
632        ALOGE("%s: set_usage rc = %d", __func__, err);
633        ret = UNKNOWN_ERROR;
634        goto end;
635    }
636    ALOGD("%s: usage = %d, geometry: %p, %d, %d, %d",
637          __func__, gralloc_usage, mWindow, mWidth, mHeight, mFormat);
638
639    //Allocate cnt number of buffers from native window
640    for (int cnt = 0; cnt < count; cnt++) {
641        int stride;
642        err = mWindow->dequeue_buffer(mWindow, &mBufferHandle[cnt], &stride);
643        if(!err) {
644            ALOGV("dequeue buf hdl =%p", mBufferHandle[cnt]);
645            err = mWindow->lock_buffer(mWindow, mBufferHandle[cnt]);
646            // lock the buffer using genlock
647            ALOGV("camera call genlock_lock, hdl=%p", *mBufferHandle[cnt]);
648            if (GENLOCK_NO_ERROR != genlock_lock_buffer(
649                            (native_handle_t *)(*mBufferHandle[cnt]),
650                            GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) {
651                ALOGE("%s: genlock_lock_buffer(WRITE) failed", __func__);
652                mLocalFlag[cnt] = BUFFER_UNLOCKED;
653            } else {
654                ALOGV("genlock_lock_buffer hdl =%p", *mBufferHandle[cnt]);
655                mLocalFlag[cnt] = BUFFER_LOCKED;
656            }
657        } else {
658            mLocalFlag[cnt] = BUFFER_NOT_OWNED;
659            ALOGE("%s: dequeue_buffer idx = %d err = %d", __func__, cnt, err);
660        }
661
662        ALOGV("%s: dequeue buf: %p\n", __func__, mBufferHandle[cnt]);
663
664        if(err != 0) {
665            ALOGE("%s: dequeue_buffer failed: %s (%d)",
666                  __func__, strerror(-err), -err);
667            ret = UNKNOWN_ERROR;
668            for(int i = 0; i < cnt; i++) {
669                if (BUFFER_LOCKED == mLocalFlag[i]) {
670                    ALOGD("%s: camera call genlock_unlock", __func__);
671                    if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)
672                                                  (*(mBufferHandle[i])))) {
673                        ALOGE("%s: genlock_unlock_buffer failed: hdl =%p",
674                              __func__, (*(mBufferHandle[i])) );
675                     } else {
676                         mLocalFlag[i] = BUFFER_UNLOCKED;
677                     }
678                }
679                if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
680                    err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
681                    ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
682                }
683                mLocalFlag[i] = BUFFER_NOT_OWNED;
684                mBufferHandle[i] = NULL;
685            }
686            memset(&mMemInfo, 0, sizeof(mMemInfo));
687            goto end;
688        }
689
690        mPrivateHandle[cnt] =
691            (struct private_handle_t *)(*mBufferHandle[cnt]);
692        mMemInfo[cnt].main_ion_fd = open("/dev/ion", O_RDONLY);
693        if (mMemInfo[cnt].main_ion_fd < 0) {
694            ALOGE("%s: failed: could not open ion device", __func__);
695        } else {
696            memset(&ion_info_fd, 0, sizeof(ion_info_fd));
697            ion_info_fd.fd = mPrivateHandle[cnt]->fd;
698            if (ioctl(mMemInfo[cnt].main_ion_fd,
699                      ION_IOC_IMPORT, &ion_info_fd) < 0) {
700                ALOGE("%s: ION import failed\n", __func__);
701            }
702        }
703        mCameraMemory[cnt] =
704            mGetMemory(mPrivateHandle[cnt]->fd,
705                    mPrivateHandle[cnt]->size,
706                    1,
707                    (void *)this);
708        ALOGD("%s: idx = %d, fd = %d, size = %d, offset = %d",
709              __func__, cnt, mPrivateHandle[cnt]->fd,
710              mPrivateHandle[cnt]->size,
711              mPrivateHandle[cnt]->offset);
712        mMemInfo[cnt].fd =
713            mPrivateHandle[cnt]->fd;
714        mMemInfo[cnt].size =
715            mPrivateHandle[cnt]->size;
716        mMemInfo[cnt].handle = ion_info_fd.handle;
717    }
718    mBufferCount = count;
719
720    //Cancel min_undequeued_buffer buffers back to the window
721    for (int i = 0; i < mMinUndequeuedBuffers; i ++) {
722        if (BUFFER_LOCKED == mLocalFlag[i]) {
723            if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)
724                                          (*(mBufferHandle[i])))) {
725                ALOGE("%s: genlock_unlock_buffer failed: hdl =%p",
726                      __func__, (*(mBufferHandle[i])));
727            } else {
728                mLocalFlag[i] = BUFFER_UNLOCKED;
729            }
730        }
731        err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
732        mLocalFlag[i] = BUFFER_NOT_OWNED;
733    }
734
735end:
736    ALOGI(" %s : X ",__func__);
737    return ret;
738}
739
740void QCameraGrallocMemory::deallocate()
741{
742    ALOGI("%s: E ", __FUNCTION__);
743
744    for (int cnt = 0; cnt < mBufferCount; cnt++) {
745        mCameraMemory[cnt]->release(mCameraMemory[cnt]);
746        struct ion_handle_data ion_handle;
747        memset(&ion_handle, 0, sizeof(ion_handle));
748        ion_handle.handle = mMemInfo[cnt].handle;
749        if (ioctl(mMemInfo[cnt].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
750            ALOGE("ion free failed");
751        }
752        close(mMemInfo[cnt].main_ion_fd);
753        if (BUFFER_LOCKED == mLocalFlag[cnt]) {
754            ALOGD("camera call genlock_unlock");
755            if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)
756                                                    (*(mBufferHandle[cnt])))) {
757                ALOGE("genlock_unlock_buffer failed, handle =%p",
758                    (*(mBufferHandle[cnt])));
759                continue;
760            } else {
761                ALOGD("genlock_unlock_buffer, handle =%p",
762                    (*(mBufferHandle[cnt])));
763                mLocalFlag[cnt] = BUFFER_UNLOCKED;
764            }
765        }
766        if(mLocalFlag[cnt] != BUFFER_NOT_OWNED) {
767            if (mWindow) {
768                mWindow->cancel_buffer(mWindow, mBufferHandle[cnt]);
769                ALOGD("cancel_buffer: hdl =%p", (*mBufferHandle[cnt]));
770            } else {
771                ALOGE("Preview window is NULL, cannot cancel_buffer: hdl =%p",
772                      (*mBufferHandle[cnt]));
773            }
774        }
775        mLocalFlag[cnt] = BUFFER_NOT_OWNED;
776        ALOGD("put buffer %d successfully", cnt);
777    }
778    mBufferCount = 0;
779    ALOGI(" %s : X ",__FUNCTION__);
780}
781
782int QCameraGrallocMemory::cacheOps(int index, unsigned int cmd)
783{
784    if (index >= mBufferCount)
785        return BAD_INDEX;
786    return cacheOpsInternal(index, cmd, mCameraMemory[index]->data);
787}
788
789int QCameraGrallocMemory::getRegFlags(uint8_t *regFlags) const
790{
791    int i = 0;
792    for (i = 0; i < mMinUndequeuedBuffers; i ++)
793        regFlags[i] = 0;
794    for (; i < mBufferCount; i ++)
795        regFlags[i] = 1;
796    return NO_ERROR;
797}
798
799camera_memory_t *QCameraGrallocMemory::getMemory(int index, bool metadata) const
800{
801    if (index >= mBufferCount || metadata)
802        return NULL;
803    return mCameraMemory[index];
804}
805
806int QCameraGrallocMemory::getMatchBufIndex(const void *opaque,
807                                           bool metadata) const
808{
809    int index = -1;
810    if (metadata) {
811        return -1;
812    }
813    for (int i = 0; i < mBufferCount; i++) {
814        if (mCameraMemory[i]->data == opaque) {
815            index = i;
816            break;
817        }
818    }
819    return index;
820}
821
822void *QCameraGrallocMemory::getPtr(int index) const
823{
824    if (index >= mBufferCount) {
825        ALOGE("index out of bound");
826        return (void *)BAD_INDEX;
827    }
828    return mCameraMemory[index]->data;
829}
830
831}; //namespace qcamera
832