bool DisplayHardwareBase::DisplayEventThread::threadLoop() { int err = 0; char buf; int fd; fd = open(kSleepFileName, O_RDONLY, 0); do { err = read(fd, &buf, 1); } while (err < 0 && errno == EINTR); close(fd); LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno)); if (err >= 0) { sp<SurfaceFlinger> flinger = mFlinger.promote(); LOGD("About to give-up screen, flinger = %p", flinger.get()); if (flinger != 0) { mBarrier.close(); flinger->screenReleased(0); mBarrier.wait(); } } fd = open(kWakeFileName, O_RDONLY, 0); do { err = read(fd, &buf, 1); } while (err < 0 && errno == EINTR); close(fd); LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno)); if (err >= 0) { sp<SurfaceFlinger> flinger = mFlinger.promote(); LOGD("Screen about to return, flinger = %p", flinger.get()); if (flinger != 0) flinger->screenAcquired(0); } return true; }
void GameModeManager::LoadHerissonTexture(int type) { LOGW_IF(type > 8, "type > 8"); LOGW_IF(type < 1, "type < 1"); type = (type > 8 ? 8 : (type < 1 ? 1 : type)); char tmp[32]; snprintf(tmp, 32, "herisson_%d", type); ANIMATION(herisson)->name = Murmur::RuntimeHash(tmp); }
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; if (usage & GRALLOC_USAGE_HW_MASK) { err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); } else { err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride); } LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bytesPerPixel(format); list.add(*handle, rec); } return err; }
status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking) { int active; int timeout = 0; status_t result; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = audioBuffer->frameCount; audioBuffer->frameCount = 0; audioBuffer->size = 0; uint32_t framesReady = cblk->framesReady(); if (framesReady == 0) { Mutex::Autolock _l(cblk->lock); goto start_loop_here; while (framesReady == 0) { active = mActive; if (UNLIKELY(!active)) return NO_MORE_BUFFERS; if (UNLIKELY(!blocking)) return WOULD_BLOCK; timeout = 0; result = cblk->cv.waitRelative(cblk->lock, seconds(1)); if (__builtin_expect(result!=NO_ERROR, false)) { LOGW( "obtainBuffer timed out (is the CPU pegged?) " "user=%08x, server=%08x", cblk->user, cblk->server); timeout = 1; } // read the server count again start_loop_here: framesReady = cblk->framesReady(); } } LOGW_IF(timeout, "*** SERIOUS WARNING *** obtainBuffer() timed out " "but didn't need to be locked. We recovered, but " "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); if (framesReq > framesReady) { framesReq = framesReady; } uint32_t u = cblk->user; uint32_t bufferEnd = cblk->userBase + cblk->frameCount; if (u + framesReady > bufferEnd) { framesReq = bufferEnd - u; } audioBuffer->flags = 0; audioBuffer->channelCount= mChannelCount; audioBuffer->format = mFormat; audioBuffer->frameCount = framesReq; audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t); audioBuffer->raw = (int8_t*)cblk->buffer(u); active = mActive; return active ? status_t(NO_ERROR) : status_t(STOPPED); }
static jboolean Emulator_initialize(JNIEnv *env, jobject self, jstring jdir, jstring jlib) { static EngineCallbacks cbs; const char *dir = env->GetStringUTFChars(jdir, NULL); const char *lib = env->GetStringUTFChars(jlib, NULL); jboolean rv = JNI_FALSE; engine = loadEmuEngine(dir, lib); if (engine == NULL || !engine->initialize(&cbs)) { LOGE("Cannot load emulator engine"); goto bail; } audioPlayer = loadAudioPlayer(dir); LOGW_IF(audioPlayer == NULL, "Cannot initialize sound module"); ticksInitialize(); emuState = EMUSTATE_PAUSED; renderSurface = NULL; currentGame = NULL; resumeRequested = false; autoFrameSkip = true; maxFrameSkips = 2; soundEnabled = false; rv = JNI_TRUE; bail: env->ReleaseStringUTFChars(jdir, dir); env->ReleaseStringUTFChars(jlib, lib); return rv; }
int getMaxFiles() { const std::string files = getEnv("LOG_MAXFILES"); LOGD_IF(!files.empty()) << "ENV.LOG_MAXFILES:" << files; LOGW_IF(files.empty()) << "ENV.LOG_MAXFILES:" << "NULL"; return files.empty() ? 0 : std::atoi(files.c_str()); }
size_t getMaxFileSize() { const std::string size = getEnv("LOG_MAXFILESIZE"); LOGD_IF(!size.empty()) << "ENV.LOG_MAXFILESIZE:" << size; LOGW_IF(size.empty()) << "ENV.LOG_MAXFILESIZE:" << "NULL"; return size.empty() ? 0 : std::atoi(size.c_str()); }
SoundPool::SoundPool(jobject soundPoolRef, int maxChannels, int streamType, int srcQuality) { LOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d", maxChannels, streamType, srcQuality); // check limits mMaxChannels = maxChannels; if (mMaxChannels < 1) { mMaxChannels = 1; } else if (mMaxChannels > 32) { mMaxChannels = 32; } LOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels); mQuit = false; mSoundPoolRef = soundPoolRef; mDecodeThread = 0; mStreamType = streamType; mSrcQuality = srcQuality; mAllocated = 0; mNextSampleID = 0; mNextChannelID = 0; mChannelPool = new SoundChannel[mMaxChannels]; for (int i = 0; i < mMaxChannels; ++i) { mChannelPool[i].init(this); mChannels.push_back(&mChannelPool[i]); } // start decode thread startThreads(); }
status_t GraphicBufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds, void** vaddr) { status_t err; #ifdef MISSING_GRALLOC_BUFFERS int tries=5; #endif err = mAllocMod->lock(mAllocMod, handle, usage, bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); #ifdef MISSING_GRALLOC_BUFFERS while (err && tries) { usleep(1000); err = mAllocMod->unlock(mAllocMod, handle); err = mAllocMod->lock(mAllocMod, handle, usage, bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); tries--; } #endif LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err)); return err; }
plog::Severity getLevel() { const std::string level = getEnv("LOG_LEVEL"); LOGD_IF(!level.empty()) << "ENV.LOG_LEVEL:" << level << ":" << plog::severityFromString(level.c_str()); LOGW_IF(level.empty()) << "ENV.LOG_LEVEL:" << "NULL"; return level.empty() ? plog::debug : plog::severityFromString(level.c_str()); }
status_t GraphicBufferMapper::unlock(buffer_handle_t handle) { status_t err; err = mAllocMod->unlock(mAllocMod, handle); LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); return err; }
status_t GraphicBufferMapper::getphys(buffer_handle_t handle, void** paddr) { status_t err; err = mAllocMod->getphys(mAllocMod, handle, paddr); LOGW_IF(err, "getphys(%p) fail %d(%s)", handle, err, strerror(-err)); return err; }
status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle) { status_t err; err = mAllocMod->unregisterBuffer(mAllocMod, handle); LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)", handle, err, strerror(-err)); return err; }
// must be called with mLock and cblk.lock held. Callers must also hold strong references on // the IAudioRecord and IMemory in case they are recreated here. // If the IAudioRecord is successfully restored, the cblk pointer is updated status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) { status_t result; if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { LOGW("dead IAudioRecord, creating a new one"); // signal old cblk condition so that other threads waiting for available buffers stop // waiting now cblk->cv.broadcast(); cblk->lock.unlock(); // if the new IAudioRecord is created, openRecord_l() will modify the // following member variables: mAudioRecord, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioRecord and IMemory result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask, mFrameCount, mFlags, getInput_l()); if (result == NO_ERROR) { result = mAudioRecord->start(); } if (result != NO_ERROR) { mActive = false; } // signal old cblk condition for other threads waiting for restore completion android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); cblk->cv.broadcast(); } else { if (!(cblk->flags & CBLK_RESTORED_MSK)) { LOGW("dead IAudioRecord, waiting for a new one to be created"); mLock.unlock(); result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); cblk->lock.unlock(); mLock.lock(); } else { LOGW("dead IAudioRecord, already restored"); result = NO_ERROR; cblk->lock.unlock(); } if (result != NO_ERROR || mActive == 0) { result = status_t(STOPPED); } } LOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); if (result == NO_ERROR) { // from now on we switch to the newly created cblk cblk = mCblk; } cblk->lock.lock(); LOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); return result; }
void SurfaceTexture::freeAllBuffersLocked() { LOGW_IF(!mQueue.isEmpty(), "freeAllBuffersLocked called but mQueue is not empty"); mCurrentTexture = INVALID_BUFFER_SLOT; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { freeBufferLocked(i); } #ifdef QCOM_HARDWARE mGraphicBufferAlloc->freeAllGraphicBuffersExcept(-1); #endif }
bool DisplayHardwareBase::DisplayEventThread::threadLoop() { int err = 0; char buf; int fd; fd = open(kSleepFileName, O_RDONLY, 0); if (fd == -1 && errno == ENOENT) { usleep(166667); // Sleep to avoid 100% CPU usage. return true; // End silently if FB_EARLYSUSPEND appears to be missing, as on kernels >= 3.3 } do { err = read(fd, &buf, 1); } while (err < 0 && errno == EINTR); close(fd); LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno)); if (err >= 0) { sp<SurfaceFlinger> flinger = mFlinger.promote(); LOGD("About to give-up screen, flinger = %p", flinger.get()); if (flinger != 0) { mBarrier.close(); flinger->screenReleased(0); mBarrier.wait(); } } fd = open(kWakeFileName, O_RDONLY, 0); do { err = read(fd, &buf, 1); } while (err < 0 && errno == EINTR); close(fd); LOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno)); if (err >= 0) { sp<SurfaceFlinger> flinger = mFlinger.promote(); LOGD("Screen about to return, flinger = %p", flinger.get()); if (flinger != 0) flinger->screenAcquired(0); } return true; }
status_t GraphicBufferAllocator::free(buffer_handle_t handle) { status_t err; err = mAllocDev->free(mAllocDev, handle); LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); list.removeItem(handle); } return err; }
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; #ifdef MISSING_EGL_PIXEL_FORMAT_YV12 if (format == HAL_PIXEL_FORMAT_YV12) { format = HAL_PIXEL_FORMAT_RGBA_8888; } if (format == 0x1B) { format = HAL_PIXEL_FORMAT_RGBA_8888; } if (usage & GRALLOC_USAGE_EXTERNAL_DISP) { usage ^= GRALLOC_USAGE_EXTERNAL_DISP; } #endif err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); int bpp = bytesPerPixel(format); if (bpp < 0) { // probably a HAL custom format. in any case, we don't know // what its pixel size is. bpp = 0; } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bpp; list.add(*handle, rec); } return err; }
status_t SurfaceComposerClient::destroySurface(SurfaceID sid) { if (mStatus != NO_ERROR) return mStatus; // it's okay to destroy a surface while a transaction is open, // (transactions really are a client-side concept) // however, this indicates probably a misuse of the API or a bug // in the client code. LOGW_IF(mTransactionOpen, "Destroying surface while a transaction is open. " "Client %p: destroying surface %d, mTransactionOpen=%d", this, sid, mTransactionOpen); status_t err = mClient->destroySurface(sid); return err; }
void SurfaceTexture::freeAllBuffersExceptHeadLocked() { LOGW_IF(!mQueue.isEmpty(), "freeAllBuffersExceptCurrentLocked called but mQueue is not empty"); int head = -1; if (!mQueue.empty()) { Fifo::iterator front(mQueue.begin()); head = *front; } mCurrentTexture = INVALID_BUFFER_SLOT; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { if (i != head) { freeBufferLocked(i); } } #ifdef QCOM_HARDWARE mGraphicBufferAlloc->freeAllGraphicBuffersExcept(head); #endif }
HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mModule(0), mHwc(0), mList(0), mCapacity(0), mNumOVLayers(0), mNumFBLayers(0), mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE) { int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); if (err == 0) { err = hwc_open(mModule, &mHwc); LOGE_IF(err, "%s device failed to initialize (%s)", HWC_HARDWARE_COMPOSER, strerror(-err)); if (err == 0) { if (mHwc->registerProcs) { mCBContext.hwc = this; mCBContext.procs.invalidate = &hook_invalidate; mHwc->registerProcs(mHwc, &mCBContext.procs); } } } }
int HWComposer::init() { int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); if (err) return err; err = hwc_open(mModule, &mHwc); LOGE_IF(err, "%s device failed to initialize (%s)", HWC_HARDWARE_COMPOSER, strerror(-err)); if (err) { mHwc = NULL; return err; } if (mHwc->registerProcs) { mCBContext.hwc = this; mHwc->registerProcs(mHwc, &mCBContext.procs); } return 0; }
SimpleMemory::~SimpleMemory() { size_t freedOffset = getOffset(); size_t freedSize = getSize(); // keep the size to unmap in excess size_t pagesize = getpagesize(); size_t start = freedOffset; size_t end = start + freedSize; start &= ~(pagesize-1); end = (end + pagesize-1) & ~(pagesize-1); // give back to the kernel the pages we don't need size_t free_start = freedOffset; size_t free_end = free_start + freedSize; if (start < free_start) start = free_start; if (end > free_end) end = free_end; start = (start + pagesize-1) & ~(pagesize-1); end &= ~(pagesize-1); if (start < end) { void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start); size_t size = end-start; #ifndef NDEBUG memset(start_ptr, 0xdf, size); #endif // MADV_REMOVE is not defined on Dapper based Goobuntu #ifdef MADV_REMOVE if (size) { int err = madvise(start_ptr, size, MADV_REMOVE); LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s", start_ptr, size, err<0 ? strerror(errno) : "Ok"); } #endif } }
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { // make sure to not allocate a 0 x 0 buffer w = clamp(w); h = clamp(h); // we have a h/w allocator and h/w buffer is requested status_t err; if (usage & GRALLOC_USAGE_HW_MASK) { err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); } else { err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride); } LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); alloc_rec_t rec; rec.w = w; rec.h = h; rec.format = format; rec.usage = usage; rec.vaddr = 0; rec.size = h * stride[0] * bytesPerPixel(format); list.add(*handle, rec); } else { String8 s; dump(s); LOGD("%s", s.string()); } return err; }
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; #ifdef MISSING_EGL_PIXEL_FORMAT_YV12 if (format == HAL_PIXEL_FORMAT_YV12) { format = HAL_PIXEL_FORMAT_RGBA_8888; } if (format == 27) { //OMX_COLOR_FormatCbYCrY (both are 16bpp) format = HAL_PIXEL_FORMAT_RGB_565; } if (!(usage & GRALLOC_USAGE_SW_READ_MASK)) { usage |= GRALLOC_USAGE_SW_READ_RARELY; } if (!(usage & GRALLOC_USAGE_SW_WRITE_MASK)) { usage |= GRALLOC_USAGE_SW_WRITE_RARELY; } if (usage & GRALLOC_USAGE_EXTERNAL_DISP) { usage ^= GRALLOC_USAGE_EXTERNAL_DISP; } #endif #ifdef CUSTOM_OMX_16BPP_YUV // 27: OMX_COLOR_FormatCbYCrY (both are 16bpp, so same buffer size) if (format == CUSTOM_OMX_16BPP_YUV) { LOGD("%s: Override OMX_COLOR_FormatCbYCrY", __FUNCTION__); format = HAL_PIXEL_FORMAT_RGB_565; } #endif err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); int bpp = bytesPerPixel(format); if (bpp < 0) { // probably a HAL custom format. in any case, we don't know // what its pixel size is. bpp = 0; } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bpp; list.add(*handle, rec); } return err; }
// must be called with mLock held status_t AudioTrack::createTrack_l( int streamType, uint32_t sampleRate, uint32_t format, uint32_t channelMask, int frameCount, uint32_t flags, const sp<IMemory>& sharedBuffer, audio_io_handle_t output, bool enforceFrameCount) { status_t status; const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); if (audioFlinger == 0) { LOGE("Could not get audioflinger"); return NO_INIT; } int afSampleRate; if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; } int afFrameCount; if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { return NO_INIT; } uint32_t afLatency; if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { return NO_INIT; } mNotificationFramesAct = mNotificationFramesReq; if (!audio_is_linear_pcm(format)) { if (sharedBuffer != 0) { frameCount = sharedBuffer->size(); } } else { // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); if (minBufCount < 2) minBufCount = 2; int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; if (sharedBuffer == 0) { if (frameCount == 0) { frameCount = minFrameCount; } if (mNotificationFramesAct == 0) { mNotificationFramesAct = frameCount/2; } // Make sure that application is notified with sufficient margin // before underrun if (mNotificationFramesAct > (uint32_t)frameCount/2) { mNotificationFramesAct = frameCount/2; } if (frameCount < minFrameCount) { LOGW_IF(enforceFrameCount, "Minimum buffer size corrected from %d to %d", frameCount, minFrameCount); frameCount = minFrameCount; } } else { // Ensure that buffer alignment matches channelcount int channelCount = popcount(channelMask); if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) { LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount); return BAD_VALUE; } frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t); } } sp<IAudioTrack> track = audioFlinger->createTrack(getpid(), streamType, sampleRate, format, channelMask, frameCount, ((uint16_t)flags) << 16, sharedBuffer, output, &mSessionId, &status); if (track == 0) { LOGE("AudioFlinger could not create track, status: %d", status); return status; } sp<IMemory> cblk = track->getCblk(); if (cblk == 0) { LOGE("Could not get control block"); return NO_INIT; } mAudioTrack.clear(); mAudioTrack = track; mCblkMemory.clear(); mCblkMemory = cblk; mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags); if (sharedBuffer == 0) { mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); } else { mCblk->buffers = sharedBuffer->pointer(); // Force buffer full condition as data is already present in shared memory mCblk->stepUser(mCblk->frameCount); } mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000); mCblk->sendLevel = uint16_t(mSendLevel * 0x1000); mAudioTrack->attachAuxEffect(mAuxEffectId); mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->waitTimeMs = 0; mRemainingFrames = mNotificationFramesAct; mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate; return NO_ERROR; }
DisplayHardwareBase::ConsoleManagerThread::ConsoleManagerThread( const sp<SurfaceFlinger>& flinger) : DisplayEventThreadBase(flinger), consoleFd(-1) { sSignalCatcherPid = 0; // create a new console char const * const ttydev = "/dev/tty0"; int fd = open(ttydev, O_RDWR | O_SYNC); if (fd<0) { LOGE("Can't open %s", ttydev); this->consoleFd = -errno; return; } // to make sure that we are in text mode int res = ioctl(fd, KDSETMODE, (void*) KD_TEXT); if (res<0) { LOGE("ioctl(%d, KDSETMODE, ...) failed, res %d (%s)", fd, res, strerror(errno)); } // get the current console struct vt_stat vs; res = ioctl(fd, VT_GETSTATE, &vs); if (res<0) { LOGE("ioctl(%d, VT_GETSTATE, ...) failed, res %d (%s)", fd, res, strerror(errno)); this->consoleFd = -errno; return; } // switch to console 7 (which is what X normaly uses) int vtnum = 7; do { res = ioctl(fd, VT_ACTIVATE, (void*)vtnum); } while(res < 0 && errno == EINTR); if (res<0) { LOGE("ioctl(%d, VT_ACTIVATE, ...) failed, %d (%s) for %d", fd, errno, strerror(errno), vtnum); this->consoleFd = -errno; return; } do { res = ioctl(fd, VT_WAITACTIVE, (void*)vtnum); } while(res < 0 && errno == EINTR); if (res<0) { LOGE("ioctl(%d, VT_WAITACTIVE, ...) failed, %d %d %s for %d", fd, res, errno, strerror(errno), vtnum); this->consoleFd = -errno; return; } // open the new console close(fd); fd = open(ttydev, O_RDWR | O_SYNC); if (fd<0) { LOGE("Can't open new console %s", ttydev); this->consoleFd = -errno; return; } /* disable console line buffer, echo, ... */ struct termios ttyarg; ioctl(fd, TCGETS , &ttyarg); ttyarg.c_iflag = 0; ttyarg.c_lflag = 0; ioctl(fd, TCSETS , &ttyarg); // set up signals so we're notified when the console changes // we can't use SIGUSR1 because it's used by the java-vm vm.mode = VT_PROCESS; vm.waitv = 0; vm.relsig = SIGUSR2; vm.acqsig = SIGUNUSED; vm.frsig = 0; struct sigaction act; sigemptyset(&act.sa_mask); act.sa_handler = sigHandler; act.sa_flags = 0; sigaction(vm.relsig, &act, NULL); sigemptyset(&act.sa_mask); act.sa_handler = sigHandler; act.sa_flags = 0; sigaction(vm.acqsig, &act, NULL); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, vm.relsig); sigaddset(&mask, vm.acqsig); sigprocmask(SIG_BLOCK, &mask, NULL); // switch to graphic mode res = ioctl(fd, KDSETMODE, (void*)KD_GRAPHICS); LOGW_IF(res<0, "ioctl(%d, KDSETMODE, KD_GRAPHICS) failed, res %d", fd, res); this->prev_vt_num = vs.v_active; this->vt_num = vtnum; this->consoleFd = fd; }
status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage); if ((w && !h) || (!w && h)) { ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h); return BAD_VALUE; } status_t returnFlags(OK); EGLDisplay dpy = EGL_NO_DISPLAY; EGLSyncKHR fence = EGL_NO_SYNC_KHR; { // Scope for the lock Mutex::Autolock lock(mMutex); int found = -1; int foundSync = -1; int dequeuedCount = 0; bool tryAgain = true; #ifdef MISSING_GRALLOC_BUFFERS int dequeueRetries = 5; #endif while (tryAgain) { if (mAbandoned) { ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!"); return NO_INIT; } // We need to wait for the FIFO to drain if the number of buffer // needs to change. // // The condition "number of buffers needs to change" is true if // - the client doesn't care about how many buffers there are // - AND the actual number of buffer is different from what was // set in the last setBufferCountServer() // - OR - // setBufferCountServer() was set to a value incompatible with // the synchronization mode (for instance because the sync mode // changed since) // // As long as this condition is true AND the FIFO is not empty, we // wait on mDequeueCondition. const int minBufferCountNeeded = mSynchronousMode ? MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS; const bool numberOfBuffersNeedsToChange = !mClientBufferCount && ((mServerBufferCount != mBufferCount) || (mServerBufferCount < minBufferCountNeeded)); if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) { // wait for the FIFO to drain mDequeueCondition.wait(mMutex); // NOTE: we continue here because we need to reevaluate our // whole state (eg: we could be abandoned or disconnected) continue; } if (numberOfBuffersNeedsToChange) { // here we're guaranteed that mQueue is empty freeAllBuffersLocked(); mBufferCount = mServerBufferCount; if (mBufferCount < minBufferCountNeeded) mBufferCount = minBufferCountNeeded; mCurrentTexture = INVALID_BUFFER_SLOT; returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS; } // look for a free buffer to give to the client found = INVALID_BUFFER_SLOT; foundSync = INVALID_BUFFER_SLOT; dequeuedCount = 0; for (int i = 0; i < mBufferCount; i++) { const int state = mSlots[i].mBufferState; if (state == BufferSlot::DEQUEUED) { dequeuedCount++; } // if buffer is FREE it CANNOT be current LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i), "dequeueBuffer: buffer %d is both FREE and current!", i); if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) { if (state == BufferSlot::FREE || i == mCurrentTexture) { foundSync = i; if (i != mCurrentTexture) { found = i; break; } } } else { if (state == BufferSlot::FREE) { /* We return the oldest of the free buffers to avoid * stalling the producer if possible. This is because * the consumer may still have pending reads of the * buffers in flight. */ bool isOlder = mSlots[i].mFrameNumber < mSlots[found].mFrameNumber; if (found < 0 || isOlder) { foundSync = i; found = i; } } } } // clients are not allowed to dequeue more than one buffer // if they didn't set a buffer count. if (!mClientBufferCount && dequeuedCount) { #ifdef MISSING_GRALLOC_BUFFERS if (--dequeueRetries) { LOGD("SurfaceTexture::dequeue: Not allowed to dequeue more " "than a buffer SLEEPING\n"); usleep(10000); } else { mClientBufferCount = mServerBufferCount; LOGD("SurfaceTexture::dequeue: Not allowed to dequeue more " "than a buffer RETRY mBufferCount:%d mServerBufferCount:%d\n", mBufferCount, mServerBufferCount); } continue; #else ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without " "setting the buffer count"); #endif return -EINVAL; } // See whether a buffer has been queued since the last // setBufferCount so we know whether to perform the // MIN_UNDEQUEUED_BUFFERS check below. bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT; if (bufferHasBeenQueued) { // make sure the client is not trying to dequeue more buffers // than allowed. const int avail = mBufferCount - (dequeuedCount+1); if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) { #ifdef MISSING_GRALLOC_BUFFERS if (mClientBufferCount != 0) { mBufferCount++; mClientBufferCount = mServerBufferCount = mBufferCount; LOGD("SurfaceTexture::dequeuebuffer: MIN EXCEEDED " "mBuffer:%d bumped\n", mBufferCount); continue; } #endif ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded " "(dequeued=%d)", MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode), dequeuedCount); return -EBUSY; } } // we're in synchronous mode and didn't find a buffer, we need to // wait for some buffers to be consumed tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT); if (tryAgain) { mDequeueCondition.wait(mMutex); } } if (mSynchronousMode && found == INVALID_BUFFER_SLOT) { // foundSync guaranteed to be != INVALID_BUFFER_SLOT found = foundSync; } if (found == INVALID_BUFFER_SLOT) { // This should not happen. ST_LOGE("dequeueBuffer: no available buffer slots"); return -EBUSY; } const int buf = found; *outBuf = found; const bool useDefaultSize = !w && !h; if (useDefaultSize) { // use the default size w = mDefaultWidth; h = mDefaultHeight; } const bool updateFormat = (format != 0); if (!updateFormat) { // keep the current (or default) format format = mPixelFormat; } // buffer is now in DEQUEUED (but can also be current at the same time, // if we're in synchronous mode) mSlots[buf].mBufferState = BufferSlot::DEQUEUED; const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); #ifdef QCOM_HARDWARE qBufGeometry currentGeometry; if (buffer != NULL) currentGeometry.set(buffer->width, buffer->height, buffer->format); else currentGeometry.set(0, 0, 0); qBufGeometry requiredGeometry; requiredGeometry.set(w, h, format); qBufGeometry updatedGeometry; updatedGeometry.set(mNextBufferInfo.width, mNextBufferInfo.height, mNextBufferInfo.format); #endif if ((buffer == NULL) || #ifdef QCOM_HARDWARE needNewBuffer(currentGeometry, requiredGeometry, updatedGeometry) || #else (uint32_t(buffer->width) != w) || (uint32_t(buffer->height) != h) || (uint32_t(buffer->format) != format) || #endif ((uint32_t(buffer->usage) & usage) != usage)) { #ifdef QCOM_HARDWARE if (buffer != NULL) { mGraphicBufferAlloc->freeGraphicBufferAtIndex(buf); } #endif usage |= GraphicBuffer::USAGE_HW_TEXTURE; status_t error; sp<GraphicBuffer> graphicBuffer( mGraphicBufferAlloc->createGraphicBuffer( w, h, format, usage, &error)); if (graphicBuffer == 0) { ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer " "failed"); return error; } if (updateFormat) { mPixelFormat = format; } #ifdef QCOM_HARDWARE checkBuffer((native_handle_t *)graphicBuffer->handle, mReqSize, usage); #endif mSlots[buf].mGraphicBuffer = graphicBuffer; mSlots[buf].mRequestBufferCalled = false; mSlots[buf].mFence = EGL_NO_SYNC_KHR; if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) { eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage); mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR; mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; } if (mCurrentTexture == buf) { // The current texture no longer references the buffer in this slot // since we just allocated a new buffer. mCurrentTexture = INVALID_BUFFER_SLOT; } returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION; } dpy = mSlots[buf].mEglDisplay; fence = mSlots[buf].mFence; mSlots[buf].mFence = EGL_NO_SYNC_KHR; } if (fence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. if (result == EGL_FALSE) { LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError()); } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { LOGE("dequeueBuffer: timeout waiting for fence"); } eglDestroySyncKHR(dpy, fence); } ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf, mSlots[*outBuf].mGraphicBuffer->handle, returnFlags); return returnFlags; }