diff options
Diffstat (limited to 'native')
| -rw-r--r-- | native/android/Android.bp | 6 | ||||
| -rw-r--r-- | native/android/TEST_MAPPING | 19 | ||||
| -rw-r--r-- | native/android/configuration.cpp | 2 | ||||
| -rw-r--r-- | native/android/libandroid.map.txt | 3 | ||||
| -rw-r--r-- | native/android/performance_hint.cpp | 24 | ||||
| -rw-r--r-- | native/android/system_fonts.cpp | 9 | ||||
| -rw-r--r-- | native/android/tests/performance_hint/PerformanceHintNativeTest.cpp | 62 | ||||
| -rw-r--r-- | native/android/tests/thermal/Android.bp | 65 | ||||
| -rw-r--r-- | native/android/tests/thermal/NativeThermalUnitTest.cpp | 158 | ||||
| -rw-r--r-- | native/android/tests/thermal/OWNERS | 1 | ||||
| -rw-r--r-- | native/android/thermal.cpp | 124 | ||||
| -rw-r--r-- | native/webview/TEST_MAPPING | 2 |
12 files changed, 429 insertions, 46 deletions
diff --git a/native/android/Android.bp b/native/android/Android.bp index 254eb4494ed8..7f3792d06795 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -46,7 +46,10 @@ cc_defaults { cc_library_shared { name: "libandroid", - defaults: ["libandroid_defaults"], + defaults: [ + "libandroid_defaults", + "android.hardware.power-ndk_shared", + ], srcs: [ "activity_manager.cpp", @@ -95,7 +98,6 @@ cc_library_shared { "libpowermanager", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", - "android.hardware.power-V4-ndk", "libnativedisplay", ], diff --git a/native/android/TEST_MAPPING b/native/android/TEST_MAPPING index 6a5d2c008b1d..7c710982e4f6 100644 --- a/native/android/TEST_MAPPING +++ b/native/android/TEST_MAPPING @@ -12,6 +12,25 @@ } ], "file_patterns": ["permission_manager.cpp"] + }, + { + "name": "CtsOsTestCases", + "options": [ + { + "include-filter": "android.os.cts.PerformanceHintManagerTest" + } + ], + "file_patterns": ["performance_hint.cpp"] + } + ], + "postsubmit": [ + { + "name": "CtsThermalTestCases", + "file_patterns": ["thermal.cpp"] + }, + { + "name": "NativeThermalUnitTestCases", + "file_patterns": ["thermal.cpp"] } ] } diff --git a/native/android/configuration.cpp b/native/android/configuration.cpp index b50514d27bac..283445fc8a9a 100644 --- a/native/android/configuration.cpp +++ b/native/android/configuration.cpp @@ -36,7 +36,7 @@ void AConfiguration_delete(AConfiguration* config) { void AConfiguration_fromAssetManager(AConfiguration* out, AAssetManager* am) { ScopedLock<AssetManager2> locked_mgr(*AssetManagerForNdkAssetManager(am)); - ResTable_config config = locked_mgr->GetConfiguration(); + ResTable_config config = locked_mgr->GetConfigurations()[0]; // AConfiguration is not a virtual subclass, so we can memcpy. memcpy(out, &config, sizeof(config)); diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index d74f9b7bb659..fea6c5f95358 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -327,6 +327,7 @@ LIBANDROID { AThermal_registerThermalStatusListener; # introduced=30 AThermal_unregisterThermalStatusListener; # introduced=30 AThermal_getThermalHeadroom; # introduced=31 + AThermal_getThermalHeadroomThresholds; # introduced=VanillaIceCream APerformanceHint_getManager; # introduced=Tiramisu APerformanceHint_createSession; # introduced=Tiramisu APerformanceHint_getPreferredUpdateRateNanos; # introduced=Tiramisu @@ -334,12 +335,14 @@ LIBANDROID { APerformanceHint_reportActualWorkDuration; # introduced=Tiramisu APerformanceHint_closeSession; # introduced=Tiramisu APerformanceHint_setThreads; # introduced=UpsideDownCake + APerformanceHint_setPreferPowerEfficiency; # introduced=VanillaIceCream local: *; }; LIBANDROID_PLATFORM { global: + AThermal_setIThermalServiceForTesting; APerformanceHint_setIHintManagerForTesting; APerformanceHint_sendHint; APerformanceHint_getThreadIds; diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index b3628fa3e5ce..c25df6e08fd0 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "perf_hint" #include <aidl/android/hardware/power/SessionHint.h> +#include <aidl/android/hardware/power/SessionMode.h> #include <android/os/IHintManager.h> #include <android/os/IHintSession.h> #include <android/performance_hint.h> @@ -36,6 +37,7 @@ using namespace android::os; using namespace std::chrono_literals; using AidlSessionHint = aidl::android::hardware::power::SessionHint; +using AidlSessionMode = aidl::android::hardware::power::SessionMode; struct APerformanceHintSession; @@ -72,6 +74,7 @@ public: int sendHint(SessionHint hint); int setThreads(const int32_t* threadIds, size_t size); int getThreadIds(int32_t* const threadIds, size_t* size); + int setPreferPowerEfficiency(bool enabled); private: friend struct APerformanceHintManager; @@ -274,9 +277,10 @@ int APerformanceHintSession::setThreads(const int32_t* threadIds, size_t 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) { + if (ret.exceptionCode() == binder::Status::Exception::EX_ILLEGAL_ARGUMENT) { return EINVAL; + } else if (ret.exceptionCode() == binder::Status::Exception::EX_SECURITY) { + return EPERM; } return EPIPE; } @@ -306,6 +310,18 @@ int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size return 0; } +int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) { + binder::Status ret = + mHintSession->setMode(static_cast<int32_t>(AidlSessionMode::POWER_EFFICIENCY), enabled); + + if (!ret.isOk()) { + ALOGE("%s: HintSession setPreferPowerEfficiency failed: %s", __FUNCTION__, + ret.exceptionMessage().c_str()); + return EPIPE; + } + return OK; +} + // ===================================== C API APerformanceHintManager* APerformanceHint_getManager() { return APerformanceHintManager::getInstance(); @@ -356,6 +372,10 @@ int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const ->getThreadIds(threadIds, size); } +int APerformanceHint_setPreferPowerEfficiency(APerformanceHintSession* session, bool enabled) { + return session->setPreferPowerEfficiency(enabled); +} + void APerformanceHint_setIHintManagerForTesting(void* iManager) { delete gHintManagerForTesting; gHintManagerForTesting = nullptr; diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp index ceab164aa324..91f78ce6f950 100644 --- a/native/android/system_fonts.cpp +++ b/native/android/system_fonts.cpp @@ -249,14 +249,15 @@ ASystemFontIterator* ASystemFontIterator_open() { locale.emplace(minikin::getLocaleString(localeId)); } std::vector<std::pair<uint32_t, float>> axes; - for (const auto& [tag, value] : font->typeface()->GetAxes()) { + for (const auto& [tag, value] : font->baseTypeface()->GetAxes()) { axes.push_back(std::make_pair(tag, value)); } - fonts.insert({font->typeface()->GetFontPath(), std::move(locale), + fonts.insert({font->baseTypeface()->GetFontPath(), std::move(locale), font->style().weight(), font->style().slant() == minikin::FontStyle::Slant::ITALIC, - static_cast<uint32_t>(font->typeface()->GetFontIndex()), axes}); + static_cast<uint32_t>(font->baseTypeface()->GetFontIndex()), + axes}); } }); @@ -321,7 +322,7 @@ AFont* _Nonnull AFontMatcher_match( .font; std::unique_ptr<AFont> result = std::make_unique<AFont>(); const android::MinikinFontSkia* minikinFontSkia = - reinterpret_cast<android::MinikinFontSkia*>(font->typeface().get()); + reinterpret_cast<android::MinikinFontSkia*>(font->baseTypeface().get()); result->mFilePath = minikinFontSkia->getFilePath(); result->mWeight = font->style().weight(); result->mItalic = font->style().slant() == minikin::FontStyle::Slant::ITALIC; diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index 791adfd33fcd..22d33b139ccf 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -56,7 +56,8 @@ 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, 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)); }; @@ -178,4 +179,63 @@ TEST_F(PerformanceHintTest, SetThreads) { .WillOnce(Return(Status())); result = APerformanceHint_setThreads(session, newTids.data(), newTids.size()); EXPECT_EQ(0, result); + + testing::Mock::VerifyAndClearExpectations(mMockIHintManager); + 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)); + 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); + ASSERT_TRUE(session); + + EXPECT_CALL(*iSession, 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)); + 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); + ASSERT_TRUE(session); +}
\ No newline at end of file diff --git a/native/android/tests/thermal/Android.bp b/native/android/tests/thermal/Android.bp new file mode 100644 index 000000000000..8540d8327ada --- /dev/null +++ b/native/android/tests/thermal/Android.bp @@ -0,0 +1,65 @@ +// Copyright (C) 2021 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. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +cc_test { + name: "NativeThermalUnitTestCases", + + multilib: { + lib32: { + suffix: "32", + }, + lib64: { + suffix: "64", + }, + }, + + srcs: ["NativeThermalUnitTest.cpp"], + + shared_libs: [ + "libandroid", + "liblog", + "libbinder", + "libpowermanager", + "libutils", + ], + + static_libs: [ + "libbase", + "libgmock", + "libgtest", + ], + stl: "c++_shared", + + test_suites: [ + "device-tests", + ], + + cflags: [ + "-Werror", + "-Wall", + ], + + header_libs: [ + "libandroid_headers_private", + ], +} diff --git a/native/android/tests/thermal/NativeThermalUnitTest.cpp b/native/android/tests/thermal/NativeThermalUnitTest.cpp new file mode 100644 index 000000000000..6d6861a3026a --- /dev/null +++ b/native/android/tests/thermal/NativeThermalUnitTest.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2023 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 "NativeThermalUnitTest" + +#include <android/os/IThermalService.h> +#include <android/thermal.h> +#include <binder/IBinder.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <thermal_private.h> + +using android::binder::Status; + +using namespace testing; +using namespace android; +using namespace android::os; + +class MockIThermalService : public IThermalService { +public: + MOCK_METHOD(Status, registerThermalEventListener, + (const ::android::sp<::android::os::IThermalEventListener>& listener, + bool* _aidl_return), + (override)); + MOCK_METHOD(Status, registerThermalEventListenerWithType, + (const ::android::sp<::android::os::IThermalEventListener>& listener, int32_t type, + bool* _aidl_return), + (override)); + MOCK_METHOD(Status, unregisterThermalEventListener, + (const ::android::sp<::android::os::IThermalEventListener>& listener, + bool* _aidl_return), + (override)); + MOCK_METHOD(Status, getCurrentTemperatures, + (::std::vector<::android::os::Temperature> * _aidl_return), (override)); + MOCK_METHOD(Status, getCurrentTemperaturesWithType, + (int32_t type, ::std::vector<::android::os::Temperature>* _aidl_return), + (override)); + MOCK_METHOD(Status, registerThermalStatusListener, + (const ::android::sp<::android::os::IThermalStatusListener>& listener, + bool* _aidl_return), + (override)); + MOCK_METHOD(Status, unregisterThermalStatusListener, + (const ::android::sp<::android::os::IThermalStatusListener>& listener, + bool* _aidl_return), + (override)); + MOCK_METHOD(Status, getCurrentThermalStatus, (int32_t * _aidl_return), (override)); + MOCK_METHOD(Status, getCurrentCoolingDevices, + (::std::vector<::android::os::CoolingDevice> * _aidl_return), (override)); + MOCK_METHOD(Status, getCurrentCoolingDevicesWithType, + (int32_t type, ::std::vector<::android::os::CoolingDevice>* _aidl_return), + (override)); + MOCK_METHOD(Status, getThermalHeadroom, (int32_t forecastSeconds, float* _aidl_return), + (override)); + MOCK_METHOD(Status, getThermalHeadroomThresholds, (::std::vector<float> * _aidl_return), + (override)); + MOCK_METHOD(IBinder*, onAsBinder, (), (override)); +}; + +class NativeThermalUnitTest : public Test { +public: + void SetUp() override { + mMockIThermalService = new StrictMock<MockIThermalService>(); + AThermal_setIThermalServiceForTesting(mMockIThermalService); + mThermalManager = AThermal_acquireManager(); + } + + void TearDown() override { + AThermal_setIThermalServiceForTesting(nullptr); + AThermal_releaseManager(mThermalManager); + } + + StrictMock<MockIThermalService>* mMockIThermalService = nullptr; + AThermalManager* mThermalManager = nullptr; +}; + +static void checkThermalHeadroomThresholds(const std::vector<float>& expected, + const AThermalHeadroomThreshold* thresholds, + size_t size) { + if (thresholds == nullptr) { + FAIL() << "Unexpected null thresholds pointer"; + } + for (int i = 0; i < (int)size; i++) { + auto t = thresholds[i]; + ASSERT_EQ(i, t.thermalStatus) << "threshold " << i << " should have status " << i; + ASSERT_EQ(expected[i], t.headroom) + << "threshold " << i << " should have headroom " << expected[i]; + } +} + +TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholds) { + std::vector<float> expected = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_)) + .Times(Exactly(1)) + .WillRepeatedly(DoAll(SetArgPointee<0>(expected), Return(Status()))); + const AThermalHeadroomThreshold* thresholds1 = nullptr; + size_t size1; + ASSERT_EQ(OK, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds1, &size1)); + checkThermalHeadroomThresholds(expected, thresholds1, size1); + // following calls should be cached + EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_)).Times(0); + + const AThermalHeadroomThreshold* thresholds2 = nullptr; + size_t size2; + ASSERT_EQ(OK, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds2, &size2)); + checkThermalHeadroomThresholds(expected, thresholds2, size2); +} + +TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithServerError) { + const AThermalHeadroomThreshold* thresholds = nullptr; + size_t size; + EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_)) + .Times(Exactly(1)) + .WillOnce(Return( + Status::fromExceptionCode(binder::Status::Exception::EX_ILLEGAL_ARGUMENT))); + ASSERT_EQ(EPIPE, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds, &size)); + ASSERT_EQ(nullptr, thresholds); +} + +TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithFeatureDisabled) { + const AThermalHeadroomThreshold* thresholds = nullptr; + size_t size; + EXPECT_CALL(*mMockIThermalService, getThermalHeadroomThresholds(_)) + .Times(Exactly(1)) + .WillOnce(Return(Status::fromExceptionCode( + binder::Status::Exception::EX_UNSUPPORTED_OPERATION))); + ASSERT_EQ(ENOSYS, AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds, &size)); + ASSERT_EQ(nullptr, thresholds); +} + +TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithNullPtr) { + const AThermalHeadroomThreshold* thresholds = nullptr; + size_t size; + size_t* nullSize = nullptr; + ASSERT_EQ(EINVAL, + AThermal_getThermalHeadroomThresholds(mThermalManager, &thresholds, nullSize)); + ASSERT_EQ(nullptr, thresholds); + ASSERT_EQ(EINVAL, AThermal_getThermalHeadroomThresholds(mThermalManager, nullptr, &size)); +} + +TEST_F(NativeThermalUnitTest, TestGetThermalHeadroomThresholdsFailedWithNonEmptyPtr) { + const AThermalHeadroomThreshold* initialized = new AThermalHeadroomThreshold[1]; + size_t size; + ASSERT_EQ(EINVAL, AThermal_getThermalHeadroomThresholds(mThermalManager, &initialized, &size)); + delete[] initialized; +} diff --git a/native/android/tests/thermal/OWNERS b/native/android/tests/thermal/OWNERS new file mode 100644 index 000000000000..e3bbee92057d --- /dev/null +++ b/native/android/tests/thermal/OWNERS @@ -0,0 +1 @@ +include /ADPF_OWNERS diff --git a/native/android/thermal.cpp b/native/android/thermal.cpp index 1f6ef4755aff..b43f2f16a7cb 100644 --- a/native/android/thermal.cpp +++ b/native/android/thermal.cpp @@ -16,27 +16,32 @@ #define LOG_TAG "thermal" -#include <cerrno> -#include <thread> -#include <limits> - -#include <android/thermal.h> +#include <android-base/thread_annotations.h> #include <android/os/BnThermalStatusListener.h> #include <android/os/IThermalService.h> +#include <android/thermal.h> #include <binder/IServiceManager.h> +#include <thermal_private.h> #include <utils/Log.h> +#include <cerrno> +#include <limits> +#include <thread> + using android::sp; using namespace android; using namespace android::os; struct ThermalServiceListener : public BnThermalStatusListener { - public: - virtual binder::Status onStatusChange(int32_t status) override; - ThermalServiceListener(AThermalManager *manager) {mMgr = manager;} - private: - AThermalManager *mMgr; +public: + virtual binder::Status onStatusChange(int32_t status) override; + ThermalServiceListener(AThermalManager *manager) { + mMgr = manager; + } + +private: + AThermalManager *mMgr; }; struct ListenerCallback { @@ -44,22 +49,29 @@ struct ListenerCallback { void* data; }; +static IThermalService *gIThermalServiceForTesting = nullptr; + struct AThermalManager { - public: - static AThermalManager* createAThermalManager(); - AThermalManager() = delete; - ~AThermalManager(); - status_t notifyStateChange(int32_t status); - status_t getCurrentThermalStatus(int32_t *status); - status_t addListener(AThermal_StatusCallback, void *data); - status_t removeListener(AThermal_StatusCallback, void *data); - status_t getThermalHeadroom(int32_t forecastSeconds, float *result); - private: - AThermalManager(sp<IThermalService> service); - sp<IThermalService> mThermalSvc; - sp<ThermalServiceListener> mServiceListener; - std::vector<ListenerCallback> mListeners; - std::mutex mMutex; +public: + static AThermalManager *createAThermalManager(); + AThermalManager() = delete; + ~AThermalManager(); + status_t notifyStateChange(int32_t status); + status_t getCurrentThermalStatus(int32_t *status); + status_t addListener(AThermal_StatusCallback, void *data); + status_t removeListener(AThermal_StatusCallback, void *data); + status_t getThermalHeadroom(int32_t forecastSeconds, float *result); + status_t getThermalHeadroomThresholds(const AThermalHeadroomThreshold **, size_t *size); + +private: + AThermalManager(sp<IThermalService> service); + sp<IThermalService> mThermalSvc; + std::mutex mListenerMutex; + sp<ThermalServiceListener> mServiceListener GUARDED_BY(mListenerMutex); + std::vector<ListenerCallback> mListeners GUARDED_BY(mListenerMutex); + std::mutex mThresholdsMutex; + const AThermalHeadroomThreshold *mThresholds = nullptr; // GUARDED_BY(mThresholdsMutex) + size_t mThresholdsCount GUARDED_BY(mThresholdsMutex); }; binder::Status ThermalServiceListener::onStatusChange(int32_t status) { @@ -70,6 +82,9 @@ binder::Status ThermalServiceListener::onStatusChange(int32_t status) { } AThermalManager* AThermalManager::createAThermalManager() { + if (gIThermalServiceForTesting) { + return new AThermalManager(gIThermalServiceForTesting); + } sp<IBinder> binder = defaultServiceManager()->checkService(String16("thermalservice")); @@ -81,12 +96,10 @@ AThermalManager* AThermalManager::createAThermalManager() { } AThermalManager::AThermalManager(sp<IThermalService> service) - : mThermalSvc(service), - mServiceListener(nullptr) { -} + : mThermalSvc(std::move(service)), mServiceListener(nullptr) {} AThermalManager::~AThermalManager() { - std::unique_lock<std::mutex> lock(mMutex); + std::unique_lock<std::mutex> listenerLock(mListenerMutex); mListeners.clear(); if (mServiceListener != nullptr) { @@ -94,10 +107,13 @@ AThermalManager::~AThermalManager() { mThermalSvc->unregisterThermalStatusListener(mServiceListener, &success); mServiceListener = nullptr; } + listenerLock.unlock(); + std::unique_lock<std::mutex> lock(mThresholdsMutex); + delete[] mThresholds; } status_t AThermalManager::notifyStateChange(int32_t status) { - std::unique_lock<std::mutex> lock(mMutex); + std::unique_lock<std::mutex> lock(mListenerMutex); AThermalStatus thermalStatus = static_cast<AThermalStatus>(status); for (auto listener : mListeners) { @@ -107,7 +123,7 @@ status_t AThermalManager::notifyStateChange(int32_t status) { } status_t AThermalManager::addListener(AThermal_StatusCallback callback, void *data) { - std::unique_lock<std::mutex> lock(mMutex); + std::unique_lock<std::mutex> lock(mListenerMutex); if (callback == nullptr) { // Callback can not be nullptr @@ -141,7 +157,7 @@ status_t AThermalManager::addListener(AThermal_StatusCallback callback, void *da } status_t AThermalManager::removeListener(AThermal_StatusCallback callback, void *data) { - std::unique_lock<std::mutex> lock(mMutex); + std::unique_lock<std::mutex> lock(mListenerMutex); auto it = std::remove_if(mListeners.begin(), mListeners.end(), @@ -198,6 +214,32 @@ status_t AThermalManager::getThermalHeadroom(int32_t forecastSeconds, float *res return OK; } +status_t AThermalManager::getThermalHeadroomThresholds(const AThermalHeadroomThreshold **result, + size_t *size) { + std::unique_lock<std::mutex> lock(mThresholdsMutex); + if (mThresholds == nullptr) { + auto thresholds = std::make_unique<std::vector<float>>(); + binder::Status ret = mThermalSvc->getThermalHeadroomThresholds(thresholds.get()); + if (!ret.isOk()) { + if (ret.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { + // feature is not enabled + return ENOSYS; + } + return EPIPE; + } + mThresholdsCount = thresholds->size(); + auto t = new AThermalHeadroomThreshold[mThresholdsCount]; + for (int i = 0; i < (int)mThresholdsCount; i++) { + t[i].headroom = (*thresholds)[i]; + t[i].thermalStatus = static_cast<AThermalStatus>(i); + } + mThresholds = t; + } + *size = mThresholdsCount; + *result = mThresholds; + return OK; +} + /** * Acquire an instance of the thermal manager. This must be freed using * {@link AThermal_releaseManager}. @@ -291,14 +333,24 @@ int AThermal_unregisterThermalStatusListener(AThermalManager *manager, * threshold. Returns NaN if the device does not support this functionality or if * this function is called significantly faster than once per second. */ -float AThermal_getThermalHeadroom(AThermalManager *manager, - int forecastSeconds) { +float AThermal_getThermalHeadroom(AThermalManager *manager, int forecastSeconds) { float result = 0.0f; status_t ret = manager->getThermalHeadroom(forecastSeconds, &result); - if (ret != OK) { result = std::numeric_limits<float>::quiet_NaN(); } - return result; } + +int AThermal_getThermalHeadroomThresholds(AThermalManager *manager, + const AThermalHeadroomThreshold **outThresholds, + size_t *size) { + if (outThresholds == nullptr || *outThresholds != nullptr || size == nullptr) { + return EINVAL; + } + return manager->getThermalHeadroomThresholds(outThresholds, size); +} + +void AThermal_setIThermalServiceForTesting(void *iThermalService) { + gIThermalServiceForTesting = static_cast<IThermalService *>(iThermalService); +} diff --git a/native/webview/TEST_MAPPING b/native/webview/TEST_MAPPING index c1bc6d720ece..07f438329e43 100644 --- a/native/webview/TEST_MAPPING +++ b/native/webview/TEST_MAPPING @@ -26,6 +26,7 @@ }, { "name": "GtsWebViewTestCases", + "keywords": ["internal"], "options": [ { "exclude-annotation": "android.test.FlakyTest" @@ -34,6 +35,7 @@ }, { "name": "GtsWebViewHostTestCases", + "keywords": ["internal"], "options": [ { "exclude-annotation": "android.test.FlakyTest" |