diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/binder/IBatteryStats.cpp | 80 | ||||
| -rw-r--r-- | libs/gui/BitTube.cpp | 5 | ||||
| -rw-r--r-- | libs/gui/BufferQueueCore.cpp | 11 | ||||
| -rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 131 | ||||
| -rw-r--r-- | libs/gui/GLConsumer.cpp | 324 | ||||
| -rw-r--r-- | libs/gui/ISensorEventConnection.cpp | 15 | ||||
| -rw-r--r-- | libs/gui/Sensor.cpp | 81 | ||||
| -rw-r--r-- | libs/gui/SensorEventQueue.cpp | 10 | ||||
| -rw-r--r-- | libs/ui/GraphicBuffer.cpp | 1 |
9 files changed, 356 insertions, 302 deletions
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp index 5702151ca5..8f3b7b49ad 100644 --- a/libs/binder/IBatteryStats.cpp +++ b/libs/binder/IBatteryStats.cpp @@ -49,6 +49,46 @@ public: data.writeInt32(sensor); remote()->transact(NOTE_STOP_SENSOR_TRANSACTION, data, &reply); } + + virtual void noteStartVideo(int uid) { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + data.writeInt32(uid); + remote()->transact(NOTE_START_VIDEO_TRANSACTION, data, &reply); + } + + virtual void noteStopVideo(int uid) { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + data.writeInt32(uid); + remote()->transact(NOTE_STOP_VIDEO_TRANSACTION, data, &reply); + } + + virtual void noteStartAudio(int uid) { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + data.writeInt32(uid); + remote()->transact(NOTE_START_AUDIO_TRANSACTION, data, &reply); + } + + virtual void noteStopAudio(int uid) { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + data.writeInt32(uid); + remote()->transact(NOTE_STOP_AUDIO_TRANSACTION, data, &reply); + } + + virtual void noteResetVideo() { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + remote()->transact(NOTE_RESET_VIDEO_TRANSACTION, data, &reply); + } + + virtual void noteResetAudio() { + Parcel data, reply; + data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor()); + remote()->transact(NOTE_RESET_AUDIO_TRANSACTION, data, &reply); + } }; IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats"); @@ -75,6 +115,46 @@ status_t BnBatteryStats::onTransact( reply->writeNoException(); return NO_ERROR; } break; + case NOTE_START_VIDEO_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + int uid = data.readInt32(); + noteStartVideo(uid); + reply->writeNoException(); + return NO_ERROR; + } break; + case NOTE_STOP_VIDEO_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + int uid = data.readInt32(); + noteStopVideo(uid); + reply->writeNoException(); + return NO_ERROR; + } break; + case NOTE_START_AUDIO_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + int uid = data.readInt32(); + noteStartAudio(uid); + reply->writeNoException(); + return NO_ERROR; + } break; + case NOTE_STOP_AUDIO_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + int uid = data.readInt32(); + noteStopAudio(uid); + reply->writeNoException(); + return NO_ERROR; + } break; + case NOTE_RESET_VIDEO_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + noteResetVideo(); + reply->writeNoException(); + return NO_ERROR; + } break; + case NOTE_RESET_AUDIO_TRANSACTION: { + CHECK_INTERFACE(IBatteryStats, data, reply); + noteResetAudio(); + reply->writeNoException(); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp index 0282834703..3ed1f370a5 100644 --- a/libs/gui/BitTube.cpp +++ b/libs/gui/BitTube.cpp @@ -99,6 +99,11 @@ int BitTube::getFd() const return mReceiveFd; } +int BitTube::getSendFd() const +{ + return mSendFd; +} + ssize_t BitTube::write(void const* vaddr, size_t size) { ssize_t err, len; diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index 40e6884e39..ec1e63112d 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -64,7 +64,9 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) : mMaxAcquiredBufferCount(1), mBufferHasBeenQueued(false), mFrameCounter(0), - mTransformHint(0) + mTransformHint(0), + mIsAllocating(false), + mIsAllocatingCondition() { if (allocator == NULL) { sp<ISurfaceComposer> composer(ComposerService::getComposerService()); @@ -226,4 +228,11 @@ bool BufferQueueCore::stillTracking(const BufferItem* item) const { (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle); } +void BufferQueueCore::waitWhileAllocatingLocked() const { + ATRACE_CALL(); + while (mIsAllocating) { + mIsAllocatingCondition.wait(mMutex); + } +} + } // namespace android diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 849a12b969..cbca3acd2c 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -74,6 +74,7 @@ status_t BufferQueueProducer::setBufferCount(int bufferCount) { sp<IConsumerListener> listener; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); + mCore->waitWhileAllocatingLocked(); if (mCore->mIsAbandoned) { BQ_LOGE("setBufferCount: BufferQueue has been abandoned"); @@ -266,6 +267,7 @@ status_t BufferQueueProducer::dequeueBuffer(int *outSlot, { // Autolock scope Mutex::Autolock lock(mCore->mMutex); + mCore->waitWhileAllocatingLocked(); if (format == 0) { format = mCore->mDefaultBufferFormat; @@ -424,6 +426,7 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer, } Mutex::Autolock lock(mCore->mMutex); + mCore->waitWhileAllocatingLocked(); if (mCore->mIsAbandoned) { BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned"); @@ -468,6 +471,7 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot, } Mutex::Autolock lock(mCore->mMutex); + mCore->waitWhileAllocatingLocked(); status_t returnFlags = NO_ERROR; int found; @@ -796,6 +800,7 @@ status_t BufferQueueProducer::disconnect(int api) { sp<IConsumerListener> listener; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); + mCore->waitWhileAllocatingLocked(); if (mCore->mIsAbandoned) { // It's not really an error to disconnect after the surface has @@ -862,55 +867,101 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) void BufferQueueProducer::allocateBuffers(bool async, uint32_t width, uint32_t height, uint32_t format, uint32_t usage) { - Vector<int> freeSlots; + ATRACE_CALL(); + while (true) { + Vector<int> freeSlots; + size_t newBufferCount = 0; + uint32_t allocWidth = 0; + uint32_t allocHeight = 0; + uint32_t allocFormat = 0; + uint32_t allocUsage = 0; + { // Autolock scope + Mutex::Autolock lock(mCore->mMutex); + mCore->waitWhileAllocatingLocked(); + + int currentBufferCount = 0; + for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { + if (mSlots[slot].mGraphicBuffer != NULL) { + ++currentBufferCount; + } else { + if (mSlots[slot].mBufferState != BufferSlot::FREE) { + BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE", + slot); + continue; + } - Mutex::Autolock lock(mCore->mMutex); + freeSlots.push_back(slot); + } + } - int currentBufferCount = 0; - for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) { - if (mSlots[slot].mGraphicBuffer != NULL) { - ++currentBufferCount; - } else { - if (mSlots[slot].mBufferState != BufferSlot::FREE) { - BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE", - slot); - continue; + int maxBufferCount = mCore->getMaxBufferCountLocked(async); + BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers", + currentBufferCount, maxBufferCount); + if (maxBufferCount <= currentBufferCount) + return; + newBufferCount = maxBufferCount - currentBufferCount; + if (freeSlots.size() < newBufferCount) { + BQ_LOGE("allocateBuffers: ran out of free slots"); + return; } + allocWidth = width > 0 ? width : mCore->mDefaultWidth; + allocHeight = height > 0 ? height : mCore->mDefaultHeight; + allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat; + allocUsage = usage | mCore->mConsumerUsageBits; - freeSlots.push_front(slot); - } - } + mCore->mIsAllocating = true; + } // Autolock scope - int maxBufferCount = mCore->getMaxBufferCountLocked(async); - BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers", - currentBufferCount, maxBufferCount); - for (; currentBufferCount < maxBufferCount; ++currentBufferCount) { - if (freeSlots.empty()) { - BQ_LOGE("allocateBuffers: ran out of free slots"); - return; + Vector<sp<GraphicBuffer> > buffers; + for (size_t i = 0; i < newBufferCount; ++i) { + status_t result = NO_ERROR; + sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( + allocWidth, allocHeight, allocFormat, allocUsage, &result)); + if (result != NO_ERROR) { + BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" + " %u, usage %u)", width, height, format, usage); + Mutex::Autolock lock(mCore->mMutex); + mCore->mIsAllocating = false; + mCore->mIsAllocatingCondition.broadcast(); + return; + } + buffers.push_back(graphicBuffer); } - width = width > 0 ? width : mCore->mDefaultWidth; - height = height > 0 ? height : mCore->mDefaultHeight; - format = format != 0 ? format : mCore->mDefaultBufferFormat; - usage |= mCore->mConsumerUsageBits; + { // Autolock scope + Mutex::Autolock lock(mCore->mMutex); + uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth; + uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight; + uint32_t checkFormat = format != 0 ? format : mCore->mDefaultBufferFormat; + uint32_t checkUsage = usage | mCore->mConsumerUsageBits; + if (checkWidth != allocWidth || checkHeight != allocHeight || + checkFormat != allocFormat || checkUsage != allocUsage) { + // Something changed while we released the lock. Retry. + BQ_LOGV("allocateBuffers: size/format/usage changed while allocating. Retrying."); + mCore->mIsAllocating = false; + mCore->mIsAllocatingCondition.broadcast(); + continue; + } - status_t result = NO_ERROR; - sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer( - width, height, format, usage, &result)); - if (result != NO_ERROR) { - BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format" - " %u, usage %u)", width, height, format, usage); - return; - } + for (size_t i = 0; i < newBufferCount; ++i) { + int slot = freeSlots[i]; + if (mSlots[slot].mBufferState != BufferSlot::FREE) { + // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we + // allocated. + BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. " + "Dropping allocated buffer.", slot); + continue; + } + mCore->freeBufferLocked(slot); // Clean up the slot first + mSlots[slot].mGraphicBuffer = buffers[i]; + mSlots[slot].mFrameNumber = 0; + mSlots[slot].mFence = Fence::NO_FENCE; + BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); + } - int slot = freeSlots[freeSlots.size() - 1]; - mCore->freeBufferLocked(slot); // Clean up the slot first - mSlots[slot].mGraphicBuffer = graphicBuffer; - mSlots[slot].mFrameNumber = 0; - mSlots[slot].mFence = Fence::NO_FENCE; - BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot); - freeSlots.pop(); + mCore->mIsAllocating = false; + mCore->mIsAllocatingCondition.broadcast(); + } // Autolock scope } } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 924fc0d7e8..939c4a9e45 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -279,8 +279,12 @@ status_t GLConsumer::releaseTexImage() { return err; } + if (mReleasedTexImage == NULL) { + mReleasedTexImage = new EglImage(getDebugTexImageBuffer()); + } + mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; - mCurrentTextureBuf = getDebugTexImageBuffer(); + mCurrentTextureImage = mReleasedTexImage; mCurrentCrop.makeInvalid(); mCurrentTransform = 0; mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; @@ -288,9 +292,11 @@ status_t GLConsumer::releaseTexImage() { mCurrentFence = Fence::NO_FENCE; if (mAttached) { - // bind a dummy texture - glBindTexture(mTexTarget, mTexName); - bindUnslottedBufferLocked(mEglDisplay); + // This binds a dummy buffer (mReleasedTexImage). + status_t err = bindTextureImageLocked(); + if (err != NO_ERROR) { + return err; + } } else { // detached, don't touch the texture (and we may not even have an // EGLDisplay here. @@ -332,29 +338,12 @@ status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item, return err; } - int slot = item->mBuf; - bool destroyEglImage = false; - - if (mEglSlots[slot].mEglImage != EGL_NO_IMAGE_KHR) { - if (item->mGraphicBuffer != NULL) { - // This buffer has not been acquired before, so we must assume - // that any EGLImage in mEglSlots is stale. - destroyEglImage = true; - } else if (mEglSlots[slot].mCropRect != item->mCrop) { - // We've already seen this buffer before, but it now has a - // different crop rect, so we'll need to recreate the EGLImage if - // we're using the EGL_ANDROID_image_crop extension. - destroyEglImage = hasEglAndroidImageCrop(); - } - } - - if (destroyEglImage) { - if (!eglDestroyImageKHR(mEglDisplay, mEglSlots[slot].mEglImage)) { - ST_LOGW("acquireBufferLocked: eglDestroyImageKHR failed for slot=%d", - slot); - // keep going - } - mEglSlots[slot].mEglImage = EGL_NO_IMAGE_KHR; + // If item->mGraphicBuffer is not null, this buffer has not been acquired + // before, so any prior EglImage created is using a stale buffer. This + // replaces any old EglImage with a new one (using the new buffer). + if (item->mGraphicBuffer != NULL) { + int slot = item->mBuf; + mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer); } return NO_ERROR; @@ -395,29 +384,18 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) return err; } - // If the mEglSlot entry is empty, create an EGLImage for the gralloc - // buffer currently in the slot in ConsumerBase. - // + // Ensure we have a valid EglImageKHR for the slot, creating an EglImage + // if nessessary, for the gralloc buffer currently in the slot in + // ConsumerBase. // We may have to do this even when item.mGraphicBuffer == NULL (which - // means the buffer was previously acquired), if we destroyed the - // EGLImage when detaching from a context but the buffer has not been - // re-allocated. - if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) { - EGLImageKHR image = createImage(mEglDisplay, - mSlots[buf].mGraphicBuffer, item.mCrop); - if (image == EGL_NO_IMAGE_KHR) { - ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", - mEglDisplay, buf); - const sp<GraphicBuffer>& gb = mSlots[buf].mGraphicBuffer; - ST_LOGW("buffer size=%ux%u st=%u usage=0x%x fmt=%d", - gb->getWidth(), gb->getHeight(), gb->getStride(), - gb->getUsage(), gb->getPixelFormat()); - releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, - mEglDisplay, EGL_NO_SYNC_KHR); - return UNKNOWN_ERROR; - } - mEglSlots[buf].mEglImage = image; - mEglSlots[buf].mCropRect = item.mCrop; + // means the buffer was previously acquired). + err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop); + if (err != NO_ERROR) { + ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", + mEglDisplay, buf); + releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, + mEglDisplay, EGL_NO_SYNC_KHR); + return UNKNOWN_ERROR; } // Do whatever sync ops we need to do before releasing the old slot. @@ -433,15 +411,15 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) } ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", - mCurrentTexture, - mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, + mCurrentTexture, mCurrentTextureImage != NULL ? + mCurrentTextureImage->graphicBufferHandle() : 0, buf, mSlots[buf].mGraphicBuffer->handle); // release old buffer if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { status_t status = releaseBufferLocked( - mCurrentTexture, mCurrentTextureBuf, mEglDisplay, - mEglSlots[mCurrentTexture].mEglFence); + mCurrentTexture, mCurrentTextureImage->graphicBuffer(), + mEglDisplay, mEglSlots[mCurrentTexture].mEglFence); if (status < NO_ERROR) { ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); @@ -452,7 +430,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) // Update the GLConsumer state. mCurrentTexture = buf; - mCurrentTextureBuf = mSlots[buf].mGraphicBuffer; + mCurrentTextureImage = mEglSlots[buf].mEglImage; mCurrentCrop = item.mCrop; mCurrentTransform = item.mTransform; mCurrentScalingMode = item.mScalingMode; @@ -477,25 +455,26 @@ status_t GLConsumer::bindTextureImageLocked() { } glBindTexture(mTexTarget, mTexName); - if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT) { - if (mCurrentTextureBuf == NULL) { - ST_LOGE("bindTextureImage: no currently-bound texture"); - return NO_INIT; - } - status_t err = bindUnslottedBufferLocked(mEglDisplay); - if (err != NO_ERROR) { - return err; - } - } else { - EGLImageKHR image = mEglSlots[mCurrentTexture].mEglImage; + if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && + mCurrentTextureImage == NULL) { + ST_LOGE("bindTextureImage: no currently-bound texture"); + return NO_INIT; + } - glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); + status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay, + mCurrentCrop); - while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGE("bindTextureImage: error binding external texture image %p" - ": %#04x", image, error); - return UNKNOWN_ERROR; - } + if (err != NO_ERROR) { + ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d", + mEglDisplay, mCurrentTexture); + return UNKNOWN_ERROR; + } + + mCurrentTextureImage->bindToTextureTarget(mTexTarget); + + while ((error = glGetError()) != GL_NO_ERROR) { + ST_LOGE("bindTextureImage: error binding external image: %#04x", error); + return UNKNOWN_ERROR; } // Wait for the new buffer to be ready. @@ -537,7 +516,7 @@ void GLConsumer::setReleaseFence(const sp<Fence>& fence) { if (fence->isValid() && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { status_t err = addReleaseFence(mCurrentTexture, - mCurrentTextureBuf, fence); + mCurrentTextureImage->graphicBuffer(), fence); if (err != OK) { ST_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err); @@ -583,18 +562,6 @@ status_t GLConsumer::detachFromContext() { glDeleteTextures(1, &mTexName); } - // Because we're giving up the EGLDisplay we need to free all the EGLImages - // that are associated with it. They'll be recreated when the - // GLConsumer gets attached to a new OpenGL ES context (and thus gets a - // new EGLDisplay). - for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { - EGLImageKHR img = mEglSlots[i].mEglImage; - if (img != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(mEglDisplay, img); - mEglSlots[i].mEglImage = EGL_NO_IMAGE_KHR; - } - } - mEglDisplay = EGL_NO_DISPLAY; mEglContext = EGL_NO_CONTEXT; mAttached = false; @@ -635,54 +602,23 @@ status_t GLConsumer::attachToContext(uint32_t tex) { // buffer. glBindTexture(mTexTarget, GLuint(tex)); - if (mCurrentTextureBuf != NULL) { - // The EGLImageKHR that was associated with the slot was destroyed when - // the GLConsumer was detached from the old context, so we need to - // recreate it here. - status_t err = bindUnslottedBufferLocked(dpy); - if (err != NO_ERROR) { - return err; - } - } - mEglDisplay = dpy; mEglContext = ctx; mTexName = tex; mAttached = true; - return OK; -} - -status_t GLConsumer::bindUnslottedBufferLocked(EGLDisplay dpy) { - ST_LOGV("bindUnslottedBuffer ct=%d ctb=%p", - mCurrentTexture, mCurrentTextureBuf.get()); - - // Create a temporary EGLImageKHR. - Rect crop; - EGLImageKHR image = createImage(dpy, mCurrentTextureBuf, mCurrentCrop); - if (image == EGL_NO_IMAGE_KHR) { - return UNKNOWN_ERROR; - } - - // Attach the current buffer to the GL texture. - glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image); - - GLint error; - status_t err = OK; - while ((error = glGetError()) != GL_NO_ERROR) { - ST_LOGE("bindUnslottedBuffer: error binding external texture image %p " - "(slot %d): %#04x", image, mCurrentTexture, error); - err = UNKNOWN_ERROR; + if (mCurrentTextureImage != NULL) { + // This may wait for a buffer a second time. This is likely required if + // this is a different context, since otherwise the wait could be skipped + // by bouncing through another context. For the same context the extra + // wait is redundant. + status_t err = bindTextureImageLocked(); + if (err != NO_ERROR) { + return err; + } } - // We destroy the EGLImageKHR here because the current buffer may no - // longer be associated with one of the buffer slots, so we have - // nowhere to to store it. If the buffer is still associated with a - // slot then another EGLImageKHR will be created next time that buffer - // gets acquired in updateTexImage. - eglDestroyImageKHR(dpy, image); - - return err; + return OK; } @@ -708,7 +644,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) { } sp<Fence> fence(new Fence(fenceFd)); status_t err = addReleaseFenceLocked(mCurrentTexture, - mCurrentTextureBuf, fence); + mCurrentTextureImage->graphicBuffer(), fence); if (err != OK) { ST_LOGE("syncForReleaseLocked: error adding release fence: " "%s (%d)", strerror(-err), err); @@ -787,11 +723,11 @@ void GLConsumer::setFilteringEnabled(bool enabled) { bool needsRecompute = mFilteringEnabled != enabled; mFilteringEnabled = enabled; - if (needsRecompute && mCurrentTextureBuf==NULL) { - ST_LOGD("setFilteringEnabled called with mCurrentTextureBuf == NULL"); + if (needsRecompute && mCurrentTextureImage==NULL) { + ST_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL"); } - if (needsRecompute && mCurrentTextureBuf != NULL) { + if (needsRecompute && mCurrentTextureImage != NULL) { computeCurrentTransformMatrixLocked(); } } @@ -825,10 +761,11 @@ void GLConsumer::computeCurrentTransformMatrixLocked() { } } - sp<GraphicBuffer>& buf(mCurrentTextureBuf); + sp<GraphicBuffer> buf = (mCurrentTextureImage == NULL) ? + NULL : mCurrentTextureImage->graphicBuffer(); if (buf == NULL) { - ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureBuf is NULL"); + ST_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL"); } float mtxBeforeFlipV[16]; @@ -911,39 +848,10 @@ nsecs_t GLConsumer::getFrameNumber() { return mCurrentFrameNumber; } -EGLImageKHR GLConsumer::createImage(EGLDisplay dpy, - const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) { - EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); - EGLint attrs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_IMAGE_CROP_LEFT_ANDROID, crop.left, - EGL_IMAGE_CROP_TOP_ANDROID, crop.top, - EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right, - EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom, - EGL_NONE, - }; - if (!crop.isValid()) { - // No crop rect to set, so terminate the attrib array before the crop. - attrs[2] = EGL_NONE; - } else if (!isEglImageCroppable(crop)) { - // The crop rect is not at the origin, so we can't set the crop on the - // EGLImage because that's not allowed by the EGL_ANDROID_image_crop - // extension. In the future we can add a layered extension that - // removes this restriction if there is hardware that can support it. - attrs[2] = EGL_NONE; - } - EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, - EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); - if (image == EGL_NO_IMAGE_KHR) { - EGLint error = eglGetError(); - ST_LOGE("error creating EGLImage: %#x", error); - } - return image; -} - sp<GraphicBuffer> GLConsumer::getCurrentBuffer() const { Mutex::Autolock lock(mMutex); - return mCurrentTextureBuf; + return (mCurrentTextureImage == NULL) ? + NULL : mCurrentTextureImage->graphicBuffer(); } Rect GLConsumer::getCurrentCrop() const { @@ -1067,18 +975,13 @@ void GLConsumer::freeBufferLocked(int slotIndex) { if (slotIndex == mCurrentTexture) { mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; } - EGLImageKHR img = mEglSlots[slotIndex].mEglImage; - if (img != EGL_NO_IMAGE_KHR) { - ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img); - eglDestroyImageKHR(mEglDisplay, img); - } - mEglSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR; + mEglSlots[slotIndex].mEglImage.clear(); ConsumerBase::freeBufferLocked(slotIndex); } void GLConsumer::abandonLocked() { ST_LOGV("abandonLocked"); - mCurrentTextureBuf.clear(); + mCurrentTextureImage.clear(); ConsumerBase::abandonLocked(); } @@ -1138,4 +1041,87 @@ static void mtxMul(float out[16], const float a[16], const float b[16]) { out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; } +GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) : + mGraphicBuffer(graphicBuffer), + mEglImage(EGL_NO_IMAGE_KHR), + mEglDisplay(EGL_NO_DISPLAY) { +} + +GLConsumer::EglImage::~EglImage() { + if (mEglImage != EGL_NO_IMAGE_KHR) { + if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { + ALOGE("~EglImage: eglDestroyImageKHR failed"); + } + } +} + +status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, + const Rect& cropRect) { + // If there's an image and it's no longer valid, destroy it. + bool haveImage = mEglImage != EGL_NO_IMAGE_KHR; + bool displayInvalid = mEglDisplay != eglDisplay; + bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect; + if (haveImage && (displayInvalid || cropInvalid)) { + if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { + ALOGE("createIfNeeded: eglDestroyImageKHR failed"); + } + mEglImage = EGL_NO_IMAGE_KHR; + mEglDisplay = EGL_NO_DISPLAY; + } + + // If there's no image, create one. + if (mEglImage == EGL_NO_IMAGE_KHR) { + mEglDisplay = eglDisplay; + mCropRect = cropRect; + mEglImage = createImage(mEglDisplay, mGraphicBuffer, mCropRect); + } + + // Fail if we can't create a valid image. + if (mEglImage == EGL_NO_IMAGE_KHR) { + mEglDisplay = EGL_NO_DISPLAY; + mCropRect.makeInvalid(); + const sp<GraphicBuffer>& buffer = mGraphicBuffer; + ALOGE("Failed to create image. size=%ux%u st=%u usage=0x%x fmt=%d", + buffer->getWidth(), buffer->getHeight(), buffer->getStride(), + buffer->getUsage(), buffer->getPixelFormat()); + return UNKNOWN_ERROR; + } + + return OK; +} + +void GLConsumer::EglImage::bindToTextureTarget(uint32_t texTarget) { + glEGLImageTargetTexture2DOES(texTarget, (GLeglImageOES)mEglImage); +} + +EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, + const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) { + EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer(); + EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_IMAGE_CROP_LEFT_ANDROID, crop.left, + EGL_IMAGE_CROP_TOP_ANDROID, crop.top, + EGL_IMAGE_CROP_RIGHT_ANDROID, crop.right, + EGL_IMAGE_CROP_BOTTOM_ANDROID, crop.bottom, + EGL_NONE, + }; + if (!crop.isValid()) { + // No crop rect to set, so terminate the attrib array before the crop. + attrs[2] = EGL_NONE; + } else if (!isEglImageCroppable(crop)) { + // The crop rect is not at the origin, so we can't set the crop on the + // EGLImage because that's not allowed by the EGL_ANDROID_image_crop + // extension. In the future we can add a layered extension that + // removes this restriction if there is hardware that can support it. + attrs[2] = EGL_NONE; + } + EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, + EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); + if (image == EGL_NO_IMAGE_KHR) { + EGLint error = eglGetError(); + ALOGE("error creating EGLImage: %#x", error); + } + return image; +} + }; // namespace android diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp index 8f88141427..28fcb53d8f 100644 --- a/libs/gui/ISensorEventConnection.cpp +++ b/libs/gui/ISensorEventConnection.cpp @@ -34,8 +34,7 @@ enum { GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, ENABLE_DISABLE, SET_EVENT_RATE, - FLUSH_SENSOR, - DECREASE_WAKE_LOCK_REFCOUNT + FLUSH_SENSOR }; class BpSensorEventConnection : public BpInterface<ISensorEventConnection> @@ -84,13 +83,6 @@ public: remote()->transact(FLUSH_SENSOR, data, &reply); return reply.readInt32(); } - - virtual void decreaseWakeLockRefCount() { - Parcel data, reply; - data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor()); - remote()->transact(DECREASE_WAKE_LOCK_REFCOUNT, data, &reply, IBinder::FLAG_ONEWAY); - return; - } }; IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection"); @@ -133,11 +125,6 @@ status_t BnSensorEventConnection::onTransact( reply->writeInt32(result); return NO_ERROR; } break; - case DECREASE_WAKE_LOCK_REFCOUNT: { - CHECK_INTERFACE(ISensorEventConnection, data, reply); - decreaseWakeLockRefCount(); - return NO_ERROR; - } break; } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 2103a95233..613b8e215f 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -166,83 +166,6 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mStringType = SENSOR_STRING_TYPE_TEMPERATURE; mFlags |= SENSOR_FLAG_ON_CHANGE_MODE; break; - case SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR: - mStringType = SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR; - mFlags |= SENSOR_FLAG_ON_CHANGE_MODE; - break; - case SENSOR_TYPE_WAKE_UP_ACCELEROMETER: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_ACCELEROMETER; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_ORIENTATION: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_ORIENTATION; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_GYROSCOPE: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_LIGHT: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_LIGHT; - mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_PRESSURE: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_PRESSURE; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_GRAVITY: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_GRAVITY; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_LINEAR_ACCELERATION: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_ROTATION_VECTOR: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_ROTATION_VECTOR; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_RELATIVE_HUMIDITY: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY; - mFlags |= (SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_AMBIENT_TEMPERATURE: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE; - mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_GAME_ROTATION_VECTOR: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_STEP_DETECTOR: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_DETECTOR; - mFlags |= (SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_STEP_COUNTER: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_COUNTER; - mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR; - mFlags |= (SENSOR_FLAG_CONTINUOUS_MODE | SENSOR_FLAG_WAKE_UP); - break; - case SENSOR_TYPE_WAKE_UP_HEART_RATE: - mStringType = SENSOR_STRING_TYPE_WAKE_UP_HEART_RATE; - mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS; - mFlags |= (SENSOR_FLAG_ON_CHANGE_MODE | SENSOR_FLAG_WAKE_UP); - break; case SENSOR_TYPE_WAKE_UP_TILT_DETECTOR: mStringType = SENSOR_STRING_TYPE_WAKE_UP_TILT_DETECTOR; mFlags |= (SENSOR_FLAG_SPECIAL_REPORTING_MODE | SENSOR_FLAG_WAKE_UP); @@ -255,6 +178,10 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mStringType = SENSOR_STRING_TYPE_GLANCE_GESTURE; mFlags |= (SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP); break; + case SENSOR_TYPE_PICK_UP_GESTURE: + mStringType = SENSOR_STRING_TYPE_PICK_UP_GESTURE; + mFlags |= (SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP); + break; default: // Only pipe the stringType, requiredPermission and flags for custom sensors. if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) { diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp index c2eaf4ec76..842502d424 100644 --- a/libs/gui/SensorEventQueue.cpp +++ b/libs/gui/SensorEventQueue.cpp @@ -18,6 +18,7 @@ #include <stdint.h> #include <sys/types.h> +#include <sys/socket.h> #include <utils/Errors.h> #include <utils/RefBase.h> @@ -147,7 +148,14 @@ status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const void SensorEventQueue::sendAck(const ASensorEvent* events, int count) { for (int i = 0; i < count; ++i) { if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) { - mSensorEventConnection->decreaseWakeLockRefCount(); + // Send just a byte of data to acknowledge for the wake up sensor events + // received + char buf = '1'; + ssize_t size = ::send(mSensorChannel->getFd(), &buf, sizeof(buf), + MSG_DONTWAIT | MSG_NOSIGNAL); + if (size < 0) { + ALOGE("sendAck failure %d", size); + } } } return; diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index e21dc53ca5..9b0bd601cb 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -126,6 +126,7 @@ void GraphicBuffer::dumpAllocationsToSystemLog() ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const { + LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer"); return static_cast<ANativeWindowBuffer*>( const_cast<GraphicBuffer*>(this)); } |