am 9040362b: am fc6a2bff: am 146f31b6: Merge "Eliminate benign overflow condition triggered upon loop termination in Input.cpp"
* commit '9040362b1ec56f077e9bca395939a6669ffa8303':
Eliminate benign overflow condition triggered upon loop termination in Input.cpp
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 3155766..ddf3aa8 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -207,7 +207,7 @@
sp<GLConsumer> glc = new GLConsumer(consumer, name,
GL_TEXTURE_EXTERNAL_OES, false, true);
glc->setDefaultBufferSize(w, h);
- glc->setDefaultMaxBufferCount(3);
+ producer->setMaxDequeuedBufferCount(2);
glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
sp<ANativeWindow> anw = new Surface(producer);
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
index e73516d..7154fab 100644
--- a/cmds/servicemanager/servicemanager.rc
+++ b/cmds/servicemanager/servicemanager.rc
@@ -7,4 +7,5 @@
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
+ onrestart restart inputflinger
onrestart restart drm
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 421abe5..ac07190 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -732,9 +732,23 @@
AKEYCODE_STEM_2 = 266,
/** Generic stem key 3 for Wear */
AKEYCODE_STEM_3 = 267,
+ /** Directional Pad Up-Left */
+ AKEYCODE_DPAD_UP_LEFT = 268,
+ /** Directional Pad Down-Left */
+ AKEYCODE_DPAD_DOWN_LEFT = 269,
+ /** Directional Pad Up-Right */
+ AKEYCODE_DPAD_UP_RIGHT = 270,
+ /** Directional Pad Down-Right */
+ AKEYCODE_DPAD_DOWN_RIGHT = 271,
+ /** Skip forward media key */
AKEYCODE_MEDIA_SKIP_FORWARD = 272,
+ /** Skip backward media key */
AKEYCODE_MEDIA_SKIP_BACKWARD = 273,
+ /** Step forward media key.
+ * Steps media forward one from at a time. */
AKEYCODE_MEDIA_STEP_FORWARD = 274,
+ /** Step backward media key.
+ * Steps media backward one from at a time. */
AKEYCODE_MEDIA_STEP_BACKWARD = 275,
/** Put device to sleep unless a wakelock is held. */
AKEYCODE_SOFT_SLEEP = 276
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 145efe6..504ac64 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -98,13 +98,8 @@
};
};
- union {
- // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
- int mSlot;
-
- // mBuf is the former name for mSlot
- int mBuf;
- };
+ // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
+ int mSlot;
// mIsDroppable whether this buffer was queued with the
// property that it can be replaced by a new buffer for the purpose of
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index cde302f..b2daae4 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -100,20 +100,8 @@
// is 1x1.
virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
- //
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
- virtual status_t setDefaultMaxBufferCount(int bufferCount);
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before connect().
- virtual status_t disableAsyncBuffer();
+ // see IGraphicBufferConsumer::setMaxBufferCount
+ virtual status_t setMaxBufferCount(int bufferCount);
// setMaxAcquiredBufferCount sets the maximum number of buffers that can
// be acquired by the consumer at one time (default 1). This call will
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 99134ea..e824124 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -105,12 +105,6 @@
// connected, mDequeueCondition must be broadcast.
int getMaxBufferCountLocked(bool async) const;
- // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
- // that will be used if the producer does not override the buffer slot
- // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
- // initial default is 2.
- status_t setDefaultMaxBufferCountLocked(int count);
-
// freeBufferLocked frees the GraphicBuffer and sync resources for the
// given slot.
void freeBufferLocked(int slot);
@@ -192,21 +186,10 @@
// a buffer attached
std::list<int> mFreeBuffers;
- // mOverrideMaxBufferCount is the limit on the number of buffers that will
- // be allocated at one time. This value is set by the producer by calling
- // setBufferCount. The default is 0, which means that the producer doesn't
- // care about the number of buffers in the pool. In that case,
- // mDefaultMaxBufferCount is used as the limit.
- int mOverrideMaxBufferCount;
-
// mDequeueCondition is a condition variable used for dequeueBuffer in
// synchronous mode.
mutable Condition mDequeueCondition;
- // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
- // to prevent dequeueBuffer from blocking.
- bool mUseAsyncBuffer;
-
// mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
// block. This flag is set during connect when both the producer and
// consumer are controlled by the application.
@@ -229,11 +212,9 @@
// is specified.
android_dataspace mDefaultBufferDataSpace;
- // mDefaultMaxBufferCount is the default limit on the number of buffers that
- // will be allocated at one time. This default limit is set by the consumer.
- // The limit (as opposed to the default limit) may be overriden by the
- // producer.
- int mDefaultMaxBufferCount;
+ // mMaxBufferCount is the limit on the number of buffers that will be
+ // allocated at one time. This limit can be set by the consumer.
+ int mMaxBufferCount;
// mMaxAcquiredBufferCount is the number of buffers that the consumer may
// acquire at one time. It defaults to 1, and can be changed by the consumer
@@ -242,6 +223,11 @@
// the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
int mMaxAcquiredBufferCount;
+ // mMaxDequeuedBufferCount is the number of buffers that the producer may
+ // dequeue at one time. It defaults to 1, and can be changed by the producer
+ // via setMaxDequeuedBufferCount.
+ int mMaxDequeuedBufferCount;
+
// mBufferHasBeenQueued is true once a buffer has been queued. It is reset
// when something causes all buffers to be freed (e.g., changing the buffer
// count).
@@ -280,6 +266,11 @@
// number will fail.
uint32_t mGenerationNumber;
+ // mAsyncMode indicates whether or not async mode is enabled.
+ // In async mode an extra buffer will be allocated to allow the producer to
+ // enqueue buffers without blocking.
+ bool mAsyncMode;
+
}; // class BufferQueueCore
} // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 9754a89..267c50f 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -39,22 +39,11 @@
// flags indicating that previously-returned buffers are no longer valid.
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
- // setBufferCount updates the number of available buffer slots. If this
- // method succeeds, buffer slots will be both unallocated and owned by
- // the BufferQueue object (i.e. they are not owned by the producer or
- // consumer).
- //
- // This will fail if the producer has dequeued any buffers, or if
- // bufferCount is invalid. bufferCount must generally be a value
- // between the minimum undequeued buffer count (exclusive) and NUM_BUFFER_SLOTS
- // (inclusive). It may also be set to zero (the default) to indicate
- // that the producer does not wish to set a value. The minimum value
- // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- // ...).
- //
- // This may only be called by the producer. The consumer will be told
- // to discard buffers through the onBuffersReleased callback.
- virtual status_t setBufferCount(int bufferCount);
+ // see IGraphicsBufferProducer::setMaxDequeuedBufferCount
+ virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+
+ // see IGraphicsBufferProducer::setAsyncMode
+ virtual status_t setAsyncMode(bool async);
// dequeueBuffer gets the next buffer slot index for the producer to use.
// If a buffer slot is available then that slot index is written to the
@@ -128,7 +117,7 @@
//
// The buffer will not be overwritten until the fence signals. The fence
// will usually be the one obtained from dequeueBuffer.
- virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+ virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
// Query native window attributes. The "what" values are enumerated in
// window.h (e.g. NATIVE_WINDOW_FORMAT).
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index 3b07a31..f9d0e7d 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -67,6 +67,25 @@
uint8_t *dataCr;
uint32_t chromaStride;
uint32_t chromaStep;
+
+ LockedBuffer() :
+ data(NULL),
+ width(0),
+ height(0),
+ format(PIXEL_FORMAT_NONE),
+ stride(0),
+ crop(0, 0, 0, 0),
+ transform(0),
+ scalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+ timestamp(0),
+ dataSpace(HAL_DATASPACE_UNKNOWN),
+ frameNumber(0),
+ flexFormat(PIXEL_FORMAT_NONE),
+ dataCb(NULL),
+ dataCr(NULL),
+ chromaStride(0),
+ chromaStep(0)
+ {}
};
// Create a new CPU consumer. The maxLockedBuffers parameter specifies
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index c35c7be..0e4acee 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -112,11 +112,6 @@
// union fence.
void setReleaseFence(const sp<Fence>& fence);
- // setDefaultMaxBufferCount sets the default limit on the maximum number
- // of buffers that will be allocated at one time. The image producer may
- // override the limit.
- status_t setDefaultMaxBufferCount(int bufferCount);
-
// getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
// associated with the texture image set by the most recent call to
// updateTexImage.
@@ -201,6 +196,7 @@
status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
status_t setConsumerUsageBits(uint32_t usage);
status_t setTransformHint(uint32_t hint);
+ status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
// detachFromContext detaches the GLConsumer from the calling thread's
// current OpenGL ES context. This context must be the same as the context
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 60ec9cc..d4c9ee5 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -188,32 +188,28 @@
// * BAD_VALUE - either w or h was zero
virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
- // setDefaultMaxBufferCount sets the default value for the maximum buffer
- // count (the initial default is 2). If the producer has requested a
- // buffer count using setBufferCount, the default buffer count will only
- // take effect if the producer sets the count back to zero.
+ // setMaxBufferCount sets the maximum value for the number of buffers used
+ // in the buffer queue (the initial default is NUM_BUFFER_SLOTS). If a call
+ // to setMaxAcquiredBufferCount (by the consumer), or a call to setAsyncMode
+ // or setMaxDequeuedBufferCount (by the producer), would cause this value to
+ // be exceeded then that call will fail. This call will fail if a producer
+ // is connected to the BufferQueue.
//
- // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
+ // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count
+ // cannot be less than maxAcquiredBufferCount.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - bufferCount was out of range (see above).
- virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0;
-
- // disableAsyncBuffer disables the extra buffer used in async mode
- // (when both producer and consumer have set their "isControlledByApp"
- // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
- //
- // This can only be called before consumerConnect().
- //
- // Return of a value other than NO_ERROR means an error has occurred:
- // * INVALID_OPERATION - attempting to call this after consumerConnect.
- virtual status_t disableAsyncBuffer() = 0;
+ // * INVALID_OPERATION - attempting to call this after a producer connected.
+ virtual status_t setMaxBufferCount(int bufferCount) = 0;
// setMaxAcquiredBufferCount sets the maximum number of buffers that can
// be acquired by the consumer at one time (default 1). This call will
// fail if a producer is connected to the BufferQueue.
//
- // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS.
+ // maxAcquiredBuffers must be (inclusive) between 1 and
+ // MAX_MAX_ACQUIRED_BUFFERS. It also cannot cause the maxBufferCount value
+ // to be exceeded.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - maxAcquiredBuffers was out of range (see above).
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 9530de1..6885eb0 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -74,33 +74,54 @@
// The slot must be in the range of [0, NUM_BUFFER_SLOTS).
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
// * BAD_VALUE - one of the two conditions occurred:
// * slot was out of range (see above)
// * buffer specified by the slot is not dequeued
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
- // setBufferCount sets the number of buffer slots available. Calling this
- // will also cause all buffer slots to be emptied. The caller should empty
- // its mirrored copy of the buffer slots when calling this method.
+ // setMaxDequeuedBufferCount sets the maximum number of buffers that can be
+ // dequeued by the producer at one time. If this method succeeds, buffer
+ // slots will be both unallocated and owned by the BufferQueue object (i.e.
+ // they are not owned by the producer or consumer). Calling this will also
+ // cause all buffer slots to be emptied. If the caller is caching the
+ // contents of the buffer slots, it should empty that cache after calling
+ // this method.
//
- // This function should not be called when there are any dequeued buffer
- // slots, doing so will result in a BAD_VALUE error returned.
+ // This function should not be called when there are any currently dequeued
+ // buffer slots. Doing so will result in a BAD_VALUE error.
//
- // The buffer count should be at most NUM_BUFFER_SLOTS (inclusive), but at least
- // the minimum undequeued buffer count (exclusive). The minimum value
- // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
- // In particular the range is (minUndequeudBuffers, NUM_BUFFER_SLOTS].
- //
- // The buffer count may also be set to 0 (the default), to indicate that
- // the producer does not wish to set a value.
+ // The buffer count should be at least 1 (inclusive), but at most
+ // (NUM_BUFFER_SLOTS - the minimum undequeued buffer count) (exclusive). The
+ // minimum undequeued buffer count can be obtained by calling
+ // query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
//
// Return of a value other than NO_ERROR means an error has occurred:
// * NO_INIT - the buffer queue has been abandoned.
// * BAD_VALUE - one of the below conditions occurred:
- // * bufferCount was out of range (see above)
- // * client has one or more buffers dequeued
- virtual status_t setBufferCount(int bufferCount) = 0;
+ // * bufferCount was out of range (see above)
+ // * client has one or more buffers dequeued
+ // * this call would cause the maxBufferCount value to be exceeded
+ virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) = 0;
+
+ // Set the async flag if the producer intends to asynchronously queue
+ // buffers without blocking. Typically this is used for triple-buffering
+ // and/or when the swap interval is set to zero.
+ //
+ // Enabling async mode will internally allocate an additional buffer to
+ // allow for the asynchronous behavior. If it is not enabled queue/dequeue
+ // calls may block.
+ //
+ // This function should not be called when there are any currently dequeued
+ // buffer slots, doing so will result in a BAD_VALUE error.
+ //
+ // Return of a value other than NO_ERROR means an error has occurred:
+ // * NO_INIT - the buffer queue has been abandoned.
+ // * BAD_VALUE - one of the below conditions occurred:
+ // * client has one or more buffers dequeued
+ // * this call would cause the maxBufferCount value to be exceeded
+ virtual status_t setAsyncMode(bool async) = 0;
// dequeueBuffer requests a new buffer slot for the client to use. Ownership
// of the slot is transfered to the client, meaning that the server will not
@@ -150,7 +171,8 @@
// success.
//
// Return of a negative means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
// * BAD_VALUE - both in async mode and buffer count was less than the
// max numbers of buffers that can be allocated at once.
// * INVALID_OPERATION - cannot attach the buffer because it would cause
@@ -178,7 +200,8 @@
// requestBuffer).
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
// * BAD_VALUE - the given slot number is invalid, either because it is
// out of the range [0, NUM_BUFFER_SLOTS), or because the slot
// it refers to is not currently dequeued and requested.
@@ -198,7 +221,8 @@
// equivalent to fence from the dequeueBuffer call.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
// * BAD_VALUE - either outBuffer or outFence were NULL.
// * NO_MEMORY - no slots were found that were both free and contained a
// GraphicBuffer.
@@ -217,7 +241,8 @@
// success.
//
// Return of a negative value means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
// * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
// async mode and buffer count override, or the generation
// number of the buffer did not match the buffer queue.
@@ -251,7 +276,8 @@
// (refer to the documentation below).
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
// * BAD_VALUE - one of the below conditions occurred:
// * fence was NULL
// * scaling mode was unknown
@@ -364,9 +390,19 @@
//
// The buffer is not queued for use by the consumer.
//
+ // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
+ //
// The buffer will not be overwritten until the fence signals. The fence
// will usually be the one obtained from dequeueBuffer.
- virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;
+ //
+ // Return of a value other than NO_ERROR means an error has occurred:
+ // * NO_INIT - the buffer queue has been abandoned or the producer is not
+ // connected.
+ // * BAD_VALUE - one of the below conditions occurred:
+ // * fence was NULL
+ // * slot index was out of range (see above).
+ // * the slot was not in the dequeued state
+ virtual status_t cancelBuffer(int slot, const sp<Fence>& fence) = 0;
// query retrieves some information for this surface
// 'what' tokens allowed are that of NATIVE_WINDOW_* in <window.h>
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 72f1067..ed2331b 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -183,6 +183,8 @@
virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
public:
+ virtual int setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+ virtual int setAsyncMode(bool async);
virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
virtual int unlockAndPost();
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index f0a6238..efc1687 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -307,6 +307,10 @@
DEFINE_KEYCODE(STEM_1),
DEFINE_KEYCODE(STEM_2),
DEFINE_KEYCODE(STEM_3),
+ DEFINE_KEYCODE(DPAD_UP_LEFT),
+ DEFINE_KEYCODE(DPAD_DOWN_LEFT),
+ DEFINE_KEYCODE(DPAD_UP_RIGHT),
+ DEFINE_KEYCODE(DPAD_DOWN_RIGHT),
DEFINE_KEYCODE(MEDIA_SKIP_FORWARD),
DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD),
DEFINE_KEYCODE(MEDIA_STEP_FORWARD),
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index cbe8733..b2574d0 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,11 +58,10 @@
: what(0),
x(0), y(0), z(0), w(0), h(0), layerStack(0),
alpha(0), flags(0), mask(0),
- reserved(0)
+ reserved(0), crop(Rect::INVALID_RECT)
{
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
- crop.makeInvalid();
}
status_t write(Parcel& output) const;
@@ -117,6 +116,8 @@
eDisplaySizeChanged = 0x08
};
+ DisplayState();
+
uint32_t what;
sp<IBinder> token;
sp<IGraphicBufferProducer> surface;
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 8c190dd..84eb100 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -72,7 +72,7 @@
}
void operator()(region_rasterizer& rasterizer) {
- RECT current;
+ RECT current(Rect::EMPTY_RECT);
do {
SpannerInner spannerInner(spanner.lhs, spanner.rhs);
int inside = spanner.next(current.top, current.bottom);
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index 3886f93..6310502 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -32,13 +32,12 @@
typedef ARect::value_type value_type;
static const Rect INVALID_RECT;
+ static const Rect EMPTY_RECT;
// we don't provide copy-ctor and operator= on purpose
// because we want the compiler generated versions
- inline Rect() {
- left = right = top = bottom = 0;
- }
+ inline Rect() : Rect(INVALID_RECT) {}
inline Rect(int32_t w, int32_t h) {
left = top = 0;
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 2a14918..e9b3a0b 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -130,11 +130,6 @@
// Region object.
Rect const* getArray(size_t* count) const;
- // returns a SharedBuffer as well as the number of rects.
- // ownership is transfered to the caller.
- // the caller must call SharedBuffer::release() to free the memory.
- SharedBuffer const* getSharedBuffer(size_t* count) const;
-
/* no user serviceable parts here... */
// add a rectangle to the internal list. This rectangle must
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 45191f5..8315c58 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -350,13 +350,11 @@
size_t Parcel::dataAvail() const
{
- // TODO: decide what to do about the possibility that this can
- // report an available-data size that exceeds a Java int's max
- // positive value, causing havoc. Fortunately this will only
- // happen if someone constructs a Parcel containing more than two
- // gigabytes of data, which on typical phone hardware is simply
- // not possible.
- return dataSize() - dataPosition();
+ size_t result = dataSize() - dataPosition();
+ if (result > INT32_MAX) {
+ abort();
+ }
+ return result;
}
size_t Parcel::dataPosition() const
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 8f64ae0..6a883cf 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -24,6 +24,7 @@
namespace android {
BufferItem::BufferItem() :
+ mCrop(Rect::INVALID_RECT),
mTransform(0),
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mTimestamp(0),
@@ -34,7 +35,6 @@
mIsDroppable(false),
mAcquireCalled(false),
mTransformToDisplayInverse(false) {
- mCrop.makeInvalid();
}
BufferItem::~BufferItem() {}
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 578b8d9..6f4c89d 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -78,7 +78,7 @@
}
}
- item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer;
+ item->mGraphicBuffer = mSlots[item->mSlot].mGraphicBuffer;
return OK;
}
@@ -89,9 +89,9 @@
Mutex::Autolock _l(mMutex);
- err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence);
+ err = addReleaseFenceLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
- err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer, EGL_NO_DISPLAY,
+ err = releaseBufferLocked(item.mSlot, item.mGraphicBuffer, EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR);
if (err != OK) {
BI_LOGE("Failed to release buffer: %s (%d)",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index bb3e1b0..950a074 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -482,24 +482,29 @@
return NO_ERROR;
}
-status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
+status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
ATRACE_CALL();
- Mutex::Autolock lock(mCore->mMutex);
- return mCore->setDefaultMaxBufferCountLocked(bufferCount);
-}
-status_t BufferQueueConsumer::disableAsyncBuffer() {
- ATRACE_CALL();
+ if (bufferCount < 1 || bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+ BQ_LOGE("setMaxBufferCount: invalid count %d", bufferCount);
+ return BAD_VALUE;
+ }
Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mConsumerListener != NULL) {
- BQ_LOGE("disableAsyncBuffer: consumer already connected");
+ if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("setMaxBufferCount: producer is already connected");
return INVALID_OPERATION;
}
- BQ_LOGV("disableAsyncBuffer");
- mCore->mUseAsyncBuffer = false;
+ if (bufferCount < mCore->mMaxAcquiredBufferCount) {
+ BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
+ "mMaxAcquiredBufferCount (%d)", bufferCount,
+ mCore->mMaxAcquiredBufferCount);
+ return BAD_VALUE;
+ }
+
+ mCore->mMaxBufferCount = bufferCount;
return NO_ERROR;
}
@@ -521,6 +526,15 @@
return INVALID_OPERATION;
}
+ if ((maxAcquiredBuffers + mCore->mMaxDequeuedBufferCount +
+ (mCore->mAsyncMode ? 1 : 0)) > mCore->mMaxBufferCount) {
+ BQ_LOGE("setMaxAcquiredBufferCount: %d acquired buffers would exceed "
+ "the maxBufferCount (%d) (maxDequeued %d async %d)",
+ maxAcquiredBuffers, mCore->mMaxBufferCount,
+ mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode);
+ return BAD_VALUE;
+ }
+
BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
return NO_ERROR;
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 851a396..8b97c2a 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -30,9 +30,6 @@
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
-template <typename T>
-static inline T max(T a, T b) { return a > b ? a : b; }
-
namespace android {
static String8 getUniqueName() {
@@ -55,16 +52,15 @@
mQueue(),
mFreeSlots(),
mFreeBuffers(),
- mOverrideMaxBufferCount(0),
mDequeueCondition(),
- mUseAsyncBuffer(true),
mDequeueBufferCannotBlock(false),
mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
mDefaultWidth(1),
mDefaultHeight(1),
mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
- mDefaultMaxBufferCount(2),
+ mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
mMaxAcquiredBufferCount(1),
+ mMaxDequeuedBufferCount(1),
mBufferHasBeenQueued(false),
mFrameCounter(0),
mTransformHint(0),
@@ -72,7 +68,8 @@
mIsAllocatingCondition(),
mAllowAllocation(true),
mBufferAge(0),
- mGenerationNumber(0)
+ mGenerationNumber(0),
+ mAsyncMode(false)
{
if (allocator == NULL) {
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -104,11 +101,12 @@
}
result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
- "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
- "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n",
- prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock,
- mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint,
- mQueue.size(), fifo.string());
+ "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d, "
+ "default-size=[%dx%d], default-format=%d, transform-hint=%02x, "
+ "FIFO(%zu)={%s}\n",
+ prefix, mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
+ mDequeueBufferCannotBlock, mDefaultWidth, mDefaultHeight,
+ mDefaultBufferFormat, mTransformHint, mQueue.size(), fifo.string());
// Trim the free buffers so as to not spam the dump
int maxBufferCount = 0;
@@ -142,10 +140,6 @@
int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
// If dequeueBuffer is allowed to error out, we don't have to add an
// extra buffer.
- if (!mUseAsyncBuffer) {
- return mMaxAcquiredBufferCount;
- }
-
if (mDequeueBufferCannotBlock || async) {
return mMaxAcquiredBufferCount + 1;
}
@@ -158,13 +152,11 @@
}
int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
- int minMaxBufferCount = getMinMaxBufferCountLocked(async);
+ int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
+ (async ? 1 : 0);
- int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
- if (mOverrideMaxBufferCount != 0) {
- assert(mOverrideMaxBufferCount >= minMaxBufferCount);
- maxBufferCount = mOverrideMaxBufferCount;
- }
+ // limit maxBufferCount by mMaxBufferCount always
+ maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
// Any buffers that are dequeued by the producer or sitting in the queue
// waiting to be consumed need to have their slots preserved. Such buffers
@@ -180,22 +172,6 @@
return maxBufferCount;
}
-status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
- const int minBufferCount = mUseAsyncBuffer ? 2 : 1;
- if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
- "[%d, %d]",
- count, minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
- BQ_LOGV("setDefaultMaxBufferCount: setting count to %d", count);
- mDefaultMaxBufferCount = count;
- mDequeueCondition.broadcast();
-
- return NO_ERROR;
-}
-
void BufferQueueCore::freeBufferLocked(int slot) {
BQ_LOGV("freeBufferLocked: slot %d", slot);
bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 87e5b4d..06cdeab 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -57,6 +57,11 @@
return NO_INIT;
}
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
@@ -72,9 +77,11 @@
return NO_ERROR;
}
-status_t BufferQueueProducer::setBufferCount(int bufferCount) {
+status_t BufferQueueProducer::setMaxDequeuedBufferCount(
+ int maxDequeuedBuffers) {
ATRACE_CALL();
- BQ_LOGV("setBufferCount: count = %d", bufferCount);
+ BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
+ maxDequeuedBuffers);
sp<IConsumerListener> listener;
{ // Autolock scope
@@ -82,34 +89,42 @@
mCore->waitWhileAllocatingLocked();
if (mCore->mIsAbandoned) {
- BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
+ BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
+ "abandoned");
return NO_INIT;
}
- if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
- BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
- bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
- return BAD_VALUE;
- }
-
// There must be no dequeued buffers when changing the buffer count.
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
- BQ_LOGE("setBufferCount: buffer owned by producer");
+ BQ_LOGE("setMaxDequeuedBufferCount: buffer owned by producer");
return BAD_VALUE;
}
}
- if (bufferCount == 0) {
- mCore->mOverrideMaxBufferCount = 0;
- mCore->mDequeueCondition.broadcast();
- return NO_ERROR;
+ int bufferCount = mCore->getMinUndequeuedBufferCountLocked(
+ mCore->mAsyncMode);
+ bufferCount += maxDequeuedBuffers;
+
+ if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+ BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
+ "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
+ return BAD_VALUE;
}
- const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
+ const int minBufferSlots = mCore->getMinMaxBufferCountLocked(
+ mCore->mAsyncMode);
if (bufferCount < minBufferSlots) {
- BQ_LOGE("setBufferCount: requested buffer count %d is less than "
- "minimum %d", bufferCount, minBufferSlots);
+ BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
+ "less than minimum %d", bufferCount, minBufferSlots);
+ return BAD_VALUE;
+ }
+
+ if (bufferCount > mCore->mMaxBufferCount) {
+ BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
+ "exceed the maxBufferCount (%d) (maxAcquired %d async %d)",
+ maxDequeuedBuffers, mCore->mMaxBufferCount,
+ mCore->mMaxAcquiredBufferCount, mCore->mAsyncMode);
return BAD_VALUE;
}
@@ -118,7 +133,7 @@
// clear the queue, however, so that currently queued buffers still
// get displayed.
mCore->freeAllBuffersLocked();
- mCore->mOverrideMaxBufferCount = bufferCount;
+ mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
mCore->mDequeueCondition.broadcast();
listener = mCore->mConsumerListener;
} // Autolock scope
@@ -131,6 +146,50 @@
return NO_ERROR;
}
+status_t BufferQueueProducer::setAsyncMode(bool async) {
+ ATRACE_CALL();
+ BQ_LOGV("setAsyncMode: async = %d", async);
+
+ sp<IConsumerListener> listener;
+ { // Autolock scope
+ Mutex::Autolock lock(mCore->mMutex);
+ mCore->waitWhileAllocatingLocked();
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ // There must be no dequeued buffers when changing the async mode.
+ for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
+ if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
+ BQ_LOGE("setAsyncMode: buffer owned by producer");
+ return BAD_VALUE;
+ }
+ }
+
+ if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
+ (async ? 1 : 0)) > mCore->mMaxBufferCount) {
+ BQ_LOGE("setAsyncMode(%d): this call would cause the "
+ "maxBufferCount (%d) to be exceeded (maxAcquired %d "
+ "maxDequeued %d)", async,mCore->mMaxBufferCount,
+ mCore->mMaxAcquiredBufferCount,
+ mCore->mMaxDequeuedBufferCount);
+ return BAD_VALUE;
+ }
+
+ mCore->mAsyncMode = async;
+ mCore->mDequeueCondition.broadcast();
+ listener = mCore->mConsumerListener;
+ } // Autolock scope
+
+ // Call back without lock held
+ if (listener != NULL) {
+ listener->onBuffersReleased();
+ }
+ return NO_ERROR;
+}
+
status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
bool async, int* found, status_t* returnFlags) const {
bool tryAgain = true;
@@ -141,16 +200,6 @@
}
const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
- if (async && mCore->mOverrideMaxBufferCount) {
- // FIXME: Some drivers are manually setting the buffer count
- // (which they shouldn't), so we do this extra test here to
- // handle that case. This is TEMPORARY until we get this fixed.
- if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
- BQ_LOGE("%s: async mode is invalid with buffer count override",
- caller);
- return BAD_VALUE;
- }
- }
// Free up any buffers that are in slots beyond the max buffer count
for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
@@ -176,33 +225,16 @@
}
}
- // Producers are not allowed to dequeue more than one buffer if they
- // did not set a buffer count
- if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
- BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
- "buffer count", caller);
+ // Producers are not allowed to dequeue more than
+ // mMaxDequeuedBufferCount buffers.
+ // This check is only done if a buffer has already been queued
+ if (mCore->mBufferHasBeenQueued &&
+ dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
+ BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
+ "(%d)", caller, mCore->mMaxDequeuedBufferCount);
return INVALID_OPERATION;
}
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the min undequeued
- // buffers check below
- if (mCore->mBufferHasBeenQueued) {
- // Make sure the producer is not trying to dequeue more buffers
- // than allowed
- const int newUndequeuedCount =
- maxBufferCount - (dequeuedCount + 1);
- const int minUndequeuedCount =
- mCore->getMinUndequeuedBufferCountLocked(async);
- if (newUndequeuedCount < minUndequeuedCount) {
- BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
- "(dequeued=%d undequeued=%d)",
- caller, minUndequeuedCount,
- dequeuedCount, newUndequeuedCount);
- return INVALID_OPERATION;
- }
- }
-
*found = BufferQueueCore::INVALID_BUFFER_SLOT;
// If we disconnect and reconnect quickly, we can be in a state where
@@ -241,7 +273,7 @@
// buffer (which could cause us to have to wait here), which is
// okay, since it is only used to implement an atomic acquire +
// release (e.g., in GLConsumer::updateTexImage())
- if (mCore->mDequeueBufferCannotBlock &&
+ if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
(acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
return WOULD_BLOCK;
}
@@ -259,6 +291,16 @@
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mConsumerName = mCore->mConsumerName;
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
} // Autolock scope
BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
@@ -426,6 +468,11 @@
return NO_INIT;
}
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("detachBuffer(P): BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
@@ -460,13 +507,19 @@
}
Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
if (mCore->mIsAbandoned) {
BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
return NO_INIT;
}
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ mCore->waitWhileAllocatingLocked();
+
if (mCore->mFreeBuffers.empty()) {
return NO_MEMORY;
}
@@ -497,7 +550,16 @@
}
Mutex::Autolock lock(mCore->mMutex);
- mCore->waitWhileAllocatingLocked();
+
+ if (mCore->mIsAbandoned) {
+ BQ_LOGE("attachBuffer(P): BufferQueue has been abandoned");
+ return NO_INIT;
+ }
+
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("attachBuffer(P): BufferQueue has no connected producer");
+ return NO_INIT;
+ }
if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
@@ -506,6 +568,8 @@
return BAD_VALUE;
}
+ mCore->waitWhileAllocatingLocked();
+
status_t returnFlags = NO_ERROR;
int found;
// TODO: Should we provide an async flag to attachBuffer? It seems
@@ -547,7 +611,7 @@
int64_t timestamp;
bool isAutoTimestamp;
android_dataspace dataSpace;
- Rect crop;
+ Rect crop(Rect::EMPTY_RECT);
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
@@ -585,18 +649,13 @@
return NO_INIT;
}
- const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
- if (async && mCore->mOverrideMaxBufferCount) {
- // FIXME: Some drivers are manually setting the buffer count
- // (which they shouldn't), so we do this extra test here to
- // handle that case. This is TEMPORARY until we get this fixed.
- if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
- BQ_LOGE("queueBuffer: async mode is invalid with "
- "buffer count override");
- return BAD_VALUE;
- }
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
}
+ const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
+
if (slot < 0 || slot >= maxBufferCount) {
BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
slot, maxBufferCount);
@@ -619,7 +678,7 @@
const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
- Rect croppedRect;
+ Rect croppedRect(Rect::EMPTY_RECT);
crop.intersect(bufferRect, &croppedRect);
if (croppedRect != crop) {
BQ_LOGE("queueBuffer: crop rect is not contained within the "
@@ -731,27 +790,32 @@
return NO_ERROR;
}
-void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
ATRACE_CALL();
BQ_LOGV("cancelBuffer: slot %d", slot);
Mutex::Autolock lock(mCore->mMutex);
if (mCore->mIsAbandoned) {
BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
- return;
+ return NO_INIT;
+ }
+
+ if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+ BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
}
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
- return;
+ return BAD_VALUE;
} else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
"(state = %d)", slot, mSlots[slot].mBufferState);
- return;
+ return BAD_VALUE;
} else if (fence == NULL) {
BQ_LOGE("cancelBuffer: fence is NULL");
- return;
+ return BAD_VALUE;
}
mCore->mFreeBuffers.push_front(slot);
@@ -759,6 +823,8 @@
mSlots[slot].mFence = fence;
mCore->mDequeueCondition.broadcast();
mCore->validateConsistencyLocked();
+
+ return NO_ERROR;
}
int BufferQueueProducer::query(int what, int *outValue) {
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 04ab06b..d01187f 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -239,14 +239,14 @@
}
if (item->mGraphicBuffer != NULL) {
- mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
+ mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
}
- mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
- mSlots[item->mBuf].mFence = item->mFence;
+ mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
+ mSlots[item->mSlot].mFence = item->mFence;
CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
- item->mBuf, item->mFrameNumber);
+ item->mSlot, item->mFrameNumber);
return OK;
}
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index e29b740..7ed3d0f 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -106,22 +106,22 @@
}
}
- int buf = b.mBuf;
+ int slot = b.mSlot;
void *bufferPointer = NULL;
android_ycbcr ycbcr = android_ycbcr();
- PixelFormat format = mSlots[buf].mGraphicBuffer->getPixelFormat();
+ PixelFormat format = mSlots[slot].mGraphicBuffer->getPixelFormat();
PixelFormat flexFormat = format;
if (isPossiblyYUV(format)) {
if (b.mFence.get()) {
- err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
+ err = mSlots[slot].mGraphicBuffer->lockAsyncYCbCr(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&ycbcr,
b.mFence->dup());
} else {
- err = mSlots[buf].mGraphicBuffer->lockYCbCr(
+ err = mSlots[slot].mGraphicBuffer->lockYCbCr(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&ycbcr);
@@ -141,13 +141,13 @@
if (bufferPointer == NULL) { // not flexible YUV
if (b.mFence.get()) {
- err = mSlots[buf].mGraphicBuffer->lockAsync(
+ err = mSlots[slot].mGraphicBuffer->lockAsync(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&bufferPointer,
b.mFence->dup());
} else {
- err = mSlots[buf].mGraphicBuffer->lock(
+ err = mSlots[slot].mGraphicBuffer->lock(
GraphicBuffer::USAGE_SW_READ_OFTEN,
b.mCrop,
&bufferPointer);
@@ -169,19 +169,19 @@
assert(lockedIdx < mMaxLockedBuffers);
AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
- ab.mSlot = buf;
+ ab.mSlot = slot;
ab.mBufferPointer = bufferPointer;
- ab.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+ ab.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
nativeBuffer->data =
reinterpret_cast<uint8_t*>(bufferPointer);
- nativeBuffer->width = mSlots[buf].mGraphicBuffer->getWidth();
- nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
+ nativeBuffer->width = mSlots[slot].mGraphicBuffer->getWidth();
+ nativeBuffer->height = mSlots[slot].mGraphicBuffer->getHeight();
nativeBuffer->format = format;
nativeBuffer->flexFormat = flexFormat;
nativeBuffer->stride = (ycbcr.y != NULL) ?
static_cast<uint32_t>(ycbcr.ystride) :
- mSlots[buf].mGraphicBuffer->getStride();
+ mSlots[slot].mGraphicBuffer->getStride();
nativeBuffer->crop = b.mCrop;
nativeBuffer->transform = b.mTransform;
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 757e08a..1572a89 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -130,6 +130,7 @@
GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
ConsumerBase(bq, isControlledByApp),
+ mCurrentCrop(Rect::EMPTY_RECT),
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentFence(Fence::NO_FENCE),
@@ -157,6 +158,7 @@
GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
bool useFenceSync, bool isControlledByApp) :
ConsumerBase(bq, isControlledByApp),
+ mCurrentCrop(Rect::EMPTY_RECT),
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentFence(Fence::NO_FENCE),
@@ -181,12 +183,6 @@
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
}
-status_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return mConsumer->setDefaultMaxBufferCount(bufferCount);
-}
-
-
status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
{
Mutex::Autolock lock(mMutex);
@@ -355,7 +351,7 @@
// 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;
+ int slot = item->mSlot;
mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
}
@@ -379,12 +375,12 @@
{
status_t err = NO_ERROR;
- int buf = item.mBuf;
+ int slot = item.mSlot;
if (!mAttached) {
GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
"ES context");
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return INVALID_OPERATION;
}
@@ -392,7 +388,7 @@
// Confirm state.
err = checkAndUpdateEglStateLocked();
if (err != NO_ERROR) {
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return err;
}
@@ -402,11 +398,11 @@
// ConsumerBase.
// We may have to do this even when item.mGraphicBuffer == NULL (which
// means the buffer was previously acquired).
- err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
+ err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
if (err != NO_ERROR) {
GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
- mEglDisplay, buf);
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ mEglDisplay, slot);
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return UNKNOWN_ERROR;
}
@@ -418,7 +414,7 @@
// release the old buffer, so instead we just drop the new frame.
// As we are still under lock since acquireBuffer, it is safe to
// release by slot.
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
mEglDisplay, EGL_NO_SYNC_KHR);
return err;
}
@@ -426,7 +422,7 @@
GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
mCurrentTexture, mCurrentTextureImage != NULL ?
mCurrentTextureImage->graphicBufferHandle() : 0,
- buf, mSlots[buf].mGraphicBuffer->handle);
+ slot, mSlots[slot].mGraphicBuffer->handle);
// release old buffer
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
@@ -442,8 +438,8 @@
}
// Update the GLConsumer state.
- mCurrentTexture = buf;
- mCurrentTextureImage = mEglSlots[buf].mEglImage;
+ mCurrentTexture = slot;
+ mCurrentTextureImage = mEglSlots[slot].mEglImage;
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
mCurrentScalingMode = item.mScalingMode;
@@ -1046,6 +1042,11 @@
return mConsumer->setTransformHint(hint);
}
+status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
+ Mutex::Autolock lock(mMutex);
+ return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+}
+
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
{
result.appendFormat(
@@ -1083,7 +1084,8 @@
GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
mGraphicBuffer(graphicBuffer),
mEglImage(EGL_NO_IMAGE_KHR),
- mEglDisplay(EGL_NO_DISPLAY) {
+ mEglDisplay(EGL_NO_DISPLAY),
+ mCropRect(Rect::EMPTY_RECT) {
}
GLConsumer::EglImage::~EglImage() {
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index b86f4c5..d2f482e 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -43,8 +43,7 @@
CONSUMER_DISCONNECT,
GET_RELEASED_BUFFERS,
SET_DEFAULT_BUFFER_SIZE,
- SET_DEFAULT_MAX_BUFFER_COUNT,
- DISABLE_ASYNC_BUFFER,
+ SET_MAX_BUFFER_COUNT,
SET_MAX_ACQUIRED_BUFFER_COUNT,
SET_CONSUMER_NAME,
SET_DEFAULT_BUFFER_FORMAT,
@@ -172,21 +171,11 @@
return reply.readInt32();
}
- virtual status_t setDefaultMaxBufferCount(int bufferCount) {
+ virtual status_t setMaxBufferCount(int bufferCount) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
data.writeInt32(bufferCount);
- status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
- }
-
- virtual status_t disableAsyncBuffer() {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply);
+ status_t result = remote()->transact(SET_MAX_BUFFER_COUNT, data, &reply);
if (result != NO_ERROR) {
return result;
}
@@ -363,16 +352,10 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case SET_DEFAULT_MAX_BUFFER_COUNT: {
+ case SET_MAX_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
int bufferCount = data.readInt32();
- status_t result = setDefaultMaxBufferCount(bufferCount);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case DISABLE_ASYNC_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- status_t result = disableAsyncBuffer();
+ status_t result = setMaxBufferCount(bufferCount);
reply->writeInt32(result);
return NO_ERROR;
}
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index d7a7885..86b6971 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -34,7 +34,6 @@
enum {
REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- SET_BUFFER_COUNT,
DEQUEUE_BUFFER,
DETACH_BUFFER,
DETACH_NEXT_BUFFER,
@@ -49,6 +48,8 @@
ALLOW_ALLOCATION,
SET_GENERATION_NUMBER,
GET_CONSUMER_NAME,
+ SET_MAX_DEQUEUED_BUFFER_COUNT,
+ SET_ASYNC_MODE
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -82,12 +83,27 @@
return result;
}
- virtual status_t setBufferCount(int bufferCount)
- {
+ virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
+ data.writeInterfaceToken(
+ IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeInt32(maxDequeuedBuffers);
+ status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
+ data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
+ }
+
+ virtual status_t setAsyncMode(bool async) {
+ Parcel data, reply;
+ data.writeInterfaceToken(
+ IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeInt32(async);
+ status_t result = remote()->transact(SET_ASYNC_MODE,
+ data, &reply);
if (result != NO_ERROR) {
return result;
}
@@ -190,12 +206,17 @@
return result;
}
- virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
+ virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeInt32(buf);
data.write(*fence.get());
- remote()->transact(CANCEL_BUFFER, data, &reply);
+ status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
}
virtual int query(int what, int* value) {
@@ -334,10 +355,17 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case SET_BUFFER_COUNT: {
+ case SET_MAX_DEQUEUED_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int bufferCount = data.readInt32();
- int result = setBufferCount(bufferCount);
+ int maxDequeuedBuffers = data.readInt32();
+ int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
+ case SET_ASYNC_MODE: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ bool async = data.readInt32();
+ int result = setAsyncMode(async);
reply->writeInt32(result);
return NO_ERROR;
}
@@ -348,7 +376,7 @@
uint32_t height = data.readUint32();
PixelFormat format = static_cast<PixelFormat>(data.readInt32());
uint32_t usage = data.readUint32();
- int buf;
+ int buf = 0;
sp<Fence> fence;
int result = dequeueBuffer(&buf, &fence, async, width, height,
format, usage);
@@ -389,7 +417,7 @@
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
sp<GraphicBuffer> buffer = new GraphicBuffer();
data.read(*buffer.get());
- int slot;
+ int slot = 0;
int result = attachBuffer(&slot, buffer);
reply->writeInt32(slot);
reply->writeInt32(result);
@@ -411,12 +439,13 @@
int buf = data.readInt32();
sp<Fence> fence = new Fence();
data.read(*fence.get());
- cancelBuffer(buf, fence);
+ status_t result = cancelBuffer(buf, fence);
+ reply->writeInt32(result);
return NO_ERROR;
}
case QUERY: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
- int value;
+ int value = 0;
int what = data.readInt32();
int res = query(what, &value);
reply->writeInt32(value);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 78886d5..b4cbf84 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -353,7 +353,7 @@
sp<IBinder> display = data.readStrongBinder();
sp<IGraphicBufferProducer> producer =
interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
- Rect sourceCrop;
+ Rect sourceCrop(Rect::EMPTY_RECT);
data.read(sourceCrop);
uint32_t reqWidth = data.readUint32();
uint32_t reqHeight = data.readUint32();
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 00323dc..eafda86 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -77,6 +77,16 @@
}
+DisplayState::DisplayState() :
+ what(0),
+ layerStack(0),
+ orientation(eOrientationDefault),
+ viewport(Rect::EMPTY_RECT),
+ frame(Rect::EMPTY_RECT),
+ width(0),
+ height(0) {
+}
+
status_t DisplayState::write(Parcel& output) const {
output.writeStrongBinder(token);
output.writeStrongBinder(IInterface::asBinder(surface));
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 4b3603e..81c0549 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -38,7 +38,8 @@
Sensor::Sensor()
: mHandle(0), mType(0),
mMinValue(0), mMaxValue(0), mResolution(0),
- mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0),
+ mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
+ mFifoMaxEventCount(0), mRequiredAppOp(0),
mMaxDelay(0), mFlags(0)
{
}
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 43f9214..dce0e87 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -132,7 +132,7 @@
ALOGV("acquired buffer %#" PRIx64 " from input",
bufferItem.mGraphicBuffer->getId());
- status = mInput->detachBuffer(bufferItem.mBuf);
+ status = mInput->detachBuffer(bufferItem.mSlot);
LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
"detaching buffer from input failed (%d)", status);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 4b76f98..de5c275 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -43,6 +43,7 @@
const sp<IGraphicBufferProducer>& bufferProducer,
bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
+ mCrop(Rect::EMPTY_RECT),
mGenerationNumber(0)
{
// Initialize the ANativeWindow function pointers.
@@ -67,7 +68,6 @@
mReqUsage = 0;
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
mDataSpace = HAL_DATASPACE_UNKNOWN;
- mCrop.clear();
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0;
mStickyTransform = 0;
@@ -184,7 +184,9 @@
va_list args;
va_start(args, operation);
Surface* c = getSelf(window);
- return c->perform(operation, args);
+ int result = c->perform(operation, args);
+ va_end(args);
+ return result;
}
int Surface::setSwapInterval(int interval) {
@@ -332,7 +334,7 @@
// Make sure the crop rectangle is entirely inside the buffer.
- Rect crop;
+ Rect crop(Rect::EMPTY_RECT);
mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
@@ -779,7 +781,7 @@
{
ATRACE_CALL();
- Rect realRect;
+ Rect realRect(Rect::EMPTY_RECT);
if (rect == NULL || rect->isEmpty()) {
realRect.clear();
} else {
@@ -800,9 +802,54 @@
ALOGV("Surface::setBufferCount");
Mutex::Autolock lock(mMutex);
- status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
+ status_t err = NO_ERROR;
+ if (bufferCount == 0) {
+ err = mGraphicBufferProducer->setMaxDequeuedBufferCount(1);
+ } else {
+ int minUndequeuedBuffers = 0;
+ err = mGraphicBufferProducer->query(
+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
+ if (err == NO_ERROR) {
+ err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
+ bufferCount - minUndequeuedBuffers);
+ }
+ }
+
+ if (err == NO_ERROR) {
+ freeAllBuffers();
+ }
+
ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
- bufferCount, strerror(-err));
+ bufferCount, strerror(-err));
+
+ return err;
+}
+
+int Surface::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
+ ATRACE_CALL();
+ ALOGV("Surface::setMaxDequeuedBufferCount");
+ Mutex::Autolock lock(mMutex);
+
+ status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
+ maxDequeuedBuffers);
+ ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
+ "returned %s", maxDequeuedBuffers, strerror(-err));
+
+ if (err == NO_ERROR) {
+ freeAllBuffers();
+ }
+
+ return err;
+}
+
+int Surface::setAsyncMode(bool async) {
+ ATRACE_CALL();
+ ALOGV("Surface::setAsyncMode");
+ Mutex::Autolock lock(mMutex);
+
+ status_t err = mGraphicBufferProducer->setAsyncMode(async);
+ ALOGE_IF(err, "IGraphicBufferProducer::setAsyncMode(%d) returned %s",
+ async, strerror(-err));
if (err == NO_ERROR) {
freeAllBuffers();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6ad47d8..9167a0c 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -310,9 +310,9 @@
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
return BAD_INDEX;
- if (mask & layer_state_t::eLayerOpaque ||
- mask & layer_state_t::eLayerHidden ||
- mask & layer_state_t::eLayerSecure) {
+ if ((mask & layer_state_t::eLayerOpaque) ||
+ (mask & layer_state_t::eLayerHidden) ||
+ (mask & layer_state_t::eLayerSecure)) {
s->what |= layer_state_t::eFlagsChanged;
}
s->flags &= ~mask;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 1a54875..8a3be3d 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -145,7 +145,7 @@
IGraphicBufferProducer::QueueBufferOutput qbo;
mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
&qbo);
- mProducer->setBufferCount(4);
+ mProducer->setMaxDequeuedBufferCount(3);
int slot;
sp<Fence> fence;
@@ -189,6 +189,9 @@
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
+
+ EXPECT_EQ(OK, mConsumer->setMaxBufferCount(5));
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(5));
}
TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
@@ -206,6 +209,28 @@
BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
}
+TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ mConsumer->consumerConnect(dc, false);
+
+ // Test single buffer mode
+ EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
+}
+
+TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ mConsumer->consumerConnect(dc, false);
+
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
+ BufferQueue::NUM_BUFFER_SLOTS + 1));
+
+ EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
+ EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
+}
+
TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
@@ -288,8 +313,8 @@
BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
- ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
- ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mBuf)); // Not acquired
+ ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
+ ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
uint32_t* dataIn;
ASSERT_EQ(OK, item.mGraphicBuffer->lock(
@@ -348,7 +373,7 @@
BufferItem item;
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
- ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
+ ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
int newSlot;
ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 2dc9ccc..289cc74 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -444,19 +444,14 @@
}
}
-void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
- const android_native_rect_t& rect);
-
-void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride);
-
-void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
- uint8_t g, uint8_t b, uint8_t a);
-
// Configures the ANativeWindow producer-side interface based on test parameters
void configureANW(const sp<ANativeWindow>& anw,
const CpuConsumerTestParams& params,
int maxBufferSlack) {
status_t err;
+ err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU);
+ ASSERT_NO_ERROR(err, "connect error: ");
+
err = native_window_set_buffers_dimensions(anw.get(),
params.width, params.height);
ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
diff --git a/libs/gui/tests/GLTest.h b/libs/gui/tests/GLTest.h
index d3c4a95..f0d27a8 100644
--- a/libs/gui/tests/GLTest.h
+++ b/libs/gui/tests/GLTest.h
@@ -35,9 +35,11 @@
protected:
GLTest() :
+ mDisplaySecs(0),
mEglDisplay(EGL_NO_DISPLAY),
mEglSurface(EGL_NO_SURFACE),
- mEglContext(EGL_NO_CONTEXT) {
+ mEglContext(EGL_NO_CONTEXT),
+ mGlConfig(NULL) {
}
virtual void SetUp();
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 4ef9a69..34fb998 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -208,6 +208,27 @@
return mProducer->dequeueBuffer(&result->slot, &result->fence, async, w, h, format, usage);
}
+ void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
+ sp<GraphicBuffer> *buffer)
+ {
+ ASSERT_TRUE(slot != NULL);
+ ASSERT_TRUE(fence != NULL);
+ ASSERT_TRUE(buffer != NULL);
+
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(slot, fence,
+ QUEUE_BUFFER_INPUT_ASYNC, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+
+ EXPECT_LE(0, *slot);
+ EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
+
+ // Request the buffer (pre-requisite for queueing)
+ ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
+ }
+
private: // hide from test body
sp<DummyConsumer> mDC;
@@ -334,12 +355,11 @@
int dequeuedSlot = -1;
sp<Fence> dequeuedFence;
- // XX: OK to assume first call returns this flag or not? Not really documented.
- ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
QUEUE_BUFFER_INPUT_ASYNC,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS));
+ TEST_PRODUCER_USAGE_BITS)));
EXPECT_LE(0, dequeuedSlot);
EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
@@ -400,11 +420,11 @@
int dequeuedSlot = -1;
sp<Fence> dequeuedFence;
- ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
QUEUE_BUFFER_INPUT_ASYNC,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS));
+ TEST_PRODUCER_USAGE_BITS)));
// Slot was enqueued without requesting a buffer
{
@@ -470,30 +490,29 @@
int dequeuedSlot = -1;
sp<Fence> dequeuedFence;
- ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
QUEUE_BUFFER_INPUT_ASYNC,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS));
+ TEST_PRODUCER_USAGE_BITS)));
// No return code, but at least test that it doesn't blow up...
// TODO: add a return code
mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
}
-TEST_F(IGraphicBufferProducerTest, SetBufferCount_Succeeds) {
+TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ int minUndequeuedBuffers;
+ ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBuffers));
- // The producer does not wish to set a buffer count
- EXPECT_OK(mProducer->setBufferCount(0)) << "bufferCount: " << 0;
- // TODO: how to test "0" buffer count?
+ const int minBuffers = 1;
+ const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
- int minBuffers;
- ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minBuffers));
-
- // The MIN_UNDEQUEUED_BUFFERS limit is exclusive, so need to increment by at least 1
- minBuffers++;
-
- ASSERT_OK(mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
+ ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
+ << "bufferCount: " << minBuffers;
std::vector<DequeueBufferResult> dequeueList;
@@ -501,72 +520,231 @@
for (int i = 0; i < minBuffers; ++i) {
DequeueBufferResult result;
- EXPECT_LE(OK,
- dequeueBuffer(QUEUE_BUFFER_INPUT_ASYNC,
+ EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (dequeueBuffer(QUEUE_BUFFER_INPUT_ASYNC,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS, &result))
+ TEST_PRODUCER_USAGE_BITS, &result)))
<< "iteration: " << i << ", slot: " << result.slot;
dequeueList.push_back(result);
}
// Cancel every buffer, so we can set buffer count again
- for (int i = 0; i < minBuffers; ++i) {
- DequeueBufferResult& result = dequeueList[i];
+ for (auto& result : dequeueList) {
mProducer->cancelBuffer(result.slot, result.fence);
}
- ASSERT_OK(mProducer->setBufferCount(BufferQueue::NUM_BUFFER_SLOTS));
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
- // Should now be able to dequeue up to NUM_BUFFER_SLOTS times
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; ++i) {
+ // Should now be able to dequeue up to maxBuffers times
+ for (int i = 0; i < maxBuffers; ++i) {
int dequeuedSlot = -1;
sp<Fence> dequeuedFence;
- EXPECT_LE(OK,
- mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
QUEUE_BUFFER_INPUT_ASYNC,
- DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS))
+ DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS)))
<< "iteration: " << i << ", slot: " << dequeuedSlot;
}
}
-TEST_F(IGraphicBufferProducerTest, SetBufferCount_Fails) {
- int minBuffers;
- ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minBuffers));
+TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ int minUndequeuedBuffers;
+ ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBuffers));
- // The MIN_UNDEQUEUED_BUFFERS limit is exclusive, so need to increment by at least 1
- minBuffers++;
+ const int minBuffers = 1;
+ const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
+ ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
// Buffer count was out of range
- EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(-1)) << "bufferCount: " << -1;
- EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(minBuffers - 1)) << "bufferCount: " << minBuffers - 1;
- EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(BufferQueue::NUM_BUFFER_SLOTS + 1))
- << "bufferCount: " << BufferQueue::NUM_BUFFER_SLOTS + 1;
+ EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
+ << "bufferCount: " << 0;
+ EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
+ << "bufferCount: " << maxBuffers + 1;
- // Pre-requisite to fail out a valid setBufferCount call
+ // Prerequisite to fail out a valid setBufferCount call
{
int dequeuedSlot = -1;
sp<Fence> dequeuedFence;
- ASSERT_LE(OK,
- mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
QUEUE_BUFFER_INPUT_ASYNC,
- DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS))
+ DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT,
+ TEST_PRODUCER_USAGE_BITS)))
<< "slot: " << dequeuedSlot;
}
// Client has one or more buffers dequeued
- EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
+ EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(minBuffers))
+ << "bufferCount: " << minBuffers;
// Abandon buffer queue
ASSERT_OK(mConsumer->consumerDisconnect());
// Fail because the buffer queue was abandoned
- EXPECT_EQ(NO_INIT, mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
+ EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
+ << "bufferCount: " << minBuffers;
}
+TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
+ ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
+ ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
+
+ int dequeuedSlot = -1;
+ sp<Fence> dequeuedFence;
+ IGraphicBufferProducer::QueueBufferInput input(QUEUE_BUFFER_INPUT_TIMESTAMP,
+ QUEUE_BUFFER_INPUT_IS_AUTO_TIMESTAMP, QUEUE_BUFFER_INPUT_DATASPACE,
+ QUEUE_BUFFER_INPUT_RECT, QUEUE_BUFFER_INPUT_SCALING_MODE,
+ QUEUE_BUFFER_INPUT_TRANSFORM, true, QUEUE_BUFFER_INPUT_FENCE);
+ IGraphicBufferProducer::QueueBufferOutput output;
+ sp<GraphicBuffer> dequeuedBuffer;
+
+ // Should now be able to queue/dequeue as many buffers as we want without
+ // blocking
+ for (int i = 0; i < 5; ++i) {
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ true, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS))) << "slot : "
+ << dequeuedSlot;
+ ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
+ ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
+ }
+}
+
+TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+ // Prerequisite to fail out a valid setBufferCount call
+ {
+ int dequeuedSlot = -1;
+ sp<Fence> dequeuedFence;
+
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+ QUEUE_BUFFER_INPUT_ASYNC, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS))) << "slot: "
+ << dequeuedSlot;
+ }
+
+ // Client has one or more buffers dequeued
+ EXPECT_EQ(BAD_VALUE, mProducer->setAsyncMode(false)) << "asyncMode: "
+ << false;
+
+ // Abandon buffer queue
+ ASSERT_OK(mConsumer->consumerDisconnect());
+
+ // Fail because the buffer queue was abandoned
+ EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
+ << false;
+}
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_dequeueBuffer) {
+ int slot = -1;
+ sp<Fence> fence;
+
+ ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence,
+ QUEUE_BUFFER_INPUT_ASYNC, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_detachNextBuffer) {
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_requestBuffer) {
+ ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+ int slot = -1;
+ sp<Fence> fence;
+
+ ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+ (mProducer->dequeueBuffer(&slot, &fence,
+ QUEUE_BUFFER_INPUT_ASYNC, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+ DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+
+ EXPECT_LE(0, slot);
+ EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
+
+ ASSERT_OK(mProducer->disconnect(TEST_API));
+
+ sp<GraphicBuffer> buffer;
+
+ ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
+}
+
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_detachBuffer) {
+ int slot = -1;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+ ASSERT_OK(mProducer->disconnect(TEST_API));
+
+ ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_queueBuffer) {
+ int slot = -1;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+ ASSERT_OK(mProducer->disconnect(TEST_API));
+
+ // A generic "valid" input
+ IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+ IGraphicBufferProducer::QueueBufferOutput output;
+
+ ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_cancelBuffer) {
+ int slot = -1;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+ ASSERT_OK(mProducer->disconnect(TEST_API));
+
+ ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+ DisconnectedProducerReturnsError_attachBuffer) {
+ int slot = -1;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+ ASSERT_OK(mProducer->detachBuffer(slot));
+
+ ASSERT_OK(mProducer->disconnect(TEST_API));
+
+ ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+}
+
} // namespace android
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 00cc39d..afd149e 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -128,7 +128,7 @@
ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
- ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
+ ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
@@ -196,7 +196,7 @@
ASSERT_EQ(*dataOut, TEST_DATA);
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
- ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf,
+ ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mSlot,
item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
Fence::NO_FENCE));
}
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 1a50b24..2356f54 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -37,7 +37,8 @@
SurfaceTextureClientTest():
mEglDisplay(EGL_NO_DISPLAY),
mEglSurface(EGL_NO_SURFACE),
- mEglContext(EGL_NO_CONTEXT) {
+ mEglContext(EGL_NO_CONTEXT),
+ mEglConfig(NULL) {
}
virtual void SetUp() {
@@ -215,6 +216,7 @@
}
TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer* buf;
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
EXPECT_EQ(1, buf->width);
@@ -224,6 +226,7 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -235,6 +238,7 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -246,6 +250,7 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
@@ -257,6 +262,7 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
@@ -275,6 +281,7 @@
}
TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -292,6 +299,7 @@
}
TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
sp<GLConsumer> st(mST);
ANativeWindowBuffer* buf;
EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
@@ -304,6 +312,7 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
ANativeWindowBuffer* buf[2];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -324,6 +333,7 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
ANativeWindowBuffer* buf[2];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -350,6 +360,7 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
@@ -373,6 +384,7 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -393,6 +405,7 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -413,8 +426,8 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
-
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
EXPECT_EQ(OK, mST->updateTexImage());
@@ -438,6 +451,7 @@
TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
android_native_buffer_t* buf[3];
android_native_buffer_t* firstBuf;
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
@@ -457,6 +471,7 @@
TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
// We should be able to dequeue all the buffers before we've queued mANWy.
@@ -482,6 +497,7 @@
}
TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
android_native_rect_t rect = {-2, -13, 40, 18};
native_window_set_crop(mANW.get(), &rect);
@@ -536,6 +552,7 @@
};
android_native_buffer_t* buf[3];
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
// dequeue/queue/update so we have a current buffer
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -559,6 +576,7 @@
TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) {
android_native_buffer_t* buf[3];
float mtx[16] = {};
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -589,6 +607,7 @@
TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) {
android_native_buffer_t* buf[3];
float mtx[16] = {};
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -638,6 +657,7 @@
crop.right = 5;
crop.bottom = 5;
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8));
ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp
index c243fc0..0606839 100644
--- a/libs/gui/tests/SurfaceTextureFBO_test.cpp
+++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp
@@ -27,6 +27,8 @@
const int texWidth = 64;
const int texHeight = 64;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
index 9776733..b4e25f3 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
@@ -134,8 +134,6 @@
}
};
- ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
-
runProducerThread(new PT());
// Allow three frames to be rendered and queued before starting the
diff --git a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
index 6edbfb8..b3f6066 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
@@ -29,8 +29,9 @@
mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
// This test requires 3 buffers to avoid deadlock because we're
- // both producer and consumer, and only using one thread.
- mST->setDefaultMaxBufferCount(3);
+ // both producer and consumer, and only using one thread. Set max dequeued
+ // to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Do the producer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -81,7 +82,8 @@
mST->setDefaultBufferSize(texWidth, texHeight);
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Do the producer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -330,7 +332,8 @@
enum { texHeight = 64 };
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Set the user buffer size.
native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
@@ -387,7 +390,8 @@
enum { texHeight = 16 };
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Set the transform hint.
mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
@@ -448,7 +452,8 @@
enum { texHeight = 16 };
// This test requires 3 buffers to complete run on a single thread.
- mST->setDefaultMaxBufferCount(3);
+ // Set max dequeued to 2, and max acquired already defaults to 1.
+ ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
// Set the transform hint.
mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index fad133f..1a904b5 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -28,6 +28,8 @@
const int texWidth = 64;
const int texHeight = 66;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -76,6 +78,8 @@
const int texWidth = 64;
const int texHeight = 64;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -124,6 +128,8 @@
const int texWidth = 64;
const int texHeight = 66;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -190,7 +196,8 @@
enum { texHeight = 16 };
enum { numFrames = 1024 };
- ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -334,6 +341,8 @@
const int texWidth = 64;
const int texHeight = 66;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -378,6 +387,8 @@
const int texWidth = 64;
const int texHeight = 64;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
texWidth, texHeight));
ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -436,7 +447,10 @@
virtual bool threadLoop() {
ANativeWindowBuffer* anb;
- native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
+ if (native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU) !=
+ NO_ERROR) {
+ return false;
+ }
for (int numFrames =0 ; numFrames < 2; numFrames ++) {
@@ -453,7 +467,10 @@
}
}
- native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
+ if (native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU)
+ != NO_ERROR) {
+ return false;
+ }
return false;
}
@@ -487,7 +504,7 @@
// attempt to release a buffer that it does not owned
TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
- NATIVE_WINDOW_API_EGL));
+ NATIVE_WINDOW_API_CPU));
ANativeWindowBuffer *anb;
@@ -501,9 +518,9 @@
EXPECT_EQ(OK,mST->updateTexImage());
ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
- NATIVE_WINDOW_API_EGL));
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
- NATIVE_WINDOW_API_EGL));
+ NATIVE_WINDOW_API_CPU));
EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
@@ -513,7 +530,7 @@
EXPECT_EQ(OK,mST->updateTexImage());
ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
- NATIVE_WINDOW_API_EGL));
+ NATIVE_WINDOW_API_CPU));
}
TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
@@ -615,6 +632,11 @@
Mutex::Autolock lock(mMutex);
ANativeWindowBuffer* anb;
+ if (native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU) !=
+ NO_ERROR) {
+ return false;
+ }
+
// Frame 1
if (native_window_dequeue_buffer_and_wait(mANW.get(),
&anb) != NO_ERROR) {
@@ -658,8 +680,6 @@
Mutex mMutex;
};
- ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
-
sp<Thread> pt(new ProducerThread(mANW));
pt->run();
@@ -681,6 +701,9 @@
int texHeight = 16;
ANativeWindowBuffer* anb;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+ NATIVE_WINDOW_API_CPU));
+
GLint maxTextureSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL.h b/libs/gui/tests/SurfaceTextureMultiContextGL.h
index 7934bbc..3cca035 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL.h
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL.h
@@ -27,7 +27,8 @@
enum { THIRD_TEX_ID = 456 };
SurfaceTextureMultiContextGLTest():
- mSecondEglContext(EGL_NO_CONTEXT) {
+ mSecondEglContext(EGL_NO_CONTEXT),
+ mThirdEglContext(EGL_NO_CONTEXT) {
}
virtual void SetUp() {
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
index 1cd101e..5b02dcf 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
@@ -26,6 +26,7 @@
namespace android {
TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -40,6 +41,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -55,6 +57,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
DetachFromContextSucceedsAfterProducerDisconnect) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -70,6 +73,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -82,6 +86,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -96,6 +101,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -112,6 +118,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -128,6 +135,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Detach from the primary context.
@@ -139,6 +147,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -169,6 +178,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
AttachToContextSucceedsAfterProducerDisconnect) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -200,6 +210,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
AttachToContextSucceedsBeforeUpdateTexImage) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Detach from the primary context.
@@ -230,6 +241,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -247,6 +259,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -259,6 +272,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Attempt to attach to the primary context.
@@ -266,6 +280,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -285,6 +300,7 @@
}
TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Latch the texture contents on the primary context.
@@ -323,6 +339,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
// Detach from the primary context.
@@ -361,7 +378,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
- ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
// produce two frames and consume them both on the primary context
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
@@ -388,7 +405,7 @@
TEST_F(SurfaceTextureMultiContextGLTest,
AttachAfterDisplayTerminatedSucceeds) {
- ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+ ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
// produce two frames and consume them both on the primary context
ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3f495f8..6f0104a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -100,6 +100,8 @@
ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
64, 64, 0, 0x7fffffff, false));
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
+ NATIVE_WINDOW_API_CPU));
// Set the PROTECTED usage bit and verify that the screenshot fails. Note
// that we need to dequeue a buffer in order for it to actually get
// allocated in SurfaceFlinger.
@@ -190,6 +192,8 @@
// Allocate a buffer with a generation number of 0
ANativeWindowBuffer* buffer;
int fenceFd;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(),
+ NATIVE_WINDOW_API_CPU));
ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
diff --git a/libs/gui/tests/TextureRenderer.cpp b/libs/gui/tests/TextureRenderer.cpp
index 90951b3..e822e6e 100644
--- a/libs/gui/tests/TextureRenderer.cpp
+++ b/libs/gui/tests/TextureRenderer.cpp
@@ -28,7 +28,8 @@
namespace android {
TextureRenderer::TextureRenderer(GLuint texName,
- const sp<GLConsumer>& st) : mTexName(texName), mST(st) {
+ const sp<GLConsumer>& st) : mTexName(texName), mST(st), mPgm(0),
+ mPositionHandle(-1), mTexSamplerHandle(-1), mTexMatrixHandle(-1) {
}
void TextureRenderer::SetUp() {
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 3ead25c..59db157 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -74,7 +74,7 @@
*/
FramebufferNativeWindow::FramebufferNativeWindow()
- : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
+ : BASE(), fbDev(0), grDev(0), mCurrentBufferIndex(0), mUpdateOnDemand(false)
{
hw_module_t const* module;
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index e55db30..72d390c 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -43,7 +43,7 @@
GraphicBuffer::GraphicBuffer()
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId())
+ mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{
width =
height =
@@ -56,7 +56,7 @@
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
PixelFormat inFormat, uint32_t inUsage)
: BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId())
+ mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{
width =
height =
@@ -72,7 +72,7 @@
native_handle_t* inHandle, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mId(getUniqueId())
+ mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{
width = static_cast<int>(inWidth);
height = static_cast<int>(inHeight);
@@ -85,7 +85,8 @@
GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
: BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
mBufferMapper(GraphicBufferMapper::get()),
- mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId())
+ mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()),
+ mGenerationNumber(0)
{
width = buffer->width;
height = buffer->height;
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index dcce21f..99cbedc 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -20,6 +20,7 @@
namespace android {
const Rect Rect::INVALID_RECT{0, 0, -1, -1};
+const Rect Rect::EMPTY_RECT{0, 0, 0, 0};
static inline int32_t min(int32_t a, int32_t b) {
return (a < b) ? a : b;
@@ -110,7 +111,7 @@
}
Rect Rect::reduce(const Rect& exclude) const {
- Rect result;
+ Rect result(Rect::EMPTY_RECT);
uint32_t mask = 0;
mask |= (exclude.left > left) ? 1 : 0;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 3810da4..ac37990 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -798,7 +798,7 @@
Region result;
result.mStorage.clear();
for (size_t r = 0; r < numRects; ++r) {
- Rect rect;
+ Rect rect(Rect::EMPTY_RECT);
status_t status = rect.unflatten(buffer, size);
if (status != NO_ERROR) {
return status;
@@ -835,18 +835,6 @@
return begin();
}
-SharedBuffer const* Region::getSharedBuffer(size_t* count) const {
- // We can get to the SharedBuffer of a Vector<Rect> because Rect has
- // a trivial destructor.
- SharedBuffer const* sb = SharedBuffer::bufferFromData(mStorage.array());
- if (count) {
- size_t numRects = isRect() ? 1 : mStorage.size() - 1;
- count[0] = numRects;
- }
- sb->acquire();
- return sb;
-}
-
// ----------------------------------------------------------------------------
void Region::dump(String8& out, const char* what, uint32_t /* flags */) const
diff --git a/services/inputflinger/host/Android.mk b/services/inputflinger/host/Android.mk
index b828175..0a7fc27 100644
--- a/services/inputflinger/host/Android.mk
+++ b/services/inputflinger/host/Android.mk
@@ -58,5 +58,6 @@
libutils
LOCAL_MODULE := inputflinger
+LOCAL_INIT_RC := inputflinger.rc
include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index cb4ccbe..bd11d56 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -35,48 +35,6 @@
#define INDENT2 " "
-namespace android {
-
-static input_host_callbacks_t kCallbacks = {
- .create_device_identifier = create_device_identifier,
- .create_device_definition = create_device_definition,
- .create_input_report_definition = create_input_report_definition,
- .create_output_report_definition = create_output_report_definition,
- .free_report_definition = free_report_definition,
- .input_device_definition_add_report = input_device_definition_add_report,
- .input_report_definition_add_collection = input_report_definition_add_collection,
- .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
- .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
- .register_device = register_device,
- .input_allocate_report = input_allocate_report,
- .input_report_set_usage_int = input_report_set_usage_int,
- .input_report_set_usage_bool = input_report_set_usage_bool,
- .report_event = report_event,
- .input_get_device_property_map = input_get_device_property_map,
- .input_get_device_property = input_get_device_property,
- .input_get_property_key = input_get_property_key,
- .input_get_property_value = input_get_property_value,
- .input_free_device_property = input_free_device_property,
- .input_free_device_property_map = input_free_device_property_map,
-};
-
-InputDriver::InputDriver(const char* name) : mName(String8(name)) {
- const hw_module_t* module;
- int err = input_open(&module, name);
- LOG_ALWAYS_FATAL_IF(err != 0, "Input module %s not found", name);
- mHal = reinterpret_cast<const input_module_t*>(module);
-}
-
-void InputDriver::init(InputHostInterface* host) {
- mHal->init(mHal, static_cast<input_host_t*>(host), kCallbacks);
-}
-
-void InputDriver::dump(String8& result) {
- result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
-}
-
-} // namespace android
-
struct input_property_map {
android::PropertyMap* propertyMap;
};
@@ -127,92 +85,130 @@
std::unordered_map<input_collection_id_t, input_collection, InputCollectionIdHasher> collections;
};
-// HAL wrapper functions
namespace android {
-::input_device_identifier_t* create_device_identifier(input_host_t* host,
- const char* name, int32_t product_id, int32_t vendor_id,
- input_bus_t bus, const char* unique_id) {
+static input_host_callbacks_t kCallbacks = {
+ .create_device_identifier = create_device_identifier,
+ .create_device_definition = create_device_definition,
+ .create_input_report_definition = create_input_report_definition,
+ .create_output_report_definition = create_output_report_definition,
+ .free_report_definition = free_report_definition,
+ .input_device_definition_add_report = input_device_definition_add_report,
+ .input_report_definition_add_collection = input_report_definition_add_collection,
+ .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
+ .input_report_definition_declare_usages_bool = input_report_definition_declare_usages_bool,
+ .register_device = register_device,
+ .input_allocate_report = input_allocate_report,
+ .input_report_set_usage_int = input_report_set_usage_int,
+ .input_report_set_usage_bool = input_report_set_usage_bool,
+ .report_event = report_event,
+ .input_get_device_property_map = input_get_device_property_map,
+ .input_get_device_property = input_get_device_property,
+ .input_get_property_key = input_get_property_key,
+ .input_get_property_value = input_get_property_value,
+ .input_free_device_property = input_free_device_property,
+ .input_free_device_property_map = input_free_device_property_map,
+};
+
+InputDriver::InputDriver(const char* name) : mName(String8(name)) {
+ const hw_module_t* module;
+ int err = input_open(&module, name);
+ LOG_ALWAYS_FATAL_IF(err != 0, "Input module %s not found", name);
+ mHal = reinterpret_cast<const input_module_t*>(module);
+}
+
+void InputDriver::init() {
+ mHal->init(mHal, static_cast<input_host_t*>(this), kCallbacks);
+}
+
+input_device_identifier_t* InputDriver::createDeviceIdentifier(
+ const char* name, int32_t productId, int32_t vendorId,
+ input_bus_t bus, const char* uniqueId) {
auto identifier = new ::input_device_identifier {
.name = name,
- .productId = product_id,
- .vendorId = vendor_id,
- //.bus = bus,
- .uniqueId = unique_id,
+ .productId = productId,
+ .vendorId = vendorId,
+ .bus = bus,
+ .uniqueId = uniqueId,
};
- // store this identifier somewhere? in the host?
+ // TODO: store this identifier somewhere
return identifier;
}
-input_device_definition_t* create_device_definition(input_host_t* host) {
+input_device_definition_t* InputDriver::createDeviceDefinition() {
return new ::input_device_definition;
}
-input_report_definition_t* create_input_report_definition(input_host_t* host) {
+input_report_definition_t* InputDriver::createInputReportDefinition() {
return new ::input_report_definition;
}
-input_report_definition_t* create_output_report_definition(input_host_t* host) {
+input_report_definition_t* InputDriver::createOutputReportDefinition() {
return new ::input_report_definition;
}
-void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
- delete report_def;
+void InputDriver::freeReportDefinition(input_report_definition_t* reportDef) {
+ delete reportDef;
}
-void input_device_definition_add_report(input_host_t* host,
- input_device_definition_t* d, input_report_definition_t* r) {
+void InputDriver::inputDeviceDefinitionAddReport(input_device_definition_t* d,
+ input_report_definition_t* r) {
d->reportDefs.push_back(r);
}
-void input_report_definition_add_collection(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
+void InputDriver::inputReportDefinitionAddCollection(input_report_definition_t* report,
+ input_collection_id_t id, int32_t arity) {
report->collections[id] = {.arity = arity};
}
-void input_report_definition_declare_usage_int(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t usage, int32_t min, int32_t max, float resolution) {
+void InputDriver::inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+ input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+ float resolution) {
if (report->collections.find(id) != report->collections.end()) {
report->collections[id].intUsages.push_back({
.usage = usage, .min = min, .max = max, .resolution = resolution});
}
}
-void input_report_definition_declare_usages_bool(input_host_t* host,
- input_report_definition_t* report, input_collection_id_t id,
- input_usage_t* usage, size_t usage_count) {
+void InputDriver::inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+ input_collection_id_t id, input_usage_t* usage, size_t usageCount) {
if (report->collections.find(id) != report->collections.end()) {
- for (size_t i = 0; i < usage_count; ++i) {
+ for (size_t i = 0; i < usageCount; ++i) {
report->collections[id].boolUsages.push_back(usage[i]);
}
}
}
-input_device_handle_t* register_device(input_host_t* host,
- input_device_identifier_t* id, input_device_definition_t* d) {
- ALOGD("Registering device %s with %d input reports", id->name, d->reportDefs.size());
+input_device_handle_t* InputDriver::registerDevice(input_device_identifier_t* id,
+ input_device_definition_t* d) {
+ ALOGD("Registering device %s with %zu input reports", id->name, d->reportDefs.size());
+ // TODO: save this device handle
return new input_device_handle{ .id = id, .def = d };
}
-input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+void InputDriver::unregisterDevice(input_device_handle_t* handle) {
+ delete handle;
+}
+
+input_report_t* InputDriver::inputAllocateReport(input_report_definition_t* r) {
ALOGD("Allocating input report for definition %p", r);
return nullptr;
}
-void input_report_set_usage_int(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
+void InputDriver::inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+ input_usage_t usage, int32_t value, int32_t arity_index) {
+}
-void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
- input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
+void InputDriver::inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+ input_usage_t usage, bool value, int32_t arity_index) {
+}
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
+void InputDriver::reportEvent(input_device_handle_t* d, input_report_t* report) {
ALOGD("report_event %p for handle %p", report, d);
}
-input_property_map_t* input_get_device_property_map(input_host_t* host,
- input_device_identifier_t* id) {
+input_property_map_t* InputDriver::inputGetDevicePropertyMap(input_device_identifier_t* id) {
InputDeviceIdentifier idi;
idi.name = id->name;
idi.uniqueId = id->uniqueId;
@@ -241,7 +237,7 @@
return nullptr;
}
-input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+input_property_t* InputDriver::inputGetDeviceProperty(input_property_map_t* map,
const char* key) {
String8 keyString(key);
if (map != nullptr) {
@@ -258,31 +254,159 @@
return nullptr;
}
-const char* input_get_property_key(input_host_t* host, input_property_t* property) {
+const char* InputDriver::inputGetPropertyKey(input_property_t* property) {
if (property != nullptr) {
return property->key.string();
}
return nullptr;
}
-const char* input_get_property_value(input_host_t* host, input_property_t* property) {
+const char* InputDriver::inputGetPropertyValue(input_property_t* property) {
if (property != nullptr) {
return property->value.string();
}
return nullptr;
}
-void input_free_device_property(input_host_t* host, input_property_t* property) {
+void InputDriver::inputFreeDeviceProperty(input_property_t* property) {
if (property != nullptr) {
delete property;
}
}
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+void InputDriver::inputFreeDevicePropertyMap(input_property_map_t* map) {
if (map != nullptr) {
delete map->propertyMap;
delete map;
}
}
+void InputDriver::dump(String8& result) {
+ result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
+}
+
+} // namespace android
+
+// HAL wrapper functions
+
+namespace android {
+
+::input_device_identifier_t* create_device_identifier(input_host_t* host,
+ const char* name, int32_t product_id, int32_t vendor_id,
+ input_bus_t bus, const char* unique_id) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->createDeviceIdentifier(name, product_id, vendor_id, bus, unique_id);
+}
+
+input_device_definition_t* create_device_definition(input_host_t* host) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->createDeviceDefinition();
+}
+
+input_report_definition_t* create_input_report_definition(input_host_t* host) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->createInputReportDefinition();
+}
+
+input_report_definition_t* create_output_report_definition(input_host_t* host) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->createOutputReportDefinition();
+}
+
+void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->freeReportDefinition(report_def);
+}
+
+void input_device_definition_add_report(input_host_t* host,
+ input_device_definition_t* d, input_report_definition_t* r) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputDeviceDefinitionAddReport(d, r);
+}
+
+void input_report_definition_add_collection(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputReportDefinitionAddCollection(report, id, arity);
+}
+
+void input_report_definition_declare_usage_int(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t usage, int32_t min, int32_t max, float resolution) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputReportDefinitionDeclareUsageInt(report, id, usage, min, max, resolution);
+}
+
+void input_report_definition_declare_usages_bool(input_host_t* host,
+ input_report_definition_t* report, input_collection_id_t id,
+ input_usage_t* usage, size_t usage_count) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputReportDefinitionDeclareUsagesBool(report, id, usage, usage_count);
+}
+
+input_device_handle_t* register_device(input_host_t* host,
+ input_device_identifier_t* id, input_device_definition_t* d) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->registerDevice(id, d);
+}
+
+void unregister_device(input_host_t* host, input_device_handle_t* handle) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->unregisterDevice(handle);
+}
+
+input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->inputAllocateReport(r);
+}
+
+void input_report_set_usage_int(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputReportSetUsageInt(r, id, usage, value, arity_index);
+}
+
+void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
+ input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputReportSetUsageBool(r, id, usage, value, arity_index);
+}
+
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->reportEvent(d, report);
+}
+
+input_property_map_t* input_get_device_property_map(input_host_t* host,
+ input_device_identifier_t* id) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->inputGetDevicePropertyMap(id);
+}
+
+input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
+ const char* key) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->inputGetDeviceProperty(map, key);
+}
+
+const char* input_get_property_key(input_host_t* host, input_property_t* property) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->inputGetPropertyKey(property);
+}
+
+const char* input_get_property_value(input_host_t* host, input_property_t* property) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ return driver->inputGetPropertyValue(property);
+}
+
+void input_free_device_property(input_host_t* host, input_property_t* property) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputFreeDeviceProperty(property);
+}
+
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+ auto driver = static_cast<InputDriverInterface*>(host);
+ driver->inputFreeDevicePropertyMap(map);
+}
+
} // namespace android
diff --git a/services/inputflinger/host/InputDriver.h b/services/inputflinger/host/InputDriver.h
index 9bc14a7..8d5a31e 100644
--- a/services/inputflinger/host/InputDriver.h
+++ b/services/inputflinger/host/InputDriver.h
@@ -26,17 +26,56 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
+// Declare a concrete type for the HAL
+struct input_host {
+};
+
namespace android {
-class InputHostInterface;
-
-class InputDriverInterface : public virtual RefBase {
+class InputDriverInterface : public input_host_t, public virtual RefBase {
protected:
InputDriverInterface() = default;
virtual ~InputDriverInterface() = default;
public:
- virtual void init(InputHostInterface* host) = 0;
+ virtual void init() = 0;
+
+ virtual input_device_identifier_t* createDeviceIdentifier(
+ const char* name, int32_t productId, int32_t vendorId,
+ input_bus_t bus, const char* uniqueId) = 0;
+ virtual input_device_definition_t* createDeviceDefinition() = 0;
+ virtual input_report_definition_t* createInputReportDefinition() = 0;
+ virtual input_report_definition_t* createOutputReportDefinition() = 0;
+ virtual void freeReportDefinition(input_report_definition_t* reportDef) = 0;
+
+ virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
+ input_report_definition_t* r) = 0;
+ virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
+ input_collection_id_t id, int32_t arity) = 0;
+ virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+ input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+ float resolution) = 0;
+ virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+ input_collection_id_t id, input_usage_t* usage, size_t usageCount) = 0;
+
+ virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
+ input_device_definition_t* d) = 0;
+ virtual void unregisterDevice(input_device_handle_t* handle) = 0;
+
+ virtual input_report_t* inputAllocateReport(input_report_definition_t* r) = 0;
+ virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+ input_usage_t usage, int32_t value, int32_t arity_index) = 0;
+ virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+ input_usage_t usage, bool value, int32_t arity_index) = 0;
+ virtual void reportEvent(input_device_handle_t* d, input_report_t* report) = 0;
+
+ virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) = 0;
+ virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
+ const char* key) = 0;
+ virtual const char* inputGetPropertyKey(input_property_t* property) = 0;
+ virtual const char* inputGetPropertyValue(input_property_t* property) = 0;
+ virtual void inputFreeDeviceProperty(input_property_t* property) = 0;
+ virtual void inputFreeDevicePropertyMap(input_property_map_t* map) = 0;
virtual void dump(String8& result) = 0;
};
@@ -46,7 +85,44 @@
InputDriver(const char* name);
virtual ~InputDriver() = default;
- virtual void init(InputHostInterface* host) override;
+ virtual void init() override;
+
+ virtual input_device_identifier_t* createDeviceIdentifier(
+ const char* name, int32_t productId, int32_t vendorId,
+ input_bus_t bus, const char* uniqueId) override;
+ virtual input_device_definition_t* createDeviceDefinition() override;
+ virtual input_report_definition_t* createInputReportDefinition() override;
+ virtual input_report_definition_t* createOutputReportDefinition() override;
+ virtual void freeReportDefinition(input_report_definition_t* reportDef) override;
+
+ virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
+ input_report_definition_t* r) override;
+ virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
+ input_collection_id_t id, int32_t arity) override;
+ virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+ input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+ float resolution) override;
+ virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+ input_collection_id_t id, input_usage_t* usage, size_t usageCount) override;
+
+ virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
+ input_device_definition_t* d) override;
+ virtual void unregisterDevice(input_device_handle_t* handle) override;
+
+ virtual input_report_t* inputAllocateReport(input_report_definition_t* r) override;
+ virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+ input_usage_t usage, int32_t value, int32_t arity_index) override;
+ virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+ input_usage_t usage, bool value, int32_t arity_index) override;
+ virtual void reportEvent(input_device_handle_t* d, input_report_t* report) override;
+
+ virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) override;
+ virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
+ const char* key) override;
+ virtual const char* inputGetPropertyKey(input_property_t* property) override;
+ virtual const char* inputGetPropertyValue(input_property_t* property) override;
+ virtual void inputFreeDeviceProperty(input_property_t* property) override;
+ virtual void inputFreeDevicePropertyMap(input_property_map_t* map) override;
virtual void dump(String8& result) override;
diff --git a/services/inputflinger/host/InputHost.cpp b/services/inputflinger/host/InputHost.cpp
index 51d3e6b..094200a 100644
--- a/services/inputflinger/host/InputHost.cpp
+++ b/services/inputflinger/host/InputHost.cpp
@@ -28,7 +28,7 @@
void InputHost::registerInputDriver(InputDriverInterface* driver) {
LOG_ALWAYS_FATAL_IF(driver == nullptr, "Cannot register a nullptr as an InputDriver!");
- driver->init(this);
+ driver->init();
mDrivers.push_back(driver);
}
diff --git a/services/inputflinger/host/InputHost.h b/services/inputflinger/host/InputHost.h
index 42a66e0..eda4a89 100644
--- a/services/inputflinger/host/InputHost.h
+++ b/services/inputflinger/host/InputHost.h
@@ -26,15 +26,11 @@
#include "InputDriver.h"
-// Declare a concrete type for the HAL
-struct input_host {
-};
-
namespace android {
class InputDriverInterface;
-class InputHostInterface : public input_host_t, public virtual RefBase {
+class InputHostInterface : public virtual RefBase {
protected:
InputHostInterface() = default;
virtual ~InputHostInterface() = default;
diff --git a/services/inputflinger/host/inputflinger.rc b/services/inputflinger/host/inputflinger.rc
new file mode 100644
index 0000000..ae71ee5
--- /dev/null
+++ b/services/inputflinger/host/inputflinger.rc
@@ -0,0 +1,5 @@
+service inputflinger /system/bin/inputflinger
+ class main
+ user system
+ group input
+# onrestart restart zygote
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index b07d544..7b1f346 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -58,12 +58,12 @@
status_t CorrectedGyroSensor::activate(void* ident, bool enabled) {
mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
- return mSensorFusion.activate(ident, enabled);
+ return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
}
status_t CorrectedGyroSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
mSensorDevice.setDelay(ident, mGyro.getHandle(), ns);
- return mSensorFusion.setDelay(ident, ns);
+ return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
Sensor CorrectedGyroSensor::getSensor() const {
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index 4f63c31..359d289 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -24,28 +24,44 @@
// -----------------------------------------------------------------------
+/*==================== BEGIN FUSION SENSOR PARAMETER =========================*/
+
+/* Note:
+ * If a platform uses software fusion, it is necessary to tune the following
+ * parameters to fit the hardware sensors prior to release.
+ *
+ * The DEFAULT_ parameters will be used in FUSION_9AXIS and FUSION_NOMAG mode.
+ * The GEOMAG_ parameters will be used in FUSION_NOGYRO mode.
+ */
+
/*
- * gyroVAR gives the measured variance of the gyro's output per
+ * GYRO_VAR gives the measured variance of the gyro's output per
* Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
* which is independent of the sampling frequency.
*
* The variance of gyro's output at a given sampling period can be
* calculated as:
- * variance(T) = gyroVAR / T
+ * variance(T) = GYRO_VAR / T
*
* The variance of the INTEGRATED OUTPUT at a given sampling period can be
* calculated as:
- * variance_integrate_output(T) = gyroVAR * T
- *
+ * variance_integrate_output(T) = GYRO_VAR * T
*/
-static const float gyroVAR = 1e-7; // (rad/s)^2 / Hz
-static const float biasVAR = 1e-8; // (rad/s)^2 / s (guessed)
+static const float DEFAULT_GYRO_VAR = 1e-7; // (rad/s)^2 / Hz
+static const float DEFAULT_GYRO_BIAS_VAR = 1e-12; // (rad/s)^2 / s (guessed)
+static const float GEOMAG_GYRO_VAR = 1e-4; // (rad/s)^2 / Hz
+static const float GEOMAG_GYRO_BIAS_VAR = 1e-8; // (rad/s)^2 / s (guessed)
/*
* Standard deviations of accelerometer and magnetometer
*/
-static const float accSTDEV = 0.05f; // m/s^2 (measured 0.08 / CDD 0.05)
-static const float magSTDEV = 0.5f; // uT (measured 0.7 / CDD 0.5)
+static const float DEFAULT_ACC_STDEV = 0.015f; // m/s^2 (measured 0.08 / CDD 0.05)
+static const float DEFAULT_MAG_STDEV = 0.1f; // uT (measured 0.7 / CDD 0.5)
+static const float GEOMAG_ACC_STDEV = 0.05f; // m/s^2 (measured 0.08 / CDD 0.05)
+static const float GEOMAG_MAG_STDEV = 0.1f; // uT (measured 0.7 / CDD 0.5)
+
+
+/* ====================== END FUSION SENSOR PARAMETER ========================*/
static const float SYMMETRY_TOLERANCE = 1e-10f;
@@ -54,7 +70,8 @@
* ill-conditioning and div by zeros.
* Threshhold: 10% of g, in m/s^2
*/
-static const float FREE_FALL_THRESHOLD = 0.981f;
+static const float NOMINAL_GRAVITY = 9.81f;
+static const float FREE_FALL_THRESHOLD = 0.1f * (NOMINAL_GRAVITY);
static const float FREE_FALL_THRESHOLD_SQ =
FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD;
@@ -87,6 +104,9 @@
static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ =
MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG;
+static const float W_EPS = 1e-4f;
+static const float SQRT_3 = 1.732f;
+static const float WVEC_EPS = 1e-4f/SQRT_3;
// -----------------------------------------------------------------------
template <typename TYPE, size_t C, size_t R>
@@ -173,7 +193,7 @@
init();
}
-void Fusion::init() {
+void Fusion::init(int mode) {
mInitState = 0;
mGyroRate = 0;
@@ -183,6 +203,19 @@
mCount[2] = 0;
mData = 0;
+ mMode = mode;
+
+ if (mMode != FUSION_NOGYRO) { //normal or game rotation
+ mParam.gyroVar = DEFAULT_GYRO_VAR;
+ mParam.gyroBiasVar = DEFAULT_GYRO_BIAS_VAR;
+ mParam.accStdev = DEFAULT_ACC_STDEV;
+ mParam.magStdev = DEFAULT_MAG_STDEV;
+ } else {
+ mParam.gyroVar = GEOMAG_GYRO_VAR;
+ mParam.gyroBiasVar = GEOMAG_GYRO_BIAS_VAR;
+ mParam.accStdev = GEOMAG_ACC_STDEV;
+ mParam.magStdev = GEOMAG_MAG_STDEV;
+ }
}
void Fusion::initFusion(const vec4_t& q, float dT)
@@ -205,11 +238,11 @@
const float dT3 = dT2*dT;
// variance of integrated output at 1/dT Hz (random drift)
- const float q00 = gyroVAR * dT + 0.33333f * biasVAR * dT3;
+ const float q00 = mParam.gyroVar * dT + 0.33333f * mParam.gyroBiasVar * dT3;
// variance of drift rate ramp
- const float q11 = biasVAR * dT;
- const float q10 = 0.5f * biasVAR * dT2;
+ const float q11 = mParam.gyroBiasVar * dT;
+ const float q10 = 0.5f * mParam.gyroBiasVar * dT2;
const float q01 = q10;
GQGt[0][0] = q00; // rad^2
@@ -223,7 +256,9 @@
}
bool Fusion::hasEstimate() const {
- return (mInitState == (MAG|ACC|GYRO));
+ return ((mInitState & MAG) || (mMode == FUSION_NOMAG)) &&
+ ((mInitState & GYRO) || (mMode == FUSION_NOGYRO)) &&
+ (mInitState & ACC);
}
bool Fusion::checkInitComplete(int what, const vec3_t& d, float dT) {
@@ -234,6 +269,9 @@
mData[0] += d * (1/length(d));
mCount[0]++;
mInitState |= ACC;
+ if (mMode == FUSION_NOGYRO ) {
+ mGyroRate = dT;
+ }
} else if (what == MAG) {
mData[1] += d * (1/length(d));
mCount[1]++;
@@ -242,25 +280,29 @@
mGyroRate = dT;
mData[2] += d*dT;
mCount[2]++;
- if (mCount[2] == 64) {
- // 64 samples is good enough to estimate the gyro drift and
- // doesn't take too much time.
- mInitState |= GYRO;
- }
+ mInitState |= GYRO;
}
- if (mInitState == (MAG|ACC|GYRO)) {
+ if (hasEstimate()) {
// Average all the values we collected so far
mData[0] *= 1.0f/mCount[0];
- mData[1] *= 1.0f/mCount[1];
+ if (mMode != FUSION_NOMAG) {
+ mData[1] *= 1.0f/mCount[1];
+ }
mData[2] *= 1.0f/mCount[2];
// calculate the MRPs from the data collection, this gives us
// a rough estimate of our initial state
mat33_t R;
- vec3_t up(mData[0]);
- vec3_t east(cross_product(mData[1], up));
- east *= 1/length(east);
+ vec3_t up(mData[0]);
+ vec3_t east;
+
+ if (mMode != FUSION_NOMAG) {
+ east = normalize(cross_product(mData[1], up));
+ } else {
+ east = getOrthogonal(up);
+ }
+
vec3_t north(cross_product(up, east));
R << east << north << up;
const vec4_t q = matrixToQuat(R);
@@ -278,21 +320,43 @@
predict(w, dT);
}
-status_t Fusion::handleAcc(const vec3_t& a) {
+status_t Fusion::handleAcc(const vec3_t& a, float dT) {
+ if (!checkInitComplete(ACC, a, dT))
+ return BAD_VALUE;
+
// ignore acceleration data if we're close to free-fall
- if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) {
+ const float l = length(a);
+ if (l < FREE_FALL_THRESHOLD) {
return BAD_VALUE;
}
- if (!checkInitComplete(ACC, a))
- return BAD_VALUE;
+ const float l_inv = 1.0f/l;
- const float l = 1/length(a);
- update(a*l, Ba, accSTDEV*l);
+ if ( mMode == FUSION_NOGYRO ) {
+ //geo mag
+ vec3_t w_dummy;
+ w_dummy = x1; //bias
+ predict(w_dummy, dT);
+ }
+
+ if ( mMode == FUSION_NOMAG) {
+ vec3_t m;
+ m = getRotationMatrix()*Bm;
+ update(m, Bm, mParam.magStdev);
+ }
+
+ vec3_t unityA = a * l_inv;
+ const float d = sqrtf(fabsf(l- NOMINAL_GRAVITY));
+ const float p = l_inv * mParam.accStdev*expf(d);
+
+ update(unityA, Ba, p);
return NO_ERROR;
}
status_t Fusion::handleMag(const vec3_t& m) {
+ if (!checkInitComplete(MAG, m))
+ return BAD_VALUE;
+
// the geomagnetic-field should be between 30uT and 60uT
// reject if too large to avoid spurious magnetic sources
const float magFieldSq = length_squared(m);
@@ -304,9 +368,6 @@
return BAD_VALUE;
}
- if (!checkInitComplete(MAG, m))
- return BAD_VALUE;
-
// Orthogonalize the magnetic field to the gravity field, mapping it into
// tangent to Earth.
const vec3_t up( getRotationMatrix() * Ba );
@@ -324,10 +385,10 @@
// then pass it in as the update.
vec3_t north( cross_product(up, east) );
- const float l = 1 / length(north);
- north *= l;
+ const float l_inv = 1 / length(north);
+ north *= l_inv;
- update(north, Bm, magSTDEV*l);
+ update(north, Bm, mParam.magStdev*l_inv);
return NO_ERROR;
}
@@ -372,8 +433,11 @@
void Fusion::predict(const vec3_t& w, float dT) {
const vec4_t q = x0;
const vec3_t b = x1;
- const vec3_t we = w - b;
+ vec3_t we = w - b;
+ if (length(we) < WVEC_EPS) {
+ we = (we[0]>0.f)?WVEC_EPS:-WVEC_EPS;
+ }
// q(k+1) = O(we)*q(k)
// --------------------
//
@@ -406,7 +470,7 @@
const mat33_t wx2(wx*wx);
const float lwedT = length(we)*dT;
const float hlwedT = 0.5f*lwedT;
- const float ilwe = 1/length(we);
+ const float ilwe = 1.f/length(we);
const float k0 = (1-cosf(lwedT))*(ilwe*ilwe);
const float k1 = sinf(lwedT);
const float k2 = cosf(hlwedT);
@@ -422,6 +486,7 @@
Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1);
x0 = O*q;
+
if (x0.w < 0)
x0 = -x0;
@@ -466,15 +531,37 @@
const vec3_t e(z - Bb);
const vec3_t dq(K[0]*e);
- const vec3_t db(K[1]*e);
q += getF(q)*(0.5f*dq);
x0 = normalize_quat(q);
- x1 += db;
+
+ if (mMode != FUSION_NOMAG) {
+ const vec3_t db(K[1]*e);
+ x1 += db;
+ }
checkState();
}
+vec3_t Fusion::getOrthogonal(const vec3_t &v) {
+ vec3_t w;
+ if (fabsf(v[0])<= fabsf(v[1]) && fabsf(v[0]) <= fabsf(v[2])) {
+ w[0]=0.f;
+ w[1] = v[2];
+ w[2] = -v[1];
+ } else if (fabsf(v[1]) <= fabsf(v[2])) {
+ w[0] = v[2];
+ w[1] = 0.f;
+ w[2] = -v[0];
+ }else {
+ w[0] = v[1];
+ w[1] = -v[0];
+ w[2] = 0.f;
+ }
+ return normalize(w);
+}
+
+
// -----------------------------------------------------------------------
}; // namespace android
diff --git a/services/sensorservice/Fusion.h b/services/sensorservice/Fusion.h
index 7062999..602779f 100644
--- a/services/sensorservice/Fusion.h
+++ b/services/sensorservice/Fusion.h
@@ -27,6 +27,13 @@
typedef mat<float, 3, 4> mat34_t;
+enum FUSION_MODE{
+ FUSION_9AXIS, // use accel gyro mag
+ FUSION_NOMAG, // use accel gyro (game rotation, gravity)
+ FUSION_NOGYRO, // use accel mag (geomag rotation)
+ NUM_FUSION_MODE
+};
+
class Fusion {
/*
* the state vector is made of two sub-vector containing respectively:
@@ -55,9 +62,9 @@
public:
Fusion();
- void init();
+ void init(int mode = FUSION_9AXIS);
void handleGyro(const vec3_t& w, float dT);
- status_t handleAcc(const vec3_t& a);
+ status_t handleAcc(const vec3_t& a, float dT);
status_t handleMag(const vec3_t& m);
vec4_t getAttitude() const;
vec3_t getBias() const;
@@ -65,12 +72,21 @@
bool hasEstimate() const;
private:
+ struct Parameter {
+ float gyroVar;
+ float gyroBiasVar;
+ float accStdev;
+ float magStdev;
+ } mParam;
+
mat<mat33_t, 2, 2> Phi;
vec3_t Ba, Bm;
uint32_t mInitState;
float mGyroRate;
vec<vec3_t, 3> mData;
size_t mCount[3];
+ int mMode;
+
enum { ACC=0x1, MAG=0x2, GYRO=0x4 };
bool checkInitComplete(int, const vec3_t& w, float d = 0);
void initFusion(const vec4_t& q0, float dT);
@@ -78,6 +94,7 @@
void predict(const vec3_t& w, float dT);
void update(const vec3_t& z, const vec3_t& Bi, float sigma);
static mat34_t getF(const vec4_t& p);
+ static vec3_t getOrthogonal(const vec3_t &v);
};
}; // namespace android
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index 61118bc..a165a5b 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -46,9 +46,9 @@
{
if (event.type == SENSOR_TYPE_ACCELEROMETER) {
vec3_t g;
- if (!mSensorFusion.hasEstimate())
+ if (!mSensorFusion.hasEstimate(FUSION_NOMAG))
return false;
- const mat33_t R(mSensorFusion.getRotationMatrix());
+ const mat33_t R(mSensorFusion.getRotationMatrix(FUSION_NOMAG));
// FIXME: we need to estimate the length of gravity because
// the accelerometer may have a small scaling error. This
// translates to an offset in the linear-acceleration sensor.
@@ -66,11 +66,11 @@
}
status_t GravitySensor::activate(void* ident, bool enabled) {
- return mSensorFusion.activate(ident, enabled);
+ return mSensorFusion.activate(FUSION_NOMAG, ident, enabled);
}
status_t GravitySensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
- return mSensorFusion.setDelay(ident, ns);
+ return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
}
Sensor GravitySensor::getSensor() const {
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index 6d85cca..d55f336 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -66,11 +66,11 @@
}
status_t OrientationSensor::activate(void* ident, bool enabled) {
- return mSensorFusion.activate(ident, enabled);
+ return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
}
status_t OrientationSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
- return mSensorFusion.setDelay(ident, ns);
+ return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
Sensor OrientationSensor::getSensor() const {
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index cb305eb..238845b 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -27,9 +27,10 @@
namespace android {
// ---------------------------------------------------------------------------
-RotationVectorSensor::RotationVectorSensor()
+RotationVectorSensor::RotationVectorSensor(int mode)
: mSensorDevice(SensorDevice::getInstance()),
- mSensorFusion(SensorFusion::getInstance())
+ mSensorFusion(SensorFusion::getInstance()),
+ mMode(mode)
{
}
@@ -37,15 +38,15 @@
const sensors_event_t& event)
{
if (event.type == SENSOR_TYPE_ACCELEROMETER) {
- if (mSensorFusion.hasEstimate()) {
- const vec4_t q(mSensorFusion.getAttitude());
+ if (mSensorFusion.hasEstimate(mMode)) {
+ const vec4_t q(mSensorFusion.getAttitude(mMode));
*outEvent = event;
outEvent->data[0] = q.x;
outEvent->data[1] = q.y;
outEvent->data[2] = q.z;
outEvent->data[3] = q.w;
- outEvent->sensor = '_rov';
- outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
+ outEvent->sensor = getSensorToken();
+ outEvent->type = getSensorType();
return true;
}
}
@@ -53,20 +54,20 @@
}
status_t RotationVectorSensor::activate(void* ident, bool enabled) {
- return mSensorFusion.activate(ident, enabled);
+ return mSensorFusion.activate(mMode, ident, enabled);
}
status_t RotationVectorSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
- return mSensorFusion.setDelay(ident, ns);
+ return mSensorFusion.setDelay(mMode, ident, ns);
}
Sensor RotationVectorSensor::getSensor() const {
sensor_t hwSensor;
- hwSensor.name = "Rotation Vector Sensor";
+ hwSensor.name = getSensorName();
hwSensor.vendor = "AOSP";
hwSensor.version = 3;
- hwSensor.handle = '_rov';
- hwSensor.type = SENSOR_TYPE_ROTATION_VECTOR;
+ hwSensor.handle = getSensorToken();
+ hwSensor.type = getSensorType();
hwSensor.maxRange = 1;
hwSensor.resolution = 1.0f / (1<<24);
hwSensor.power = mSensorFusion.getPowerUsage();
@@ -75,6 +76,48 @@
return sensor;
}
+int RotationVectorSensor::getSensorType() const {
+ switch(mMode) {
+ case FUSION_9AXIS:
+ return SENSOR_TYPE_ROTATION_VECTOR;
+ case FUSION_NOMAG:
+ return SENSOR_TYPE_GAME_ROTATION_VECTOR;
+ case FUSION_NOGYRO:
+ return SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+const char* RotationVectorSensor::getSensorName() const {
+ switch(mMode) {
+ case FUSION_9AXIS:
+ return "Rotation Vector Sensor";
+ case FUSION_NOMAG:
+ return "Game Rotation Vector Sensor";
+ case FUSION_NOGYRO:
+ return "GeoMag Rotation Vector Sensor";
+ default:
+ assert(0);
+ return NULL;
+ }
+}
+
+int RotationVectorSensor::getSensorToken() const {
+ switch(mMode) {
+ case FUSION_9AXIS:
+ return '_rov';
+ case FUSION_NOMAG:
+ return '_gar';
+ case FUSION_NOGYRO:
+ return '_geo';
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
// ---------------------------------------------------------------------------
GyroDriftSensor::GyroDriftSensor()
@@ -102,11 +145,11 @@
}
status_t GyroDriftSensor::activate(void* ident, bool enabled) {
- return mSensorFusion.activate(ident, enabled);
+ return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
}
status_t GyroDriftSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
- return mSensorFusion.setDelay(ident, ns);
+ return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
}
Sensor GyroDriftSensor::getSensor() const {
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index bb97fe1..1fc316b 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -35,9 +35,14 @@
class RotationVectorSensor : public SensorInterface {
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
+ int mMode;
+
+ int getSensorType() const;
+ const char* getSensorName() const ;
+ int getSensorToken() const ;
public:
- RotationVectorSensor();
+ RotationVectorSensor(int mode = FUSION_9AXIS);
virtual bool process(sensors_event_t* outEvent,
const sensors_event_t& event);
virtual status_t activate(void* ident, bool enabled);
@@ -46,6 +51,16 @@
virtual bool isVirtual() const { return true; }
};
+class GameRotationVectorSensor : public RotationVectorSensor {
+public:
+ GameRotationVectorSensor() : RotationVectorSensor(FUSION_NOMAG) {}
+};
+
+class GeoMagRotationVectorSensor : public RotationVectorSensor {
+public:
+ GeoMagRotationVectorSensor() : RotationVectorSensor(FUSION_NOGYRO) {}
+};
+
class GyroDriftSensor : public SensorInterface {
SensorDevice& mSensorDevice;
SensorFusion& mSensorFusion;
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 6d93009..9863f62 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -25,11 +25,17 @@
SensorFusion::SensorFusion()
: mSensorDevice(SensorDevice::getInstance()),
- mEnabled(false), mGyroTime(0)
+ mAttitude(mAttitudes[FUSION_9AXIS]),
+ mGyroTime(0), mAccTime(0)
{
sensor_t const* list;
Sensor uncalibratedGyro;
ssize_t count = mSensorDevice.getSensorList(&list);
+
+ mEnabled[FUSION_9AXIS] = false;
+ mEnabled[FUSION_NOMAG] = false;
+ mEnabled[FUSION_NOGYRO] = false;
+
if (count > 0) {
for (size_t i=0 ; i<size_t(count) ; i++) {
if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
@@ -55,81 +61,121 @@
// and power/cpu usage.
mEstimatedGyroRate = 200;
mTargetDelayNs = 1000000000LL/mEstimatedGyroRate;
- mFusion.init();
+
+ for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+ mFusions[i].init(i);
+ }
}
}
void SensorFusion::process(const sensors_event_t& event) {
+
if (event.type == mGyro.getType()) {
- if (mGyroTime != 0) {
- const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
- mFusion.handleGyro(vec3_t(event.data), dT);
+ float dT;
+ if ( event.timestamp - mGyroTime> 0 &&
+ event.timestamp - mGyroTime< (int64_t)(5e7) ) { //0.05sec
+
+ dT = (event.timestamp - mGyroTime) / 1000000000.0f;
// here we estimate the gyro rate (useful for debugging)
const float freq = 1 / dT;
if (freq >= 100 && freq<1000) { // filter values obviously wrong
const float alpha = 1 / (1 + dT); // 1s time-constant
mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha;
}
+
+ const vec3_t gyro(event.data);
+ for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+ if (mEnabled[i]) {
+ // fusion in no gyro mode will ignore
+ mFusions[i].handleGyro(gyro, dT);
+ }
+ }
}
mGyroTime = event.timestamp;
} else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
const vec3_t mag(event.data);
- mFusion.handleMag(mag);
+ for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+ if (mEnabled[i]) {
+ mFusions[i].handleMag(mag);// fusion in no mag mode will ignore
+ }
+ }
} else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
- const vec3_t acc(event.data);
- mFusion.handleAcc(acc);
- mAttitude = mFusion.getAttitude();
+ float dT;
+ if ( event.timestamp - mAccTime> 0 &&
+ event.timestamp - mAccTime< (int64_t)(1e8) ) { //0.1sec
+ dT = (event.timestamp - mAccTime) / 1000000000.0f;
+
+ const vec3_t acc(event.data);
+ for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+ if (mEnabled[i]) {
+ mFusions[i].handleAcc(acc, dT);
+ mAttitudes[i] = mFusions[i].getAttitude();
+ }
+ }
+ }
+ mAccTime = event.timestamp;
}
}
template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
-status_t SensorFusion::activate(void* ident, bool enabled) {
+status_t SensorFusion::activate(int mode, void* ident, bool enabled) {
ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorFusion::activate(ident=%p, enabled=%d)",
- ident, enabled);
+ "SensorFusion::activate(mode=%d, ident=%p, enabled=%d)",
+ mode, ident, enabled);
- const ssize_t idx = mClients.indexOf(ident);
+ const ssize_t idx = mClients[mode].indexOf(ident);
if (enabled) {
if (idx < 0) {
- mClients.add(ident);
+ mClients[mode].add(ident);
}
} else {
if (idx >= 0) {
- mClients.removeItemsAt(idx);
+ mClients[mode].removeItemsAt(idx);
+ }
+ }
+
+ const bool newState = mClients[mode].size() != 0;
+ if (newState != mEnabled[mode]) {
+ mEnabled[mode] = newState;
+ if (newState) {
+ mFusions[mode].init(mode);
}
}
mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
- mSensorDevice.activate(ident, mMag.getHandle(), enabled);
- mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
+ if (mode != FUSION_NOMAG) {
+ mSensorDevice.activate(ident, mMag.getHandle(), enabled);
+ }
+ if (mode != FUSION_NOGYRO) {
+ mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
+ }
- const bool newState = mClients.size() != 0;
- if (newState != mEnabled) {
- mEnabled = newState;
- if (newState) {
- mFusion.init();
- mGyroTime = 0;
- }
+ return NO_ERROR;
+}
+
+status_t SensorFusion::setDelay(int mode, void* ident, int64_t ns) {
+ // Call batch with timeout zero instead of setDelay().
+ if (ns > (int64_t)5e7) {
+ ns = (int64_t)(5e7);
+ }
+ mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
+ if (mode != FUSION_NOMAG) {
+ mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
+ }
+ if (mode != FUSION_NOGYRO) {
+ mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
}
return NO_ERROR;
}
-status_t SensorFusion::setDelay(void* ident, int64_t ns) {
- // Call batch with timeout zero instead of setDelay().
- mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
- mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
- mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
- return NO_ERROR;
-}
-
-float SensorFusion::getPowerUsage() const {
+float SensorFusion::getPowerUsage(int mode) const {
float power = mAcc.getPowerUsage() +
- mMag.getPowerUsage() +
- mGyro.getPowerUsage();
+ ((mode != FUSION_NOMAG) ? mMag.getPowerUsage() : 0) +
+ ((mode != FUSION_NOGYRO) ? mGyro.getPowerUsage() : 0);
return power;
}
@@ -138,21 +184,55 @@
}
void SensorFusion::dump(String8& result) {
- const Fusion& fusion(mFusion);
+ const Fusion& fusion_9axis(mFusions[FUSION_9AXIS]);
result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "
"q=< %g, %g, %g, %g > (%g), "
"b=< %g, %g, %g >\n",
- mEnabled ? "enabled" : "disabled",
- mClients.size(),
+ mEnabled[FUSION_9AXIS] ? "enabled" : "disabled",
+ mClients[FUSION_9AXIS].size(),
mEstimatedGyroRate,
- fusion.getAttitude().x,
- fusion.getAttitude().y,
- fusion.getAttitude().z,
- fusion.getAttitude().w,
- length(fusion.getAttitude()),
- fusion.getBias().x,
- fusion.getBias().y,
- fusion.getBias().z);
+ fusion_9axis.getAttitude().x,
+ fusion_9axis.getAttitude().y,
+ fusion_9axis.getAttitude().z,
+ fusion_9axis.getAttitude().w,
+ length(fusion_9axis.getAttitude()),
+ fusion_9axis.getBias().x,
+ fusion_9axis.getBias().y,
+ fusion_9axis.getBias().z);
+
+ const Fusion& fusion_nomag(mFusions[FUSION_NOMAG]);
+ result.appendFormat("game fusion(no mag) %s (%zd clients), "
+ "gyro-rate=%7.2fHz, "
+ "q=< %g, %g, %g, %g > (%g), "
+ "b=< %g, %g, %g >\n",
+ mEnabled[FUSION_NOMAG] ? "enabled" : "disabled",
+ mClients[FUSION_NOMAG].size(),
+ mEstimatedGyroRate,
+ fusion_nomag.getAttitude().x,
+ fusion_nomag.getAttitude().y,
+ fusion_nomag.getAttitude().z,
+ fusion_nomag.getAttitude().w,
+ length(fusion_nomag.getAttitude()),
+ fusion_nomag.getBias().x,
+ fusion_nomag.getBias().y,
+ fusion_nomag.getBias().z);
+
+ const Fusion& fusion_nogyro(mFusions[FUSION_NOGYRO]);
+ result.appendFormat("geomag fusion (no gyro) %s (%zd clients), "
+ "gyro-rate=%7.2fHz, "
+ "q=< %g, %g, %g, %g > (%g), "
+ "b=< %g, %g, %g >\n",
+ mEnabled[FUSION_NOGYRO] ? "enabled" : "disabled",
+ mClients[FUSION_NOGYRO].size(),
+ mEstimatedGyroRate,
+ fusion_nogyro.getAttitude().x,
+ fusion_nogyro.getAttitude().y,
+ fusion_nogyro.getAttitude().z,
+ fusion_nogyro.getAttitude().w,
+ length(fusion_nogyro.getAttitude()),
+ fusion_nogyro.getBias().x,
+ fusion_nogyro.getBias().y,
+ fusion_nogyro.getBias().z);
}
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
index 432adbc..ad636d5 100644
--- a/services/sensorservice/SensorFusion.h
+++ b/services/sensorservice/SensorFusion.h
@@ -42,30 +42,52 @@
Sensor mAcc;
Sensor mMag;
Sensor mGyro;
- Fusion mFusion;
- bool mEnabled;
+
+ Fusion mFusions[NUM_FUSION_MODE]; // normal, no_mag, no_gyro
+
+ bool mEnabled[NUM_FUSION_MODE];
+
+ vec4_t &mAttitude;
+ vec4_t mAttitudes[NUM_FUSION_MODE];
+
+ SortedVector<void*> mClients[3];
+
float mEstimatedGyroRate;
nsecs_t mTargetDelayNs;
+
nsecs_t mGyroTime;
- vec4_t mAttitude;
- SortedVector<void*> mClients;
+ nsecs_t mAccTime;
SensorFusion();
public:
void process(const sensors_event_t& event);
- bool isEnabled() const { return mEnabled; }
- bool hasEstimate() const { return mFusion.hasEstimate(); }
- mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
- vec4_t getAttitude() const { return mAttitude; }
- vec3_t getGyroBias() const { return mFusion.getBias(); }
+ bool isEnabled() const {
+ return mEnabled[FUSION_9AXIS] ||
+ mEnabled[FUSION_NOMAG] ||
+ mEnabled[FUSION_NOGYRO];
+ }
+
+ bool hasEstimate(int mode = FUSION_9AXIS) const {
+ return mFusions[mode].hasEstimate();
+ }
+
+ mat33_t getRotationMatrix(int mode = FUSION_9AXIS) const {
+ return mFusions[mode].getRotationMatrix();
+ }
+
+ vec4_t getAttitude(int mode = FUSION_9AXIS) const {
+ return mAttitudes[mode];
+ }
+
+ vec3_t getGyroBias() const { return mFusions[FUSION_9AXIS].getBias(); }
float getEstimatedRate() const { return mEstimatedGyroRate; }
- status_t activate(void* ident, bool enabled);
- status_t setDelay(void* ident, int64_t ns);
+ status_t activate(int mode, void* ident, bool enabled);
+ status_t setDelay(int mode, void* ident, int64_t ns);
- float getPowerUsage() const;
+ float getPowerUsage(int mode=FUSION_9AXIS) const;
int32_t getMinDelay() const;
void dump(String8& result);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 1a486a3..8e2109b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -88,11 +88,14 @@
uint32_t virtualSensorsNeeds =
(1<<SENSOR_TYPE_GRAVITY) |
(1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
- (1<<SENSOR_TYPE_ROTATION_VECTOR);
+ (1<<SENSOR_TYPE_ROTATION_VECTOR) |
+ (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) |
+ (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);
mLastEventSeen.setCapacity(count);
for (ssize_t i=0 ; i<count ; i++) {
- registerSensor( new HardwareSensor(list[i]) );
+ bool useThisSensor=true;
+
switch (list[i].type) {
case SENSOR_TYPE_ACCELEROMETER:
hasAccel = true;
@@ -110,9 +113,18 @@
case SENSOR_TYPE_GRAVITY:
case SENSOR_TYPE_LINEAR_ACCELERATION:
case SENSOR_TYPE_ROTATION_VECTOR:
- virtualSensorsNeeds &= ~(1<<list[i].type);
+ case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+ if (IGNORE_HARDWARE_FUSION) {
+ useThisSensor = false;
+ } else {
+ virtualSensorsNeeds &= ~(1<<list[i].type);
+ }
break;
}
+ if (useThisSensor) {
+ registerSensor( new HardwareSensor(list[i]) );
+ }
}
// it's safe to instantiate the SensorFusion object here
@@ -124,26 +136,15 @@
mUserSensorList = mSensorList;
if (hasGyro && hasAccel && hasMag) {
- Sensor aSensor;
-
// Add Android virtual sensors if they're not already
// available in the HAL
+ Sensor aSensor;
aSensor = registerVirtualSensor( new RotationVectorSensor() );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
mUserSensorList.add(aSensor);
}
- aSensor = registerVirtualSensor( new GravitySensor(list, count) );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
- mUserSensorList.add(aSensor);
- }
-
- aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
- if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
- mUserSensorList.add(aSensor);
- }
-
aSensor = registerVirtualSensor( new OrientationSensor() );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
// if we are doing our own rotation-vector, also add
@@ -151,11 +152,46 @@
mUserSensorList.replaceAt(aSensor, orientationIndex);
}
+ aSensor = registerVirtualSensor(
+ new LinearAccelerationSensor(list, count) );
+ if (virtualSensorsNeeds &
+ (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
+ mUserSensorList.add(aSensor);
+ }
+
// virtual debugging sensors are not added to mUserSensorList
registerVirtualSensor( new CorrectedGyroSensor(list, count) );
registerVirtualSensor( new GyroDriftSensor() );
}
+ if (hasAccel && hasGyro) {
+ Sensor aSensor;
+
+ aSensor = registerVirtualSensor(
+ new GravitySensor(list, count) );
+ if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
+ mUserSensorList.add(aSensor);
+ }
+
+ aSensor = registerVirtualSensor(
+ new GameRotationVectorSensor() );
+ if (virtualSensorsNeeds &
+ (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) {
+ mUserSensorList.add(aSensor);
+ }
+ }
+
+ if (hasAccel && hasMag) {
+ Sensor aSensor;
+
+ aSensor = registerVirtualSensor(
+ new GeoMagRotationVectorSensor() );
+ if (virtualSensorsNeeds &
+ (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) {
+ mUserSensorList.add(aSensor);
+ }
+ }
+
// debugging sensor list
mUserSensorListDebug = mSensorList;
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 9a573ae..7d81d6e 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -46,7 +46,7 @@
#endif
// ---------------------------------------------------------------------------
-
+#define IGNORE_HARDWARE_FUSION false
#define DEBUG_CONNECTIONS false
// Max size is 100 KB which is enough to accept a batch of about 1000 events.
#define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 49389e0..2a025b8 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -134,7 +134,7 @@
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
: flinger(flinger), client(client),
- handle(handle), gbp(gbp),
+ handle(handle), gbp(gbp), result(NO_ERROR),
name(name), w(w), h(h), format(format), flags(flags) {
}
status_t getResult() const { return result; }
diff --git a/services/surfaceflinger/DisplayHardware/FloatRect.h b/services/surfaceflinger/DisplayHardware/FloatRect.h
index b08a951..3b75cc0 100644
--- a/services/surfaceflinger/DisplayHardware/FloatRect.h
+++ b/services/surfaceflinger/DisplayHardware/FloatRect.h
@@ -29,7 +29,8 @@
float right;
float bottom;
- inline FloatRect() { }
+ inline FloatRect()
+ : left(0), top(0), right(0), bottom(0) { }
inline FloatRect(const Rect& other)
: left(other.left), top(other.top), right(other.right), bottom(other.bottom) { }
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6ef3295..a6bc158 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -66,7 +66,7 @@
GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
- mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
+ mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
}
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
@@ -106,7 +106,7 @@
// releaseBuffer call and we should be in the same state we'd be in if we
// had released the old buffer first.
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
- item.mBuf != mCurrentBufferSlot) {
+ item.mSlot != mCurrentBufferSlot) {
// Release the previous buffer.
err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
@@ -115,7 +115,7 @@
return err;
}
}
- mCurrentBufferSlot = item.mBuf;
+ mCurrentBufferSlot = item.mSlot;
mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
outFence = item.mFence;
outBuffer = mCurrentBuffer;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0859149..d37fcb2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -1036,12 +1036,10 @@
}
}
virtual void setVisibleRegionScreen(const Region& reg) {
- // Region::getSharedBuffer creates a reference to the underlying
- // SharedBuffer of this Region, this reference is freed
- // in onDisplayed()
hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
- SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
- visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
+ mVisibleRegion = reg;
+ visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
+ mVisibleRegion.getArray(&visibleRegion.numRects));
}
virtual void setSurfaceDamage(const Region& reg) {
if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
@@ -1055,8 +1053,9 @@
surfaceDamage.rects = NULL;
return;
}
- SharedBuffer const* sb = reg.getSharedBuffer(&surfaceDamage.numRects);
- surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
+ mSurfaceDamage = reg;
+ surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
+ mSurfaceDamage.getArray(&surfaceDamage.numRects));
}
virtual void setSidebandStream(const sp<NativeHandle>& stream) {
ALOG_ASSERT(stream->handle() != NULL);
@@ -1078,29 +1077,15 @@
}
}
virtual void onDisplayed() {
- hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
- SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
- if (sb) {
- sb->release();
- // not technically needed but safer
- visibleRegion.numRects = 0;
- visibleRegion.rects = NULL;
- }
-
getLayer()->acquireFenceFd = -1;
-
- if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
- return;
- }
-
- hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
- sb = SharedBuffer::bufferFromData(surfaceDamage.rects);
- if (sb) {
- sb->release();
- surfaceDamage.numRects = 0;
- surfaceDamage.rects = NULL;
- }
}
+
+protected:
+ // We need to hold "copies" of these for memory management purposes. The
+ // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
+ // internally doesn't copy the memory unless one of the copies is modified.
+ Region mVisibleRegion;
+ Region mSurfaceDamage;
};
/*
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index ba4c198..0880a44 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -92,7 +92,6 @@
mConsumer->setConsumerName(ConsumerBase::mName);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
- mConsumer->setDefaultMaxBufferCount(2);
}
VirtualDisplaySurface::~VirtualDisplaySurface() {
@@ -282,8 +281,13 @@
return NO_ERROR;
}
-status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
- return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
+status_t VirtualDisplaySurface::setMaxDequeuedBufferCount(
+ int maxDequeuedBuffers) {
+ return mSource[SOURCE_SINK]->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+}
+
+status_t VirtualDisplaySurface::setAsyncMode(bool async) {
+ return mSource[SOURCE_SINK]->setAsyncMode(async);
}
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
@@ -442,11 +446,11 @@
result = acquireBufferLocked(&item, 0);
if (result != NO_ERROR)
return result;
- VDS_LOGW_IF(item.mBuf != sslot,
+ VDS_LOGW_IF(item.mSlot != sslot,
"queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
- item.mBuf, sslot);
- mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
- mFbFence = mSlots[item.mBuf].mFence;
+ item.mSlot, sslot);
+ mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mSlot);
+ mFbFence = mSlots[item.mSlot].mFence;
} else {
LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
@@ -472,7 +476,8 @@
return NO_ERROR;
}
-void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
+status_t VirtualDisplaySurface::cancelBuffer(int pslot,
+ const sp<Fence>& fence) {
if (mDisplayId < 0)
return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 6298751..91e94f1 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -98,7 +98,8 @@
// IGraphicBufferProducer interface, used by the GLES driver.
//
virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
- virtual status_t setBufferCount(int bufferCount);
+ virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+ virtual status_t setAsyncMode(bool async);
virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
virtual status_t detachBuffer(int slot);
@@ -107,7 +108,7 @@
virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);
virtual status_t queueBuffer(int pslot,
const QueueBufferInput& input, QueueBufferOutput* output);
- virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
+ virtual status_t cancelBuffer(int pslot, const sp<Fence>& fence);
virtual int query(int what, int* value);
virtual status_t connect(const sp<IProducerListener>& listener,
int api, bool producerControlledByApp, QueueBufferOutput* output);
diff --git a/services/surfaceflinger/EventLog/EventLogTags.logtags b/services/surfaceflinger/EventLog/EventLogTags.logtags
index 791e0e4..6c851dd 100644
--- a/services/surfaceflinger/EventLog/EventLogTags.logtags
+++ b/services/surfaceflinger/EventLog/EventLogTags.logtags
@@ -36,6 +36,7 @@
# 60100 - 60199 reserved for surfaceflinger
60100 sf_frame_dur (window|3),(dur0|1),(dur1|1),(dur2|1),(dur3|1),(dur4|1),(dur5|1),(dur6|1)
+60110 sf_stop_bootanim (time|2|3)
# NOTE - the range 1000000-2000000 is reserved for partners and others who
# want to define their own log tags without conflicting with the core platform.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5ff79a9..33af4a5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -135,9 +135,8 @@
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
- mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
- mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
+ mProducer->setMaxDequeuedBufferCount(2);
#endif
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 1ad86a6..99efd39 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -119,6 +119,7 @@
continue;
case Looper::POLL_ERROR:
ALOGE("Looper::POLL_ERROR");
+ continue;
case Looper::POLL_TIMEOUT:
// timeout (should not happen)
continue;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index fb7af97..f16ad59 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -56,8 +56,13 @@
return mProducer->requestBuffer(slot, buf);
}
-status_t MonitoredProducer::setBufferCount(int bufferCount) {
- return mProducer->setBufferCount(bufferCount);
+status_t MonitoredProducer::setMaxDequeuedBufferCount(
+ int maxDequeuedBuffers) {
+ return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+}
+
+status_t MonitoredProducer::setAsyncMode(bool async) {
+ return mProducer->setAsyncMode(async);
}
status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
@@ -84,8 +89,8 @@
return mProducer->queueBuffer(slot, input, output);
}
-void MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
- mProducer->cancelBuffer(slot, fence);
+status_t MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+ return mProducer->cancelBuffer(slot, fence);
}
int MonitoredProducer::query(int what, int* value) {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index da95766..0bdc050 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -35,7 +35,8 @@
// From IGraphicBufferProducer
virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
- virtual status_t setBufferCount(int bufferCount);
+ virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+ virtual status_t setAsyncMode(bool async);
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
virtual status_t detachBuffer(int slot);
@@ -45,7 +46,7 @@
const sp<GraphicBuffer>& buffer);
virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
QueueBufferOutput* output);
- virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+ virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
virtual int query(int what, int* value);
virtual status_t connect(const sp<IProducerListener>& token, int api,
bool producerControlledByApp, QueueBufferOutput* output);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 7cd42e4..27357b9 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -148,7 +148,7 @@
return engine;
}
-RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) {
+RenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {
}
RenderEngine::~RenderEngine() {
@@ -316,7 +316,7 @@
friend class Adder;
KeyedVector<Attribute, EGLint> mList;
struct Attribute {
- Attribute() {};
+ Attribute() : v(0) {};
Attribute(EGLint v) : v(v) { }
EGLint v;
bool operator < (const Attribute& other) const {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fdc3650..285b829 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -52,6 +52,7 @@
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StopWatch.h>
+#include <utils/Timers.h>
#include <utils/Trace.h>
#include <private/android_filesystem_config.h>
@@ -235,9 +236,8 @@
sp<BBinder> token = new DisplayToken(this);
Mutex::Autolock _l(mStateLock);
- DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL);
+ DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
info.displayName = displayName;
- info.isSecure = secure;
mCurrentState.displays.add(token, info);
return token;
@@ -266,9 +266,8 @@
ALOGW_IF(mBuiltinDisplays[type],
"Overwriting display token for display type %d", type);
mBuiltinDisplays[type] = new BBinder();
- DisplayDeviceState info(type);
// All non-virtual displays are currently considered secure.
- info.isSecure = true;
+ DisplayDeviceState info(type, true);
mCurrentState.displays.add(mBuiltinDisplays[type], info);
}
@@ -304,6 +303,10 @@
// formerly we would just kill the process, but we now ask it to exit so it
// can choose where to stop the animation.
property_set("service.bootanim.exit", "1");
+
+ const int LOGTAG_SF_STOP_BOOTANIM = 60110;
+ LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
+ ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -3127,8 +3130,12 @@
GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl)
: impl(impl),
looper(new Looper(true)),
+ result(NO_ERROR),
exitPending(false),
- exitRequested(false)
+ exitRequested(false),
+ code(0),
+ data(NULL),
+ reply(NULL)
{}
// Binder thread
@@ -3524,11 +3531,22 @@
// ---------------------------------------------------------------------------
SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
- : type(DisplayDevice::DISPLAY_ID_INVALID), width(0), height(0) {
+ : type(DisplayDevice::DISPLAY_ID_INVALID),
+ layerStack(DisplayDevice::NO_LAYER_STACK),
+ orientation(0),
+ width(0),
+ height(0),
+ isSecure(false) {
}
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
- : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0), width(0), height(0) {
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
+ DisplayDevice::DisplayType type, bool isSecure)
+ : type(type),
+ layerStack(DisplayDevice::NO_LAYER_STACK),
+ orientation(0),
+ width(0),
+ height(0),
+ isSecure(isSecure) {
viewport.makeInvalid();
frame.makeInvalid();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b3baadd..4e0160a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -162,7 +162,7 @@
struct DisplayDeviceState {
DisplayDeviceState();
- DisplayDeviceState(DisplayDevice::DisplayType type);
+ DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
bool isValid() const { return type >= 0; }
bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index ed1f31b..930e7c7 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -72,9 +72,9 @@
// We call the rejecter here, in case the caller has a reason to
// not accept this buffer. This is used by SurfaceFlinger to
// reject buffers which have the wrong size
- int buf = item.mBuf;
- if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
+ int slot = item.mSlot;
+ if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
+ releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, EGL_NO_SYNC_KHR);
return BUFFER_REJECTED;
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index dcde512..ee4ad4e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -24,10 +24,13 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/LayerState.h>
#include <utils/String8.h>
#include <ui/DisplayInfo.h>
+#include <math.h>
+
namespace android {
// Fill an RGBA_8888 formatted surface with a single color.
@@ -38,8 +41,8 @@
ASSERT_TRUE(s != NULL);
ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL));
uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
- for (uint32_t y = 0; y < outBuffer.height; y++) {
- for (uint32_t x = 0; x < outBuffer.width; x++) {
+ for (int y = 0; y < outBuffer.height; y++) {
+ for (int x = 0; x < outBuffer.width; x++) {
uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
pixel[0] = r;
pixel[1] = g;
@@ -76,7 +79,7 @@
String8 err(String8::format("pixel @ (%3d, %3d): "
"expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
- EXPECT_EQ(String8(), err);
+ EXPECT_EQ(String8(), err) << err.string();
}
}
@@ -134,6 +137,8 @@
SurfaceComposerClient::openGlobalTransaction();
+ mComposerClient->setDisplayLayerStack(display, 0);
+
ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-2));
ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
@@ -249,4 +254,184 @@
}
}
+TEST_F(LayerUpdateTest, LayerCropWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before crop");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ Rect cropRect(16, 16, 32, 32);
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should crop the foreground surface.
+ SCOPED_TRACE("after crop");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 63, 63, 195);
+ sc->checkPixel( 95, 80, 195, 63, 63);
+ sc->checkPixel( 80, 95, 195, 63, 63);
+ sc->checkPixel( 96, 96, 63, 63, 195);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerSetLayerWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setLayer");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should hide the foreground surface beneath the background.
+ SCOPED_TRACE("after setLayer");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 63, 63, 195);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerShowHideWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before hide");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should hide the foreground surface.
+ SCOPED_TRACE("after hide, before show");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 63, 63, 195);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should show the foreground surface.
+ SCOPED_TRACE("after show");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerSetAlphaWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setAlpha");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should set foreground to be 75% opaque.
+ SCOPED_TRACE("after setAlpha");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 162, 63, 96);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerSetLayerStackWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setLayerStack");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should hide the foreground surface since it goes to a different
+ // layer stack.
+ SCOPED_TRACE("after setLayerStack");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 63, 63, 195);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerSetFlagsWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setFlags");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags(
+ layer_state_t::eLayerHidden, layer_state_t::eLayerHidden));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ // This should hide the foreground surface
+ SCOPED_TRACE("after setFlags");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 75, 75, 63, 63, 195);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+}
+
+TEST_F(LayerUpdateTest, LayerSetMatrixWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before setMatrix");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 91, 96, 195, 63, 63);
+ sc->checkPixel( 96, 101, 195, 63, 63);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2,
+ -M_SQRT1_2, M_SQRT1_2));
+ SurfaceComposerClient::closeGlobalTransaction(true);
+ {
+ SCOPED_TRACE("after setMatrix");
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel( 24, 24, 63, 63, 195);
+ sc->checkPixel( 91, 96, 195, 63, 63);
+ sc->checkPixel( 96, 91, 63, 63, 195);
+ sc->checkPixel(145, 145, 63, 63, 195);
+ }
+}
+
}
diff --git a/services/surfaceflinger/tests/resize/Android.mk b/services/surfaceflinger/tests/resize/Android.mk
deleted file mode 100644
index d81679e..0000000
--- a/services/surfaceflinger/tests/resize/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- resize.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libui \
- libgui
-
-LOCAL_MODULE:= test-resize
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
deleted file mode 100644
index 8b051e8..0000000
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <cutils/memory.h>
-
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-
-using namespace android;
-
-namespace android {
-
-int main(int argc, char** argv)
-{
- // set up the thread-pool
- sp<ProcessState> proc(ProcessState::self());
- ProcessState::self()->startThreadPool();
-
- // create a client to surfaceflinger
- sp<SurfaceComposerClient> client = new SurfaceComposerClient();
-
- sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
- 160, 240, PIXEL_FORMAT_RGB_565, 0);
-
- sp<Surface> surface = surfaceControl->getSurface();
-
- SurfaceComposerClient::openGlobalTransaction();
- surfaceControl->setLayer(100000);
- SurfaceComposerClient::closeGlobalTransaction();
-
- ANativeWindow_Buffer outBuffer;
- surface->lock(&outBuffer, NULL);
- ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
- android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
- surface->unlockAndPost();
-
- surface->lock(&outBuffer);
- android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
- surface->unlockAndPost();
-
- SurfaceComposerClient::openGlobalTransaction();
- surfaceControl->setSize(320, 240);
- SurfaceComposerClient::closeGlobalTransaction();
-
-
- IPCThreadState::self()->joinThreadPool();
-
- return 0;
-}
diff --git a/services/surfaceflinger/tests/screencap/Android.mk b/services/surfaceflinger/tests/screencap/Android.mk
deleted file mode 100644
index 5cdd1a8..0000000
--- a/services/surfaceflinger/tests/screencap/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- screencap.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libbinder \
- libskia \
- libui \
- libgui
-
-LOCAL_MODULE:= test-screencap
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_C_INCLUDES += \
- external/skia/include/core \
- external/skia/include/effects \
- external/skia/include/images \
- external/skia/src/ports \
- external/skia/include/utils
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/screencap/screencap.cpp b/services/surfaceflinger/tests/screencap/screencap.cpp
deleted file mode 100644
index f842fc3..0000000
--- a/services/surfaceflinger/tests/screencap/screencap.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-
-#include <binder/IMemory.h>
-#include <gui/ISurfaceComposer.h>
-
-#include <SkImageEncoder.h>
-#include <SkBitmap.h>
-
-using namespace android;
-
-int main(int argc, char** argv)
-{
- if (argc != 2) {
- printf("usage: %s path\n", argv[0]);
- exit(0);
- }
-
- const String16 name("SurfaceFlinger");
- sp<ISurfaceComposer> composer;
- getService(name, &composer);
-
- sp<IMemoryHeap> heap;
- uint32_t w, h;
- PixelFormat f;
- sp<IBinder> display(composer->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t err = composer->captureScreen(display, &heap, &w, &h, &f, 0, 0);
- if (err != NO_ERROR) {
- fprintf(stderr, "screen capture failed: %s\n", strerror(-err));
- exit(0);
- }
-
- printf("screen capture success: w=%u, h=%u, pixels=%p\n",
- w, h, heap->getBase());
-
- printf("saving file as PNG in %s ...\n", argv[1]);
-
- SkBitmap b;
- b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
- b.setPixels(heap->getBase());
- SkImageEncoder::EncodeFile(argv[1], b,
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
-
- return 0;
-}
diff --git a/services/surfaceflinger/tests/transform/Android.mk b/services/surfaceflinger/tests/transform/Android.mk
deleted file mode 100644
index 6219dae..0000000
--- a/services/surfaceflinger/tests/transform/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- TransformTest.cpp \
- ../../Transform.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- libui \
-
-LOCAL_MODULE:= test-transform
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_C_INCLUDES += ../..
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/transform/TransformTest.cpp b/services/surfaceflinger/tests/transform/TransformTest.cpp
deleted file mode 100644
index e112c4e..0000000
--- a/services/surfaceflinger/tests/transform/TransformTest.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utils/Errors.h>
-#include "../../Transform.h"
-
-using namespace android;
-
-int main(int argc, char **argv)
-{
- Transform tr90(Transform::ROT_90);
- Transform trFH(Transform::FLIP_H);
- Transform trFV(Transform::FLIP_V);
-
- Transform tr90FH(Transform::ROT_90 | Transform::FLIP_H);
- Transform tr90FV(Transform::ROT_90 | Transform::FLIP_V);
-
- tr90.dump("tr90");
- trFH.dump("trFH");
- trFV.dump("trFV");
-
- tr90FH.dump("tr90FH");
- tr90FV.dump("tr90FV");
-
- (trFH*tr90).dump("trFH*tr90");
- (trFV*tr90).dump("trFV*tr90");
-
- (tr90*trFH).dump("tr90*trFH");
- (tr90*trFV).dump("tr90*trFV");
-
- return 0;
-}