Check how long the system has been forced into big image
Bug: 110939839
Test: sanity check CHRE
Change-Id: Ief5a212e673fdc0cb261d24e48fea88656e30e22
diff --git a/platform/slpi/include/chre/platform/slpi/see/island_vote_client.h b/platform/slpi/include/chre/platform/slpi/see/island_vote_client.h
index 283cef8..f112e99 100644
--- a/platform/slpi/include/chre/platform/slpi/see/island_vote_client.h
+++ b/platform/slpi/include/chre/platform/slpi/see/island_vote_client.h
@@ -67,6 +67,10 @@
void decrementBigImageRefCount();
private:
+ //! The maximum allowed duration to be voted into big image by
+ //! incrementBigImageRefCount before a FATAL_ERROR is triggered.
+ static constexpr Seconds kSeeMaxBigImageDuration = Seconds(300);
+
//! Last big image request made through voteBigImage().
bool mLastBigImageRequest = false;
@@ -93,6 +97,16 @@
* @return true if the vote returned success.
*/
bool voteSnsPowerMode(bool bigImage);
+
+ /**
+ * Check how long the system has been voted into big image due to
+ * incrementBigImageRefCount. If longer than kSeeMaxBigImageDuration, trigger
+ * a crash.
+ *
+ * @return the duration in milliseconds since the system has been voted into
+ * big image due to incrementBigImageRefCount.
+ */
+ uint64_t checkBigImageDuration() const;
#endif // CHRE_SLPI_UIMG_ENABLED
};
diff --git a/platform/slpi/see/island_vote_client.cc b/platform/slpi/see/island_vote_client.cc
index 02fe701..e7a81d2 100644
--- a/platform/slpi/see/island_vote_client.cc
+++ b/platform/slpi/see/island_vote_client.cc
@@ -26,6 +26,8 @@
namespace chre {
+constexpr Seconds IslandVoteClient::kSeeMaxBigImageDuration;
+
IslandVoteClient::IslandVoteClient(const char *clientName) {
#ifdef CHRE_SLPI_UIMG_ENABLED
mClientHandle = sns_island_aggregator_register_client(clientName);
@@ -75,6 +77,8 @@
voteSnsPowerMode(true /* bigImage */);
mLastBigImageVote = true;
}
+ } else {
+ checkBigImageDuration();
}
}
@@ -83,10 +87,8 @@
CHRE_ASSERT_LOG(mBigImageRefCount > 0,
"Tried to decrement big image ref count when it's 0");
+ uint64_t duration = checkBigImageDuration();
if (--mBigImageRefCount == 0) {
- uint64_t duration =
- Milliseconds(SystemTime::getMonotonicTime()).getMilliseconds()
- - mRefCountStart.getMilliseconds();
LOGW("Big image ref count ends: %" PRIu64 " ms", duration);
// There's no big image activity now, restore the intended uimg power state.
@@ -110,6 +112,22 @@
}
return success;
}
+
+uint64_t IslandVoteClient::checkBigImageDuration() const {
+ uint64_t duration = 0;
+ if (mBigImageRefCount > 0) {
+ duration = Milliseconds(SystemTime::getMonotonicTime()).getMilliseconds()
+ - mRefCountStart.getMilliseconds();
+ }
+
+ // Bimg memory fallback only intends to handle a surge of uimg memory
+ // requests. If there's a prolonged period of memory fallback, this might
+ // indicate a memory leak or inadequate uimg heap size.
+ if (duration > kSeeMaxBigImageDuration.getMilliseconds()) {
+ FATAL_ERROR("Forced into big image for %" PRIu64 " msec", duration);
+ }
+ return duration;
+}
#endif // CHRE_SLPI_UIMG_ENABLED
//! Explicitly instantiate the IslandVoteClient singleton to reduce code size.
diff --git a/util/include/chre/util/time.h b/util/include/chre/util/time.h
index 9a2c065..0d97231 100644
--- a/util/include/chre/util/time.h
+++ b/util/include/chre/util/time.h
@@ -22,10 +22,10 @@
namespace chre {
//! The number of milliseconds in one min.
-constexpr uint64_t kOneMinuteInMillisecods(60000);
+constexpr uint64_t kOneMinuteInMilliseconds(60000);
//! The number of milliseconds in one second.
-constexpr uint64_t kOneSecondInMillisecods(1000);
+constexpr uint64_t kOneSecondInMilliseconds(1000);
//! The number of nanoseconds in one second.
constexpr uint64_t kOneSecondInNanoseconds(1000000000);
@@ -60,6 +60,13 @@
*/
constexpr uint64_t toRawNanoseconds() const;
+ /**
+ * Obtains the number of Milliseconds stored by this time duration.
+ *
+ * @return the value of milliseconds.
+ */
+ constexpr uint64_t getMilliseconds() const;
+
private:
uint64_t mSeconds;
};
diff --git a/util/include/chre/util/time_impl.h b/util/include/chre/util/time_impl.h
index 9d8adba..7e79cf8 100644
--- a/util/include/chre/util/time_impl.h
+++ b/util/include/chre/util/time_impl.h
@@ -28,10 +28,18 @@
// Perform the simple unit conversion. Warning: overflow is caught and
// handled by returning UINT64_MAX. A ternary expression is used because
// constexpr requires it.
- return mSeconds > (UINT64_MAX / kOneSecondInNanoseconds) ? UINT64_MAX
+ return (mSeconds > (UINT64_MAX / kOneSecondInNanoseconds)) ? UINT64_MAX
: mSeconds * kOneSecondInNanoseconds;
}
+constexpr uint64_t Seconds::getMilliseconds() const {
+ // Perform the simple unit conversion. Warning: overflow is caught and
+ // handled by returning UINT64_MAX. A ternary expression is used because
+ // constexpr requires it.
+ return (mSeconds > (UINT64_MAX / kOneSecondInMilliseconds)) ? UINT64_MAX
+ : mSeconds * kOneSecondInMilliseconds;
+}
+
constexpr Milliseconds::Milliseconds()
: mMilliseconds(0) {}
@@ -51,7 +59,11 @@
}
constexpr uint64_t Milliseconds::getMicroseconds() const {
- return mMilliseconds * kOneMillisecondInMicroseconds;
+ // Perform the simple unit conversion. Warning: overflow is caught and
+ // handled by returning UINT64_MAX. A ternary expression is used because
+ // constexpr requires it.
+ return (mMilliseconds > (UINT64_MAX / kOneMillisecondInMicroseconds))
+ ? UINT64_MAX : mMilliseconds * kOneMillisecondInMicroseconds ;
}
constexpr uint64_t Milliseconds::getMilliseconds() const {
diff --git a/util/tests/time_test.cc b/util/tests/time_test.cc
index 94d1032..96616e4 100644
--- a/util/tests/time_test.cc
+++ b/util/tests/time_test.cc
@@ -22,10 +22,11 @@
using chre::Milliseconds;
using chre::Microseconds;
using chre::Nanoseconds;
+using chre::kOneSecondInMilliseconds;
using chre::kOneSecondInNanoseconds;
+using chre::kOneMillisecondInMicroseconds;
using chre::kOneMillisecondInNanoseconds;
using chre::kOneMicrosecondInNanoseconds;
-using chre::kOneMillisecondInMicroseconds;
// Tests for Time constants
TEST(Time, CheckTimeConversionConstants) {
@@ -46,6 +47,16 @@
EXPECT_EQ(t.toRawNanoseconds(), UINT64_MAX);
}
+TEST(Time, ConvertSecToMillisec) {
+ Seconds t(5);
+ EXPECT_EQ(t.getMilliseconds(), 5 * kOneSecondInMilliseconds);
+}
+
+TEST(Time, ConvertSecToMillisecOverflowIsUint64Max) {
+ Seconds t(UINT64_MAX / kOneSecondInMilliseconds + 1);
+ EXPECT_EQ(t.getMilliseconds(), UINT64_MAX);
+}
+
// Tests for Milliseconds
TEST(Time, DefaultMillisecIsZero) {
Milliseconds t;
@@ -68,6 +79,11 @@
EXPECT_EQ(t.getMicroseconds(), 5 * kOneMillisecondInMicroseconds);
}
+TEST(Time, ConvertMillisecToMicrosecOverflowIsUint64Max) {
+ Milliseconds t(UINT64_MAX / kOneMillisecondInMicroseconds + 1);
+ EXPECT_EQ(t.getMicroseconds(), UINT64_MAX);
+}
+
TEST(Time, ConvertMillisecToNanosec) {
Milliseconds t(5);
EXPECT_EQ(t.toRawNanoseconds(), 5 * kOneMillisecondInNanoseconds);