summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/binder/IBatteryStats.cpp80
-rw-r--r--libs/gui/BitTube.cpp5
-rw-r--r--libs/gui/BufferQueueCore.cpp11
-rw-r--r--libs/gui/BufferQueueProducer.cpp131
-rw-r--r--libs/gui/GLConsumer.cpp324
-rw-r--r--libs/gui/ISensorEventConnection.cpp15
-rw-r--r--libs/gui/Sensor.cpp81
-rw-r--r--libs/gui/SensorEventQueue.cpp10
-rw-r--r--libs/ui/GraphicBuffer.cpp1
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));
}