summaryrefslogtreecommitdiff
path: root/native
diff options
context:
space:
mode:
Diffstat (limited to 'native')
-rw-r--r--native/android/Android.bp5
-rw-r--r--native/android/OWNERS2
-rw-r--r--native/android/input.cpp4
-rw-r--r--native/android/input_transfer_token.cpp63
-rw-r--r--native/android/libandroid.map.txt12
-rw-r--r--native/android/performance_hint.cpp236
-rw-r--r--native/android/surface_control.cpp4
-rw-r--r--native/android/surface_control_input_receiver.cpp217
-rw-r--r--native/android/tests/performance_hint/Android.bp1
-rw-r--r--native/android/tests/performance_hint/PerformanceHintNativeTest.cpp329
-rw-r--r--native/webview/plat_support/draw_fn.h9
-rw-r--r--native/webview/plat_support/draw_functor.cpp21
12 files changed, 606 insertions, 297 deletions
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 7f3792d06795..8945bd1444f0 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -54,10 +54,12 @@ cc_library_shared {
srcs: [
"activity_manager.cpp",
"asset_manager.cpp",
+ "surface_control_input_receiver.cpp",
"choreographer.cpp",
"configuration.cpp",
"hardware_buffer_jni.cpp",
"input.cpp",
+ "input_transfer_token.cpp",
"looper.cpp",
"native_activity.cpp",
"native_window_jni.cpp",
@@ -83,6 +85,7 @@ cc_library_shared {
"libinput",
"libutils",
"libbinder",
+ "libbinder_ndk",
"libui",
"libgui",
"libharfbuzz_ng", // Only for including hb.h via minikin
@@ -98,7 +101,9 @@ cc_library_shared {
"libpowermanager",
"android.hardware.configstore@1.0",
"android.hardware.configstore-utils",
+ "android.os.flags-aconfig-cc",
"libnativedisplay",
+ "libfmq",
],
static_libs: [
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 0b86909929b0..9a3527da9623 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -16,6 +16,8 @@ per-file system_fonts.cpp = file:/graphics/java/android/graphics/fonts/OWNERS
per-file native_window_jni.cpp = file:/services/core/java/com/android/server/wm/OWNERS
per-file native_activity.cpp = file:/services/core/java/com/android/server/wm/OWNERS
per-file surface_control.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+per-file surface_control_input_receiver.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+per-file input_transfer_token.cpp = file:/services/core/java/com/android/server/wm/OWNERS
# Graphics
per-file choreographer.cpp = file:/graphics/java/android/graphics/OWNERS
diff --git a/native/android/input.cpp b/native/android/input.cpp
index 53699bc706ea..0a223142954f 100644
--- a/native/android/input.cpp
+++ b/native/android/input.cpp
@@ -124,11 +124,11 @@ int64_t AMotionEvent_getEventTime(const AInputEvent* motion_event) {
}
float AMotionEvent_getXOffset(const AInputEvent* motion_event) {
- return static_cast<const MotionEvent*>(motion_event)->getXOffset();
+ return static_cast<const MotionEvent*>(motion_event)->getRawXOffset();
}
float AMotionEvent_getYOffset(const AInputEvent* motion_event) {
- return static_cast<const MotionEvent*>(motion_event)->getYOffset();
+ return static_cast<const MotionEvent*>(motion_event)->getRawYOffset();
}
float AMotionEvent_getXPrecision(const AInputEvent* motion_event) {
diff --git a/native/android/input_transfer_token.cpp b/native/android/input_transfer_token.cpp
new file mode 100644
index 000000000000..2e74aa3dbcbe
--- /dev/null
+++ b/native/android/input_transfer_token.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "InputTransferToken"
+
+#include <android/input_transfer_token_jni.h>
+#include <android_runtime/android_window_InputTransferToken.h>
+#include <gui/InputTransferToken.h>
+#include <log/log_main.h>
+
+using namespace android;
+
+#define CHECK_NOT_NULL(name) \
+ LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
+
+extern void InputTransferToken_acquire(InputTransferToken* inputTransferToken) {
+ // incStrong/decStrong token must be the same, doesn't matter what it is
+ inputTransferToken->incStrong((void*)InputTransferToken_acquire);
+}
+
+void InputTransferToken_release(InputTransferToken* inputTransferToken) {
+ // incStrong/decStrong token must be the same, doesn't matter what it is
+ inputTransferToken->decStrong((void*)InputTransferToken_acquire);
+}
+
+AInputTransferToken* AInputTransferToken_fromJava(JNIEnv* env, jobject inputTransferTokenObj) {
+ CHECK_NOT_NULL(env);
+ CHECK_NOT_NULL(inputTransferTokenObj);
+ InputTransferToken* inputTransferToken =
+ android_window_InputTransferToken_getNativeInputTransferToken(env,
+ inputTransferTokenObj);
+ CHECK_NOT_NULL(inputTransferToken);
+ InputTransferToken_acquire(inputTransferToken);
+ return reinterpret_cast<AInputTransferToken*>(inputTransferToken);
+}
+
+jobject AInputTransferToken_toJava(JNIEnv* _Nonnull env,
+ const AInputTransferToken* aInputTransferToken) {
+ CHECK_NOT_NULL(env);
+ CHECK_NOT_NULL(aInputTransferToken);
+ const InputTransferToken* inputTransferToken =
+ reinterpret_cast<const InputTransferToken*>(aInputTransferToken);
+ return android_window_InputTransferToken_getJavaInputTransferToken(env, *inputTransferToken);
+}
+
+void AInputTransferToken_release(AInputTransferToken* aInputTransferToken) {
+ CHECK_NOT_NULL(aInputTransferToken);
+ InputTransferToken* inputTransferToken =
+ reinterpret_cast<InputTransferToken*>(aInputTransferToken);
+ InputTransferToken_release(inputTransferToken);
+}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 35e37b2a6893..346c87daec87 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -98,6 +98,17 @@ LIBANDROID {
AInputQueue_getEvent;
AInputQueue_hasEvents;
AInputQueue_preDispatchEvent;
+ AInputReceiver_createBatchedInputReceiver; # introduced=35
+ AInputReceiver_createUnbatchedInputReceiver; # introduced=35
+ AInputReceiver_release; # introduced=35
+ AInputReceiver_getInputTransferToken; # introduced=35
+ AInputReceiverCallbacks_create; # introduced=35
+ AInputReceiverCallbacks_release; # introduced=35
+ AInputReceiverCallbacks_setKeyEventCallback; # introduced=35
+ AInputReceiverCallbacks_setMotionEventCallback; # introduced=35
+ AInputTransferToken_fromJava; # introduced=35
+ AInputTransferToken_release; # introduced=35
+ AInputTransferToken_toJava; # introduced=35
AKeyEvent_getAction;
AKeyEvent_getDownTime;
AKeyEvent_getEventTime;
@@ -355,6 +366,7 @@ LIBANDROID_PLATFORM {
APerformanceHint_setIHintManagerForTesting;
APerformanceHint_sendHint;
APerformanceHint_getThreadIds;
+ APerformanceHint_createSessionInternal;
extern "C++" {
ASurfaceControl_registerSurfaceStatsListener*;
ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 279f9d682b9f..83056b267365 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -18,15 +18,15 @@
#include <aidl/android/hardware/power/SessionHint.h>
#include <aidl/android/hardware/power/SessionMode.h>
+#include <aidl/android/hardware/power/SessionTag.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/os/IHintManager.h>
+#include <aidl/android/os/IHintSession.h>
#include <android-base/stringprintf.h>
-#include <android/WorkDuration.h>
-#include <android/os/IHintManager.h>
-#include <android/os/IHintSession.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
#include <android/performance_hint.h>
#include <android/trace.h>
-#include <binder/Binder.h>
-#include <binder/IBinder.h>
-#include <binder/IServiceManager.h>
#include <inttypes.h>
#include <performance_hint_private.h>
#include <utils/SystemClock.h>
@@ -37,41 +37,56 @@
#include <vector>
using namespace android;
-using namespace android::os;
+using namespace aidl::android::os;
using namespace std::chrono_literals;
-using AidlSessionHint = aidl::android::hardware::power::SessionHint;
-using AidlSessionMode = aidl::android::hardware::power::SessionMode;
+// Namespace for AIDL types coming from the PowerHAL
+namespace hal = aidl::android::hardware::power;
+
using android::base::StringPrintf;
struct APerformanceHintSession;
constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count();
+struct AWorkDuration : public hal::WorkDuration {};
struct APerformanceHintManager {
public:
static APerformanceHintManager* getInstance();
- APerformanceHintManager(sp<IHintManager> service, int64_t preferredRateNanos);
+ APerformanceHintManager(std::shared_ptr<IHintManager> service, int64_t preferredRateNanos);
APerformanceHintManager() = delete;
~APerformanceHintManager() = default;
APerformanceHintSession* createSession(const int32_t* threadIds, size_t size,
- int64_t initialTargetWorkDurationNanos);
+ int64_t initialTargetWorkDurationNanos,
+ hal::SessionTag tag = hal::SessionTag::OTHER);
int64_t getPreferredRateNanos() const;
private:
- static APerformanceHintManager* create(sp<IHintManager> iHintManager);
+ // Necessary to create an empty binder object
+ static void* tokenStubOnCreate(void*) {
+ return nullptr;
+ }
+ static void tokenStubOnDestroy(void*) {}
+ static binder_status_t tokenStubOnTransact(AIBinder*, transaction_code_t, const AParcel*,
+ AParcel*) {
+ return STATUS_OK;
+ }
- sp<IHintManager> mHintManager;
- const sp<IBinder> mToken = sp<BBinder>::make();
+ static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);
+
+ std::shared_ptr<IHintManager> mHintManager;
+ ndk::SpAIBinder mToken;
const int64_t mPreferredRateNanos;
};
struct APerformanceHintSession {
public:
- APerformanceHintSession(sp<IHintManager> hintManager, sp<IHintSession> session,
- int64_t preferredRateNanos, int64_t targetDurationNanos);
+ APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
+ std::shared_ptr<IHintSession> session, int64_t preferredRateNanos,
+ int64_t targetDurationNanos,
+ std::optional<hal::SessionConfig> sessionConfig);
APerformanceHintSession() = delete;
~APerformanceHintSession();
@@ -86,10 +101,10 @@ public:
private:
friend struct APerformanceHintManager;
- int reportActualWorkDurationInternal(WorkDuration* workDuration);
+ int reportActualWorkDurationInternal(AWorkDuration* workDuration);
- sp<IHintManager> mHintManager;
- sp<IHintSession> mHintSession;
+ std::shared_ptr<IHintManager> mHintManager;
+ std::shared_ptr<IHintSession> mHintSession;
// HAL preferred update rate
const int64_t mPreferredRateNanos;
// Target duration for choosing update rate
@@ -101,11 +116,12 @@ private:
// Last hint reported from sendHint indexed by hint value
std::vector<int64_t> mLastHintSentTimestamp;
// Cached samples
- std::vector<WorkDuration> mActualWorkDurations;
+ std::vector<hal::WorkDuration> mActualWorkDurations;
std::string mSessionName;
- static int32_t sIDCounter;
+ static int64_t sIDCounter;
// The most recent set of thread IDs
std::vector<int32_t> mLastThreadIDs;
+ std::optional<hal::SessionConfig> mSessionConfig;
// Tracing helpers
void traceThreads(std::vector<int32_t>& tids);
void tracePowerEfficient(bool powerEfficient);
@@ -114,19 +130,25 @@ private:
void traceTargetDuration(int64_t targetDuration);
};
-static IHintManager* gIHintManagerForTesting = nullptr;
+static std::shared_ptr<IHintManager>* gIHintManagerForTesting = nullptr;
static APerformanceHintManager* gHintManagerForTesting = nullptr;
-int32_t APerformanceHintSession::sIDCounter = 0;
+// Start above the int32 range so we don't collide with config sessions
+int64_t APerformanceHintSession::sIDCounter = INT32_MAX;
// ===================================== APerformanceHintManager implementation
-APerformanceHintManager::APerformanceHintManager(sp<IHintManager> manager,
+APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager> manager,
int64_t preferredRateNanos)
- : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {}
+ : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) {
+ static AIBinder_Class* tokenBinderClass =
+ AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy,
+ tokenStubOnTransact);
+ mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr));
+}
APerformanceHintManager* APerformanceHintManager::getInstance() {
if (gHintManagerForTesting) return gHintManagerForTesting;
if (gIHintManagerForTesting) {
- APerformanceHintManager* manager = create(gIHintManagerForTesting);
+ APerformanceHintManager* manager = create(*gIHintManagerForTesting);
gIHintManagerForTesting = nullptr;
return manager;
}
@@ -134,20 +156,19 @@ APerformanceHintManager* APerformanceHintManager::getInstance() {
return instance;
}
-APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manager) {
+APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintManager> manager) {
if (!manager) {
- manager = interface_cast<IHintManager>(
- defaultServiceManager()->checkService(String16("performance_hint")));
+ manager = IHintManager::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService("performance_hint")));
}
if (manager == nullptr) {
ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__);
return nullptr;
}
int64_t preferredRateNanos = -1L;
- binder::Status ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
+ ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos);
if (!ret.isOk()) {
- ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__, ret.getMessage());
return nullptr;
}
if (preferredRateNanos <= 0) {
@@ -157,16 +178,20 @@ APerformanceHintManager* APerformanceHintManager::create(sp<IHintManager> manage
}
APerformanceHintSession* APerformanceHintManager::createSession(
- const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) {
+ const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos,
+ hal::SessionTag tag) {
std::vector<int32_t> tids(threadIds, threadIds + size);
- sp<IHintSession> session;
- binder::Status ret =
- mHintManager->createHintSession(mToken, tids, initialTargetWorkDurationNanos, &session);
+ std::shared_ptr<IHintSession> session;
+ ndk::ScopedAStatus ret;
+ std::optional<hal::SessionConfig> sessionConfig;
+ ret = mHintManager->createHintSessionWithConfig(mToken, tids, initialTargetWorkDurationNanos,
+ tag, &sessionConfig, &session);
+
if (!ret.isOk() || !session) {
return nullptr;
}
auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos,
- initialTargetWorkDurationNanos);
+ initialTargetWorkDurationNanos, sessionConfig);
out->traceThreads(tids);
out->traceTargetDuration(initialTargetWorkDurationNanos);
out->tracePowerEfficient(false);
@@ -179,27 +204,32 @@ int64_t APerformanceHintManager::getPreferredRateNanos() const {
// ===================================== APerformanceHintSession implementation
-APerformanceHintSession::APerformanceHintSession(sp<IHintManager> hintManager,
- sp<IHintSession> session,
+APerformanceHintSession::APerformanceHintSession(std::shared_ptr<IHintManager> hintManager,
+ std::shared_ptr<IHintSession> session,
int64_t preferredRateNanos,
- int64_t targetDurationNanos)
+ int64_t targetDurationNanos,
+ std::optional<hal::SessionConfig> sessionConfig)
: mHintManager(hintManager),
mHintSession(std::move(session)),
mPreferredRateNanos(preferredRateNanos),
mTargetDurationNanos(targetDurationNanos),
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);
- mSessionName = android::base::StringPrintf("ADPF Session %" PRId32, ++sIDCounter);
+ mLastTargetMetTimestamp(0),
+ mSessionConfig(sessionConfig) {
+ if (sessionConfig->id > INT32_MAX) {
+ ALOGE("Session ID too large, must fit 32-bit integer");
+ }
+ constexpr int numEnums =
+ ndk::enum_range<hal::SessionHint>().end() - ndk::enum_range<hal::SessionHint>().begin();
+ mLastHintSentTimestamp = std::vector<int64_t>(numEnums, 0);
+ int64_t traceId = sessionConfig.has_value() ? sessionConfig->id : ++sIDCounter;
+ mSessionName = android::base::StringPrintf("ADPF Session %" PRId64, traceId);
}
APerformanceHintSession::~APerformanceHintSession() {
- binder::Status ret = mHintSession->close();
+ ndk::ScopedAStatus ret = mHintSession->close();
if (!ret.isOk()) {
- ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ ALOGE("%s: HintSession close failed: %s", __FUNCTION__, ret.getMessage());
}
}
@@ -208,10 +238,10 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano
ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
return EINVAL;
}
- binder::Status ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
+ ndk::ScopedAStatus ret = mHintSession->updateTargetWorkDuration(targetDurationNanos);
if (!ret.isOk()) {
ALOGE("%s: HintSession updateTargetWorkDuration failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ret.getMessage());
return EPIPE;
}
mTargetDurationNanos = targetDurationNanos;
@@ -228,9 +258,12 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano
}
int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) {
- WorkDuration workDuration(0, actualDurationNanos, actualDurationNanos, 0);
+ hal::WorkDuration workDuration{.durationNanos = actualDurationNanos,
+ .workPeriodStartTimestampNanos = 0,
+ .cpuDurationNanos = actualDurationNanos,
+ .gpuDurationNanos = 0};
- return reportActualWorkDurationInternal(&workDuration);
+ return reportActualWorkDurationInternal(static_cast<AWorkDuration*>(&workDuration));
}
int APerformanceHintSession::sendHint(SessionHint hint) {
@@ -238,17 +271,17 @@ int APerformanceHintSession::sendHint(SessionHint hint) {
ALOGE("%s: invalid session hint %d", __FUNCTION__, hint);
return EINVAL;
}
- int64_t now = elapsedRealtimeNano();
+ int64_t now = uptimeNanos();
// Limit sendHint to a pre-detemined rate for safety
if (now < (mLastHintSentTimestamp[hint] + SEND_HINT_TIMEOUT)) {
return 0;
}
- binder::Status ret = mHintSession->sendHint(hint);
+ ndk::ScopedAStatus ret = mHintSession->sendHint(hint);
if (!ret.isOk()) {
- ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ ALOGE("%s: HintSession sendHint failed: %s", __FUNCTION__, ret.getMessage());
return EPIPE;
}
mLastHintSentTimestamp[hint] = now;
@@ -261,12 +294,12 @@ int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t size) {
return EINVAL;
}
std::vector<int32_t> tids(threadIds, threadIds + size);
- binder::Status ret = mHintManager->setHintSessionThreads(mHintSession, tids);
+ ndk::ScopedAStatus ret = mHintManager->setHintSessionThreads(mHintSession, tids);
if (!ret.isOk()) {
- ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
- if (ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) {
+ ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
+ if (ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT) {
return EINVAL;
- } else if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY) {
+ } else if (ret.getExceptionCode() == EX_SECURITY) {
return EPERM;
}
return EPIPE;
@@ -279,9 +312,9 @@ int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t size) {
int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size) {
std::vector<int32_t> tids;
- binder::Status ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
+ ndk::ScopedAStatus ret = mHintManager->getHintSessionThreadIds(mHintSession, &tids);
if (!ret.isOk()) {
- ALOGE("%s: failed: %s", __FUNCTION__, ret.exceptionMessage().c_str());
+ ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
return EPIPE;
}
@@ -301,28 +334,28 @@ int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size
}
int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) {
- binder::Status ret =
- mHintSession->setMode(static_cast<int32_t>(AidlSessionMode::POWER_EFFICIENCY), enabled);
+ ndk::ScopedAStatus ret =
+ mHintSession->setMode(static_cast<int32_t>(hal::SessionMode::POWER_EFFICIENCY),
+ enabled);
if (!ret.isOk()) {
ALOGE("%s: HintSession setPreferPowerEfficiency failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ret.getMessage());
return EPIPE;
}
tracePowerEfficient(enabled);
return OK;
}
-int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* aWorkDuration) {
- WorkDuration* workDuration = static_cast<WorkDuration*>(aWorkDuration);
+int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* workDuration) {
return reportActualWorkDurationInternal(workDuration);
}
-int APerformanceHintSession::reportActualWorkDurationInternal(WorkDuration* workDuration) {
- int64_t actualTotalDurationNanos = workDuration->actualTotalDurationNanos;
+int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* workDuration) {
+ int64_t actualTotalDurationNanos = workDuration->durationNanos;
int64_t now = uptimeNanos();
- workDuration->timestampNanos = now;
- traceActualDuration(workDuration->actualTotalDurationNanos);
+ workDuration->timeStampNanos = now;
+ traceActualDuration(workDuration->durationNanos);
mActualWorkDurations.push_back(std::move(*workDuration));
if (actualTotalDurationNanos >= mTargetDurationNanos) {
@@ -346,14 +379,14 @@ int APerformanceHintSession::reportActualWorkDurationInternal(WorkDuration* work
mLastTargetMetTimestamp = now;
}
- binder::Status ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
+ ndk::ScopedAStatus ret = mHintSession->reportActualWorkDuration2(mActualWorkDurations);
if (!ret.isOk()) {
ALOGE("%s: HintSession reportActualWorkDuration failed: %s", __FUNCTION__,
- ret.exceptionMessage().c_str());
+ ret.getMessage());
mFirstTargetMetTimestamp = 0;
mLastTargetMetTimestamp = 0;
traceBatchSize(mActualWorkDurations.size());
- return ret.exceptionCode() == binder::Status::EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
+ return ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT ? EINVAL : EPIPE;
}
mActualWorkDurations.clear();
traceBatchSize(0);
@@ -430,6 +463,15 @@ APerformanceHintSession* APerformanceHint_createSession(APerformanceHintManager*
return manager->createSession(threadIds, size, initialTargetWorkDurationNanos);
}
+APerformanceHintSession* APerformanceHint_createSessionInternal(
+ APerformanceHintManager* manager, const int32_t* threadIds, size_t size,
+ int64_t initialTargetWorkDurationNanos, SessionTag tag) {
+ VALIDATE_PTR(manager)
+ VALIDATE_PTR(threadIds)
+ return manager->createSession(threadIds, size, initialTargetWorkDurationNanos,
+ static_cast<hal::SessionTag>(tag));
+}
+
int64_t APerformanceHint_getPreferredUpdateRateNanos(APerformanceHintManager* manager) {
VALIDATE_PTR(manager)
return manager->getPreferredRateNanos();
@@ -453,9 +495,9 @@ void APerformanceHint_closeSession(APerformanceHintSession* session) {
delete session;
}
-int APerformanceHint_sendHint(void* session, SessionHint hint) {
+int APerformanceHint_sendHint(APerformanceHintSession* session, SessionHint hint) {
VALIDATE_PTR(session)
- return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint);
+ return session->sendHint(hint);
}
int APerformanceHint_setThreads(APerformanceHintSession* session, const pid_t* threadIds,
@@ -465,11 +507,10 @@ int APerformanceHint_setThreads(APerformanceHintSession* session, const pid_t* t
return session->setThreads(threadIds, size);
}
-int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const threadIds,
+int APerformanceHint_getThreadIds(APerformanceHintSession* session, int32_t* const threadIds,
size_t* const size) {
- VALIDATE_PTR(aPerformanceHintSession)
- return static_cast<APerformanceHintSession*>(aPerformanceHintSession)
- ->getThreadIds(threadIds, size);
+ VALIDATE_PTR(session)
+ return session->getThreadIds(threadIds, size);
}
int APerformanceHint_setPreferPowerEfficiency(APerformanceHintSession* session, bool enabled) {
@@ -481,18 +522,16 @@ int APerformanceHint_reportActualWorkDuration2(APerformanceHintSession* session,
AWorkDuration* workDurationPtr) {
VALIDATE_PTR(session)
VALIDATE_PTR(workDurationPtr)
- WorkDuration& workDuration = *static_cast<WorkDuration*>(workDurationPtr);
- VALIDATE_INT(workDuration.workPeriodStartTimestampNanos, > 0)
- VALIDATE_INT(workDuration.actualTotalDurationNanos, > 0)
- VALIDATE_INT(workDuration.actualCpuDurationNanos, >= 0)
- VALIDATE_INT(workDuration.actualGpuDurationNanos, >= 0)
- VALIDATE_INT(workDuration.actualGpuDurationNanos + workDuration.actualCpuDurationNanos, > 0)
+ VALIDATE_INT(workDurationPtr->durationNanos, > 0)
+ VALIDATE_INT(workDurationPtr->workPeriodStartTimestampNanos, > 0)
+ VALIDATE_INT(workDurationPtr->cpuDurationNanos, >= 0)
+ VALIDATE_INT(workDurationPtr->gpuDurationNanos, >= 0)
+ VALIDATE_INT(workDurationPtr->gpuDurationNanos + workDurationPtr->cpuDurationNanos, > 0)
return session->reportActualWorkDuration(workDurationPtr);
}
AWorkDuration* AWorkDuration_create() {
- WorkDuration* workDuration = new WorkDuration();
- return static_cast<AWorkDuration*>(workDuration);
+ return new AWorkDuration();
}
void AWorkDuration_release(AWorkDuration* aWorkDuration) {
@@ -500,37 +539,36 @@ void AWorkDuration_release(AWorkDuration* aWorkDuration) {
delete aWorkDuration;
}
-void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
- int64_t workPeriodStartTimestampNanos) {
- VALIDATE_PTR(aWorkDuration)
- WARN_INT(workPeriodStartTimestampNanos, > 0)
- static_cast<WorkDuration*>(aWorkDuration)->workPeriodStartTimestampNanos =
- workPeriodStartTimestampNanos;
-}
-
void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* aWorkDuration,
int64_t actualTotalDurationNanos) {
VALIDATE_PTR(aWorkDuration)
WARN_INT(actualTotalDurationNanos, > 0)
- static_cast<WorkDuration*>(aWorkDuration)->actualTotalDurationNanos = actualTotalDurationNanos;
+ aWorkDuration->durationNanos = actualTotalDurationNanos;
+}
+
+void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration,
+ int64_t workPeriodStartTimestampNanos) {
+ VALIDATE_PTR(aWorkDuration)
+ WARN_INT(workPeriodStartTimestampNanos, > 0)
+ aWorkDuration->workPeriodStartTimestampNanos = workPeriodStartTimestampNanos;
}
void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* aWorkDuration,
int64_t actualCpuDurationNanos) {
VALIDATE_PTR(aWorkDuration)
WARN_INT(actualCpuDurationNanos, >= 0)
- static_cast<WorkDuration*>(aWorkDuration)->actualCpuDurationNanos = actualCpuDurationNanos;
+ aWorkDuration->cpuDurationNanos = actualCpuDurationNanos;
}
void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* aWorkDuration,
int64_t actualGpuDurationNanos) {
VALIDATE_PTR(aWorkDuration)
WARN_INT(actualGpuDurationNanos, >= 0)
- static_cast<WorkDuration*>(aWorkDuration)->actualGpuDurationNanos = actualGpuDurationNanos;
+ aWorkDuration->gpuDurationNanos = actualGpuDurationNanos;
}
void APerformanceHint_setIHintManagerForTesting(void* iManager) {
delete gHintManagerForTesting;
gHintManagerForTesting = nullptr;
- gIHintManagerForTesting = static_cast<IHintManager*>(iManager);
+ gIHintManagerForTesting = static_cast<std::shared_ptr<IHintManager>*>(iManager);
}
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 9b1330fc048a..6ce83cd7b765 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -367,7 +367,7 @@ void ASurfaceTransaction_reparent(ASurfaceTransaction* aSurfaceTransaction,
void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
- int8_t visibility) {
+ ASurfaceTransactionVisibility visibility) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
@@ -496,7 +496,7 @@ void ASurfaceTransaction_setScale(ASurfaceTransaction* aSurfaceTransaction,
void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
- int8_t transparency) {
+ ASurfaceTransactionTransparency transparency) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
diff --git a/native/android/surface_control_input_receiver.cpp b/native/android/surface_control_input_receiver.cpp
new file mode 100644
index 000000000000..a84ec7309a62
--- /dev/null
+++ b/native/android/surface_control_input_receiver.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/choreographer.h>
+#include <android/surface_control_input_receiver.h>
+#include <binder/Binder.h>
+#include <gui/Choreographer.h>
+#include <gui/InputTransferToken.h>
+#include <input/Input.h>
+#include <input/InputConsumerNoResampling.h>
+
+#include "android_view_WindowManagerGlobal.h"
+
+using namespace android;
+
+extern void InputTransferToken_acquire(InputTransferToken* inputTransferToken);
+
+struct AInputReceiverCallbacks {
+ AInputReceiverCallbacks(void* context) : context(context) {}
+ void* context;
+ AInputReceiver_onMotionEvent onMotionEvent = nullptr;
+ AInputReceiver_onKeyEvent onKeyEvent = nullptr;
+};
+
+class InputReceiver : public InputConsumerCallbacks {
+public:
+ InputReceiver(const sp<Looper>& looper, const std::shared_ptr<InputChannel>& inputChannel,
+ const sp<IBinder>& clientToken, const sp<InputTransferToken>& inputTransferToken,
+ AInputReceiverCallbacks* callbacks)
+ : mCallbacks(callbacks),
+ mInputConsumer(inputChannel, looper, *this),
+ mClientToken(clientToken),
+ mInputTransferToken(inputTransferToken) {}
+
+ // The InputConsumer does not keep the InputReceiver alive so the receiver is cleared once the
+ // owner releases it.
+ ~InputReceiver() {
+ remove();
+ }
+
+ void onKeyEvent(std::unique_ptr<KeyEvent> event, uint32_t seq) override {
+ if (mCallbacks->onKeyEvent != nullptr) {
+ const bool handled = mCallbacks->onKeyEvent(mCallbacks->context,
+ static_cast<AInputEvent*>(event.release()));
+ mInputConsumer.finishInputEvent(seq, handled);
+ }
+ }
+
+ void onMotionEvent(std::unique_ptr<MotionEvent> event, uint32_t seq) override {
+ if (mCallbacks->onMotionEvent != nullptr) {
+ const bool handled =
+ mCallbacks->onMotionEvent(mCallbacks->context,
+ static_cast<AInputEvent*>(event.release()));
+ mInputConsumer.finishInputEvent(seq, handled);
+ }
+ }
+
+ void onFocusEvent(std::unique_ptr<FocusEvent>, uint32_t seq) override {
+ mInputConsumer.finishInputEvent(seq, false);
+ }
+ void onCaptureEvent(std::unique_ptr<CaptureEvent>, uint32_t seq) override {
+ mInputConsumer.finishInputEvent(seq, false);
+ }
+ void onDragEvent(std::unique_ptr<DragEvent>, uint32_t seq) override {
+ mInputConsumer.finishInputEvent(seq, false);
+ }
+ void onTouchModeEvent(std::unique_ptr<TouchModeEvent>, uint32_t seq) override {
+ mInputConsumer.finishInputEvent(seq, false);
+ }
+
+ virtual void onBatchedInputEventPending(int32_t) override {
+ mInputConsumer.consumeBatchedInputEvents(std::nullopt);
+ }
+
+ const AInputTransferToken* getInputTransferToken() {
+ InputTransferToken_acquire(mInputTransferToken.get());
+ return reinterpret_cast<const AInputTransferToken*>(mInputTransferToken.get());
+ }
+
+ void remove() {
+ removeInputChannel(mClientToken);
+ }
+
+ AInputReceiverCallbacks* mCallbacks;
+
+protected:
+ InputConsumerNoResampling mInputConsumer;
+
+private:
+ const sp<IBinder> mClientToken;
+ const sp<InputTransferToken> mInputTransferToken;
+};
+
+class BatchedInputReceiver : public InputReceiver {
+public:
+ BatchedInputReceiver(Choreographer& choreographer,
+ const std::shared_ptr<InputChannel>& inputChannel,
+ const sp<IBinder>& clientToken,
+ const sp<InputTransferToken>& inputTransferToken,
+ AInputReceiverCallbacks* callbacks)
+ : InputReceiver(choreographer.getLooper(), inputChannel, clientToken, inputTransferToken,
+ callbacks),
+ mChoreographer(choreographer) {}
+
+ static void vsyncCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
+ BatchedInputReceiver* receiver = static_cast<BatchedInputReceiver*>(data);
+ receiver->onVsyncCallback(callbackData);
+ }
+
+ void onVsyncCallback(const AChoreographerFrameCallbackData* callbackData) {
+ int64_t frameTimeNanos = AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData);
+ mInputConsumer.consumeBatchedInputEvents(frameTimeNanos);
+ mBatchedInputScheduled = false;
+ }
+
+ void onBatchedInputEventPending(int32_t) override {
+ scheduleBatchedInput();
+ }
+
+private:
+ Choreographer& mChoreographer;
+ bool mBatchedInputScheduled = false;
+
+ void scheduleBatchedInput() {
+ if (!mBatchedInputScheduled) {
+ mBatchedInputScheduled = true;
+ mChoreographer.postFrameCallbackDelayed(nullptr, nullptr, vsyncCallback, this, 0,
+ CallbackType::CALLBACK_INPUT);
+ }
+ }
+};
+
+static inline AInputReceiver* InputReceiver_to_AInputReceiver(InputReceiver* inputReceiver) {
+ return reinterpret_cast<AInputReceiver*>(inputReceiver);
+}
+
+static inline InputReceiver* AInputReceiver_to_InputReceiver(AInputReceiver* aInputReceiver) {
+ return reinterpret_cast<InputReceiver*>(aInputReceiver);
+}
+
+AInputReceiver* AInputReceiver_createBatchedInputReceiver(AChoreographer* aChoreographer,
+ const AInputTransferToken* hostToken,
+ const ASurfaceControl* aSurfaceControl,
+ AInputReceiverCallbacks* callbacks) {
+ // create input channel here through WMS
+ sp<IBinder> clientToken = sp<BBinder>::make();
+ sp<InputTransferToken> clientInputTransferToken = sp<InputTransferToken>::make();
+
+ std::shared_ptr<InputChannel> inputChannel =
+ createInputChannel(clientToken, reinterpret_cast<const InputTransferToken&>(*hostToken),
+ reinterpret_cast<const SurfaceControl&>(*aSurfaceControl),
+ *clientInputTransferToken);
+ return InputReceiver_to_AInputReceiver(
+ new BatchedInputReceiver(reinterpret_cast<Choreographer&>(*aChoreographer),
+ inputChannel, clientToken, clientInputTransferToken,
+ callbacks));
+}
+
+AInputReceiver* AInputReceiver_createUnbatchedInputReceiver(ALooper* aLooper,
+ const AInputTransferToken* hostToken,
+ const ASurfaceControl* aSurfaceControl,
+ AInputReceiverCallbacks* callbacks) {
+ // create input channel here through WMS
+ sp<IBinder> clientToken = sp<BBinder>::make();
+ sp<InputTransferToken> clientInputTransferToken = sp<InputTransferToken>::make();
+
+ std::shared_ptr<InputChannel> inputChannel =
+ createInputChannel(clientToken, reinterpret_cast<const InputTransferToken&>(*hostToken),
+ reinterpret_cast<const SurfaceControl&>(*aSurfaceControl),
+ *clientInputTransferToken);
+ return InputReceiver_to_AInputReceiver(new InputReceiver(reinterpret_cast<Looper*>(aLooper),
+ inputChannel, clientToken,
+ clientInputTransferToken, callbacks));
+}
+
+const AInputTransferToken* AInputReceiver_getInputTransferToken(AInputReceiver* aInputReceiver) {
+ return AInputReceiver_to_InputReceiver(aInputReceiver)->getInputTransferToken();
+}
+
+void AInputReceiver_release(AInputReceiver* aInputReceiver) {
+ InputReceiver* inputReceiver = AInputReceiver_to_InputReceiver(aInputReceiver);
+ if (inputReceiver != nullptr) {
+ inputReceiver->remove();
+ }
+ delete inputReceiver;
+}
+
+void AInputReceiverCallbacks_setMotionEventCallback(AInputReceiverCallbacks* callbacks,
+ AInputReceiver_onMotionEvent onMotionEvent) {
+ callbacks->onMotionEvent = onMotionEvent;
+}
+
+void AInputReceiverCallbacks_setKeyEventCallback(AInputReceiverCallbacks* callbacks,
+ AInputReceiver_onKeyEvent onKeyEvent) {
+ callbacks->onKeyEvent = onKeyEvent;
+}
+
+AInputReceiverCallbacks* AInputReceiverCallbacks_create(void* context) {
+ return new AInputReceiverCallbacks(context);
+}
+
+void AInputReceiverCallbacks_release(AInputReceiverCallbacks* callbacks) {
+ delete callbacks;
+} \ No newline at end of file
diff --git a/native/android/tests/performance_hint/Android.bp b/native/android/tests/performance_hint/Android.bp
index fdc1bc6a20d8..608d5d8a923a 100644
--- a/native/android/tests/performance_hint/Android.bp
+++ b/native/android/tests/performance_hint/Android.bp
@@ -39,6 +39,7 @@ cc_test {
"libandroid",
"liblog",
"libbinder",
+ "libbinder_ndk",
"libpowermanager",
"libutils",
],
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 4553b4919d2d..78a53578f5ca 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -16,11 +16,14 @@
#define LOG_TAG "PerformanceHintNativeTest"
-#include <android/WorkDuration.h>
-#include <android/os/IHintManager.h>
-#include <android/os/IHintSession.h>
+#include <aidl/android/hardware/power/ChannelConfig.h>
+#include <aidl/android/hardware/power/SessionConfig.h>
+#include <aidl/android/hardware/power/SessionTag.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+#include <aidl/android/os/IHintManager.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
#include <android/performance_hint.h>
-#include <binder/IBinder.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <performance_hint_private.h>
@@ -28,48 +31,58 @@
#include <memory>
#include <vector>
-using android::binder::Status;
-using android::os::IHintManager;
-using android::os::IHintSession;
+namespace hal = aidl::android::hardware::power;
+using aidl::android::os::IHintManager;
+using aidl::android::os::IHintSession;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
using namespace android;
using namespace testing;
class MockIHintManager : public IHintManager {
public:
- MOCK_METHOD(Status, createHintSession,
- (const sp<IBinder>& token, const ::std::vector<int32_t>& tids,
- int64_t durationNanos, ::android::sp<IHintSession>* _aidl_return),
+ MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig,
+ (const SpAIBinder& token, const ::std::vector<int32_t>& tids, int64_t durationNanos,
+ hal::SessionTag tag, std::optional<hal::SessionConfig>* config,
+ std::shared_ptr<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),
+ MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
+ MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
+ (const std::shared_ptr<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));
+ MOCK_METHOD(ScopedAStatus, getHintSessionThreadIds,
+ (const std::shared_ptr<IHintSession>& hintSession, ::std::vector<int32_t>* tids),
+ (override));
+ MOCK_METHOD(ScopedAStatus, getSessionChannel,
+ (const ::ndk::SpAIBinder& in_token, hal::ChannelConfig* _aidl_return), (override));
+ MOCK_METHOD(ScopedAStatus, closeSessionChannel, (), (override));
+ MOCK_METHOD(SpAIBinder, asBinder, (), (override));
+ MOCK_METHOD(bool, isRemote, (), (override));
};
class MockIHintSession : public IHintSession {
public:
- MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
- MOCK_METHOD(Status, reportActualWorkDuration,
+ MOCK_METHOD(ScopedAStatus, updateTargetWorkDuration, (int64_t targetDurationNanos), (override));
+ MOCK_METHOD(ScopedAStatus, reportActualWorkDuration,
(const ::std::vector<int64_t>& actualDurationNanos,
const ::std::vector<int64_t>& timeStampNanos),
(override));
- MOCK_METHOD(Status, sendHint, (int32_t hint), (override));
- MOCK_METHOD(Status, setMode, (int32_t mode, bool enabled), (override));
- MOCK_METHOD(Status, close, (), (override));
- MOCK_METHOD(IBinder*, onAsBinder, (), (override));
- MOCK_METHOD(Status, reportActualWorkDuration2,
- (const ::std::vector<android::os::WorkDuration>& workDurations), (override));
+ MOCK_METHOD(ScopedAStatus, sendHint, (int32_t hint), (override));
+ MOCK_METHOD(ScopedAStatus, setMode, (int32_t mode, bool enabled), (override));
+ MOCK_METHOD(ScopedAStatus, close, (), (override));
+ MOCK_METHOD(ScopedAStatus, reportActualWorkDuration2,
+ (const ::std::vector<hal::WorkDuration>& workDurations), (override));
+ MOCK_METHOD(SpAIBinder, asBinder, (), (override));
+ MOCK_METHOD(bool, isRemote, (), (override));
};
class PerformanceHintTest : public Test {
public:
void SetUp() override {
- mMockIHintManager = new StrictMock<MockIHintManager>();
- APerformanceHint_setIHintManagerForTesting(mMockIHintManager);
+ mMockIHintManager = ndk::SharedRefBase::make<NiceMock<MockIHintManager>>();
+ APerformanceHint_setIHintManagerForTesting(&mMockIHintManager);
}
void TearDown() override {
@@ -79,15 +92,57 @@ public:
}
APerformanceHintManager* createManager() {
- EXPECT_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<0>(123L), Return(Status())));
+ ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_))
+ .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); }));
return APerformanceHint_getManager();
}
+ APerformanceHintSession* createSession(APerformanceHintManager* manager,
+ int64_t targetDuration = 56789L, bool isHwui = false) {
+ mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
+ int64_t sessionId = 123;
+ std::vector<int32_t> tids;
+ tids.push_back(1);
+ tids.push_back(2);
+
+ ON_CALL(*mMockIHintManager,
+ createHintSessionWithConfig(_, Eq(tids), Eq(targetDuration), _, _, _))
+ .WillByDefault(DoAll(SetArgPointee<4>(std::make_optional<hal::SessionConfig>(
+ {.id = sessionId})),
+ SetArgPointee<5>(std::shared_ptr<IHintSession>(mMockSession)),
+ [] { return ScopedAStatus::ok(); }));
+
+ ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ ON_CALL(*mMockSession, sendHint(_)).WillByDefault([] { return ScopedAStatus::ok(); });
+ ON_CALL(*mMockSession, setMode(_, _)).WillByDefault([] { return ScopedAStatus::ok(); });
+ ON_CALL(*mMockSession, close()).WillByDefault([] { return ScopedAStatus::ok(); });
+ ON_CALL(*mMockSession, updateTargetWorkDuration(_)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ ON_CALL(*mMockSession, reportActualWorkDuration(_, _)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
+ return ScopedAStatus::ok();
+ });
+ if (isHwui) {
+ return APerformanceHint_createSessionInternal(manager, tids.data(), tids.size(),
+ targetDuration, SessionTag::HWUI);
+ }
+ return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ }
- StrictMock<MockIHintManager>* mMockIHintManager = nullptr;
+ std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr;
+ std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
};
+bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) {
+ return lhs.workPeriodStartTimestampNanos == rhs.workPeriodStartTimestampNanos &&
+ lhs.cpuDurationNanos == rhs.cpuDurationNanos &&
+ lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
+}
+
TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
APerformanceHintManager* manager = createManager();
int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager);
@@ -96,25 +151,11 @@ TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) {
TEST_F(PerformanceHintTest, TestSession) {
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);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
int64_t targetDurationNanos = 10;
- EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
EXPECT_EQ(0, result);
@@ -122,8 +163,7 @@ TEST_F(PerformanceHintTest, TestSession) {
int64_t actualDurationNanos = 20;
std::vector<int64_t> actualDurations;
actualDurations.push_back(20);
- EXPECT_CALL(*iSession, reportActualWorkDuration(Eq(actualDurations), _)).Times(Exactly(1));
- EXPECT_CALL(*iSession, reportActualWorkDuration2(_)).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, reportActualWorkDuration2(_)).Times(Exactly(1));
result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
EXPECT_EQ(0, result);
@@ -133,114 +173,88 @@ TEST_F(PerformanceHintTest, TestSession) {
EXPECT_EQ(EINVAL, result);
SessionHint hintId = SessionHint::CPU_LOAD_RESET;
- EXPECT_CALL(*iSession, sendHint(Eq(hintId))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, 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));
+ EXPECT_CALL(*mMockSession, 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));
+ EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(0));
result = APerformanceHint_sendHint(session, hintId);
EXPECT_EQ(0, result);
result = APerformanceHint_sendHint(session, static_cast<SessionHint>(-1));
EXPECT_EQ(EINVAL, result);
- EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
APerformanceHint_closeSession(session);
}
-TEST_F(PerformanceHintTest, SetThreads) {
+TEST_F(PerformanceHintTest, TestUpdatedSessionCreation) {
+ EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _, _)).Times(1);
APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager);
+ ASSERT_TRUE(session);
+ APerformanceHint_closeSession(session);
+}
- 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);
+TEST_F(PerformanceHintTest, TestHwuiSessionCreation) {
+ EXPECT_CALL(*mMockIHintManager,
+ createHintSessionWithConfig(_, _, _, hal::SessionTag::HWUI, _, _))
+ .Times(1);
+ APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager, 56789L, true);
+ ASSERT_TRUE(session);
+ APerformanceHint_closeSession(session);
+}
- EXPECT_CALL(*mMockIHintManager, createHintSession(_, Eq(tids), Eq(targetDuration), _))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<3>(std::move(session_sp)), Return(Status())));
+TEST_F(PerformanceHintTest, SetThreads) {
+ APerformanceHintManager* manager = createManager();
- APerformanceHintSession* session =
- APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
- std::vector<int32_t> emptyTids;
- int result = APerformanceHint_setThreads(session, emptyTids.data(), emptyTids.size());
+ int32_t emptyTids[2];
+ int result = APerformanceHint_setThreads(session, emptyTids, 0);
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()));
+ EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids))).Times(Exactly(1));
result = APerformanceHint_setThreads(session, newTids.data(), newTids.size());
EXPECT_EQ(0, result);
- testing::Mock::VerifyAndClearExpectations(mMockIHintManager);
+ testing::Mock::VerifyAndClearExpectations(mMockIHintManager.get());
std::vector<int32_t> invalidTids;
- auto status = Status::fromExceptionCode(binder::Status::Exception::EX_SECURITY);
invalidTids.push_back(4);
invalidTids.push_back(6);
EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(invalidTids)))
.Times(Exactly(1))
- .WillOnce(Return(status));
+ .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_SECURITY))));
result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size());
EXPECT_EQ(EPERM, result);
}
TEST_F(PerformanceHintTest, SetPowerEfficient) {
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);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
- EXPECT_CALL(*iSession, setMode(_, Eq(true))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, setMode(_, Eq(true))).Times(Exactly(1));
int result = APerformanceHint_setPreferPowerEfficiency(session, true);
EXPECT_EQ(0, result);
- EXPECT_CALL(*iSession, setMode(_, Eq(false))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, setMode(_, Eq(false))).Times(Exactly(1));
result = APerformanceHint_setPreferPowerEfficiency(session, false);
EXPECT_EQ(0, result);
}
TEST_F(PerformanceHintTest, CreateZeroTargetDurationSession) {
APerformanceHintManager* manager = createManager();
-
- std::vector<int32_t> tids;
- tids.push_back(1);
- tids.push_back(2);
- int64_t targetDuration = 0;
-
- 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);
+ APerformanceHintSession* session = createSession(manager, 0);
ASSERT_TRUE(session);
}
@@ -251,12 +265,12 @@ MATCHER_P(WorkDurationEq, expected, "") {
return false;
}
for (int i = 0; i < expected.size(); ++i) {
- android::os::WorkDuration expectedWorkDuration = expected[i];
- android::os::WorkDuration actualWorkDuration = arg[i];
- if (!expectedWorkDuration.equalsWithoutTimestamp(actualWorkDuration)) {
+ hal::WorkDuration expectedWorkDuration = expected[i];
+ hal::WorkDuration actualWorkDuration = arg[i];
+ if (!equalsWithoutTimestamp(expectedWorkDuration, actualWorkDuration)) {
*result_listener << "WorkDuration at [" << i << "] is different: "
- << "Expected: " << expectedWorkDuration
- << ", Actual: " << actualWorkDuration;
+ << "Expected: " << expectedWorkDuration.toString()
+ << ", Actual: " << actualWorkDuration.toString();
return false;
}
}
@@ -265,92 +279,37 @@ MATCHER_P(WorkDurationEq, expected, "") {
TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) {
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);
+ APerformanceHintSession* session = createSession(manager);
ASSERT_TRUE(session);
int64_t targetDurationNanos = 10;
- EXPECT_CALL(*iSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
EXPECT_EQ(0, result);
usleep(2); // Sleep for longer than preferredUpdateRateNanos.
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, 20, 13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(0, result);
- }
-
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(-1, 20, 13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(22, result);
- }
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, -20, 13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(22, result);
- }
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, 20, -13, 8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
- .Times(Exactly(1));
- result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(EINVAL, result);
- }
- {
- std::vector<android::os::WorkDuration> actualWorkDurations;
- android::os::WorkDuration workDuration(1, 20, 13, -8);
- actualWorkDurations.push_back(workDuration);
-
- EXPECT_CALL(*iSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
+ struct TestPair {
+ hal::WorkDuration duration;
+ int expectedResult;
+ };
+ std::vector<TestPair> testPairs{
+ {{1, 20, 1, 13, 8}, OK}, {{1, -20, 1, 13, 8}, EINVAL},
+ {{1, 20, -1, 13, 8}, EINVAL}, {{1, -20, 1, -13, 8}, EINVAL},
+ {{1, -20, 1, 13, -8}, EINVAL},
+ };
+ for (auto&& pair : testPairs) {
+ std::vector<hal::WorkDuration> actualWorkDurations;
+ actualWorkDurations.push_back(pair.duration);
+
+ EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
.Times(Exactly(1));
result = APerformanceHint_reportActualWorkDuration2(session,
- static_cast<AWorkDuration*>(
- &workDuration));
- EXPECT_EQ(EINVAL, result);
+ reinterpret_cast<AWorkDuration*>(
+ &pair.duration));
+ EXPECT_EQ(pair.expectedResult, result);
}
- EXPECT_CALL(*iSession, close()).Times(Exactly(1));
+ EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
APerformanceHint_closeSession(session);
}
diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h
index 44fe56fcaf4b..b865d0ebeb1f 100644
--- a/native/webview/plat_support/draw_fn.h
+++ b/native/webview/plat_support/draw_fn.h
@@ -23,7 +23,8 @@ extern "C" {
// 1 is Android Q. This matches kAwDrawGLInfoVersion version 3.
// 2 Adds transfer_function_* and color_space_toXYZD50 to AwDrawFn_DrawGLParams.
// 3 Adds SurfaceControl related functions.
-static const int kAwDrawFnVersion = 3;
+// 4 Adds AwDrawFn_ReportRenderingThreads to AwDrawFnFunctionTable.
+static const int kAwDrawFnVersion = 4;
// Returns parent ASurfaceControl for WebView overlays. It will be have same
// geometry as the surface we draw into and positioned below it (underlay).
@@ -268,6 +269,10 @@ typedef int AwDrawFn_CreateFunctor_v3(
// released, and it should be considered alive & active until that point.
typedef void AwDrawFn_ReleaseFunctor(int functor);
+// Report the list of threads critical for frame production for the given
+// functor. Must be called on render thread.
+typedef void AwDrawFn_ReportRenderingThreads(int functor, const int32_t* thread_ids, size_t size);
+
struct AwDrawFnFunctionTable {
int version;
AwDrawFn_QueryRenderMode* query_render_mode;
@@ -276,6 +281,8 @@ struct AwDrawFnFunctionTable {
AwDrawFn_ReleaseFunctor* release_functor;
// Added in version 3.
AwDrawFn_CreateFunctor_v3* create_functor_v3;
+ // Added in version 4.
+ AwDrawFn_ReportRenderingThreads* report_rendering_threads;
};
#ifdef __cplusplus
diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp
index 1584350bb6f1..5d3e24c382bf 100644
--- a/native/webview/plat_support/draw_functor.cpp
+++ b/native/webview/plat_support/draw_functor.cpp
@@ -290,15 +290,20 @@ AwDrawFnRenderMode QueryRenderMode(void) {
}
}
+void ReportRenderingThreads(int functor, const int32_t* thread_ids, size_t size) {
+ uirenderer::WebViewFunctor_reportRenderingThreads(functor, thread_ids, size);
+}
+
jlong GetDrawFnFunctionTable() {
- static AwDrawFnFunctionTable function_table = {
- .version = kAwDrawFnVersion,
- .query_render_mode = &QueryRenderMode,
- .create_functor = &CreateFunctor,
- .release_functor = &ReleaseFunctor,
- .create_functor_v3 = &CreateFunctor_v3,
- };
- return reinterpret_cast<intptr_t>(&function_table);
+ static AwDrawFnFunctionTable function_table = {
+ .version = kAwDrawFnVersion,
+ .query_render_mode = &QueryRenderMode,
+ .create_functor = &CreateFunctor,
+ .release_functor = &ReleaseFunctor,
+ .create_functor_v3 = &CreateFunctor_v3,
+ .report_rendering_threads = &ReportRenderingThreads,
+ };
+ return reinterpret_cast<intptr_t>(&function_table);
}
const char kClassName[] = "com/android/webview/chromium/DrawFunctor";