Merge "Change SF power hints to use early frame predictions" into tm-qpr-dev
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index c2793ac..dbccf30 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -165,6 +165,17 @@
mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
mNumAcquired = 0;
mNumFrameAvailable = 0;
+
+ TransactionCompletedListener::getInstance()->addQueueStallListener(
+ [&]() {
+ std::function<void(bool)> callbackCopy;
+ {
+ std::unique_lock _lock{mMutex};
+ callbackCopy = mTransactionHangCallback;
+ }
+ if (callbackCopy) callbackCopy(true);
+ }, this);
+
BQA_LOGV("BLASTBufferQueue created");
}
@@ -175,6 +186,7 @@
}
BLASTBufferQueue::~BLASTBufferQueue() {
+ TransactionCompletedListener::getInstance()->removeQueueStallListener(this);
if (mPendingTransactions.empty()) {
return;
}
@@ -1113,4 +1125,9 @@
return SurfaceControl::isSameSurface(mSurfaceControl, surfaceControl);
}
+void BLASTBufferQueue::setTransactionHangCallback(std::function<void(bool)> callback) {
+ std::unique_lock _lock{mMutex};
+ mTransactionHangCallback = callback;
+}
+
} // namespace android
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index f7392d4..e4b8bad 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -29,6 +29,7 @@
enum class Tag : uint32_t {
ON_TRANSACTION_COMPLETED = IBinder::FIRST_CALL_TRANSACTION,
ON_RELEASE_BUFFER,
+ ON_TRANSACTION_QUEUE_STALLED,
LAST = ON_RELEASE_BUFFER,
};
@@ -277,6 +278,11 @@
callbackId, releaseFence,
currentMaxAcquiredBufferCount);
}
+
+ void onTransactionQueueStalled() override {
+ callRemoteAsync<decltype(&ITransactionCompletedListener::onTransactionQueueStalled)>(
+ Tag::ON_TRANSACTION_QUEUE_STALLED);
+ }
};
// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see
@@ -297,6 +303,9 @@
&ITransactionCompletedListener::onTransactionCompleted);
case Tag::ON_RELEASE_BUFFER:
return callLocalAsync(data, reply, &ITransactionCompletedListener::onReleaseBuffer);
+ case Tag::ON_TRANSACTION_QUEUE_STALLED:
+ return callLocalAsync(data, reply,
+ &ITransactionCompletedListener::onTransactionQueueStalled);
}
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6642ec6..501f8cf 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -447,6 +447,27 @@
}
}
+void TransactionCompletedListener::onTransactionQueueStalled() {
+ std::unordered_map<void*, std::function<void()>> callbackCopy;
+ {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ callbackCopy = mQueueStallListeners;
+ }
+ for (auto const& it : callbackCopy) {
+ it.second();
+ }
+}
+
+void TransactionCompletedListener::addQueueStallListener(std::function<void()> stallListener,
+ void* id) {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ mQueueStallListeners[id] = stallListener;
+}
+void TransactionCompletedListener::removeQueueStallListener(void *id) {
+ std::scoped_lock<std::mutex> lock(mMutex);
+ mQueueStallListeners.erase(id);
+}
+
void TransactionCompletedListener::onReleaseBuffer(ReleaseCallbackId callbackId,
sp<Fence> releaseFence,
uint32_t currentMaxAcquiredBufferCount) {
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 65fc04d..9328a54 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -113,6 +113,14 @@
uint64_t getLastAcquiredFrameNum();
void abandon();
+ /**
+ * Set a callback to be invoked when we are hung. The boolean parameter
+ * indicates whether the hang is due to an unfired fence.
+ * TODO: The boolean is always true atm, unfired fence is
+ * the only case we detect.
+ */
+ void setTransactionHangCallback(std::function<void(bool)> callback);
+
virtual ~BLASTBufferQueue();
private:
@@ -269,6 +277,8 @@
// transaction that will be applied by some sync consumer.
bool mAppliedLastTransaction = false;
uint64_t mLastAppliedFrameNumber = 0;
+
+ std::function<void(bool)> mTransactionHangCallback;
};
} // namespace android
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index a791c66..cc136bb 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -194,6 +194,7 @@
virtual void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
uint32_t currentMaxAcquiredBufferCount) = 0;
+ virtual void onTransactionQueueStalled() = 0;
};
class BnTransactionCompletedListener : public SafeBnInterface<ITransactionCompletedListener> {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0cc43d8..efbdb36 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -772,6 +772,7 @@
// This is protected by mSurfaceStatsListenerMutex, but GUARDED_BY isn't supported for
// std::recursive_mutex
std::multimap<int32_t, SurfaceStatsCallbackEntry> mSurfaceStatsListeners;
+ std::unordered_map<void*, std::function<void()>> mQueueStallListeners;
public:
static sp<TransactionCompletedListener> getInstance();
@@ -789,6 +790,9 @@
const sp<SurfaceControl>& surfaceControl,
const std::unordered_set<CallbackId, CallbackIdHash>& callbackIds);
+ void addQueueStallListener(std::function<void()> stallListener, void* id);
+ void removeQueueStallListener(void *id);
+
/*
* Adds a jank listener to be informed about SurfaceFlinger's jank classification for a specific
* surface. Jank classifications arrive as part of the transaction callbacks about previous
@@ -817,6 +821,8 @@
// For Testing Only
static void setInstance(const sp<TransactionCompletedListener>&);
+ void onTransactionQueueStalled() override;
+
private:
ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&);
static sp<TransactionCompletedListener> sInstance;
diff --git a/libs/renderengine/TEST_MAPPING b/libs/renderengine/TEST_MAPPING
index 995dba1..db00118 100644
--- a/libs/renderengine/TEST_MAPPING
+++ b/libs/renderengine/TEST_MAPPING
@@ -3,5 +3,11 @@
{
"name": "librenderengine_test"
}
+ ],
+
+ "imports": [
+ {
+ "path": "frameworks/native/services/surfaceflinger"
+ }
]
}
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index beca7f1..86c788d 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -52,35 +52,37 @@
ALOGV("initializing random seed using %lld", (unsigned long long)now);
}
-void BlobCache::set(const void* key, size_t keySize, const void* value, size_t valueSize) {
+BlobCache::InsertResult BlobCache::set(const void* key, size_t keySize, const void* value,
+ size_t valueSize) {
if (mMaxKeySize < keySize) {
ALOGV("set: not caching because the key is too large: %zu (limit: %zu)", keySize,
mMaxKeySize);
- return;
+ return InsertResult::kKeyTooBig;
}
if (mMaxValueSize < valueSize) {
ALOGV("set: not caching because the value is too large: %zu (limit: %zu)", valueSize,
mMaxValueSize);
- return;
+ return InsertResult::kValueTooBig;
}
if (mMaxTotalSize < keySize + valueSize) {
ALOGV("set: not caching because the combined key/value size is too "
"large: %zu (limit: %zu)",
keySize + valueSize, mMaxTotalSize);
- return;
+ return InsertResult::kCombinedTooBig;
}
if (keySize == 0) {
ALOGW("set: not caching because keySize is 0");
- return;
+ return InsertResult::kInvalidKeySize;
}
- if (valueSize <= 0) {
+ if (valueSize == 0) {
ALOGW("set: not caching because valueSize is 0");
- return;
+ return InsertResult::kInvalidValueSize;
}
std::shared_ptr<Blob> cacheKey(new Blob(key, keySize, false));
CacheEntry cacheEntry(cacheKey, nullptr);
+ bool didClean = false;
while (true) {
auto index = std::lower_bound(mCacheEntries.begin(), mCacheEntries.end(), cacheEntry);
if (index == mCacheEntries.end() || cacheEntry < *index) {
@@ -92,13 +94,14 @@
if (isCleanable()) {
// Clean the cache and try again.
clean();
+ didClean = true;
continue;
} else {
ALOGV("set: not caching new key/value pair because the "
"total cache size limit would be exceeded: %zu "
"(limit: %zu)",
keySize + valueSize, mMaxTotalSize);
- break;
+ return InsertResult::kNotEnoughSpace;
}
}
mCacheEntries.insert(index, CacheEntry(keyBlob, valueBlob));
@@ -114,12 +117,13 @@
if (isCleanable()) {
// Clean the cache and try again.
clean();
+ didClean = true;
continue;
} else {
ALOGV("set: not caching new value because the total cache "
"size limit would be exceeded: %zu (limit: %zu)",
keySize + valueSize, mMaxTotalSize);
- break;
+ return InsertResult::kNotEnoughSpace;
}
}
index->setValue(valueBlob);
@@ -128,7 +132,7 @@
"value",
keySize, valueSize);
}
- break;
+ return didClean ? InsertResult::kDidClean : InsertResult::kInserted;
}
}
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
index 50b4e4c..ff03d30 100644
--- a/opengl/libs/EGL/BlobCache.h
+++ b/opengl/libs/EGL/BlobCache.h
@@ -39,6 +39,26 @@
// (key sizes plus value sizes) will not exceed maxTotalSize.
BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize);
+ // Return value from set(), below.
+ enum class InsertResult {
+ // The key is larger than maxKeySize specified in the constructor.
+ kKeyTooBig,
+ // The value is larger than maxValueSize specified in the constructor.
+ kValueTooBig,
+ // The combined key + value is larger than maxTotalSize specified in the constructor.
+ kCombinedTooBig,
+ // keySize is 0
+ kInvalidKeySize,
+ // valueSize is 0
+ kInvalidValueSize,
+ // Unable to free enough space to fit the new entry.
+ kNotEnoughSpace,
+ // The new entry was inserted, but an old entry had to be evicted.
+ kDidClean,
+ // There was enough room in the cache and the new entry was inserted.
+ kInserted,
+
+ };
// set inserts a new binary value into the cache and associates it with the
// given binary key. If the key or value are too large for the cache then
// the cache remains unchanged. This includes the case where a different
@@ -54,7 +74,7 @@
// 0 < keySize
// value != NULL
// 0 < valueSize
- void set(const void* key, size_t keySize, const void* value, size_t valueSize);
+ InsertResult set(const void* key, size_t keySize, const void* value, size_t valueSize);
// get retrieves from the cache the binary value associated with a given
// binary key. If the key is present in the cache then the length of the
diff --git a/opengl/libs/EGL/BlobCache_test.cpp b/opengl/libs/EGL/BlobCache_test.cpp
index d31373b..ceea0fb 100644
--- a/opengl/libs/EGL/BlobCache_test.cpp
+++ b/opengl/libs/EGL/BlobCache_test.cpp
@@ -49,7 +49,7 @@
TEST_F(BlobCacheTest, CacheSingleValueSucceeds) {
unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
- mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "efgh", 4));
ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
ASSERT_EQ('e', buf[0]);
ASSERT_EQ('f', buf[1]);
@@ -59,8 +59,8 @@
TEST_F(BlobCacheTest, CacheTwoValuesSucceeds) {
unsigned char buf[2] = {0xee, 0xee};
- mBC->set("ab", 2, "cd", 2);
- mBC->set("ef", 2, "gh", 2);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("ab", 2, "cd", 2));
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("ef", 2, "gh", 2));
ASSERT_EQ(size_t(2), mBC->get("ab", 2, buf, 2));
ASSERT_EQ('c', buf[0]);
ASSERT_EQ('d', buf[1]);
@@ -71,7 +71,7 @@
TEST_F(BlobCacheTest, GetOnlyWritesInsideBounds) {
unsigned char buf[6] = {0xee, 0xee, 0xee, 0xee, 0xee, 0xee};
- mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "efgh", 4));
ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf + 1, 4));
ASSERT_EQ(0xee, buf[0]);
ASSERT_EQ('e', buf[1]);
@@ -83,7 +83,7 @@
TEST_F(BlobCacheTest, GetOnlyWritesIfBufferIsLargeEnough) {
unsigned char buf[3] = {0xee, 0xee, 0xee};
- mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "efgh", 4));
ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 3));
ASSERT_EQ(0xee, buf[0]);
ASSERT_EQ(0xee, buf[1]);
@@ -91,14 +91,14 @@
}
TEST_F(BlobCacheTest, GetDoesntAccessNullBuffer) {
- mBC->set("abcd", 4, "efgh", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "efgh", 4));
ASSERT_EQ(size_t(4), mBC->get("abcd", 4, nullptr, 0));
}
TEST_F(BlobCacheTest, MultipleSetsCacheLatestValue) {
unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee};
- mBC->set("abcd", 4, "efgh", 4);
- mBC->set("abcd", 4, "ijkl", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "efgh", 4));
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "ijkl", 4));
ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
ASSERT_EQ('i', buf[0]);
ASSERT_EQ('j', buf[1]);
@@ -108,8 +108,8 @@
TEST_F(BlobCacheTest, SecondSetKeepsFirstValueIfTooLarge) {
unsigned char buf[MAX_VALUE_SIZE + 1] = {0xee, 0xee, 0xee, 0xee};
- mBC->set("abcd", 4, "efgh", 4);
- mBC->set("abcd", 4, buf, MAX_VALUE_SIZE + 1);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, "efgh", 4));
+ ASSERT_EQ(BlobCache::InsertResult::kValueTooBig, mBC->set("abcd", 4, buf, MAX_VALUE_SIZE + 1));
ASSERT_EQ(size_t(4), mBC->get("abcd", 4, buf, 4));
ASSERT_EQ('e', buf[0]);
ASSERT_EQ('f', buf[1]);
@@ -123,7 +123,7 @@
for (int i = 0; i < MAX_KEY_SIZE + 1; i++) {
key[i] = 'a';
}
- mBC->set(key, MAX_KEY_SIZE + 1, "bbbb", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kKeyTooBig, mBC->set(key, MAX_KEY_SIZE + 1, "bbbb", 4));
ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE + 1, buf, 4));
ASSERT_EQ(0xee, buf[0]);
ASSERT_EQ(0xee, buf[1]);
@@ -136,7 +136,7 @@
for (int i = 0; i < MAX_VALUE_SIZE + 1; i++) {
buf[i] = 'b';
}
- mBC->set("abcd", 4, buf, MAX_VALUE_SIZE + 1);
+ ASSERT_EQ(BlobCache::InsertResult::kValueTooBig, mBC->set("abcd", 4, buf, MAX_VALUE_SIZE + 1));
for (int i = 0; i < MAX_VALUE_SIZE + 1; i++) {
buf[i] = 0xee;
}
@@ -163,7 +163,8 @@
buf[i] = 'b';
}
- mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE);
+ ASSERT_EQ(BlobCache::InsertResult::kCombinedTooBig,
+ mBC->set(key, MAX_KEY_SIZE, buf, MAX_VALUE_SIZE));
ASSERT_EQ(size_t(0), mBC->get(key, MAX_KEY_SIZE, nullptr, 0));
}
@@ -173,7 +174,7 @@
for (int i = 0; i < MAX_KEY_SIZE; i++) {
key[i] = 'a';
}
- mBC->set(key, MAX_KEY_SIZE, "wxyz", 4);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set(key, MAX_KEY_SIZE, "wxyz", 4));
ASSERT_EQ(size_t(4), mBC->get(key, MAX_KEY_SIZE, buf, 4));
ASSERT_EQ('w', buf[0]);
ASSERT_EQ('x', buf[1]);
@@ -186,7 +187,7 @@
for (int i = 0; i < MAX_VALUE_SIZE; i++) {
buf[i] = 'b';
}
- mBC->set("abcd", 4, buf, MAX_VALUE_SIZE);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("abcd", 4, buf, MAX_VALUE_SIZE));
for (int i = 0; i < MAX_VALUE_SIZE; i++) {
buf[i] = 0xee;
}
@@ -212,13 +213,45 @@
buf[i] = 'b';
}
- mBC->set(key, MAX_KEY_SIZE, buf, bufSize);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set(key, MAX_KEY_SIZE, buf, bufSize));
ASSERT_EQ(size_t(bufSize), mBC->get(key, MAX_KEY_SIZE, nullptr, 0));
}
+// Verify that kNotEnoughSpace is returned from BlobCache::set when expected.
+// Note: This relies on internal knowledge of how BlobCache works.
+TEST_F(BlobCacheTest, NotEnoughSpace) {
+ // Insert a small entry into the cache.
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("x", 1, "y", 1));
+
+ // Attempt to put a max size entry into the cache. If the cache were empty,
+ // as in CacheMaxKeyValuePairSizeSucceeds, this would succeed. Based on the
+ // current logic of BlobCache, the small entry is not big enough to allow it
+ // to be cleaned to insert the new entry.
+ ASSERT_TRUE(MAX_KEY_SIZE < MAX_TOTAL_SIZE);
+
+ enum { bufSize = MAX_TOTAL_SIZE - MAX_KEY_SIZE };
+
+ char key[MAX_KEY_SIZE];
+ char buf[bufSize];
+ for (int i = 0; i < MAX_KEY_SIZE; i++) {
+ key[i] = 'a';
+ }
+ for (int i = 0; i < bufSize; i++) {
+ buf[i] = 'b';
+ }
+
+ ASSERT_EQ(BlobCache::InsertResult::kNotEnoughSpace, mBC->set(key, MAX_KEY_SIZE, buf, bufSize));
+ ASSERT_EQ(0, mBC->get(key, MAX_KEY_SIZE, nullptr, 0));
+
+ // The original entry remains in the cache.
+ unsigned char buf2[1] = {0xee};
+ ASSERT_EQ(size_t(1), mBC->get("x", 1, buf2, 1));
+ ASSERT_EQ('y', buf2[0]);
+}
+
TEST_F(BlobCacheTest, CacheMinKeyAndValueSizeSucceeds) {
unsigned char buf[1] = {0xee};
- mBC->set("x", 1, "y", 1);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set("x", 1, "y", 1));
ASSERT_EQ(size_t(1), mBC->get("x", 1, buf, 1));
ASSERT_EQ('y', buf[0]);
}
@@ -243,12 +276,12 @@
const int maxEntries = MAX_TOTAL_SIZE / 2;
for (int i = 0; i < maxEntries; i++) {
uint8_t k = i;
- mBC->set(&k, 1, "x", 1);
+ ASSERT_EQ(BlobCache::InsertResult::kInserted, mBC->set(&k, 1, "x", 1));
}
// Insert one more entry, causing a cache overflow.
{
uint8_t k = maxEntries;
- mBC->set(&k, 1, "x", 1);
+ ASSERT_EQ(BlobCache::InsertResult::kDidClean, mBC->set(&k, 1, "x", 1));
}
// Count the number of entries in the cache.
int numCached = 0;
@@ -261,6 +294,14 @@
ASSERT_EQ(maxEntries / 2 + 1, numCached);
}
+TEST_F(BlobCacheTest, InvalidKeySize) {
+ ASSERT_EQ(BlobCache::InsertResult::kInvalidKeySize, mBC->set("", 0, "efgh", 4));
+}
+
+TEST_F(BlobCacheTest, InvalidValueSize) {
+ ASSERT_EQ(BlobCache::InsertResult::kInvalidValueSize, mBC->set("abcd", 4, "", 0));
+}
+
class BlobCacheFlattenTest : public BlobCacheTest {
protected:
virtual void SetUp() {
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 14f9a12..94de55c 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -74,23 +74,6 @@
}
}
-void BatteryService::cleanupImpl(uid_t uid) {
- if (checkService()) {
- Mutex::Autolock _l(mActivationsLock);
- int64_t identity = IPCThreadState::self()->clearCallingIdentity();
- for (size_t i=0 ; i<mActivations.size() ; ) {
- const Info& info(mActivations[i]);
- if (info.uid == uid) {
- mBatteryStatService->noteStopSensor(info.uid, info.handle);
- mActivations.removeAt(i);
- } else {
- i++;
- }
- }
- IPCThreadState::self()->restoreCallingIdentity(identity);
- }
-}
-
bool BatteryService::checkService() {
if (mBatteryStatService == nullptr) {
const sp<IServiceManager> sm(defaultServiceManager());
diff --git a/services/sensorservice/BatteryService.h b/services/sensorservice/BatteryService.h
index 09eb2c1..13fc58a 100644
--- a/services/sensorservice/BatteryService.h
+++ b/services/sensorservice/BatteryService.h
@@ -32,7 +32,6 @@
void enableSensorImpl(uid_t uid, int handle);
void disableSensorImpl(uid_t uid, int handle);
- void cleanupImpl(uid_t uid);
struct Info {
uid_t uid;
@@ -58,9 +57,6 @@
static void disableSensor(uid_t uid, int handle) {
BatteryService::getInstance().disableSensorImpl(uid, handle);
}
- static void cleanup(uid_t uid) {
- BatteryService::getInstance().cleanupImpl(uid);
- }
};
// ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 53a3025..de050e0 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -612,8 +612,10 @@
return SENSORS_DEVICE_API_VERSION_1_4;
}
-status_t SensorDevice::flush(void* /*ident*/, int handle) {
+status_t SensorDevice::flush(void* ident, int handle) {
if (mHalWrapper == nullptr) return NO_INIT;
+ if (isClientDisabled(ident)) return INVALID_OPERATION;
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
return mHalWrapper->flush(handle);
}
@@ -754,6 +756,13 @@
status_t SensorDevice::injectSensorData(const sensors_event_t* injected_sensor_event) {
if (mHalWrapper == nullptr) return NO_INIT;
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
+ injected_sensor_event->sensor, injected_sensor_event->timestamp,
+ injected_sensor_event->data[0], injected_sensor_event->data[1],
+ injected_sensor_event->data[2], injected_sensor_event->data[3],
+ injected_sensor_event->data[4], injected_sensor_event->data[5]);
+
return mHalWrapper->injectSensorData(injected_sensor_event);
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8b81d48..88cf5ab 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1611,7 +1611,9 @@
} else {
ALOGE("sensor interface of handle=0x%08x is null!", handle);
}
- c->removeSensor(handle);
+ if (c->removeSensor(handle)) {
+ BatteryService::disableSensor(c->getUid(), handle);
+ }
}
SensorRecord* rec = mActiveSensors.valueAt(i);
ALOGE_IF(!rec, "mActiveSensors[%zu] is null (handle=0x%08x)!", i, handle);
@@ -1631,7 +1633,6 @@
}
c->updateLooperRegistration(mLooper);
mConnectionHolder.removeEventConnection(connection);
- BatteryService::cleanup(c->getUid());
if (c->needsWakeLock()) {
checkWakeLockStateLocked(&connLock);
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index d7f5d60..ef6487c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3371,7 +3371,6 @@
static constexpr float kDefaultMaxLuminance = 0.9f;
static constexpr float kDefaultAvgLuminance = 0.7f;
static constexpr float kDefaultMinLuminance = 0.1f;
- static constexpr float kUnknownLuminance = -1.f;
static constexpr float kDisplayLuminance = 400.f;
static constexpr float kClientTargetLuminanceNits = 200.f;
static constexpr float kClientTargetBrightness = 0.5f;
@@ -3769,7 +3768,7 @@
TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposition) {
verify().ifMixedCompositionIs(true)
.andIfUsesHdr(true)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(aidl::android::hardware::graphics::composer3::DimmingStage::LINEAR)
.withRenderIntent(
aidl::android::hardware::graphics::composer3::RenderIntent::COLORIMETRIC)
@@ -3778,7 +3777,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = true,
@@ -3823,7 +3822,7 @@
forHdrMixedCompositionWithDimmingStage) {
verify().ifMixedCompositionIs(true)
.andIfUsesHdr(true)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(
aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF)
.withRenderIntent(
@@ -3833,7 +3832,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = true,
@@ -3851,7 +3850,7 @@
forHdrMixedCompositionWithRenderIntent) {
verify().ifMixedCompositionIs(true)
.andIfUsesHdr(true)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(aidl::android::hardware::graphics::composer3::DimmingStage::LINEAR)
.withRenderIntent(aidl::android::hardware::graphics::composer3::RenderIntent::ENHANCE)
.andIfSkipColorTransform(false)
@@ -3859,7 +3858,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = true,
@@ -3876,7 +3875,7 @@
TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComposition) {
verify().ifMixedCompositionIs(true)
.andIfUsesHdr(false)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(aidl::android::hardware::graphics::composer3::DimmingStage::LINEAR)
.withRenderIntent(
aidl::android::hardware::graphics::composer3::RenderIntent::COLORIMETRIC)
@@ -3885,7 +3884,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = true,
@@ -3902,7 +3901,7 @@
TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientComposition) {
verify().ifMixedCompositionIs(false)
.andIfUsesHdr(true)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(aidl::android::hardware::graphics::composer3::DimmingStage::LINEAR)
.withRenderIntent(
aidl::android::hardware::graphics::composer3::RenderIntent::COLORIMETRIC)
@@ -3911,7 +3910,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = false,
@@ -3928,7 +3927,7 @@
TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrOnlyClientComposition) {
verify().ifMixedCompositionIs(false)
.andIfUsesHdr(false)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(aidl::android::hardware::graphics::composer3::DimmingStage::LINEAR)
.withRenderIntent(
aidl::android::hardware::graphics::composer3::RenderIntent::COLORIMETRIC)
@@ -3937,7 +3936,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = false,
@@ -3955,7 +3954,7 @@
usesExpectedDisplaySettingsForHdrOnlyClientCompositionWithSkipClientTransform) {
verify().ifMixedCompositionIs(false)
.andIfUsesHdr(true)
- .withDisplayBrightnessNits(kUnknownLuminance)
+ .withDisplayBrightnessNits(kDisplayLuminance)
.withDimmingStage(aidl::android::hardware::graphics::composer3::DimmingStage::LINEAR)
.withRenderIntent(
aidl::android::hardware::graphics::composer3::RenderIntent::COLORIMETRIC)
@@ -3964,7 +3963,7 @@
{.physicalDisplay = kDefaultOutputDestinationClip,
.clip = kDefaultOutputViewport,
.maxLuminance = kDefaultMaxLuminance,
- .currentLuminanceNits = kDefaultMaxLuminance,
+ .currentLuminanceNits = kDisplayLuminance,
.outputDataspace = kDefaultOutputDataspace,
.colorTransform = kDefaultColorTransformMat,
.deviceHandlesColorTransform = true,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0cb8e0e..55d41e7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3739,12 +3739,13 @@
auto& transaction = transactionQueue.front();
const auto ready =
- transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
- transaction.isAutoTimestamp,
- transaction.desiredPresentTime,
- transaction.originUid, transaction.states,
- bufferLayersReadyToPresent, transactions.size(),
- tryApplyUnsignaled);
+ transactionIsReadyToBeApplied(transaction,
+ transaction.frameTimelineInfo,
+ transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
+ transaction.originUid, transaction.states,
+ bufferLayersReadyToPresent, transactions.size(),
+ tryApplyUnsignaled);
ATRACE_INT("TransactionReadiness", static_cast<int>(ready));
if (ready == TransactionReadiness::NotReady) {
setTransactionFlags(eTransactionFlushNeeded);
@@ -3821,7 +3822,7 @@
return TransactionReadiness::NotReady;
}
- return transactionIsReadyToBeApplied(transaction.frameTimelineInfo,
+ return transactionIsReadyToBeApplied(transaction, transaction.frameTimelineInfo,
transaction.isAutoTimestamp,
transaction.desiredPresentTime,
transaction.originUid, transaction.states,
@@ -3983,7 +3984,7 @@
return true;
}
-auto SurfaceFlinger::transactionIsReadyToBeApplied(
+auto SurfaceFlinger::transactionIsReadyToBeApplied(TransactionState& transaction,
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
uid_t originUid, const Vector<ComposerState>& states,
const std::unordered_map<
@@ -4012,8 +4013,10 @@
}
bool fenceUnsignaled = false;
+ auto queueProcessTime = systemTime();
for (const ComposerState& state : states) {
const layer_state_t& s = state.state;
+
sp<Layer> layer = nullptr;
if (s.surface) {
layer = fromHandle(s.surface).promote();
@@ -4049,6 +4052,15 @@
s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled);
if (fenceUnsignaled && !allowLatchUnsignaled) {
+ if (!transaction.sentFenceTimeoutWarning &&
+ queueProcessTime - transaction.queueTime > std::chrono::nanoseconds(4s).count()) {
+ transaction.sentFenceTimeoutWarning = true;
+ auto listener = s.bufferData->releaseBufferListener;
+ if (listener) {
+ listener->onTransactionQueueStalled();
+ }
+ }
+
ATRACE_NAME("fence unsignaled");
return TransactionReadiness::NotReady;
}
@@ -4068,6 +4080,8 @@
}
void SurfaceFlinger::queueTransaction(TransactionState& state) {
+ state.queueTime = systemTime();
+
Mutex::Autolock lock(mQueueLock);
// Generate a CountDownLatch pending state if this is a synchronous transaction.
@@ -6807,7 +6821,7 @@
BlurSetting::Disabled
: compositionengine::LayerFE::ClientCompositionTargetSettings::
BlurSetting::Enabled,
- isHdrDataspace(dataspace) ? displayBrightnessNits : sdrWhitePointNits,
+ isHdrLayer(layer) ? displayBrightnessNits : sdrWhitePointNits,
};
std::vector<compositionengine::LayerFE::LayerSettings> results =
@@ -6822,7 +6836,7 @@
if (regionSampling) {
settings.backgroundBlurRadius = 0;
}
- captureResults.capturedHdrLayers |= isHdrDataspace(settings.sourceDataspace);
+ captureResults.capturedHdrLayers |= isHdrLayer(layer);
}
clientCompositionLayers.insert(clientCompositionLayers.end(),
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b6df4f6..ba0a66d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -809,7 +809,7 @@
Ready,
ReadyUnsignaled,
};
- TransactionReadiness transactionIsReadyToBeApplied(
+ TransactionReadiness transactionIsReadyToBeApplied(TransactionState& state,
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
uid_t originUid, const Vector<ComposerState>& states,
const std::unordered_map<
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index bab5326..900d566 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -98,6 +98,8 @@
int originUid;
uint64_t id;
std::shared_ptr<CountDownLatch> transactionCommittedSignal;
+ int64_t queueTime = 0;
+ bool sentFenceTimeoutWarning = false;
};
class CountDownLatch {