void GuiExtIONDevice::touchMMUAddress(int client, int ion_hnd) { if (m_dev_fd <= 0) return; // configure before querying physical address struct ion_mm_data mm_data; mm_data.mm_cmd = ION_MM_CONFIG_BUFFER; mm_data.config_buffer_param.handle = (struct ion_handle *) ion_hnd; mm_data.config_buffer_param.eModuleID = client; mm_data.config_buffer_param.security = 0; mm_data.config_buffer_param.coherent = 0; int status = ion_custom_ioctl(m_dev_fd, ION_CMD_MULTIMEDIA, &mm_data); if ((status > 0) && (status != ION_ERROR_CONFIG_LOCKED)) { GUIEXT_LOGE("Failed to config ION memory: %s", strerror(errno)); return; } // get physical address struct ion_sys_data sys_data; sys_data.sys_cmd = ION_SYS_GET_PHYS; sys_data.get_phys_param.handle = (struct ion_handle *) ion_hnd; if (ion_custom_ioctl(m_dev_fd, ION_CMD_SYSTEM, &sys_data)) { GUIEXT_LOGE("Failed to get MVA from ION: %s", strerror(errno)); return; } }
status_t GuiExtPoolItem::setOverlaySessionMode(bool decouple) { static int sVpRefCount = 0; int devFd = -1; char filename[256]; disp_session_config config; DISP_MODE disp_mode = DISP_SESSION_DIRECT_LINK_MODE; GUIEXT_LOGD("[PQ] decouple=%d, VpRefCnt=%d \n", decouple, sVpRefCount); if (decouple) { disp_mode = DISP_SESSION_DECOUPLE_MODE; sVpRefCount++; } else { disp_mode = DISP_SESSION_DIRECT_LINK_MODE; sVpRefCount--; } // If not the first VP start or last VP end, do nothing if ( !((sVpRefCount==1 && decouple) || (sVpRefCount==0 && !decouple)) ) { return NO_ERROR; } GUIEXT_LOGD("[PQ] Dynamic Switch to (mode=%d)", disp_mode); sprintf(filename, "/dev/%s", DISP_SESSION_DEVICE); devFd = open(filename, O_RDONLY); if (devFd <= 0) { GUIEXT_LOGE("[PQ] Failed to open display device(%s): fd=%d", filename, devFd); return -1; } else { GUIEXT_LOGD("[PQ] open display device(%s) successfully", filename); } memset(&config, 0, sizeof(disp_session_config)); config.device_id = HWC_DISPLAY_PRIMARY; config.type = DISP_SESSION_PRIMARY; config.session_id = MAKE_DISP_SESSION(config.type, config.device_id); config.mode = disp_mode; config.user = SESSION_USER_GUIEXT; int err = ioctl(devFd, DISP_IOCTL_SET_SESSION_MODE, &config); if (err < 0) { GUIEXT_LOGE("[PQ] Failed to set DispSession (mode=%d, errno:%d)!!", disp_mode, err); if (devFd > 0) close(devFd); return BAD_VALUE; } if (devFd > 0) close(devFd); return NO_ERROR; }
GuiExtIONDevice::GuiExtIONDevice() { m_dev_fd = open(ION_DEV_NODE, O_RDONLY); if (m_dev_fd <= 0) { GUIEXT_LOGE("Failed to open ION device: %s ", strerror(errno)); } }
uint32_t GuiExtIONDevice::import(int ion_fd) { if (m_dev_fd <= 0) return 0; struct ion_handle* ion_hnd; if (ion_import(m_dev_fd, ion_fd, &ion_hnd)) { GUIEXT_LOGE("Failed to import ION handle: %s ", strerror(errno)); return 0; } return (unsigned int)ion_hnd; }
status_t GuiExtClientProducer::free(uint32_t poolId) { status_t err; Mutex::Autolock _l(mLock); err = assertStateLocked(); if (err != NO_ERROR) { GUIEXT_LOGE("[%s] assertStateLocked fail", __func__); return err; } GUIEXT_LOGV("free +, poolId=%d", poolId); err = mGuiExtService->free(poolId); GUIEXT_LOGV("free -, poolId=%d, ret=%d", poolId, err); return err; }
status_t GuiExtClientProducer::alloc(uint32_t gralloc_usage, uint32_t w, uint32_t h, uint32_t *poolId) { status_t err; Mutex::Autolock _l(mLock); err = assertStateLocked(); if (err != NO_ERROR) { GUIEXT_LOGE("[%s] assertStateLocked fail", __func__); return err; } GUIEXT_LOGV("alloc +, gralloc_usage=%x, w=%d, h=%d", gralloc_usage, w, h); static sp<BBinder> sLife = new BBinder(); err = mGuiExtService->alloc(sLife, gralloc_usage, w, h, poolId); GUIEXT_LOGV("alloc -, poolId=%d", *poolId); return err; }
status_t GuiExtPool::free(uint32_t poolId) { Mutex::Autolock _l(mLock); ATRACE_CALL(); GUIEXT_LOGD(" free, poolId=%d", poolId); sp<GuiExtPoolItem> item = mPoolList.valueFor(poolId); if (item == NULL) { GUIEXT_LOGE("free a non-exist pool item, poolId=%d", poolId); return BAD_INDEX; } item->mProducerToken = NULL; item->mProducerPid = -1; removePoolItemLocked(poolId); return NO_ERROR; }
sp<IGraphicBufferProducer> GuiExtPoolItem::getIGraphicBufferProducer(uint32_t usage, uint32_t type) { sp<IGraphicBufferProducer> producer = mGPUUsedProducer; if (usage == GUI_EXT_USAGE_HWC) { #if SUPPORT_MULTIBQ_FOR_HWC sp<HwcBqSlot> slot = mHwcUsedBqList.valueFor(type); if (type >= HWC_NUM_DISPLAY_TYPES || slot == NULL) { GUIEXT_LOGE(" try to get HWC BufferQueue not has hwc display type=%d buffer\n", type); return NULL; } producer = slot->mProducer; #else bq = mHwcUsedBq; #endif } return producer; }
status_t GuiExtPool::alloc(const sp<IBinder>& token, uint32_t gralloc_usage, uint32_t w, uint32_t h, uint32_t * poolId) { Mutex::Autolock _l(mLock); ATRACE_CALL(); GUIEXT_LOGD(" alloc, gralloc_usage=%x, w=%d, h=%d", gralloc_usage, w, h); const nsecs_t time_start = systemTime(); uint32_t size = mPoolList.size(); if (size >= MAX_ALLOC_SIZE) { GUIEXT_LOGW(" alloc pools size is reaching %d, can't alloc", size); *poolId = 0; return NOT_ENOUGH_DATA; } if (size == 0) { DisplayInfo dinfo; sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain); SurfaceComposerClient::getDisplayInfo(display, &dinfo); mDefaultDisplayWidth = dinfo.w; mDefaultDisplayHeight = dinfo.h; sp<DispInfo> disp = new DispInfo; disp->type = 0; disp->w = mDefaultDisplayWidth; disp->h = mDefaultDisplayHeight; disp->bufNum = MAX_HWC_DEQUEUED_NUM; mDisplayList.add((uint32_t)HWC_DISPLAY_PRIMARY, disp); GUIEXT_LOGI("pool list size=0, try to get default display(w x h) = (%d x %d)", disp->w, disp->h); } *poolId = getPoolId(); bool isHwcNeeded = gralloc_usage & GRALLOC_USAGE_HW_COMPOSER; class ProducerDeathObserver : public IBinder::DeathRecipient { GuiExtPool & mPool; virtual void binderDied(const wp<IBinder>& who) { uint32_t size = mPool.mPoolList.size(); GUIEXT_LOGI("producer died, pool size=%d, binder ptr=[%p]", size, who.unsafe_get()); if (size == 0) { GUIEXT_LOGV("producer died [%p], pool size is zero", who.unsafe_get()); } else { for (uint32_t i = size-1 ;; i--) { GUIEXT_LOGV(" [p] compare index[%d], p=[%p]", i, mPool.mPoolList[i]->mProducerToken.get()); if (mPool.mPoolList[i]->mProducerToken.get() == who.unsafe_get()) { GUIEXT_LOGW(" [p] found index[%d], p=[%p], id=%d", i, mPool.mPoolList[i]->mProducerToken.get(), mPool.mPoolList[i]->mId); mPool.mPoolList[i]->mProducerToken = NULL; mPool.mPoolList[i]->mProducerPid = -1; mPool.removePoolItem(mPool.mPoolList[i]->mId); } if (i == 0) break; } GUIEXT_LOGV("producer died done"); } } public: ProducerDeathObserver(GuiExtPool & pool) : mPool(pool) { } }; sp<IBinder::DeathRecipient> observer = new ProducerDeathObserver(*const_cast<GuiExtPool*>(this)); token->linkToDeath(observer); sp<GuiExtPoolItem> item = new GuiExtPoolItem(token, isHwcNeeded, *poolId, w, h, mDisplayList, observer); status_t err; err = item->prepareBuffer(gralloc_usage); if (err != NO_ERROR) { GUIEXT_LOGE(" alloc fail, isHWcNeeded=%d, w=%d, h=%d, usage=%x, poolId=%d", isHwcNeeded, w, h, gralloc_usage, *poolId); *poolId = 0; return err; } mPoolList.add(*poolId, item); const nsecs_t time_end = systemTime(); GUIEXT_LOGI(" alloc cost time=%" PRId64 " ms, gralloc_usage=%x, w=%d, h=%d, poolId=%d", ns2ms(time_end - time_start), gralloc_usage, w, h, *poolId); return err; }