int ExynosHWCService::setForceMirrorMode(unsigned int mode) { ALOGD_IF(HWC_SERVICE_DEBUG, "%s::mode=%d", __func__, mode); mHWCCtx->force_mirror_mode = mode; mHWCCtx->procs->invalidate(mHWCCtx->procs); return NO_ERROR; }
void VirtualDisplay::setAttributes() { if(mHwcContext) { uint32_t &extW = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres; uint32_t &extH = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres; uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres; uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres; initResolution(extW, extH); // Dynamic Resolution Change depends on MDP downscaling. // MDP downscale property will be ignored to exercise DRC use case. // If DRC is in progress, ext WxH will have non-zero values. bool isDRC = (extW > 0) && (extH > 0); if(!qdutils::MDPVersion::getInstance().is8x26() && (mHwcContext->mMDPDownscaleEnabled || isDRC)) { // maxArea represents the maximum resolution between // primary and virtual display. uint32_t maxArea = max((extW * extH), (priW * priH)); setToPrimary(maxArea, priW, priH, extW, extH); setDownScaleMode(maxArea); } mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period = 1000000000l /60; ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__, mVInfo.xres, mVInfo.yres); } }
bool IntelHWComposer::handleDynamicModeSetting(void *data) { bool ret = false; ALOGD_IF(ALLOW_HWC_PRINT, "%s: handle Dynamic mode setting!\n", __func__); // check HDMI timing if (!mDrm->isDrmModeChanged((intel_display_mode_t*)data)){ ALOGD("Same HDMI timing, ignore this setting"); return true; } // send plug-out to SF for mode changing on the same device // otherwise SF will bypass the plug-in message as there is // no connection change; ret = handleHotplugEvent(0, NULL); if (!ret) { ALOGW("%s: send fake unplug event failed!\n", __func__); goto out; } // then change the mode and send plug-in to SF ret = handleHotplugEvent(1, data); if (!ret) { ALOGW("%s: send plug in event failed!\n", __func__); goto out; } out: return ret; }
void ExynosHWCService::setExynosHWCCtx(ExynosHWCCtx *HWCCtx) { ALOGD_IF(HWC_SERVICE_DEBUG, "HWCCtx=0x%x", (int)HWCCtx); if(HWCCtx) { mHWCCtx = HWCCtx; } }
int ExynosHWCService::setExternalUITransform(unsigned int transform) { ALOGD_IF(HWC_SERVICE_DEBUG, "%s::transform=%d", __func__, transform); mHWCCtx->ext_fbt_transform = transform; mHWCCtx->procs->invalidate(mHWCCtx->procs); return NO_ERROR; }
/* Do this only on brightness ADC. */ void LightSensor::configureRange(uint16_t adc_count) { if (!settings.allow_reconfig) return; bool increase; if (adc_count <= RANGE_DEC_THRESHOLD) increase = false; else if (adc_count >= RANGE_INC_THRESHOLD) increase = true; else return; if (increase && settings.range != APS_12D_RANGE_15P36_TO_64000) settings.range = static_cast<aps_12d_range>(settings.range + 1); else if (!increase && settings.range != APS_12D_RANGE_0P24_TO_1000) settings.range = static_cast<aps_12d_range>(settings.range - 1); else return; ALOGD_IF(LIGHT_DEBUG, "LightSensor: New range %d", settings.range); if (ioctl(dev_fd, APS_IOCTL_SET_SETTINGS, &settings)) ALOGE("LightSensor: Failed to set settings"); }
int ExynosHWCService::setForceGPU(unsigned int on) { ALOGD_IF(HWC_SERVICE_DEBUG, "%s::on/off=%d", __func__, on); mHWCCtx->force_gpu = on; mHWCCtx->procs->invalidate(mHWCCtx->procs); return NO_ERROR; }
void ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) { ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__); if(hwcCtx) { mHwcContext = hwcCtx; } return; }
void SensorDevice::enableAllSensors() { Mutex::Autolock _l(mLock); mDisabledClients.clear(); const int halVersion = getHalDeviceVersion(); for (size_t i = 0; i< mActivationCount.size(); ++i) { Info& info = mActivationCount.editValueAt(i); if (info.batchParams.isEmpty()) continue; info.selectBatchParams(); const int sensor_handle = mActivationCount.keyAt(i); ALOGD_IF(DEBUG_CONNECTIONS, "\t>> reenable actuating h/w sensor enable handle=%d ", sensor_handle); status_t err(NO_ERROR); if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) { err = mSensorDevice->batch(mSensorDevice, sensor_handle, info.bestBatchParams.flags, info.bestBatchParams.batchDelay, info.bestBatchParams.batchTimeout); ALOGE_IF(err, "Error calling batch on sensor %d (%s)", sensor_handle, strerror(-err)); } if (err == NO_ERROR) { err = mSensorDevice->activate( reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), sensor_handle, 1); ALOGE_IF(err, "Error activating sensor %d (%s)", sensor_handle, strerror(-err)); } if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0) { err = mSensorDevice->setDelay( reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), sensor_handle, info.bestBatchParams.batchDelay); ALOGE_IF(err, "Error calling setDelay sensor %d (%s)", sensor_handle, strerror(-err)); } } }
bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx, hwc_display_contents_1_t *list, int dpy) { int compositionType = qdutils::QCCompositionType:: getInstance().getCompositionType(); if (compositionType & qdutils::COMPOSITION_TYPE_DYN) { // DYN Composition: // use copybit, if (TotalRGBRenderArea < threashold * FB Area) // this is done based on perf inputs in ICS // TODO: Above condition needs to be re-evaluated in JB int fbWidth = ctx->dpyAttr[dpy].xres; int fbHeight = ctx->dpyAttr[dpy].yres; unsigned int fbArea = (fbWidth * fbHeight); unsigned int renderArea = getRGBRenderingArea(list); ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u", __FUNCTION__, renderArea, fbArea); if (renderArea < (mDynThreshold * fbArea)) return true; } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) { // MDP composition, use COPYBIT always return true; } else if ((compositionType & qdutils::COMPOSITION_TYPE_C2D)) { // C2D composition, use COPYBIT return true; } return false; }
status_t SensorDevice::flush(void* ident, int handle) { if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) { return INVALID_OPERATION; } ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle); return mSensorDevice->flush(mSensorDevice, handle); }
bool GenericPipe::init() { ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init"); mRotDownscaleOpt = false; int fbNum = Overlay::getFbForDpy(mDpy); if( fbNum < 0 ) { ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, mDpy); return false; } ALOGD_IF(DEBUG_OVERLAY,"%s: mFbNum:%d",__FUNCTION__, fbNum); if(!mCtrlData.ctrl.init(fbNum)) { ALOGE("GenericPipe failed to init ctrl"); return false; } if(!mCtrlData.data.init(fbNum)) { ALOGE("GenericPipe failed to init data"); return false; } return true; }
bool ExternalDisplay::writeHPDOption(int userOption) const { bool ret = true; char sysFsHPDFilePath[255]; sprintf(sysFsHPDFilePath ,"/sys/devices/virtual/graphics/fb%d/hpd", mHdmiFbNum); int hdmiHPDFile = open(sysFsHPDFilePath,O_RDWR, 0); if (hdmiHPDFile < 0) { ALOGE("%s: state file '%s' not found : ret%d err str: %s", __FUNCTION__, sysFsHPDFilePath, hdmiHPDFile, strerror(errno)); ret = false; } else { int err = -1; ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption); if(userOption) err = write(hdmiHPDFile, "1", 2); else err = write(hdmiHPDFile, "0" , 2); if (err <= 0) { ALOGE("%s: file write failed '%s'", __FUNCTION__, sysFsHPDFilePath); ret = false; } close(hdmiHPDFile); } return ret; }
bool ExternalDisplay::writeHPDOption(int userOption) const { bool ret = true; int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0); if (hdmiHPDFile < 0) { ALOGE("%s: state file '%s' not found : ret%d" "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno)); ret = false; } else { int err = -1; ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption); if(userOption) err = write(hdmiHPDFile, "1", 2); else err = write(hdmiHPDFile, "0" , 2); if (err <= 0) { ALOGE("%s: file write failed '%s'", __FUNCTION__, SYSFS_HPD); ret = false; } close(hdmiHPDFile); } return ret; }
void ExternalDisplay::setExternalDisplay(int connected) { hwc_context_t* ctx = mHwcContext; if(ctx) { ALOGD_IF(DEBUG, "%s: status = %d", __FUNCTION__, connected); if(connected) { readResolution(); //Get the best mode and set // TODO: Move this to activate setResolution(getBestMode()); setDpyAttr(); //enable hdmi vsync } else { // Disable the hdmi vsync closeFrameBuffer(); resetInfo(); } // Store the external display mExternalDisplay = connected; const char* prop = (connected) ? "1" : "0"; // set system property property_set("hw.hdmiON", prop); } return; }
bool IntelHWComposerDrm::detectMDSModeChange() { #ifdef TARGET_HAS_MULTIPLE_DISPLAY drmModeConnection hdmi = getOutputConnection(OUTPUT_HDMI); int mdsMode = 0; if (mMonitor != 0) { mdsMode = mMonitor->getDisplayMode(); ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: get MDS Mode %d", __func__, mdsMode); //TODO: overlay only support OVERLAY_EXTEND and OVERLAY_MIPI0 if (mdsMode == OVERLAY_EXTEND && hdmi == DRM_MODE_CONNECTED) setDisplayMode(OVERLAY_EXTEND); else if (mdsMode == OVERLAY_CLONE_MIPI0) setDisplayMode(OVERLAY_CLONE_MIPI0); else setDisplayMode(OVERLAY_MIPI0); } else #endif { setDisplayMode(OVERLAY_MIPI0); } return true; }
// Connection and Mode setting bool IntelHWComposerDrm::detectDisplayConnection(int disp) { ALOGD_IF(ALLOW_MONITOR_PRINT, "%s: detecting display %d drm mode info...\n", __func__, disp); //get mipi0 info drmModeConnectorPtr connector = NULL; drmModeModeInfoPtr mode = NULL; uint32_t connector_type; connector = getConnector(disp); if (!connector) { ALOGW("%s: fail to get drm connector\n", __func__); return false; } //update connection status setOutputConnection(disp, connector->connection); if (connector->connection != DRM_MODE_CONNECTED) { freeConnector(connector); return false; } //update mode info mode = getSelectMode(NULL, connector); if (mode) setOutputMode(disp, mode, 1); freeConnector(connector); return true; }
AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1), mDoable(false), mFeatureEnabled(false), mDest(overlay::utils::OV_INVALID) { int fd = openWbFb(); if(fd >= 0) { //Values in ad node: //-1 means feature is disabled on device // 0 means feature exists but turned off, will be turned on by hwc // 1 means feature is turned on by hwc // Plus, we do this feature only on split primary displays. // Plus, we do this feature only if ro.qcom.ad=2 char property[PROPERTY_VALUE_MAX]; const int ENABLED = 2; int val = 0; if(property_get("ro.qcom.ad", property, "0") > 0) { val = atoi(property); } if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) && val == ENABLED) { ALOGD_IF(DEBUG, "Assertive display feature supported"); mFeatureEnabled = true; } closeWbFb(fd); } }
bool egl_display_t::HibernationMachine::incWakeCount(WakeRefStrength strength) { Mutex::Autolock _l(mLock); ALOGE_IF(mWakeCount < 0 || mWakeCount == INT32_MAX, "Invalid WakeCount (%d) on enter\n", mWakeCount); mWakeCount++; if (strength == STRONG) mAttemptHibernation = false; if (CC_UNLIKELY(mHibernating)) { ALOGV("Awakening\n"); egl_connection_t* const cnx = &gEGLImpl; // These conditions should be guaranteed before entering hibernation; // we don't want to get into a state where we can't wake up. ALOGD_IF(!mDpyValid || !cnx->egl.eglAwakenProcessIMG, "Invalid hibernation state, unable to awaken\n"); if (!cnx->egl.eglAwakenProcessIMG()) { ALOGE("Failed to awaken EGL implementation\n"); return false; } mHibernating = false; } return true; }
static void teardownWfd(hwc_context_t* ctx) { // Teardown WFD display ALOGD_IF(UEVENT_DEBUG,"Received HDMI connection request when WFD is " "active"); { Locker::Autolock _l(ctx->mDrawLock); clear(ctx, HWC_DISPLAY_VIRTUAL); ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false; ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false; } ctx->mVirtualDisplay->teardown(); /* Need to send hotplug only when connected WFD in proprietary path */ if(ctx->mVirtualonExtActive) { ALOGE_IF(UEVENT_DEBUG,"%s: Sending EXTERNAL OFFLINE" "hotplug event for wfd display", __FUNCTION__); ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL, EXTERNAL_OFFLINE); { Locker::Autolock _l(ctx->mDrawLock); ctx->mVirtualonExtActive = false; } } /* Wait for few frames for SF to tear down the WFD session. */ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period * 2 / 1000); }
bool IdleInvalidator::setIdleTimeout(const uint32_t& timeout) { ALOGD_IF(II_DEBUG, "IdleInvalidator::%s timeout %d", __FUNCTION__, timeout); // Open a sysfs node to send the timeout value to driver. int fd = open(IDLE_TIME_PATH, O_WRONLY); if (fd < 0) { ALOGE ("%s:Unable to open %s node %s", __FUNCTION__, IDLE_TIME_PATH, strerror(errno)); return false; } char strSleepTime[64]; snprintf(strSleepTime, sizeof(strSleepTime), "%d", timeout); // Notify driver about the timeout value ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0); if(len < -1) { ALOGE ("%s:Unable to write into %s node %s", __FUNCTION__, IDLE_TIME_PATH, strerror(errno)); close(fd); return false; } close(fd); return true; }
static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) { int vsync = 0; int64_t timestamp = 0; const char *str = udata; if(!strcasestr(str, "@/devices/virtual/graphics/fb")) { ALOGD_IF(DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__); return; } // parse HDMI events // The event will be of the form: // change@/devices/virtual/graphics/fb1 ACTION=change // DEVPATH=/devices/virtual/graphics/fb1 // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29 // for now just parsing onlin/offline info is enough str = udata; if(!(strncmp(str,"online@",strlen("online@")))) { strncpy(ctx->mHDMIEvent,str,strlen(str)); ctx->hdmi_pending = true; //Invalidate hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; if(!proc) { ALOGE("%s: HWC proc not registered", __FUNCTION__); } else { proc->invalidate(proc); } } else if(!(strncmp(str,"offline@",strlen("offline@")))) { ctx->hdmi_pending = false; ctx->mExtDisplay->processUEventOffline(str); } }
IntelSpritePlane::IntelSpritePlane(int fd, int index, IntelBufferManager *bm) : IntelDisplayPlane(fd, IntelDisplayPlane::DISPLAY_PLANE_SPRITE, index, bm) { bool ret; ALOGD_IF(ALLOW_SPRITE_PRINT, "%s\n", __func__); // create data buffer IntelDisplayBuffer *dataBuffer = new IntelDisplayDataBuffer(0, 0, 0); if (!dataBuffer) { ALOGE("%s: Failed to create sprite data buffer\n", __func__); return; } // create sprite context IntelSpriteContext *spriteContext = new IntelSpriteContext(); if (!spriteContext) { ALOGE("%s: Failed to create sprite context\n", __func__); goto sprite_create_err; } // initialized successfully mDataBuffer = dataBuffer; mContext = spriteContext; mInitialized = true; return; sprite_create_err: delete dataBuffer; }
// pass the buffered IGraphicBufferProducer to the camera service status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer) { ALOGV("setPreviewTarget(%p)", bufferProducer.get()); sp <ICamera> c = mCamera; if (c == 0) return NO_INIT; ALOGD_IF(bufferProducer == 0, "app passed NULL surface"); return c->setPreviewTarget(bufferProducer); }
void QClient::MPDeathNotifier::died() { Locker::Autolock _sl(mHwcContext->mDrawLock); ALOGD_IF(QCLIENT_DEBUG, "Media Player died"); mHwcContext->mSecuring = false; mHwcContext->mSecureMode = false; if(mHwcContext->proc) mHwcContext->proc->invalidate(mHwcContext->proc); }
int ExynosHWCService::setExternalDisplayPause(bool onoff) { ALOGD_IF(HWC_SERVICE_DEBUG, "%s::onoff=%d", __func__, onoff); if (mHWCCtx) mHWCCtx->external_display_pause = onoff; return NO_ERROR; }
void ExternalDisplay::setResolution(int ID) { struct fb_var_screeninfo info; int ret = 0; if (!openFramebuffer()) return; ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo); if(ret < 0) { ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__, strerror(errno)); } ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d)," "(%d,%d,%d) %dMHz>", __FUNCTION__, mVInfo.reserved[3], mVInfo.xres, mVInfo.yres, mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin, mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin, mVInfo.pixclock/1000/1000); //If its a valid mode and its a new ID - update var_screeninfo if ((isValidMode(ID)) && mCurrentMode != ID) { const struct disp_mode_timing_type *mode = &supported_video_mode_lut[0]; unsigned count = sizeof(supported_video_mode_lut)/sizeof (*supported_video_mode_lut); for (unsigned int i = 0; i < count; ++i) { const struct disp_mode_timing_type *cur = &supported_video_mode_lut[i]; if (cur->video_format == ID) mode = cur; } mode->set_info(mVInfo); ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d" "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID, mVInfo.reserved[3], mVInfo.xres, mVInfo.yres, mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin, mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin, mVInfo.pixclock/1000/1000); mVInfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE; ret = ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo); if(ret < 0) { ALOGD("In %s: FBIOPUT_VSCREENINFO failed Err Str = %s", __FUNCTION__, strerror(errno)); } mCurrentMode = ID; } }
bool IntelHDMIDisplayDevice::prepare(hwc_display_contents_1_t *list) { ALOGD_IF(ALLOW_HWC_PRINT, "%s", __func__); if (!initCheck()) { ALOGE("%s: failed to initialize HWComposer\n", __func__); return false; } if (mIsBlank) { //ALOGW("%s: HWC is blank, bypass", __func__); return false; } int index = checkTrickMode(list, false); bool findHint = (index >= 0); bool forceCheckingList = (findHint != mVideoSeekingActive); mVideoSeekingActive = findHint; if (!list || (list->flags & HWC_GEOMETRY_CHANGED) || forceCheckingList) { onGeometryChanged(list); if (findHint) { hwc_layer_1_t *layer = &list->hwLayers[index]; if (layer != NULL) layer->compositionType = HWC_FRAMEBUFFER; } } // handle hotplug event here if (mHotplugEvent) { ALOGD_IF(ALLOW_HWC_PRINT, "%s: reset hotplug event flag\n", __func__); mHotplugEvent = false; } // handle buffer changing. setup data buffer. if (list && !updateLayersData(list)) { ALOGD_IF(ALLOW_HWC_PRINT, "prepare: revisiting layer list\n"); revisitLayerList(list, false); } if (mForceSwapBuffer && !mGraphicPlaneVisible) { ALOGD_IF(ALLOW_HWC_PRINT, "Ebable HDMI gfx plane due to forcing swap buffer"); enableHDMIGraphicPlane(true); } return true; }
int ExynosHWCService::setVideoPlayStatus(unsigned int status) { ALOGD_IF(HWC_SERVICE_DEBUG, "%s::status=%d", __func__, status); if (mHWCCtx) mHWCCtx->video_playback_status = status; return NO_ERROR; }
void SensorService::SensorEventConnection::updateLooperRegistrationLocked( const sp<Looper>& looper) { bool isConnectionActive = (mSensorInfo.size() > 0 && !mDataInjectionMode) || mDataInjectionMode; // If all sensors are unregistered OR Looper has encountered an error, we can remove the Fd from // the Looper if it has been previously added. if (!isConnectionActive || mDead) { if (mHasLooperCallbacks) { ALOGD_IF(DEBUG_CONNECTIONS, "%p removeFd fd=%d", this, mChannel->getSendFd()); looper->removeFd(mChannel->getSendFd()); mHasLooperCallbacks = false; } return; } int looper_flags = 0; if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT; if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT; for (size_t i = 0; i < mSensorInfo.size(); ++i) { const int handle = mSensorInfo.keyAt(i); sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle); if (si != nullptr && si->getSensor().isWakeUpSensor()) { looper_flags |= ALOOPER_EVENT_INPUT; } } // If flags is still set to zero, we don't need to add this fd to the Looper, if the fd has // already been added, remove it. This is likely to happen when ALL the events stored in the // cache have been sent to the corresponding app. if (looper_flags == 0) { if (mHasLooperCallbacks) { ALOGD_IF(DEBUG_CONNECTIONS, "removeFd fd=%d", mChannel->getSendFd()); looper->removeFd(mChannel->getSendFd()); mHasLooperCallbacks = false; } return; } // Add the file descriptor to the Looper for receiving acknowledegments if the app has // registered for wake-up sensors OR for sending events in the cache. int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, NULL); if (ret == 1) { ALOGD_IF(DEBUG_CONNECTIONS, "%p addFd fd=%d", this, mChannel->getSendFd()); mHasLooperCallbacks = true; } else { ALOGE("Looper::addFd failed ret=%d fd=%d", ret, mChannel->getSendFd()); } }