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;
}
Example #2
0
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;
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
0
 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());
 }
Example #7
0
 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();
}
Example #9
0
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;
}
Example #10
0
 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());
 }
Example #11
0
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;
}
Example #13
0
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;
}
Example #17
0
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
}
Example #21
0
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
    }
}
Example #24
0
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;
}
Example #25
0
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;
}
Example #26
0
// 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;
}
Example #27
0
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;
}