Merge "Reveal some network constants." into honeycomb-mr2
diff --git a/include/ui/Input.h b/include/ui/Input.h
index fb6152e..074b38f 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -608,11 +608,6 @@
// Oldest sample to consider when calculating the velocity.
static const nsecs_t MAX_AGE = 200 * 1000000; // 200 ms
- // When the total duration of the window of samples being averaged is less
- // than the window size, the resulting velocity is scaled to reduce the impact
- // of overestimation in short traces.
- static const nsecs_t MIN_WINDOW = 100 * 1000000; // 100 ms
-
// The minimum duration between samples when estimating velocity.
static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
@@ -627,6 +622,87 @@
int32_t mActivePointerId;
};
+
+/*
+ * Specifies parameters that govern pointer or wheel acceleration.
+ */
+struct VelocityControlParameters {
+ // A scale factor that is multiplied with the raw velocity deltas
+ // prior to applying any other velocity control factors. The scale
+ // factor should be used to adapt the input device resolution
+ // (eg. counts per inch) to the output device resolution (eg. pixels per inch).
+ //
+ // Must be a positive value.
+ // Default is 1.0 (no scaling).
+ float scale;
+
+ // The scaled speed at which acceleration begins to be applied.
+ // This value establishes the upper bound of a low speed regime for
+ // small precise motions that are performed without any acceleration.
+ //
+ // Must be a non-negative value.
+ // Default is 0.0 (no low threshold).
+ float lowThreshold;
+
+ // The scaled speed at which maximum acceleration is applied.
+ // The difference between highThreshold and lowThreshold controls
+ // the range of speeds over which the acceleration factor is interpolated.
+ // The wider the range, the smoother the acceleration.
+ //
+ // Must be a non-negative value greater than or equal to lowThreshold.
+ // Default is 0.0 (no high threshold).
+ float highThreshold;
+
+ // The acceleration factor.
+ // When the speed is above the low speed threshold, the velocity will scaled
+ // by an interpolated value between 1.0 and this amount.
+ //
+ // Must be a positive greater than or equal to 1.0.
+ // Default is 1.0 (no acceleration).
+ float acceleration;
+
+ VelocityControlParameters() :
+ scale(1.0f), lowThreshold(0.0f), highThreshold(0.0f), acceleration(1.0f) {
+ }
+
+ VelocityControlParameters(float scale, float lowThreshold,
+ float highThreshold, float acceleration) :
+ scale(scale), lowThreshold(lowThreshold),
+ highThreshold(highThreshold), acceleration(acceleration) {
+ }
+};
+
+/*
+ * Implements mouse pointer and wheel speed control and acceleration.
+ */
+class VelocityControl {
+public:
+ VelocityControl();
+
+ /* Sets the various parameters. */
+ void setParameters(const VelocityControlParameters& parameters);
+
+ /* Resets the current movement counters to zero.
+ * This has the effect of nullifying any acceleration. */
+ void reset();
+
+ /* Translates a raw movement delta into an appropriately
+ * scaled / accelerated delta based on the current velocity. */
+ void move(nsecs_t eventTime, float* deltaX, float* deltaY);
+
+private:
+ // If no movements are received within this amount of time,
+ // we assume the movement has stopped and reset the movement counters.
+ static const nsecs_t STOP_TIME = 500 * 1000000; // 500 ms
+
+ VelocityControlParameters mParameters;
+
+ nsecs_t mLastMovementTime;
+ VelocityTracker::Position mRawPosition;
+ VelocityTracker mVelocityTracker;
+};
+
+
/*
* Describes the characteristics and capabilities of an input device.
*/
diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h
index f355087..e88cb29 100644
--- a/include/utils/RefBase.h
+++ b/include/utils/RefBase.h
@@ -120,7 +120,14 @@
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 c02d8ac..d1d9844 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -841,6 +841,7 @@
DENSITY_DEFAULT = ACONFIGURATION_DENSITY_DEFAULT,
DENSITY_LOW = ACONFIGURATION_DENSITY_LOW,
DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM,
+ DENSITY_TV = ACONFIGURATION_DENSITY_TV,
DENSITY_HIGH = ACONFIGURATION_DENSITY_HIGH,
DENSITY_NONE = ACONFIGURATION_DENSITY_NONE
};
@@ -1452,24 +1453,20 @@
// settings is the requested settings
inline bool match(const ResTable_config& settings) const {
if (imsi != 0) {
- if ((settings.mcc != 0 && mcc != 0
- && mcc != settings.mcc) ||
- (settings.mcc == 0 && mcc != 0)) {
+ if (mcc != 0 && mcc != settings.mcc) {
return false;
}
- if ((settings.mnc != 0 && mnc != 0
- && mnc != settings.mnc) ||
- (settings.mnc == 0 && mnc != 0)) {
+ if (mnc != 0 && mnc != settings.mnc) {
return false;
}
}
if (locale != 0) {
- if (settings.language[0] != 0 && language[0] != 0
+ if (language[0] != 0
&& (language[0] != settings.language[0]
|| language[1] != settings.language[1])) {
return false;
}
- if (settings.country[0] != 0 && country[0] != 0
+ if (country[0] != 0
&& (country[0] != settings.country[0]
|| country[1] != settings.country[1])) {
return false;
@@ -1480,66 +1477,56 @@
const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE;
// Any screen sizes for larger screens than the setting do not
// match.
- if ((setScreenSize != 0 && screenSize != 0
- && screenSize > setScreenSize) ||
- (setScreenSize == 0 && screenSize != 0)) {
+ if (screenSize != 0 && screenSize > setScreenSize) {
return false;
}
const int screenLong = screenLayout&MASK_SCREENLONG;
const int setScreenLong = settings.screenLayout&MASK_SCREENLONG;
- if (setScreenLong != 0 && screenLong != 0
- && screenLong != setScreenLong) {
+ if (screenLong != 0 && screenLong != setScreenLong) {
return false;
}
const int uiModeType = uiMode&MASK_UI_MODE_TYPE;
const int setUiModeType = settings.uiMode&MASK_UI_MODE_TYPE;
- if (setUiModeType != 0 && uiModeType != 0
- && uiModeType != setUiModeType) {
+ if (uiModeType != 0 && uiModeType != setUiModeType) {
return false;
}
const int uiModeNight = uiMode&MASK_UI_MODE_NIGHT;
const int setUiModeNight = settings.uiMode&MASK_UI_MODE_NIGHT;
- if (setUiModeNight != 0 && uiModeNight != 0
- && uiModeNight != setUiModeNight) {
+ if (uiModeNight != 0 && uiModeNight != setUiModeNight) {
return false;
}
- if (settings.smallestScreenWidthDp != 0 && smallestScreenWidthDp != 0
+ if (smallestScreenWidthDp != 0
&& smallestScreenWidthDp > settings.smallestScreenWidthDp) {
return false;
}
}
if (screenSizeDp != 0) {
- if (settings.screenWidthDp != 0 && screenWidthDp != 0
- && screenWidthDp > settings.screenWidthDp) {
+ if (screenWidthDp != 0 && screenWidthDp > settings.screenWidthDp) {
//LOGI("Filtering out width %d in requested %d", screenWidthDp, settings.screenWidthDp);
return false;
}
- if (settings.screenHeightDp != 0 && screenHeightDp != 0
- && screenHeightDp > settings.screenHeightDp) {
+ if (screenHeightDp != 0 && screenHeightDp > settings.screenHeightDp) {
//LOGI("Filtering out height %d in requested %d", screenHeightDp, settings.screenHeightDp);
return false;
}
}
if (screenType != 0) {
- if (settings.orientation != 0 && orientation != 0
- && orientation != settings.orientation) {
+ if (orientation != 0 && orientation != settings.orientation) {
return false;
}
// density always matches - we can scale it. See isBetterThan
- if (settings.touchscreen != 0 && touchscreen != 0
- && touchscreen != settings.touchscreen) {
+ if (touchscreen != 0 && touchscreen != settings.touchscreen) {
return false;
}
}
if (input != 0) {
const int keysHidden = inputFlags&MASK_KEYSHIDDEN;
const int setKeysHidden = settings.inputFlags&MASK_KEYSHIDDEN;
- if (setKeysHidden != 0 && keysHidden != 0
- && keysHidden != setKeysHidden) {
+ if (keysHidden != 0 && keysHidden != setKeysHidden) {
// For compatibility, we count a request for KEYSHIDDEN_NO as also
// matching the more recent KEYSHIDDEN_SOFT. Basically
// KEYSHIDDEN_NO means there is some kind of keyboard available.
@@ -1551,36 +1538,29 @@
}
const int navHidden = inputFlags&MASK_NAVHIDDEN;
const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
- if (setNavHidden != 0 && navHidden != 0
- && navHidden != setNavHidden) {
+ if (navHidden != 0 && navHidden != setNavHidden) {
return false;
}
- if (settings.keyboard != 0 && keyboard != 0
- && keyboard != settings.keyboard) {
+ if (keyboard != 0 && keyboard != settings.keyboard) {
return false;
}
- if (settings.navigation != 0 && navigation != 0
- && navigation != settings.navigation) {
+ if (navigation != 0 && navigation != settings.navigation) {
return false;
}
}
if (screenSize != 0) {
- if (settings.screenWidth != 0 && screenWidth != 0
- && screenWidth > settings.screenWidth) {
+ if (screenWidth != 0 && screenWidth > settings.screenWidth) {
return false;
}
- if (settings.screenHeight != 0 && screenHeight != 0
- && screenHeight > settings.screenHeight) {
+ if (screenHeight != 0 && screenHeight > settings.screenHeight) {
return false;
}
}
if (version != 0) {
- if (settings.sdkVersion != 0 && sdkVersion != 0
- && sdkVersion > settings.sdkVersion) {
+ if (sdkVersion != 0 && sdkVersion > settings.sdkVersion) {
return false;
}
- if (settings.minorVersion != 0 && minorVersion != 0
- && minorVersion != settings.minorVersion) {
+ if (minorVersion != 0 && minorVersion != settings.minorVersion) {
return false;
}
}
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 684c332..1fc46aa 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -13,6 +13,10 @@
// Log debug messages about velocity tracking.
#define DEBUG_VELOCITY 0
+// Log debug messages about acceleration.
+#define DEBUG_ACCELERATION 0
+
+
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
@@ -20,6 +24,7 @@
#include <ui/Input.h>
#include <math.h>
+#include <limits.h>
#ifdef HAVE_ANDROID_OS
#include <binder/Parcel.h>
@@ -670,6 +675,10 @@
// --- VelocityTracker ---
+const uint32_t VelocityTracker::HISTORY_SIZE;
+const nsecs_t VelocityTracker::MAX_AGE;
+const nsecs_t VelocityTracker::MIN_DURATION;
+
VelocityTracker::VelocityTracker() {
clear();
}
@@ -858,14 +867,6 @@
// Make sure we used at least one sample.
if (samplesUsed != 0) {
- // Scale the velocity linearly if the window of samples is small.
- nsecs_t totalDuration = newestMovement.eventTime - oldestMovement.eventTime;
- if (totalDuration < MIN_WINDOW) {
- float scale = float(totalDuration) / float(MIN_WINDOW);
- accumVx *= scale;
- accumVy *= scale;
- }
-
*outVx = accumVx;
*outVy = accumVy;
return true;
@@ -879,6 +880,85 @@
}
+// --- VelocityControl ---
+
+const nsecs_t VelocityControl::STOP_TIME;
+
+VelocityControl::VelocityControl() {
+ reset();
+}
+
+void VelocityControl::setParameters(const VelocityControlParameters& parameters) {
+ mParameters = parameters;
+ reset();
+}
+
+void VelocityControl::reset() {
+ mLastMovementTime = LLONG_MIN;
+ mRawPosition.x = 0;
+ mRawPosition.y = 0;
+ mVelocityTracker.clear();
+}
+
+void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
+ if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
+ if (eventTime >= mLastMovementTime + STOP_TIME) {
+#if DEBUG_ACCELERATION
+ LOGD("VelocityControl: stopped, last movement was %0.3fms ago",
+ (eventTime - mLastMovementTime) * 0.000001f);
+#endif
+ reset();
+ }
+
+ mLastMovementTime = eventTime;
+ if (deltaX) {
+ mRawPosition.x += *deltaX;
+ }
+ if (deltaY) {
+ mRawPosition.y += *deltaY;
+ }
+ mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
+
+ float vx, vy;
+ float scale = mParameters.scale;
+ if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
+ float speed = hypotf(vx, vy) * scale;
+ if (speed >= mParameters.highThreshold) {
+ // Apply full acceleration above the high speed threshold.
+ scale *= mParameters.acceleration;
+ } else if (speed > mParameters.lowThreshold) {
+ // Linearly interpolate the acceleration to apply between the low and high
+ // speed thresholds.
+ scale *= 1 + (speed - mParameters.lowThreshold)
+ / (mParameters.highThreshold - mParameters.lowThreshold)
+ * (mParameters.acceleration - 1);
+ }
+
+#if DEBUG_ACCELERATION
+ LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
+ "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
+ mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+ mParameters.acceleration,
+ vx, vy, speed, scale / mParameters.scale);
+#endif
+ } else {
+#if DEBUG_ACCELERATION
+ LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
+ mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
+ mParameters.acceleration);
+#endif
+ }
+
+ if (deltaX) {
+ *deltaX *= scale;
+ }
+ if (deltaY) {
+ *deltaY *= scale;
+ }
+ }
+}
+
+
// --- InputDeviceInfo ---
InputDeviceInfo::InputDeviceInfo() {
diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp
index bb6c125..7de2633 100644
--- a/libs/utils/RefBase.cpp
+++ b/libs/utils/RefBase.cpp
@@ -345,6 +345,10 @@
const_cast<RefBase*>(this)->onFirstRef();
}
+void RefBase::destroy() const {
+ delete this;
+}
+
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
@@ -357,7 +361,7 @@
if (c == 1) {
const_cast<RefBase*>(this)->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
- delete this;
+ destroy();
}
}
refs->decWeak(id);
@@ -415,7 +419,8 @@
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
if (impl->mStrong == INITIAL_STRONG_VALUE)
- delete impl->mBase;
+ if (impl->mBase)
+ impl->mBase->destroy();
else {
// LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
@@ -423,7 +428,8 @@
} else {
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
- delete impl->mBase;
+ if (impl->mBase)
+ impl->mBase->destroy();
}
}
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 517c335..1d75a7b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -77,6 +77,10 @@
}
}
+void Layer::destroy() const {
+ mFlinger->destroyLayer(this);
+}
+
status_t Layer::setToken(const sp<UserClient>& userClient,
SharedClient* sharedClient, int32_t token)
{
@@ -145,18 +149,6 @@
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 128f93d..278d64e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -82,7 +82,6 @@
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
@@ -93,6 +92,7 @@
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 6025ed4..022f251 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -616,10 +616,7 @@
*/
// destroy client resources
- sp<LayerBaseClient> layer = getOwner();
- if (layer != 0) {
- mFlinger->destroySurface(layer);
- }
+ mFlinger->destroySurface(mOwner);
}
sp<LayerBaseClient> LayerBaseClient::Surface::getOwner() const {
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 7162e47..6c49a19 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -202,10 +202,6 @@
*/
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() { };
@@ -271,7 +267,8 @@
volatile int32_t mInvalidate;
-protected:
+public:
+ // called from class SurfaceFlinger
virtual ~LayerBase();
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a9fa1ef..9a312a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -387,6 +387,9 @@
{
waitForEvent();
+ // call Layer's destructor
+ handleDestroyLayers();
+
// check for transactions
if (UNLIKELY(mConsoleSignals)) {
handleConsoleEvents();
@@ -395,7 +398,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 = getTransactionFlags(mask);
+ uint32_t transactionFlags = peekTransactionFlags(mask);
if (LIKELY(transactionFlags)) {
handleTransaction(transactionFlags);
}
@@ -480,39 +483,26 @@
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
- Vector< sp<LayerBase> > ditchedLayers;
+ Mutex::Autolock _l(mStateLock);
+ const nsecs_t now = systemTime();
+ mDebugInTransaction = now;
- /*
- * Perform and commit the transaction
- */
+ // 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.
- { // 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
- }
+ const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+ transactionFlags = getTransactionFlags(mask);
+ handleTransactionLocked(transactionFlags);
- /*
- * 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();
- }
- }
+ mLastTransactionTime = systemTime() - now;
+ mDebugInTransaction = 0;
+ // here the transaction has been committed
}
-void SurfaceFlinger::handleTransactionLocked(
- uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
+void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
const size_t count = currentLayers.size();
@@ -584,7 +574,6 @@
const sp<LayerBase>& layer(previousLayers[i]);
if (currentLayers.indexOf( layer ) < 0) {
// this layer is not visible anymore
- ditchedLayers.add(layer);
mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
}
}
@@ -594,6 +583,31 @@
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));
@@ -1096,15 +1110,15 @@
ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
const sp<LayerBaseClient>& lbc)
{
- Mutex::Autolock _l(mStateLock);
-
// attach this layer to the client
- ssize_t name = client->attachLayer(lbc);
+ size_t name = client->attachLayer(lbc);
+
+ Mutex::Autolock _l(mStateLock);
// add this layer to the current state list
addLayer_l(lbc);
- return name;
+ return ssize_t(name);
}
status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
@@ -1155,6 +1169,11 @@
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;
@@ -1362,51 +1381,18 @@
return err;
}
-status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
+status_t SurfaceFlinger::destroySurface(const wp<LayerBaseClient>& layer)
{
// called by ~ISurface() when all references are gone
-
- 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 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;
}
status_t SurfaceFlinger::setClientState(
@@ -2381,15 +2367,17 @@
return NO_ERROR;
}
-ssize_t Client::attachLayer(const sp<LayerBaseClient>& layer)
+size_t Client::attachLayer(const sp<LayerBaseClient>& layer)
{
- int32_t name = android_atomic_inc(&mNameGenerator);
+ Mutex::Autolock _l(mLock);
+ size_t name = 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++) {
@@ -2399,9 +2387,11 @@
}
}
}
-sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
+sp<LayerBaseClient> Client::getLayerUser(int32_t i) const
+{
+ Mutex::Autolock _l(mLock);
sp<LayerBaseClient> lbc;
- const wp<LayerBaseClient>& layer(mLayers.valueFor(i));
+ 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 9566819..f81b074 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -65,7 +65,7 @@
status_t initCheck() const;
// protected by SurfaceFlinger::mStateLock
- ssize_t attachLayer(const sp<LayerBaseClient>& layer);
+ size_t attachLayer(const sp<LayerBaseClient>& layer);
void detachLayer(const LayerBaseClient* layer);
sp<LayerBaseClient> getLayerUser(int32_t i) const;
@@ -81,9 +81,15 @@
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
- DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
+ // constant
sp<SurfaceFlinger> mFlinger;
- int32_t mNameGenerator;
+
+ // protected by mLock
+ DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers;
+ size_t mNameGenerator;
+
+ // thread-safe
+ mutable Mutex mLock;
};
class UserClient : public BnSurfaceComposerClient
@@ -227,6 +233,7 @@
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;
@@ -254,7 +261,7 @@
uint32_t w, uint32_t h, uint32_t flags);
status_t removeSurface(const sp<Client>& client, SurfaceID sid);
- status_t destroySurface(const sp<LayerBaseClient>& layer);
+ status_t destroySurface(const wp<LayerBaseClient>& layer);
status_t setClientState(const sp<Client>& client,
int32_t count, const layer_state_t* states);
@@ -299,9 +306,8 @@
private:
void handleConsoleEvents();
void handleTransaction(uint32_t transactionFlags);
- void handleTransactionLocked(
- uint32_t transactionFlags,
- Vector< sp<LayerBase> >& ditchedLayers);
+ void handleTransactionLocked(uint32_t transactionFlags);
+ void handleDestroyLayers();
void computeVisibleRegions(
LayerVector& currentLayers,
@@ -324,6 +330,7 @@
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();
@@ -422,6 +429,11 @@
// these are thread safe
mutable Barrier mReadyToRunBarrier;
+
+ // protected by mDestroyedLayerLock;
+ mutable Mutex mDestroyedLayerLock;
+ Vector<LayerBase const *> mDestroyedLayers;
+
// atomic variables
enum {
eConsoleReleased = 1,