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,