Merge "Rewriting "Audio and Video" section of Dev Guide." into honeycomb-mr2
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index e88cb29..f355087 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -120,14 +120,7 @@
protected:
RefBase();
virtual ~RefBase();
-
- // called when the last reference goes away. this is responsible for
- // calling the destructor. The default implementation just does
- // "delete this;".
- // Make sure to never acquire a strong reference from this function. The
- // same restrictions than for destructors apply.
- virtual void destroy() const;
-
+
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_WEAK = 0x0001,
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index d1d9844..0603ed5 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1988,7 +1988,8 @@
String16* outName,
const String16* defType = NULL,
const String16* defPackage = NULL,
- const char** outErrorMsg = NULL);
+ const char** outErrorMsg = NULL,
+ bool* outPublicOnly = NULL);
static bool stringToInt(const char16_t* s, size_t len, Res_value* outValue);
static bool stringToFloat(const char16_t* s, size_t len, Res_value* outValue);
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index 7de2633..bb6c125 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -345,10 +345,6 @@
const_cast<RefBase*>(this)->onFirstRef();
}
-void RefBase::destroy() const {
- delete this;
-}
-
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
@@ -361,7 +357,7 @@
if (c == 1) {
const_cast<RefBase*>(this)->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
- destroy();
+ delete this;
}
}
refs->decWeak(id);
@@ -419,8 +415,7 @@
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
if (impl->mStrong == INITIAL_STRONG_VALUE)
- if (impl->mBase)
- impl->mBase->destroy();
+ delete impl->mBase;
else {
// LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
@@ -428,8 +423,7 @@
} else {
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
- if (impl->mBase)
- impl->mBase->destroy();
+ delete impl->mBase;
}
}
}
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index a64918d..ecb8c0c 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -2499,6 +2499,9 @@
goto nope;
}
}
+ if (outTypeSpecFlags) {
+ *outTypeSpecFlags = ResTable_typeSpec::SPEC_PUBLIC;
+ }
return m->id;
nope:
;
@@ -2513,6 +2516,9 @@
index);
return 0;
}
+ if (outTypeSpecFlags) {
+ *outTypeSpecFlags = ResTable_typeSpec::SPEC_PUBLIC;
+ }
return Res_MAKEARRAY(index);
}
}
@@ -2523,6 +2529,8 @@
return 0;
}
+ bool fakePublic = false;
+
// Figure out the package and type we are looking in...
const char16_t* packageEnd = NULL;
@@ -2534,7 +2542,13 @@
else if (*p == '/') typeEnd = p;
p++;
}
- if (*name == '@') name++;
+ if (*name == '@') {
+ name++;
+ if (*name == '*') {
+ fakePublic = true;
+ name++;
+ }
+ }
if (name >= nameEnd) {
return 0;
}
@@ -2639,6 +2653,9 @@
if (dtohl(entry->key.index) == (size_t)ei) {
if (outTypeSpecFlags) {
*outTypeSpecFlags = typeConfigs->typeSpecFlags[i];
+ if (fakePublic) {
+ *outTypeSpecFlags |= ResTable_typeSpec::SPEC_PUBLIC;
+ }
}
return Res_MAKEID(group->id-1, ti, i);
}
@@ -2655,7 +2672,8 @@
String16* outName,
const String16* defType,
const String16* defPackage,
- const char** outErrorMsg)
+ const char** outErrorMsg,
+ bool* outPublicOnly)
{
const char16_t* packageEnd = NULL;
const char16_t* typeEnd = NULL;
@@ -2672,6 +2690,16 @@
p = refStr;
if (*p == '@') p++;
+ if (outPublicOnly != NULL) {
+ *outPublicOnly = true;
+ }
+ if (*p == '*') {
+ p++;
+ if (outPublicOnly != NULL) {
+ *outPublicOnly = false;
+ }
+ }
+
if (packageEnd) {
*outPackage = String16(p, packageEnd-p);
p = packageEnd+1;
diff --git a/libs/utils/StreamingZipInflater.cpp b/libs/utils/StreamingZipInflater.cpp
index 5a162cc..00498bd 100644
--- a/libs/utils/StreamingZipInflater.cpp
+++ b/libs/utils/StreamingZipInflater.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_NDEBUG 1
+//#define LOG_NDEBUG 0
#define LOG_TAG "szipinf"
#include <utils/Log.h>
@@ -77,7 +77,7 @@
}
void StreamingZipInflater::initInflateState() {
- LOGD("Initializing inflate state");
+ LOGV("Initializing inflate state");
memset(&mInflateState, 0, sizeof(mInflateState));
mInflateState.zalloc = Z_NULL;
@@ -152,13 +152,13 @@
mInflateState.avail_out = mOutBufSize;
/*
- LOGD("Inflating to outbuf: avail_in=%u avail_out=%u next_in=%p next_out=%p",
+ LOGV("Inflating to outbuf: avail_in=%u avail_out=%u next_in=%p next_out=%p",
mInflateState.avail_in, mInflateState.avail_out,
mInflateState.next_in, mInflateState.next_out);
*/
int result = Z_OK;
if (mStreamNeedsInit) {
- LOGD("Initializing zlib to inflate");
+ LOGV("Initializing zlib to inflate");
result = inflateInit2(&mInflateState, -MAX_WBITS);
mStreamNeedsInit = false;
}
@@ -192,7 +192,7 @@
size_t toRead = min_of(mInBufSize, mInTotalSize - mInNextChunkOffset);
if (toRead > 0) {
ssize_t didRead = ::read(mFd, mInBuf, toRead);
- //LOGD("Reading input chunk, size %08x didread %08x", toRead, didRead);
+ //LOGV("Reading input chunk, size %08x didread %08x", toRead, didRead);
if (didRead < 0) {
// TODO: error
LOGE("Error reading asset data");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 1d75a7b..517c335 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -77,10 +77,6 @@
}
}
-void Layer::destroy() const {
- mFlinger->destroyLayer(this);
-}
-
status_t Layer::setToken(const sp<UserClient>& userClient,
SharedClient* sharedClient, int32_t token)
{
@@ -149,6 +145,18 @@
return sur;
}
+status_t Layer::ditch()
+{
+ // NOTE: Called from the main UI thread
+
+ // the layer is not on screen anymore. free as much resources as possible
+ mFreezeLock.clear();
+
+ Mutex::Autolock _l(mLock);
+ mWidth = mHeight = 0;
+ return NO_ERROR;
+}
+
status_t Layer::setBuffers( uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags)
{
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 278d64e..128f93d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -82,6 +82,7 @@
virtual bool isSecure() const { return mSecure; }
virtual bool isProtected() const;
virtual sp<Surface> createSurface() const;
+ virtual status_t ditch();
virtual void onRemoved();
// only for debugging
@@ -92,7 +93,6 @@
return mFreezeLock; }
protected:
- virtual void destroy() const;
virtual void dump(String8& result, char* scratch, size_t size) const;
private:
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 022f251..6025ed4 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -616,7 +616,10 @@
*/
// destroy client resources
- mFlinger->destroySurface(mOwner);
+ sp<LayerBaseClient> layer = getOwner();
+ if (layer != 0) {
+ mFlinger->destroySurface(layer);
+ }
}
sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 6c49a19..7162e47 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -202,6 +202,10 @@
*/
virtual bool isProtected() const { return false; }
+ /** Called from the main thread, when the surface is removed from the
+ * draw list */
+ virtual status_t ditch() { return NO_ERROR; }
+
/** called with the state lock when the surface is removed from the
* current list */
virtual void onRemoved() { };
@@ -267,8 +271,7 @@
volatile int32_t mInvalidate;
-public:
- // called from class SurfaceFlinger
+protected:
virtual ~LayerBase();
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9a312a7..a9fa1ef 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -387,9 +387,6 @@
{
waitForEvent();
- // call Layer's destructor
- handleDestroyLayers();
-
// check for transactions
if (UNLIKELY(mConsoleSignals)) {
handleConsoleEvents();
@@ -398,7 +395,7 @@
if (LIKELY(mTransactionCount == 0)) {
// if we're in a global transaction, don't do anything.
const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- uint32_t transactionFlags = peekTransactionFlags(mask);
+ uint32_t transactionFlags = getTransactionFlags(mask);
if (LIKELY(transactionFlags)) {
handleTransaction(transactionFlags);
}
@@ -483,26 +480,39 @@
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
- Mutex::Autolock _l(mStateLock);
- const nsecs_t now = systemTime();
- mDebugInTransaction = now;
+ Vector< sp<LayerBase> > ditchedLayers;
- // Here we're guaranteed that some transaction flags are set
- // so we can call handleTransactionLocked() unconditionally.
- // We call getTransactionFlags(), which will also clear the flags,
- // with mStateLock held to guarantee that mCurrentState won't change
- // until the transaction is committed.
+ /*
+ * Perform and commit the transaction
+ */
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- transactionFlags = getTransactionFlags(mask);
- handleTransactionLocked(transactionFlags);
+ { // scope for the lock
+ Mutex::Autolock _l(mStateLock);
+ const nsecs_t now = systemTime();
+ mDebugInTransaction = now;
+ handleTransactionLocked(transactionFlags, ditchedLayers);
+ mLastTransactionTime = systemTime() - now;
+ mDebugInTransaction = 0;
+ invalidateHwcGeometry();
+ // here the transaction has been committed
+ }
- mLastTransactionTime = systemTime() - now;
- mDebugInTransaction = 0;
- // here the transaction has been committed
+ /*
+ * Clean-up all layers that went away
+ * (do this without the lock held)
+ */
+
+ const size_t count = ditchedLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ if (ditchedLayers[i] != 0) {
+ //LOGD("ditching layer %p", ditchedLayers[i].get());
+ ditchedLayers[i]->ditch();
+ }
+ }
}
-void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
+void SurfaceFlinger::handleTransactionLocked(
+ uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
{
const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
const size_t count = currentLayers.size();
@@ -574,6 +584,7 @@
const sp<LayerBase>& layer(previousLayers[i]);
if (currentLayers.indexOf( layer ) < 0) {
// this layer is not visible anymore
+ ditchedLayers.add(layer);
mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
}
}
@@ -583,31 +594,6 @@
commitTransaction();
}
-void SurfaceFlinger::destroyLayer(LayerBase const* layer)
-{
- Mutex::Autolock _l(mDestroyedLayerLock);
- mDestroyedLayers.add(layer);
- signalEvent();
-}
-
-void SurfaceFlinger::handleDestroyLayers()
-{
- Vector<LayerBase const *> destroyedLayers;
-
- { // scope for the lock
- Mutex::Autolock _l(mDestroyedLayerLock);
- destroyedLayers = mDestroyedLayers;
- mDestroyedLayers.clear();
- }
-
- // call destructors without a lock held
- const size_t count = destroyedLayers.size();
- for (size_t i=0 ; i<count ; i++) {
- //LOGD("destroying %s", destroyedLayers[i]->getName().string());
- delete destroyedLayers[i];
- }
-}
-
sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
{
return new FreezeLock(const_cast<SurfaceFlinger *>(this));
@@ -1110,15 +1096,15 @@
ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
const sp<LayerBaseClient>& lbc)
{
- // attach this layer to the client
- size_t name = client->attachLayer(lbc);
-
Mutex::Autolock _l(mStateLock);
+ // attach this layer to the client
+ ssize_t name = client->attachLayer(lbc);
+
// add this layer to the current state list
addLayer_l(lbc);
- return ssize_t(name);
+ return name;
}
status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
@@ -1169,11 +1155,6 @@
return NO_ERROR;
}
-uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
-{
- return android_atomic_release_load(&mTransactionFlags);
-}
-
uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
{
return android_atomic_and(~flags, &mTransactionFlags) & flags;
@@ -1381,18 +1362,51 @@
return err;
}
-status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
+status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
{
// called by ~ISurface() when all references are gone
- status_t err = NO_ERROR;
- sp<LayerBaseClient> l(layer.promote());
- if (l != NULL) {
- Mutex::Autolock _l(mStateLock);
- err = removeLayer_l(l);
- LOGE_IF(err<0 && err != NAME_NOT_FOUND,
- "error removing layer=%p (%s)", l.get(), strerror(-err));
- }
- return err;
+
+ class MessageDestroySurface : public MessageBase {
+ SurfaceFlinger* flinger;
+ sp<LayerBaseClient> layer;
+ public:
+ MessageDestroySurface(
+ SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer)
+ : flinger(flinger), layer(layer) { }
+ virtual bool handler() {
+ sp<LayerBaseClient> l(layer);
+ layer.clear(); // clear it outside of the lock;
+ Mutex::Autolock _l(flinger->mStateLock);
+ /*
+ * remove the layer from the current list -- chances are that it's
+ * not in the list anyway, because it should have been removed
+ * already upon request of the client (eg: window manager).
+ * However, a buggy client could have not done that.
+ * Since we know we don't have any more clients, we don't need
+ * to use the purgatory.
+ */
+ status_t err = flinger->removeLayer_l(l);
+ if (err == NAME_NOT_FOUND) {
+ // The surface wasn't in the current list, which means it was
+ // removed already, which means it is in the purgatory,
+ // and need to be removed from there.
+ // This needs to happen from the main thread since its dtor
+ // must run from there (b/c of OpenGL ES). Additionally, we
+ // can't really acquire our internal lock from
+ // destroySurface() -- see postMessage() below.
+ ssize_t idx = flinger->mLayerPurgatory.remove(l);
+ LOGE_IF(idx < 0,
+ "layer=%p is not in the purgatory list", l.get());
+ }
+
+ LOGE_IF(err<0 && err != NAME_NOT_FOUND,
+ "error removing layer=%p (%s)", l.get(), strerror(-err));
+ return true;
+ }
+ };
+
+ postMessageAsync( new MessageDestroySurface(this, layer) );
+ return NO_ERROR;
}
status_t SurfaceFlinger::setClientState(
@@ -2367,17 +2381,15 @@
return NO_ERROR;
}
-size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
+ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
{
- Mutex::Autolock _l(mLock);
- size_t name = mNameGenerator++;
+ int32_t name = android_atomic_inc(&mNameGenerator);
mLayers.add(name, layer);
return name;
}
void Client::detachLayer(const LayerBaseClient* layer)
{
- Mutex::Autolock _l(mLock);
// we do a linear search here, because this doesn't happen often
const size_t count = mLayers.size();
for (size_t i=0 ; i<count ; i++) {
@@ -2387,11 +2399,9 @@
}
}
}
-sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
-{
- Mutex::Autolock _l(mLock);
+sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
sp<LayerBaseClient> lbc;
- wp<LayerBaseClient> layer(mLayers.valueFor(i));
+ const wp<LayerBaseClient>& layer(mLayers.valueFor(i));
if (layer != 0) {
lbc = layer.promote();
LOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f81b074..9566819 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -65,7 +65,7 @@
status_t initCheck() const;
// protected by SurfaceFlinger::mStateLock
- size_t attachLayer(const sp<LayerBaseClient>& layer);
+ ssize_t attachLayer(const sp<LayerBaseClient>& layer);
void detachLayer(const LayerBaseClient* layer);
sp<LayerBaseClient> getLayerUser(int32_t i) const;
@@ -81,15 +81,9 @@
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
- // constant
- sp<SurfaceFlinger> mFlinger;
-
- // protected by mLock
DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
- size_t mNameGenerator;
-
- // thread-safe
- mutable Mutex mLock;
+ sp<SurfaceFlinger> mFlinger;
+ int32_t mNameGenerator;
};
class UserClient : public BnSurfaceComposerClient
@@ -233,7 +227,6 @@
status_t addLayer(const sp<LayerBase>& layer);
status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
void invalidateHwcGeometry();
- void destroyLayer(LayerBase const* layer);
sp<Layer> getLayer(const sp<ISurface>& sur) const;
@@ -261,7 +254,7 @@
uint32_t w, uint32_t h, uint32_t flags);
status_t removeSurface(const sp<Client>& client, SurfaceID sid);
- status_t destroySurface(const wp<LayerBaseClient>& layer);
+ status_t destroySurface(const sp<LayerBaseClient>& layer);
status_t setClientState(const sp<Client>& client,
int32_t count, const layer_state_t* states);
@@ -306,8 +299,9 @@
private:
void handleConsoleEvents();
void handleTransaction(uint32_t transactionFlags);
- void handleTransactionLocked(uint32_t transactionFlags);
- void handleDestroyLayers();
+ void handleTransactionLocked(
+ uint32_t transactionFlags,
+ Vector< sp<LayerBase> >& ditchedLayers);
void computeVisibleRegions(
LayerVector& currentLayers,
@@ -330,7 +324,6 @@
status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
uint32_t getTransactionFlags(uint32_t flags);
- uint32_t peekTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags);
void commitTransaction();
@@ -429,11 +422,6 @@
// these are thread safe
mutable Barrier mReadyToRunBarrier;
-
- // protected by mDestroyedLayerLock;
- mutable Mutex mDestroyedLayerLock;
- Vector<LayerBase const *> mDestroyedLayers;
-
// atomic variables
enum {
eConsoleReleased = 1,