diff options
| author | 2020-09-10 17:22:01 +0000 | |
|---|---|---|
| committer | 2020-09-10 17:22:01 +0000 | |
| commit | 8ac6741e47c76bde065f868ea64d2f04541487b9 (patch) | |
| tree | 1a679458fdbd8d370692d56791e2bf83acee35b5 /native/android | |
| parent | 3de940cc40b1e3fdf8224e18a8308a16768cbfa8 (diff) | |
| parent | c64112eb974e9aa7638aead998f07a868acfb5a7 (diff) | |
Merge "Merge Android R"
Diffstat (limited to 'native/android')
| -rw-r--r-- | native/android/Android.bp | 21 | ||||
| -rw-r--r-- | native/android/choreographer.cpp | 223 | ||||
| -rw-r--r-- | native/android/libandroid.map.txt | 8 | ||||
| -rw-r--r-- | native/android/surface_control.cpp | 30 | ||||
| -rw-r--r-- | native/android/surface_texture.cpp | 56 | ||||
| -rw-r--r-- | native/android/system_fonts.cpp | 61 | ||||
| -rw-r--r-- | native/android/thermal.cpp | 261 |
7 files changed, 386 insertions, 274 deletions
diff --git a/native/android/Android.bp b/native/android/Android.bp index 8f36decec400..797d3fd8c2ff 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -25,6 +25,7 @@ cc_defaults { cflags: [ "-Wall", "-Werror", + "-Wextra", "-Wunused", "-Wunreachable-code", ], @@ -48,10 +49,11 @@ cc_library_shared { "sensor.cpp", "sharedmem.cpp", "storage_manager.cpp", - "surface_texture.cpp", "surface_control.cpp", + "surface_texture.cpp", "system_fonts.cpp", "trace.cpp", + "thermal.cpp" ], shared_libs: [ @@ -71,8 +73,12 @@ cc_library_shared { "libnetd_client", "libhwui", "libxml2", + "libEGL", + "libGLESv2", + "libpowermanager", "android.hardware.configstore@1.0", "android.hardware.configstore-utils", + "libnativedisplay", ], static_libs: [ @@ -80,6 +86,8 @@ cc_library_shared { "libarect", ], + header_libs: [ "libhwui_internal_headers",], + whole_static_libs: ["libnativewindow"], export_static_lib_headers: ["libarect"], @@ -115,11 +123,16 @@ llndk_library { // Aidl library for platform compat. cc_library_shared { name: "lib-platform-compat-native-api", - defaults: ["libandroid_defaults"], - + cflags: [ + "-Wall", + "-Werror", + "-Wno-missing-field-initializers", + "-Wno-unused-variable", + "-Wunused-parameter", + ], shared_libs: [ "libbinder", - "libutils", + "libutils", ], aidl: { local_include_dirs: ["aidl"], diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp index 63e073405fe0..38641de0efb3 100644 --- a/native/android/choreographer.cpp +++ b/native/android/choreographer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015 The Android Open Source Project + * Copyright 2020 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. @@ -14,212 +14,39 @@ * limitations under the License. */ -#define LOG_TAG "Choreographer" -//#define LOG_NDEBUG 0 +#include <private/android/choreographer.h> -#include <cinttypes> -#include <queue> -#include <thread> - -#include <android/choreographer.h> -#include <androidfw/DisplayEventDispatcher.h> -#include <gui/ISurfaceComposer.h> -#include <gui/SurfaceComposerClient.h> -#include <utils/Looper.h> -#include <utils/Mutex.h> -#include <utils/Timers.h> - -namespace android { - -static inline const char* toString(bool value) { - return value ? "true" : "false"; -} - -struct FrameCallback { - AChoreographer_frameCallback callback; - AChoreographer_frameCallback64 callback64; - void* data; - nsecs_t dueTime; - - inline bool operator<(const FrameCallback& rhs) const { - // Note that this is intentionally flipped because we want callbacks due sooner to be at - // the head of the queue - return dueTime > rhs.dueTime; - } -}; - - -class Choreographer : public DisplayEventDispatcher, public MessageHandler { -public: - void postFrameCallbackDelayed(AChoreographer_frameCallback cb, - AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay); - - enum { - MSG_SCHEDULE_CALLBACKS = 0, - MSG_SCHEDULE_VSYNC = 1 - }; - virtual void handleMessage(const Message& message) override; - - static Choreographer* getForThread(); - -protected: - virtual ~Choreographer() = default; - -private: - explicit Choreographer(const sp<Looper>& looper); - Choreographer(const Choreographer&) = delete; - - void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override; - void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; - void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, - int32_t configId) override; - - void scheduleCallbacks(); - - // Protected by mLock - std::priority_queue<FrameCallback> mCallbacks; - - mutable Mutex mLock; - - const sp<Looper> mLooper; - const std::thread::id mThreadId; -}; - - -static thread_local Choreographer* gChoreographer; -Choreographer* Choreographer::getForThread() { - if (gChoreographer == nullptr) { - sp<Looper> looper = Looper::getForThread(); - if (!looper.get()) { - ALOGW("No looper prepared for thread"); - return nullptr; - } - gChoreographer = new Choreographer(looper); - status_t result = gChoreographer->initialize(); - if (result != OK) { - ALOGW("Failed to initialize"); - return nullptr; - } - } - return gChoreographer; -} - -Choreographer::Choreographer(const sp<Looper>& looper) : - DisplayEventDispatcher(looper), mLooper(looper), mThreadId(std::this_thread::get_id()) { -} - -void Choreographer::postFrameCallbackDelayed( - AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) { - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - FrameCallback callback{cb, cb64, data, now + delay}; - { - AutoMutex _l{mLock}; - mCallbacks.push(callback); - } - if (callback.dueTime <= now) { - if (std::this_thread::get_id() != mThreadId) { - Message m{MSG_SCHEDULE_VSYNC}; - mLooper->sendMessage(this, m); - } else { - scheduleVsync(); - } - } else { - Message m{MSG_SCHEDULE_CALLBACKS}; - mLooper->sendMessageDelayed(delay, this, m); - } -} - -void Choreographer::scheduleCallbacks() { - AutoMutex _{mLock}; - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (mCallbacks.top().dueTime <= now) { - ALOGV("choreographer %p ~ scheduling vsync", this); - scheduleVsync(); - return; - } -} - -// TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the -// internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for -// the internal display implicitly. -void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t) { - std::vector<FrameCallback> callbacks{}; - { - AutoMutex _l{mLock}; - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - while (!mCallbacks.empty() && mCallbacks.top().dueTime < now) { - callbacks.push_back(mCallbacks.top()); - mCallbacks.pop(); - } - } - for (const auto& cb : callbacks) { - if (cb.callback64 != nullptr) { - cb.callback64(timestamp, cb.data); - } else if (cb.callback != nullptr) { - cb.callback(timestamp, cb.data); - } - } -} - -void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool connected) { - ALOGV("choreographer %p ~ received hotplug event (displayId=%" - ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", connected=%s), ignoring.", - this, displayId, toString(connected)); -} - -void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, - int32_t configId) { - ALOGV("choreographer %p ~ received config changed event (displayId=%" - ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%s), ignoring.", - this, displayId, toString(configId)); -} - -void Choreographer::handleMessage(const Message& message) { - switch (message.what) { - case MSG_SCHEDULE_CALLBACKS: - scheduleCallbacks(); - break; - case MSG_SCHEDULE_VSYNC: - scheduleVsync(); - break; - } -} - -} - -/* Glue for the NDK interface */ - -using android::Choreographer; - -static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) { - return reinterpret_cast<Choreographer*>(choreographer); -} - -static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) { - return reinterpret_cast<AChoreographer*>(choreographer); -} +using namespace android; AChoreographer* AChoreographer_getInstance() { - return Choreographer_to_AChoreographer(Choreographer::getForThread()); + return AChoreographer_routeGetInstance(); } - void AChoreographer_postFrameCallback(AChoreographer* choreographer, - AChoreographer_frameCallback callback, void* data) { - AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( - callback, nullptr, data, 0); + AChoreographer_frameCallback callback, void* data) { + return AChoreographer_routePostFrameCallback(choreographer, callback, data); } void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, - AChoreographer_frameCallback callback, void* data, long delayMillis) { - AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( - callback, nullptr, data, ms2ns(delayMillis)); + AChoreographer_frameCallback callback, void* data, + long delayMillis) { + return AChoreographer_routePostFrameCallbackDelayed(choreographer, callback, data, delayMillis); } void AChoreographer_postFrameCallback64(AChoreographer* choreographer, - AChoreographer_frameCallback64 callback, void* data) { - AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( - nullptr, callback, data, 0); + AChoreographer_frameCallback64 callback, void* data) { + return AChoreographer_routePostFrameCallback64(choreographer, callback, data); } void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer, - AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) { - AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( - nullptr, callback, data, ms2ns(delayMillis)); + AChoreographer_frameCallback64 callback, void* data, + uint32_t delayMillis) { + return AChoreographer_routePostFrameCallbackDelayed64(choreographer, callback, data, + delayMillis); +} +void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback callback, + void* data) { + return AChoreographer_routeRegisterRefreshRateCallback(choreographer, callback, data); +} +void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback callback, + void* data) { + return AChoreographer_routeUnregisterRefreshRateCallback(choreographer, callback, data); } diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index 203adfc749d2..d56aa86ae6fa 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -23,6 +23,8 @@ LIBANDROID { AChoreographer_postFrameCallbackDelayed; # introduced=24 AChoreographer_postFrameCallback64; # introduced=29 AChoreographer_postFrameCallbackDelayed64; # introduced=29 + AChoreographer_registerRefreshRateCallback; # introduced=30 + AChoreographer_unregisterRefreshRateCallback; # introduced=30 AConfiguration_copy; AConfiguration_delete; AConfiguration_diff; @@ -240,6 +242,7 @@ LIBANDROID { ASurfaceTransaction_setColor; # introduced=29 ASurfaceTransaction_setDamageRegion; # introduced=29 ASurfaceTransaction_setDesiredPresentTime; # introduced=29 + ASurfaceTransaction_setFrameRate; # introduced=30 ASurfaceTransaction_setGeometry; # introduced=29 ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29 ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29 @@ -277,6 +280,11 @@ LIBANDROID { android_res_nquery; # introduced=29 android_res_nresult; # introduced=29 android_res_nsend; # introduced=29 + AThermal_acquireManager; # introduced=30 + AThermal_releaseManager; # introduced=30 + AThermal_getCurrentThermalStatus; # introduced=30 + AThermal_registerThermalStatusListener; # introduced=30 + AThermal_unregisterThermalStatusListener; # introduced=30 local: *; }; diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp index 8fe4fecceeb5..0af6cbf3cb40 100644 --- a/native/android/surface_control.cpp +++ b/native/android/surface_control.cpp @@ -100,7 +100,11 @@ static bool isDataSpaceValid(const sp<SurfaceControl>& surfaceControl, ADataSpac return getWideColorSupport(surfaceControl); // These data space need HDR support. case HAL_DATASPACE_BT2020_PQ: - return getHdrSupport(surfaceControl); + if (!getHdrSupport(surfaceControl)) { + ALOGE("Invalid dataspace - device does not support hdr"); + return false; + } + return true; default: return false; } @@ -290,7 +294,7 @@ void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats; - for (const auto& [surfaceControl, acquireTime, previousReleaseFence] : surfaceControlStats) { + for (const auto& [surfaceControl, latchTime, acquireTime, presentFence, previousReleaseFence, transformHint, frameEvents] : surfaceControlStats) { ASurfaceControl* aSurfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); aSurfaceControlStats[aSurfaceControl].acquireTime = acquireTime; aSurfaceControlStats[aSurfaceControl].previousReleaseFence = previousReleaseFence; @@ -458,10 +462,11 @@ void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* aSurfaceTransac CHECK_NOT_NULL(aSurfaceControl); sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); - LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, aDataSpace), "invalid dataspace"); - + if (!isDataSpaceValid(surfaceControl, aDataSpace)) { + ALOGE("Failed to set buffer dataspace - invalid dataspace"); + return; + } Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); - transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace)); } @@ -527,7 +532,10 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, CHECK_NOT_NULL(aSurfaceControl); sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); - LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, dataspace), "invalid dataspace"); + if (!isDataSpaceValid(surfaceControl, dataspace)) { + ALOGE("Failed to set buffer dataspace - invalid dataspace"); + return; + } Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); half3 color; @@ -537,3 +545,13 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, transaction->setBackgroundColor(surfaceControl, color, alpha, static_cast<ui::Dataspace>(dataspace)); } + +void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, float frameRate, + int8_t compatibility) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + transaction->setFrameRate(surfaceControl, frameRate, compatibility); +} diff --git a/native/android/surface_texture.cpp b/native/android/surface_texture.cpp index ced2792775d4..ff35204b2ec9 100644 --- a/native/android/surface_texture.cpp +++ b/native/android/surface_texture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2020 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. @@ -14,63 +14,39 @@ * limitations under the License. */ -#include <android/surface_texture.h> #include <android/surface_texture_jni.h> - -#define LOG_TAG "ASurfaceTexture" - -#include <utils/Log.h> - -#include <gui/Surface.h> - -#include <android_runtime/android_graphics_SurfaceTexture.h> - -#include "surfacetexture/SurfaceTexture.h" +#include <surfacetexture/surface_texture_platform.h> using namespace android; -struct ASurfaceTexture { - sp<SurfaceTexture> consumer; - sp<IGraphicBufferProducer> producer; -}; - -ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) { - if (!surfacetexture || !android_SurfaceTexture_isInstanceOf(env, surfacetexture)) { - return nullptr; - } - ASurfaceTexture* ast = new ASurfaceTexture; - ast->consumer = SurfaceTexture_getSurfaceTexture(env, surfacetexture); - ast->producer = SurfaceTexture_getProducer(env, surfacetexture); - return ast; -} - ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) { - sp<Surface> surface = new Surface(st->producer); - ANativeWindow* win(surface.get()); - ANativeWindow_acquire(win); - return win; + return ASurfaceTexture_routeAcquireANativeWindow(st); } -void ASurfaceTexture_release(ASurfaceTexture* st) { - delete st; +int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName) { + return ASurfaceTexture_routeAttachToGLContext(st, texName); } -int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t tex) { - return st->consumer->attachToContext(tex); +int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) { + return ASurfaceTexture_routeDetachFromGLContext(st); } -int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) { - return st->consumer->detachFromContext(); +void ASurfaceTexture_release(ASurfaceTexture* st) { + return ASurfaceTexture_routeRelease(st); } int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) { - return st->consumer->updateTexImage(); + return ASurfaceTexture_routeUpdateTexImage(st); } void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) { - st->consumer->getTransformMatrix(mtx); + return ASurfaceTexture_routeGetTransformMatrix(st, mtx); } int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) { - return st->consumer->getTimestamp(); + return ASurfaceTexture_routeGetTimestamp(st); +} + +ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) { + return ASurfaceTexture_routeFromSurfaceTexture(env, surfacetexture); } diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp index 9791da63359b..45f42f1b5dc6 100644 --- a/native/android/system_fonts.cpp +++ b/native/android/system_fonts.cpp @@ -16,6 +16,8 @@ #include <jni.h> +#define LOG_TAG "SystemFont" + #include <android/font.h> #include <android/font_matcher.h> #include <android/system_fonts.h> @@ -47,9 +49,14 @@ struct XmlDocDeleter { using XmlCharUniquePtr = std::unique_ptr<xmlChar, XmlCharDeleter>; using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>; +struct ParserState { + xmlNode* mFontNode = nullptr; + XmlCharUniquePtr mLocale; +}; + struct ASystemFontIterator { XmlDocUniquePtr mXmlDoc; - xmlNode* mFontNode; + ParserState state; // The OEM customization XML. XmlDocUniquePtr mCustomizationXmlDoc; @@ -97,6 +104,7 @@ std::string xmlTrim(const std::string& in) { const xmlChar* FAMILY_TAG = BAD_CAST("family"); const xmlChar* FONT_TAG = BAD_CAST("font"); +const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang"); xmlNode* firstElement(xmlNode* node, const xmlChar* tag) { for (xmlNode* child = node->children; child; child = child->next) { @@ -116,9 +124,9 @@ xmlNode* nextSibling(xmlNode* node, const xmlChar* tag) { return nullptr; } -void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, AFont* out, +void copyFont(const XmlDocUniquePtr& xmlDoc, const ParserState& state, AFont* out, const std::string& pathPrefix) { - const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang"); + xmlNode* fontNode = state.mFontNode; XmlCharUniquePtr filePathStr( xmlNodeListGetString(xmlDoc.get(), fontNode->xmlChildrenNode, 1)); out->mFilePath = pathPrefix + xmlTrim( @@ -139,9 +147,10 @@ void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, AFont* out, out->mCollectionIndex = indexStr ? strtol(reinterpret_cast<const char*>(indexStr.get()), nullptr, 10) : 0; - XmlCharUniquePtr localeStr(xmlGetProp(xmlDoc->parent, LOCALE_ATTR_NAME)); out->mLocale.reset( - localeStr ? new std::string(reinterpret_cast<const char*>(localeStr.get())) : nullptr); + state.mLocale ? + new std::string(reinterpret_cast<const char*>(state.mLocale.get())) + : nullptr); const xmlChar* TAG_ATTR_NAME = BAD_CAST("tag"); const xmlChar* STYLEVALUE_ATTR_NAME = BAD_CAST("stylevalue"); @@ -178,25 +187,27 @@ bool isFontFileAvailable(const std::string& filePath) { return S_ISREG(st.st_mode); } -xmlNode* findFirstFontNode(const XmlDocUniquePtr& doc) { +bool findFirstFontNode(const XmlDocUniquePtr& doc, ParserState* state) { xmlNode* familySet = xmlDocGetRootElement(doc.get()); if (familySet == nullptr) { - return nullptr; + return false; } xmlNode* family = firstElement(familySet, FAMILY_TAG); if (family == nullptr) { - return nullptr; + return false; } + state->mLocale.reset(xmlGetProp(family, LOCALE_ATTR_NAME)); xmlNode* font = firstElement(family, FONT_TAG); while (font == nullptr) { family = nextSibling(family, FAMILY_TAG); if (family == nullptr) { - return nullptr; + return false; } font = firstElement(family, FONT_TAG); } - return font; + state->mFontNode = font; + return font != nullptr; } } // namespace @@ -272,38 +283,38 @@ AFont* _Nonnull AFontMatcher_match( return result.release(); } -xmlNode* findNextFontNode(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode) { - if (fontNode == nullptr) { +bool findNextFontNode(const XmlDocUniquePtr& xmlDoc, ParserState* state) { + if (state->mFontNode == nullptr) { if (!xmlDoc) { - return nullptr; // Already at the end. + return false; // Already at the end. } else { // First time to query font. - return findFirstFontNode(xmlDoc); + return findFirstFontNode(xmlDoc, state); } } else { - xmlNode* nextNode = nextSibling(fontNode, FONT_TAG); + xmlNode* nextNode = nextSibling(state->mFontNode, FONT_TAG); while (nextNode == nullptr) { - xmlNode* family = nextSibling(fontNode->parent, FAMILY_TAG); + xmlNode* family = nextSibling(state->mFontNode->parent, FAMILY_TAG); if (family == nullptr) { break; } + state->mLocale.reset(xmlGetProp(family, LOCALE_ATTR_NAME)); nextNode = firstElement(family, FONT_TAG); } - return nextNode; + state->mFontNode = nextNode; + return nextNode != nullptr; } } AFont* ASystemFontIterator_next(ASystemFontIterator* ite) { LOG_ALWAYS_FATAL_IF(ite == nullptr, "nullptr has passed as iterator argument"); if (ite->mXmlDoc) { - ite->mFontNode = findNextFontNode(ite->mXmlDoc, ite->mFontNode); - if (ite->mFontNode == nullptr) { + if (!findNextFontNode(ite->mXmlDoc, &ite->state)) { // Reached end of the XML file. Continue OEM customization. ite->mXmlDoc.reset(); - ite->mFontNode = nullptr; } else { std::unique_ptr<AFont> font = std::make_unique<AFont>(); - copyFont(ite->mXmlDoc, ite->mFontNode, font.get(), "/system/fonts/"); + copyFont(ite->mXmlDoc, ite->state, font.get(), "/system/fonts/"); if (!isFontFileAvailable(font->mFilePath)) { return ASystemFontIterator_next(ite); } @@ -312,15 +323,13 @@ AFont* ASystemFontIterator_next(ASystemFontIterator* ite) { } if (ite->mCustomizationXmlDoc) { // TODO: Filter only customizationType="new-named-family" - ite->mFontNode = findNextFontNode(ite->mCustomizationXmlDoc, ite->mFontNode); - if (ite->mFontNode == nullptr) { + if (!findNextFontNode(ite->mCustomizationXmlDoc, &ite->state)) { // Reached end of the XML file. Finishing ite->mCustomizationXmlDoc.reset(); - ite->mFontNode = nullptr; return nullptr; } else { std::unique_ptr<AFont> font = std::make_unique<AFont>(); - copyFont(ite->mCustomizationXmlDoc, ite->mFontNode, font.get(), "/product/fonts/"); + copyFont(ite->mCustomizationXmlDoc, ite->state, font.get(), "/product/fonts/"); if (!isFontFileAvailable(font->mFilePath)) { return ASystemFontIterator_next(ite); } @@ -351,7 +360,7 @@ bool AFont_isItalic(const AFont* font) { const char* AFont_getLocale(const AFont* font) { LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); - return font->mLocale ? nullptr : font->mLocale->c_str(); + return font->mLocale ? font->mLocale->c_str() : nullptr; } size_t AFont_getCollectionIndex(const AFont* font) { diff --git a/native/android/thermal.cpp b/native/android/thermal.cpp new file mode 100644 index 000000000000..545c423908a0 --- /dev/null +++ b/native/android/thermal.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2020 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 "thermal" + +#include <cerrno> +#include <thread> + +#include <android/thermal.h> +#include <android/os/BnThermalStatusListener.h> +#include <android/os/IThermalService.h> +#include <binder/IServiceManager.h> +#include <utils/Log.h> + +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; +}; + +struct ListenerCallback { + AThermal_StatusCallback callback; + void* data; +}; + +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); + private: + AThermalManager(sp<IThermalService> service); + sp<IThermalService> mThermalSvc; + sp<ThermalServiceListener> mServiceListener; + std::vector<ListenerCallback> mListeners; + std::mutex mMutex; +}; + +binder::Status ThermalServiceListener::onStatusChange(int32_t status) { + if (mMgr != nullptr) { + mMgr->notifyStateChange(status); + } + return binder::Status::ok(); +} + +AThermalManager* AThermalManager::createAThermalManager() { + sp<IBinder> binder = + defaultServiceManager()->checkService(String16("thermalservice")); + + if (binder == nullptr) { + ALOGE("%s: Thermal service is not ready ", __FUNCTION__); + return nullptr; + } + return new AThermalManager(interface_cast<IThermalService>(binder)); +} + +AThermalManager::AThermalManager(sp<IThermalService> service) + : mThermalSvc(service), + mServiceListener(nullptr) { +} + +AThermalManager::~AThermalManager() { + std::unique_lock<std::mutex> lock(mMutex); + + mListeners.clear(); + if (mServiceListener != nullptr) { + bool success = false; + mThermalSvc->unregisterThermalStatusListener(mServiceListener, &success); + mServiceListener = nullptr; + } +} + +status_t AThermalManager::notifyStateChange(int32_t status) { + std::unique_lock<std::mutex> lock(mMutex); + AThermalStatus thermalStatus = static_cast<AThermalStatus>(status); + + for (auto listener : mListeners) { + listener.callback(listener.data, thermalStatus); + } + return OK; +} + +status_t AThermalManager::addListener(AThermal_StatusCallback callback, void *data) { + std::unique_lock<std::mutex> lock(mMutex); + + if (callback == nullptr) { + // Callback can not be nullptr + return EINVAL; + } + for (const auto& cb : mListeners) { + // Don't re-add callbacks. + if (callback == cb.callback && data == cb.data) { + return EINVAL; + } + } + mListeners.emplace_back(ListenerCallback{callback, data}); + + if (mServiceListener != nullptr) { + return OK; + } + bool success = false; + mServiceListener = new ThermalServiceListener(this); + if (mServiceListener == nullptr) { + return ENOMEM; + } + auto ret = mThermalSvc->registerThermalStatusListener(mServiceListener, &success); + if (!success || !ret.isOk()) { + ALOGE("Failed in registerThermalStatusListener %d", success); + if (ret.exceptionCode() == binder::Status::EX_SECURITY) { + return EPERM; + } + return EPIPE; + } + return OK; +} + +status_t AThermalManager::removeListener(AThermal_StatusCallback callback, void *data) { + std::unique_lock<std::mutex> lock(mMutex); + + auto it = std::remove_if(mListeners.begin(), + mListeners.end(), + [&](const ListenerCallback& cb) { + return callback == cb.callback && + data == cb.data; + }); + if (it == mListeners.end()) { + // If the listener and data pointer were not previously added. + return EINVAL; + } + mListeners.erase(it, mListeners.end()); + + if (!mListeners.empty()) { + return OK; + } + if (mServiceListener == nullptr) { + return OK; + } + bool success = false; + auto ret = mThermalSvc->unregisterThermalStatusListener(mServiceListener, &success); + if (!success || !ret.isOk()) { + ALOGE("Failed in unregisterThermalStatusListener %d", success); + if (ret.exceptionCode() == binder::Status::EX_SECURITY) { + return EPERM; + } + return EPIPE; + } + mServiceListener = nullptr; + return OK; +} + +status_t AThermalManager::getCurrentThermalStatus(int32_t *status) { + binder::Status ret = mThermalSvc->getCurrentThermalStatus(status); + + if (!ret.isOk()) { + if (ret.exceptionCode() == binder::Status::EX_SECURITY) { + return EPERM; + } + return EPIPE; + } + return OK; +} + +/** + * Acquire an instance of the thermal manager. This must be freed using + * {@link AThermal_releaseManager}. + * + * @return manager instance on success, nullptr on failure. + */ +AThermalManager* AThermal_acquireManager() { + auto manager = AThermalManager::createAThermalManager(); + + return manager; +} + +/** + * Release the thermal manager pointer acquired by + * {@link AThermal_acquireManager}. + * + * @param manager The manager to be released. + * + */ +void AThermal_releaseManager(AThermalManager *manager) { + delete manager; +} + +/** + * Gets the current thermal status. + * + * @param manager The manager instance to use to query the thermal status, + * acquired by {@link AThermal_acquireManager}. + * + * @return current thermal status, ATHERMAL_STATUS_ERROR on failure. +*/ +AThermalStatus AThermal_getCurrentThermalStatus(AThermalManager *manager) { + int32_t status = 0; + status_t ret = manager->getCurrentThermalStatus(&status); + if (ret != OK) { + return AThermalStatus::ATHERMAL_STATUS_ERROR; + } + return static_cast<AThermalStatus>(status); +} + +/** + * Register the thermal status listener for thermal status change. + * + * @param manager The manager instance to use to register. + * acquired by {@link AThermal_acquireManager}. + * @param callback The callback function to be called when thermal status updated. + * @param data The data pointer to be passed when callback is called. + * + * @return 0 on success + * EINVAL if the listener and data pointer were previously added and not removed. + * EPERM if the required permission is not held. + * EPIPE if communication with the system service has failed. + */ +int AThermal_registerThermalStatusListener(AThermalManager *manager, + AThermal_StatusCallback callback, void *data) { + return manager->addListener(callback, data); +} + +/** + * Unregister the thermal status listener previously resgistered. + * + * @param manager The manager instance to use to unregister. + * acquired by {@link AThermal_acquireManager}. + * @param callback The callback function to be called when thermal status updated. + * @param data The data pointer to be passed when callback is called. + * + * @return 0 on success + * EINVAL if the listener and data pointer were not previously added. + * EPERM if the required permission is not held. + * EPIPE if communication with the system service has failed. + */ +int AThermal_unregisterThermalStatusListener(AThermalManager *manager, + AThermal_StatusCallback callback, void *data) { + return manager->removeListener(callback, data); +} |