summaryrefslogtreecommitdiff
path: root/native
diff options
context:
space:
mode:
Diffstat (limited to 'native')
-rw-r--r--native/android/Android.bp1
-rw-r--r--native/android/OWNERS3
-rw-r--r--native/android/input.cpp2
-rw-r--r--native/android/libandroid.map.txt6
-rw-r--r--native/android/performance_hint.cpp162
-rw-r--r--native/android/surface_control.cpp53
-rw-r--r--native/android/system_fonts.cpp40
-rw-r--r--native/android/tests/performance_hint/PerformanceHintNativeTest.cpp59
-rw-r--r--native/graphics/jni/Android.bp2
-rw-r--r--native/graphics/jni/imagedecoder.cpp6
10 files changed, 279 insertions, 55 deletions
diff --git a/native/android/Android.bp b/native/android/Android.bp
index f1b1d79265de..254eb4494ed8 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -95,6 +95,7 @@ cc_library_shared {
"libpowermanager",
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
+ "android.hardware.power-V4-ndk",
"libnativedisplay",
],
diff --git a/native/android/OWNERS b/native/android/OWNERS
index cfe973400c98..d41652f2ad17 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -23,3 +23,6 @@ per-file hardware_buffer_jni.cpp = file:/graphics/java/android/graphics/OWNERS
per-file native_window_jni.cpp = file:/graphics/java/android/graphics/OWNERS
per-file surface_control.cpp = file:/graphics/java/android/graphics/OWNERS
per-file surface_texture.cpp = file:/graphics/java/android/graphics/OWNERS
+
+# Input
+per-file input.cpp = file:/INPUT_OWNERS
diff --git a/native/android/input.cpp b/native/android/input.cpp
index a231d8f153e7..812db0f1c507 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -295,6 +295,8 @@ int32_t AMotionEvent_getClassification(const AInputEvent* motion_event) {
return AMOTION_EVENT_CLASSIFICATION_AMBIGUOUS_GESTURE;
case android::MotionClassification::DEEP_PRESS:
return AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS;
+ case android::MotionClassification::TWO_FINGER_SWIPE:
+ return AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE;
}
}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 4aa5bbf19682..e89c8c9aa583 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -238,6 +238,7 @@ LIBANDROID {
ASurfaceControl_createFromWindow; # introduced=29
ASurfaceControl_acquire; # introduced=31
ASurfaceControl_release; # introduced=29
+ ASurfaceControl_fromJava; # introduced=34
ASurfaceTexture_acquireANativeWindow; # introduced=28
ASurfaceTexture_attachToGLContext; # introduced=28
ASurfaceTexture_detachFromGLContext; # introduced=28
@@ -255,6 +256,7 @@ LIBANDROID {
ASurfaceTransaction_apply; # introduced=29
ASurfaceTransaction_create; # introduced=29
ASurfaceTransaction_delete; # introduced=29
+ ASurfaceTransaction_fromJava; # introduced=34
ASurfaceTransaction_reparent; # introduced=29
ASurfaceTransaction_setBuffer; # introduced=29
ASurfaceTransaction_setBufferAlpha; # introduced=29
@@ -266,6 +268,7 @@ LIBANDROID {
ASurfaceTransaction_setEnableBackPressure; # introduced=31
ASurfaceTransaction_setFrameRate; # introduced=30
ASurfaceTransaction_setFrameRateWithChangeStrategy; # introduced=31
+ ASurfaceTransaction_clearFrameRate; # introduced=34
ASurfaceTransaction_setFrameTimeline; # introduced=Tiramisu
ASurfaceTransaction_setGeometry; # introduced=29
ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29
@@ -327,6 +330,7 @@ LIBANDROID {
APerformanceHint_updateTargetWorkDuration; # introduced=Tiramisu
APerformanceHint_reportActualWorkDuration; # introduced=Tiramisu
APerformanceHint_closeSession; # introduced=Tiramisu
+ APerformanceHint_setThreads; # introduced=UpsideDownCake
local:
*;
};
@@ -334,6 +338,8 @@ LIBANDROID {
LIBANDROID_PLATFORM {
global:
APerformanceHint_setIHintManagerForTesting;
+ APerformanceHint_sendHint;
+ APerformanceHint_getThreadIds;
extern "C++" {
ASurfaceControl_registerSurfaceStatsListener*;
ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index d627984c7fff..dfbd7b55a1f0 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "perf_hint"
+#include <aidl/android/hardware/power/SessionHint.h>
#include <android/os/IHintManager.h>
#include <android/os/IHintSession.h>
#include <android/performance_hint.h>
@@ -25,14 +26,21 @@
#include <performance_hint_private.h>
#include <utils/SystemClock.h>
+#include <chrono>
#include <utility>
#include <vector>
using namespace android;
using namespace android::os;
+using namespace std::chrono_literals;
+
+using AidlSessionHint = aidl::android::hardware::power::SessionHint;
+
struct APerformanceHintSession;
+constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count();
+
struct APerformanceHintManager {
public:
static APerformanceHintManager* getInstance();
@@ -54,24 +62,32 @@ private:
struct APerformanceHintSession {
public:
- APerformanceHintSession(sp<IHintSession> session, int64_t preferredRateNanos,
- int64_t targetDurationNanos);
+ APerformanceHintSession(sp<IHintManager> hintManager, sp<IHintSession> session,
+ int64_t preferredRateNanos, int64_t targetDurationNanos);
APerformanceHintSession() = delete;
~APerformanceHintSession();
int updateTargetWorkDuration(int64_t targetDurationNanos);
int reportActualWorkDuration(int64_t actualDurationNanos);
+ int sendHint(int32_t hint);
+ int setThreads(const int32_t* threadIds, size_t size);
+ int getThreadIds(int32_t* const threadIds, size_t* size);
private:
friend struct APerformanceHintManager;
+ sp<IHintManager> mHintManager;
sp<IHintSession> mHintSession;
// HAL preferred update rate
const int64_t mPreferredRateNanos;
// Target duration for choosing update rate
int64_t mTargetDurationNanos;
- // Last update timestamp
- int64_t mLastUpdateTimestamp;
+ // First target hit timestamp
+ int64_t mFirstTargetMetTimestamp;
+ // Last target hit timestamp
+ int64_t mLastTargetMetTimestamp;
+ // Last hint reported from sendHint indexed by hint value
+ std::vector<int64_t> mLastHintSentTimestamp;
// Cached samples
std::vector<int64_t> mActualDurationsNanos;
std::vector<int64_t> mTimestampsNanos;
@@ -127,7 +143,7 @@ APerformanceHintSession* APerformanceHintManager::createSession(
if (!ret.isOk() || !session) {
return nullptr;
}
- return new APerformanceHintSession(std::move(session), mPreferredRateNanos,
+ return new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos,
initialTargetWorkDurationNanos);
}
@@ -137,13 +153,21 @@ int64_t APerformanceHintManager::getPreferredRateNanos() const {
// ===================================== APerformanceHintSession implementation
-APerformanceHintSession::APerformanceHintSession(sp<IHintSession> session,
+APerformanceHintSession::APerformanceHintSession(sp<IHintManager> hintManager,
+ sp<IHintSession> session,
int64_t preferredRateNanos,
int64_t targetDurationNanos)
- : mHintSession(std::move(session)),
+ : mHintManager(hintManager),
+ mHintSession(std::move(session)),
mPreferredRateNanos(preferredRateNanos),
mTargetDurationNanos(targetDurationNanos),
- mLastUpdateTimestamp(elapsedRealtimeNano()) {}
+ mFirstTargetMetTimestamp(0),
+ mLastTargetMetTimestamp(0) {
+ const std::vector<AidlSessionHint> sessionHintRange{ndk::enum_range<AidlSessionHint>().begin(),
+ ndk::enum_range<AidlSessionHint>().end()};
+
+ mLastHintSentTimestamp = std::vector<int64_t>(sessionHintRange.size(), 0);
+}
APerformanceHintSession::~APerformanceHintSession() {
binder::Status ret = mHintSession->close();
@@ -159,7 +183,7 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano
}
binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
if (!ret.isOk()) {
- ALOGE("%s: HintSessionn updateTargetWorkDuration failed: %s", __FUNCTION__,
+ ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
ret.exceptionMessage().c_str());
return EPIPE;
}
@@ -170,7 +194,8 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano
*/
mActualDurationsNanos.clear();
mTimestampsNanos.clear();
- mLastUpdateTimestamp = elapsedRealtimeNano();
+ mFirstTargetMetTimestamp = 0;
+ mLastTargetMetTimestamp = 0;
return 0;
}
@@ -183,25 +208,101 @@ int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNano
mActualDurationsNanos.push_back(actualDurationNanos);
mTimestampsNanos.push_back(now);
- /**
- * Cache the hint if the hint is not overtime and the mLastUpdateTimestamp is
- * still in the mPreferredRateNanos duration.
- */
- if (actualDurationNanos < mTargetDurationNanos &&
- now - mLastUpdateTimestamp <= mPreferredRateNanos) {
- return 0;
+ if (actualDurationNanos >= mTargetDurationNanos) {
+ // Reset timestamps if we are equal or over the target.
+ mFirstTargetMetTimestamp = 0;
+ } else {
+ // Set mFirstTargetMetTimestamp for first time meeting target.
+ if (!mFirstTargetMetTimestamp || !mLastTargetMetTimestamp ||
+ (now - mLastTargetMetTimestamp > 2 * mPreferredRateNanos)) {
+ mFirstTargetMetTimestamp = now;
+ }
+ /**
+ * Rate limit the change if the update is over mPreferredRateNanos since first
+ * meeting target and less than mPreferredRateNanos since last meeting target.
+ */
+ if (now - mFirstTargetMetTimestamp > mPreferredRateNanos &&
+ now - mLastTargetMetTimestamp <= mPreferredRateNanos) {
+ return 0;
+ }
+ mLastTargetMetTimestamp = now;
}
binder::Status ret =
mHintSession->reportActualWorkDuration(mActualDurationsNanos, mTimestampsNanos);
- mActualDurationsNanos.clear();
- mTimestampsNanos.clear();
if (!ret.isOk()) {
ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
ret.exceptionMessage().c_str());
+ mFirstTargetMetTimestamp = 0;
+ mLastTargetMetTimestamp = 0;
+ return EPIPE;
+ }
+ mActualDurationsNanos.clear();
+ mTimestampsNanos.clear();
+
+ return 0;
+}
+
+int APerformanceHintSession::sendHint(int32_t hint) {
+ if (hint < 0 || hint >= static_cast<int32_t>(mLastHintSentTimestamp.size())) {
+ ALOGE("%s: invalid session hint %d", __FUNCTION__, hint);
+ return EINVAL;
+ }
+ int64_t now = elapsedRealtimeNano();
+
+ // Limit sendHint to a pre-detemined rate for safety
+ if (now < (mLastHintSentTimestamp[hint] + SEND_HINT_TIMEOUT)) {
+ return 0;
+ }
+
+ binder::Status ret = mHintSession->sendHint(hint);
+
+ if (!ret.isOk()) {
+ ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ return EPIPE;
+ }
+ mLastHintSentTimestamp[hint] = now;
+ return 0;
+}
+
+int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t size) {
+ if (size == 0) {
+ ALOGE("%s: the list of thread ids must not be empty.", __FUNCTION__);
+ return EINVAL;
+ }
+ std::vector<int32_t> tids(threadIds, threadIds + size);
+ binder::Status ret = mHintManager->setHintSessionThreads(mHintSession, tids);
+ if (!ret.isOk()) {
+ ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY ||
+ ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) {
+ return EINVAL;
+ }
return EPIPE;
}
- mLastUpdateTimestamp = now;
+ return 0;
+}
+
+int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size) {
+ std::vector<int32_t> tids;
+ binder::Status ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
+ if (!ret.isOk()) {
+ ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ return EPIPE;
+ }
+
+ // When threadIds is nullptr, this is the first call to determine the size
+ // of the thread ids list.
+ if (threadIds == nullptr) {
+ *size = tids.size();
+ return 0;
+ }
+
+ // Second call to return the actual list of thread ids.
+ *size = tids.size();
+ for (size_t i = 0; i < *size; ++i) {
+ threadIds[i] = tids[i];
+ }
return 0;
}
@@ -234,6 +335,27 @@ void APerformanceHint_closeSession(APerformanceHintSession* session) {
delete session;
}
+int APerformanceHint_sendHint(void* session, int32_t hint) {
+ return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint);
+}
+
+int APerformanceHint_setThreads(APerformanceHintSession* session, const int32_t* threadIds,
+ size_t size) {
+ if (session == nullptr) {
+ return EINVAL;
+ }
+ return session->setThreads(threadIds, size);
+}
+
+int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const threadIds,
+ size_t* const size) {
+ if (aPerformanceHintSession == nullptr) {
+ return EINVAL;
+ }
+ return static_cast<APerformanceHintSession*>(aPerformanceHintSession)
+ ->getThreadIds(threadIds, size);
+}
+
void APerformanceHint_setIHintManagerForTesting(void* iManager) {
delete gHintManagerForTesting;
gHintManagerForTesting = nullptr;
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 795af8a58351..ea20c6c9e0b1 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -17,6 +17,8 @@
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/native_window.h>
#include <android/surface_control.h>
+#include <android/surface_control_jni.h>
+#include <android_runtime/android_view_SurfaceControl.h>
#include <configstore/Utils.h>
#include <gui/HdrMetadata.h>
#include <gui/ISurfaceComposer.h>
@@ -28,6 +30,8 @@
#include <ui/DynamicDisplayInfo.h>
#include <utils/Timers.h>
+#include <utility>
+
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using namespace android;
@@ -80,7 +84,7 @@ ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const c
Surface* surface = static_cast<Surface*>(window);
sp<IBinder> parentHandle = surface->getSurfaceControlHandle();
- uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
+ int32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
sp<SurfaceControl> surfaceControl;
if (parentHandle) {
surfaceControl =
@@ -88,11 +92,8 @@ ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const c
// Format is only relevant for buffer queue layers.
PIXEL_FORMAT_UNKNOWN /* format */, flags, parentHandle);
} else {
- surfaceControl =
- client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */,
- // Format is only relevant for buffer queue layers.
- PIXEL_FORMAT_UNKNOWN /* format */, flags,
- static_cast<Surface*>(window));
+ // deprecated, this should no longer be used
+ surfaceControl = nullptr;
}
if (!surfaceControl) {
@@ -137,6 +138,18 @@ void ASurfaceControl_release(ASurfaceControl* aSurfaceControl) {
SurfaceControl_release(surfaceControl);
}
+ASurfaceControl* ASurfaceControl_fromJava(JNIEnv* env, jobject surfaceControlObj) {
+ LOG_ALWAYS_FATAL_IF(!env, "nullptr passed to ASurfaceControl_fromJava as env argument");
+ LOG_ALWAYS_FATAL_IF(!surfaceControlObj,
+ "nullptr passed to ASurfaceControl_fromJava as surfaceControlObj argument");
+ SurfaceControl* surfaceControl =
+ android_view_SurfaceControl_getNativeSurfaceControl(env, surfaceControlObj);
+ LOG_ALWAYS_FATAL_IF(!surfaceControl,
+ "surfaceControlObj passed to ASurfaceControl_fromJava is not valid");
+ SurfaceControl_acquire(surfaceControl);
+ return reinterpret_cast<ASurfaceControl*>(surfaceControl);
+}
+
struct ASurfaceControlStats {
std::variant<int64_t, sp<Fence>> acquireTimeOrFence;
sp<Fence> previousReleaseFence;
@@ -193,6 +206,18 @@ void ASurfaceTransaction_delete(ASurfaceTransaction* aSurfaceTransaction) {
delete transaction;
}
+ASurfaceTransaction* ASurfaceTransaction_fromJava(JNIEnv* env, jobject transactionObj) {
+ LOG_ALWAYS_FATAL_IF(!env, "nullptr passed to ASurfaceTransaction_fromJava as env argument");
+ LOG_ALWAYS_FATAL_IF(!transactionObj,
+ "nullptr passed to ASurfaceTransaction_fromJava as transactionObj "
+ "argument");
+ Transaction* transaction =
+ android_view_SurfaceTransaction_getNativeSurfaceTransaction(env, transactionObj);
+ LOG_ALWAYS_FATAL_IF(!transaction,
+ "surfaceControlObj passed to ASurfaceTransaction_fromJava is not valid");
+ return reinterpret_cast<ASurfaceTransaction*>(transaction);
+}
+
void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) {
CHECK_NOT_NULL(aSurfaceTransaction);
@@ -622,6 +647,16 @@ void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* aSu
transaction->setFrameRate(surfaceControl, frameRate, compatibility, changeFrameRateStrategy);
}
+void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* aSurfaceTransaction,
+ ASurfaceControl* aSurfaceControl) {
+ CHECK_NOT_NULL(aSurfaceTransaction);
+ CHECK_NOT_NULL(aSurfaceControl);
+ Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
+ sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+ transaction->setFrameRate(surfaceControl, 0, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
+ ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+}
+
void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
bool enableBackpressure) {
@@ -669,6 +704,8 @@ void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* aSurfaceTransacti
AVsyncId vsyncId) {
CHECK_NOT_NULL(aSurfaceTransaction);
const auto startTime = AChoreographer_getStartTimeNanosForVsyncId(vsyncId);
- ASurfaceTransaction_to_Transaction(aSurfaceTransaction)
- ->setFrameTimelineInfo({.vsyncId = vsyncId, .startTimeNanos = startTime});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = vsyncId;
+ ftInfo.startTimeNanos = startTime;
+ ASurfaceTransaction_to_Transaction(aSurfaceTransaction)->setFrameTimelineInfo(ftInfo);
}
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 8e90a6572478..fe3132e3d2a3 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -242,31 +242,23 @@ ASystemFontIterator* ASystemFontIterator_open() {
std::unique_ptr<ASystemFontIterator> ite(new ASystemFontIterator());
std::unordered_set<AFont, FontHasher> fonts;
- minikin::SystemFonts::getFontMap(
- [&fonts](const std::vector<std::shared_ptr<minikin::FontCollection>>& collections) {
- for (const auto& fc : collections) {
- for (const auto& family : fc->getFamilies()) {
- for (uint32_t i = 0; i < family->getNumFonts(); ++i) {
- const minikin::Font* font = family->getFont(i);
-
- std::optional<std::string> locale;
- uint32_t localeId = font->getLocaleListId();
- if (localeId != minikin::kEmptyLocaleListId) {
- locale.emplace(minikin::getLocaleString(localeId));
- }
- std::vector<std::pair<uint32_t, float>> axes;
- for (const auto& [tag, value] : font->typeface()->GetAxes()) {
- axes.push_back(std::make_pair(tag, value));
- }
-
- fonts.insert(
- {font->typeface()->GetFontPath(), std::move(locale),
- font->style().weight(),
- font->style().slant() == minikin::FontStyle::Slant::ITALIC,
- static_cast<uint32_t>(font->typeface()->GetFontIndex()),
- axes});
- }
+ minikin::SystemFonts::getFontSet(
+ [&fonts](const std::vector<std::shared_ptr<minikin::Font>>& fontSet) {
+ for (const auto& font : fontSet) {
+ std::optional<std::string> locale;
+ uint32_t localeId = font->getLocaleListId();
+ if (localeId != minikin::kEmptyLocaleListId) {
+ locale.emplace(minikin::getLocaleString(localeId));
}
+ std::vector<std::pair<uint32_t, float>> axes;
+ for (const auto& [tag, value] : font->typeface()->GetAxes()) {
+ axes.push_back(std::make_pair(tag, value));
+ }
+
+ fonts.insert({font->typeface()->GetFontPath(), std::move(locale),
+ font->style().weight(),
+ font->style().slant() == minikin::FontStyle::Slant::ITALIC,
+ static_cast<uint32_t>(font->typeface()->GetFontIndex()), axes});
}
});
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index b17850e5d1e4..321a7dddb144 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -37,10 +37,15 @@ using namespace testing;
class MockIHintManager : public IHintManager {
public:
MOCK_METHOD(Status, createHintSession,
- (const ::android::sp<::android::IBinder>& token, const ::std::vector<int32_t>& tids,
- int64_t durationNanos, ::android::sp<::android::os::IHintSession>* _aidl_return),
+ (const sp<IBinder>& token, const ::std::vector<int32_t>& tids,
+ int64_t durationNanos, ::android::sp<IHintSession>* _aidl_return),
(override));
MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
+ MOCK_METHOD(Status, setHintSessionThreads,
+ (const sp<IHintSession>& hintSession, const ::std::vector<int32_t>& tids),
+ (override));
+ MOCK_METHOD(Status, getHintSessionThreadIds,
+ (const sp<IHintSession>& hintSession, ::std::vector<int32_t>* tids), (override));
MOCK_METHOD(IBinder*, onAsBinder, (), (override));
};
@@ -51,6 +56,7 @@ public:
(const ::std::vector<int64_t>& actualDurationNanos,
const ::std::vector<int64_t>& timeStampNanos),
(override));
+ MOCK_METHOD(Status, sendHint, (int32_t hints), (override));
MOCK_METHOD(Status, close, (), (override));
MOCK_METHOD(IBinder*, onAsBinder, (), (override));
};
@@ -121,6 +127,55 @@ TEST_F(PerformanceHintTest, TestSession) {
result = APerformanceHint_reportActualWorkDuration(session, -1L);
EXPECT_EQ(EINVAL, result);
+ int hintId = 2;
+ EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+ result = APerformanceHint_sendHint(session, hintId);
+ EXPECT_EQ(0, result);
+ usleep(110000); // Sleep for longer than the update timeout.
+ EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+ result = APerformanceHint_sendHint(session, hintId);
+ EXPECT_EQ(0, result);
+ // Expect to get rate limited if we try to send faster than the limiter allows
+ EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(0));
+ result = APerformanceHint_sendHint(session, hintId);
+ EXPECT_EQ(0, result);
+
+ result = APerformanceHint_sendHint(session, -1);
+ EXPECT_EQ(EINVAL, result);
+
EXPECT_CALL(*iSession, close()).Times(Exactly(1));
APerformanceHint_closeSession(session);
}
+
+TEST_F(PerformanceHintTest, SetThreads) {
+ APerformanceHintManager* manager = createManager();
+
+ std::vector<int32_t> tids;
+ tids.push_back(1);
+ tids.push_back(2);
+ int64_t targetDuration = 56789L;
+
+ StrictMock<MockIHintSession>* iSession = new StrictMock<MockIHintSession>();
+ sp<IHintSession> session_sp(iSession);
+
+ EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
+
+ APerformanceHintSession* session =
+ APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ ASSERT_TRUE(session);
+
+ std::vector<int32_t> emptyTids;
+ int result = APerformanceHint_setThreads(session, emptyTids.data(), emptyTids.size());
+ EXPECT_EQ(EINVAL, result);
+
+ std::vector<int32_t> newTids;
+ newTids.push_back(1);
+ newTids.push_back(3);
+ EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids)))
+ .Times(Exactly(1))
+ .WillOnce(Return(Status()));
+ result = APerformanceHint_setThreads(session, newTids.data(), newTids.size());
+ EXPECT_EQ(0, result);
+}
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 1709dfd973d6..10c570b30d7a 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -93,7 +93,7 @@ cc_defaults {
],
static_libs: ["libarect"],
fuzz_config: {
- cc: ["scroggo@google.com"],
+ cc: ["dichenzhang@google.com","scroggo@google.com"],
asan_options: [
"detect_odr_violation=1",
],
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index bb25274e3136..cd6ed2391608 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -25,6 +25,12 @@
#include <hwui/ImageDecoder.h>
#include <log/log.h>
#include <SkAndroidCodec.h>
+#include <SkCodec.h>
+#include <SkColorSpace.h>
+#include <SkImageInfo.h>
+#include <SkRect.h>
+#include <SkSize.h>
+#include <SkStream.h>
#include <utils/Color.h>
#include <fcntl.h>