diff options
Diffstat (limited to 'native')
29 files changed, 1755 insertions, 202 deletions
diff --git a/native/android/Android.bp b/native/android/Android.bp index 4fb5e748aaac..7c1af4a81f9d 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -49,11 +49,14 @@ cc_library_shared { "sharedmem.cpp", "storage_manager.cpp", "surface_texture.cpp", + "surface_control.cpp", + "system_fonts.cpp", "trace.cpp", ], shared_libs: [ "liblog", + "libhidlbase", "libcutils", "libandroidfw", "libinput", @@ -61,9 +64,15 @@ cc_library_shared { "libbinder", "libui", "libgui", + "libharfbuzz_ng", // Only for including hb.h via minikin "libsensor", "libandroid_runtime", + "libminikin", "libnetd_client", + "libhwui", + "libxml2", + "android.hardware.configstore@1.0", + "android.hardware.configstore-utils", ], static_libs: [ @@ -76,6 +85,12 @@ cc_library_shared { export_static_lib_headers: ["libarect"], include_dirs: ["bionic/libc/dns/include"], + + version_script: "libandroid.map.txt", + stubs: { + symbol_file: "libandroid.map.txt", + versions: ["29"], + }, } // Network library. diff --git a/native/android/OWNERS b/native/android/OWNERS index 11d4be43571e..266764a6f607 100644 --- a/native/android/OWNERS +++ b/native/android/OWNERS @@ -1,11 +1,4 @@ set noparent -per-file libandroid_net.map.txt=ek@google.com -per-file libandroid_net.map.txt=jchalard@google.com -per-file libandroid_net.map.txt=lorenzo@google.com -per-file libandroid_net.map.txt=satk@google.com - -per-file net.c=ek@google.com -per-file net.c=jchalard@google.com -per-file net.c=lorenzo@google.com -per-file net.c=satk@google.com +per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com +per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com diff --git a/native/android/choreographer.cpp b/native/android/choreographer.cpp index c3629da1cb12..63e073405fe0 100644 --- a/native/android/choreographer.cpp +++ b/native/android/choreographer.cpp @@ -24,6 +24,7 @@ #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> @@ -36,6 +37,7 @@ static inline const char* toString(bool value) { struct FrameCallback { AChoreographer_frameCallback callback; + AChoreographer_frameCallback64 callback64; void* data; nsecs_t dueTime; @@ -49,8 +51,8 @@ struct FrameCallback { class Choreographer : public DisplayEventDispatcher, public MessageHandler { public: - void postFrameCallback(AChoreographer_frameCallback cb, void* data); - void postFrameCallbackDelayed(AChoreographer_frameCallback cb, void* data, nsecs_t delay); + void postFrameCallbackDelayed(AChoreographer_frameCallback cb, + AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay); enum { MSG_SCHEDULE_CALLBACKS = 0, @@ -67,8 +69,10 @@ private: explicit Choreographer(const sp<Looper>& looper); Choreographer(const Choreographer&) = delete; - virtual void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count); - virtual void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected); + 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(); @@ -104,14 +108,10 @@ Choreographer::Choreographer(const sp<Looper>& looper) : DisplayEventDispatcher(looper), mLooper(looper), mThreadId(std::this_thread::get_id()) { } -void Choreographer::postFrameCallback(AChoreographer_frameCallback cb, void* data) { - postFrameCallbackDelayed(cb, data, 0); -} - void Choreographer::postFrameCallbackDelayed( - AChoreographer_frameCallback cb, void* data, nsecs_t delay) { + AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, void* data, nsecs_t delay) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - FrameCallback callback{cb, data, now + delay}; + FrameCallback callback{cb, cb64, data, now + delay}; { AutoMutex _l{mLock}; mCallbacks.push(callback); @@ -139,13 +139,10 @@ void Choreographer::scheduleCallbacks() { } } - -void Choreographer::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t) { - if (id != ISurfaceComposer::eDisplayIdMain) { - ALOGV("choreographer %p ~ ignoring vsync signal for non-main display (id=%d)", this, id); - 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}; @@ -156,13 +153,25 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t) { } } for (const auto& cb : callbacks) { - cb.callback(timestamp, cb.data); + if (cb.callback64 != nullptr) { + cb.callback64(timestamp, cb.data); + } else if (cb.callback != nullptr) { + cb.callback(timestamp, cb.data); + } } } -void Choreographer::dispatchHotplug(nsecs_t, int32_t id, bool connected) { - ALOGV("choreographer %p ~ received hotplug event (id=%" PRId32 ", connected=%s), ignoring.", - this, id, toString(connected)); +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) { @@ -196,10 +205,21 @@ AChoreographer* AChoreographer_getInstance() { void AChoreographer_postFrameCallback(AChoreographer* choreographer, AChoreographer_frameCallback callback, void* data) { - AChoreographer_to_Choreographer(choreographer)->postFrameCallback(callback, data); + AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( + callback, nullptr, data, 0); } void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, AChoreographer_frameCallback callback, void* data, long delayMillis) { AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( - callback, data, ms2ns(delayMillis)); + callback, nullptr, data, ms2ns(delayMillis)); +} +void AChoreographer_postFrameCallback64(AChoreographer* choreographer, + AChoreographer_frameCallback64 callback, void* data) { + AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( + nullptr, callback, data, 0); +} +void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer, + AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) { + AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( + nullptr, callback, data, ms2ns(delayMillis)); } diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index d6dcd723e721..177f2b8ee491 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -21,6 +21,8 @@ LIBANDROID { AChoreographer_getInstance; # introduced=24 AChoreographer_postFrameCallback; # introduced=24 AChoreographer_postFrameCallbackDelayed; # introduced=24 + AChoreographer_postFrameCallback64; # introduced=29 + AChoreographer_postFrameCallbackDelayed64; # introduced=29 AConfiguration_copy; AConfiguration_delete; AConfiguration_diff; @@ -144,7 +146,10 @@ LIBANDROID { AHardwareBuffer_describe; # introduced=26 AHardwareBuffer_fromHardwareBuffer; # introduced=26 AHardwareBuffer_getNativeHandle; # introduced=26 + AHardwareBuffer_isSupported; # introduced=29 AHardwareBuffer_lock; # introduced=26 + AHardwareBuffer_lockAndGetInfo; # introduced=29 + AHardwareBuffer_lockPlanes; # introduced=29 AHardwareBuffer_recvHandleFromUnixSocket; # introduced=26 AHardwareBuffer_release; # introduced=26 AHardwareBuffer_sendHandleToUnixSocket; # introduced=26 @@ -152,7 +157,6 @@ LIBANDROID { AHardwareBuffer_unlock; # introduced=26 ANativeWindow_acquire; ANativeWindow_fromSurface; - ANativeWindow_fromSurfaceTexture; # introduced-arm=13 introduced-mips=13 introduced-x86=13 ANativeWindow_toSurface; # introduced=26 ANativeWindow_getFormat; ANativeWindow_getHeight; @@ -172,6 +176,7 @@ LIBANDROID { ASensorEventQueue_hasEvents; ASensorEventQueue_registerSensor; # introduced=26 ASensorEventQueue_setEventRate; + ASensorEventQueue_requestAdditionalInfoEvents; # introduced=29 ASensorManager_configureDirectReport; # introduced=26 ASensorManager_createEventQueue; ASensorManager_createHardwareBufferDirectChannel; # introduced=26 @@ -185,6 +190,7 @@ LIBANDROID { ASensorManager_getSensorList; ASensor_getFifoMaxEventCount; # introduced=21 ASensor_getFifoReservedEventCount; # introduced=21 + ASensor_getHandle; # introduced=29 ASensor_getHighestDirectReportRateLevel; # introduced=26 ASensor_getMinDelay; ASensor_getName; @@ -205,6 +211,9 @@ LIBANDROID { AStorageManager_mountObb; AStorageManager_new; AStorageManager_unmountObb; + ASurfaceControl_create; # introduced=29 + ASurfaceControl_createFromWindow; # introduced=29 + ASurfaceControl_release; # introduced=29 ASurfaceTexture_acquireANativeWindow; # introduced=28 ASurfaceTexture_attachToGLContext; # introduced=28 ASurfaceTexture_detachFromGLContext; # introduced=28 @@ -213,12 +222,60 @@ LIBANDROID { ASurfaceTexture_getTransformMatrix; # introduced=28 ASurfaceTexture_release; # introduced=28 ASurfaceTexture_updateTexImage; # introduced=28 + ASurfaceTransactionStats_getAcquireTime; # introduced=29 + ASurfaceTransactionStats_getASurfaceControls; # introduced=29 + ASurfaceTransactionStats_getLatchTime; # introduced=29 + ASurfaceTransactionStats_getPresentFenceFd; # introduced=29 + ASurfaceTransactionStats_getPreviousReleaseFenceFd; # introduced=29 + ASurfaceTransactionStats_releaseASurfaceControls; # introduced=29 + ASurfaceTransaction_apply; # introduced=29 + ASurfaceTransaction_create; # introduced=29 + ASurfaceTransaction_delete; # introduced=29 + ASurfaceTransaction_reparent; # introduced=29 + ASurfaceTransaction_setBuffer; # introduced=29 + ASurfaceTransaction_setBufferAlpha; # introduced=29 + ASurfaceTransaction_setBufferDataSpace; # introduced=29 + ASurfaceTransaction_setBufferTransparency; # introduced=29 + ASurfaceTransaction_setColor; # introduced=29 + ASurfaceTransaction_setDamageRegion; # introduced=29 + ASurfaceTransaction_setDesiredPresentTime; # introduced=29 + ASurfaceTransaction_setGeometry; # introduced=29 + ASurfaceTransaction_setHdrMetadata_cta861_3; # introduced=29 + ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29 + ASurfaceTransaction_setOnComplete; # introduced=29 + ASurfaceTransaction_setVisibility; # introduced=29 + ASurfaceTransaction_setZOrder; # introduced=29 + ASystemFontIterator_open; # introduced=29 + ASystemFontIterator_close; # introduced=29 + ASystemFontIterator_next; # introduced=29 + AFont_close; # introduced=29 + AFont_getFontFilePath; # introduced=29 + AFont_getWeight; # introduced=29 + AFont_isItalic; # introduced=29 + AFont_getLocale; # introduced=29 + AFont_getCollectionIndex; # introduced=29 + AFont_getAxisCount; # introduced=29 + AFont_getAxisTag; # introduced=29 + AFont_getAxisValue; # introduced=29 + AFontMatcher_create; # introduced=29 + AFontMatcher_destroy; # introduced=29 + AFontMatcher_setStyle; # introduced=29 + AFontMatcher_setLocales; # introduced=29 + AFontMatcher_setFamilyVariant; # introduced=29 + AFontMatcher_match; # introduced=29 ATrace_beginSection; # introduced=23 ATrace_endSection; # introduced=23 ATrace_isEnabled; # introduced=23 + ATrace_beginAsyncSection; # introduced=29 + ATrace_endAsyncSection; # introduced=29 + ATrace_setCounter; # introduced=29 android_getaddrinfofornetwork; # introduced=23 android_setprocnetwork; # introduced=23 android_setsocknetwork; # introduced=23 + android_res_cancel; # introduced=29 + android_res_nquery; # introduced=29 + android_res_nresult; # introduced=29 + android_res_nsend; # introduced=29 local: *; }; diff --git a/native/android/libandroid_net.map.txt b/native/android/libandroid_net.map.txt index 9b5a5a1f4b52..be3531da462d 100644 --- a/native/android/libandroid_net.map.txt +++ b/native/android/libandroid_net.map.txt @@ -1,10 +1,15 @@ -# These functions have been part of the NDK since API 24. # They are also all available to vendor code. LIBANDROID_NET { global: + # These functions have been part of the NDK since API 24. + android_getaddrinfofornetwork; # vndk android_setsocknetwork; # vndk android_setprocnetwork; # vndk - android_getaddrinfofornetwork; # vndk + # These functions have been part of the NDK since API 29. + android_res_cancel; # vndk + android_res_nquery; # vndk + android_res_nresult; # vndk + android_res_nsend; # vndk local: *; }; diff --git a/native/android/net.c b/native/android/net.c index 60296a7bd00c..a8104fc23041 100644 --- a/native/android/net.c +++ b/native/android/net.c @@ -83,3 +83,31 @@ int android_getaddrinfofornetwork(net_handle_t network, return android_getaddrinfofornet(node, service, hints, netid, 0, res); } + +int android_res_nquery(net_handle_t network, const char *dname, + int ns_class, int ns_type, enum ResNsendFlags flags) { + unsigned netid; + if (!getnetidfromhandle(network, &netid)) { + return -ENONET; + } + + return resNetworkQuery(netid, dname, ns_class, ns_type, flags); +} + +int android_res_nresult(int fd, int *rcode, uint8_t *answer, size_t anslen) { + return resNetworkResult(fd, rcode, answer, anslen); +} + +int android_res_nsend(net_handle_t network, const uint8_t *msg, size_t msglen, + enum ResNsendFlags flags) { + unsigned netid; + if (!getnetidfromhandle(network, &netid)) { + return -ENONET; + } + + return resNetworkSend(netid, msg, msglen, flags); +} + +void android_res_cancel(int nsend_fd) { + resNetworkCancel(nsend_fd); +} diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp index 8e5821024cee..63082fd70bc6 100644 --- a/native/android/sensor.cpp +++ b/native/android/sensor.cpp @@ -115,6 +115,7 @@ ASensorEventQueue* ASensorManager_createEventQueue(ASensorManager* manager, if (queue != 0) { ALooper_addFd(looper, queue->getFd(), ident, ALOOPER_EVENT_INPUT, callback, data); queue->looper = looper; + queue->requestAdditionalInfo = false; queue->incStrong(manager); } return static_cast<ASensorEventQueue*>(queue.get()); @@ -274,11 +275,19 @@ ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* even return android::BAD_VALUE; } - ssize_t actual = static_cast<SensorEventQueue*>(queue)->read(events, count); + SensorEventQueue* sensorQueue = static_cast<SensorEventQueue*>(queue); + ssize_t actual = sensorQueue->read(events, count); if (actual > 0) { - static_cast<SensorEventQueue*>(queue)->sendAck(events, actual); + sensorQueue->sendAck(events, actual); } - return actual; + + return sensorQueue->filterEvents(events, actual); +} + +int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) { + RETURN_IF_QUEUE_IS_NULL(android::BAD_VALUE); + queue->requestAdditionalInfo = enable; + return android::OK; } /*****************************************************************************/ @@ -342,3 +351,8 @@ int ASensor_getHighestDirectReportRateLevel(ASensor const *sensor) { RETURN_IF_SENSOR_IS_NULL(ASENSOR_DIRECT_RATE_STOP); return static_cast<Sensor const *>(sensor)->getHighestDirectReportRateLevel(); } + +int ASensor_getHandle(ASensor const* sensor) { + RETURN_IF_SENSOR_IS_NULL(ASENSOR_INVALID); + return static_cast<Sensor const*>(sensor)->getHandle(); +} diff --git a/native/android/sharedmem.cpp b/native/android/sharedmem.cpp index 757aaecab40d..4410bd6fbeed 100644 --- a/native/android/sharedmem.cpp +++ b/native/android/sharedmem.cpp @@ -71,7 +71,7 @@ int ASharedMemory_dupFromJava(JNIEnv* env, jobject javaSharedMemory) { } int fd = env->CallIntMethod(javaSharedMemory, sSharedMemory.getFd); if (fd != -1) { - fd = dup(fd); + fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); } return fd; } diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp index bf15b8d075e7..22725254fef6 100644 --- a/native/android/storage_manager.cpp +++ b/native/android/storage_manager.cpp @@ -18,7 +18,9 @@ #include <android/storage_manager.h> #include <storage/IMountService.h> +#include <storage/ObbInfo.h> +#include <androidfw/ObbFile.h> #include <binder/Binder.h> #include <binder/IServiceManager.h> #include <cutils/atomic.h> @@ -29,7 +31,6 @@ #include <utils/Vector.h> #include <utils/threads.h> - using namespace android; struct ObbActionListener : public BnObbActionListener { @@ -79,6 +80,20 @@ protected: return cb; } + ObbInfo* getObbInfo(char* canonicalPath) { + sp<ObbFile> obbFile = new ObbFile(); + if (!obbFile->readFrom(canonicalPath)) { + return nullptr; + } + + String16 fileName(obbFile->getFileName()); + String16 packageName(obbFile->getPackageName()); + size_t length; + const unsigned char* salt = obbFile->getSalt(&length); + return new ObbInfo(fileName, packageName, + obbFile->getVersion(), obbFile->getFlags(), length, salt); + } + public: AStorageManager() { @@ -134,11 +149,18 @@ public: return; } + sp<ObbInfo> obbInfo = getObbInfo(canonicalPath); + if (obbInfo == nullptr) { + ALOGE("Couldn't get obb info for %s: %s", canonicalPath, strerror(errno)); + return; + } + ObbCallback* cb = registerObbCallback(func, data); String16 rawPath16(rawPath); String16 canonicalPath16(canonicalPath); String16 key16(key); - mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener, cb->nonce); + mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener, + cb->nonce, obbInfo); } void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) { diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp new file mode 100644 index 000000000000..8fe4fecceeb5 --- /dev/null +++ b/native/android/surface_control.cpp @@ -0,0 +1,539 @@ +/* + * Copyright 2018 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/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> +#include <android/native_window.h> +#include <android/surface_control.h> + +#include <configstore/Utils.h> + +#include <gui/HdrMetadata.h> +#include <gui/ISurfaceComposer.h> +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> +#include <gui/SurfaceControl.h> + +#include <ui/HdrCapabilities.h> + +#include <utils/Timers.h> + +using namespace android::hardware::configstore; +using namespace android::hardware::configstore::V1_0; +using namespace android; +using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs; + +using Transaction = SurfaceComposerClient::Transaction; + +#define CHECK_NOT_NULL(name) \ + LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument"); + +#define CHECK_VALID_RECT(name) \ + LOG_ALWAYS_FATAL_IF(!static_cast<const Rect&>(name).isValid(), \ + "invalid arg passed as " #name " argument"); + +static bool getWideColorSupport(const sp<SurfaceControl>& surfaceControl) { + sp<SurfaceComposerClient> client = surfaceControl->getClient(); + + const sp<IBinder> display = client->getInternalDisplayToken(); + if (display == nullptr) { + ALOGE("unable to get wide color support for disconnected internal display"); + return false; + } + + bool isWideColorDisplay = false; + status_t err = client->isWideColorDisplay(display, &isWideColorDisplay); + if (err) { + ALOGE("unable to get wide color support"); + return false; + } + return isWideColorDisplay; +} + +static bool getHdrSupport(const sp<SurfaceControl>& surfaceControl) { + sp<SurfaceComposerClient> client = surfaceControl->getClient(); + + const sp<IBinder> display = client->getInternalDisplayToken(); + if (display == nullptr) { + ALOGE("unable to get hdr capabilities for disconnected internal display"); + return false; + } + + HdrCapabilities hdrCapabilities; + status_t err = client->getHdrCapabilities(display, &hdrCapabilities); + if (err) { + ALOGE("unable to get hdr capabilities"); + return false; + } + + return !hdrCapabilities.getSupportedHdrTypes().empty(); +} + +static bool isDataSpaceValid(const sp<SurfaceControl>& surfaceControl, ADataSpace dataSpace) { + static_assert(static_cast<int>(ADATASPACE_UNKNOWN) == static_cast<int>(HAL_DATASPACE_UNKNOWN)); + static_assert(static_cast<int>(ADATASPACE_SCRGB_LINEAR) == static_cast<int>(HAL_DATASPACE_V0_SCRGB_LINEAR)); + static_assert(static_cast<int>(ADATASPACE_SRGB) == static_cast<int>(HAL_DATASPACE_V0_SRGB)); + static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB)); + static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == static_cast<int>(HAL_DATASPACE_DISPLAY_P3)); + static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ)); + + switch (static_cast<android_dataspace_t>(dataSpace)) { + case HAL_DATASPACE_UNKNOWN: + case HAL_DATASPACE_V0_SRGB: + return true; + // These data space need wide gamut support. + case HAL_DATASPACE_V0_SCRGB_LINEAR: + case HAL_DATASPACE_V0_SCRGB: + case HAL_DATASPACE_DISPLAY_P3: + return getWideColorSupport(surfaceControl); + // These data space need HDR support. + case HAL_DATASPACE_BT2020_PQ: + return getHdrSupport(surfaceControl); + default: + return false; + } +} + +Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) { + return reinterpret_cast<Transaction*>(aSurfaceTransaction); +} + +SurfaceControl* ASurfaceControl_to_SurfaceControl(ASurfaceControl* aSurfaceControl) { + return reinterpret_cast<SurfaceControl*>(aSurfaceControl); +} + +void SurfaceControl_acquire(SurfaceControl* surfaceControl) { + // incStrong/decStrong token must be the same, doesn't matter what it is + surfaceControl->incStrong((void*)SurfaceControl_acquire); +} + +void SurfaceControl_release(SurfaceControl* surfaceControl) { + // incStrong/decStrong token must be the same, doesn't matter what it is + surfaceControl->decStrong((void*)SurfaceControl_acquire); +} + +ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const char* debug_name) { + CHECK_NOT_NULL(window); + CHECK_NOT_NULL(debug_name); + + sp<SurfaceComposerClient> client = new SurfaceComposerClient(); + if (client->initCheck() != NO_ERROR) { + return nullptr; + } + + uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; + sp<SurfaceControl> surfaceControl = + client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */, + // Format is only relevant for buffer queue layers. + PIXEL_FORMAT_UNKNOWN /* format */, flags, + static_cast<Surface*>(window)); + if (!surfaceControl) { + return nullptr; + } + + SurfaceControl_acquire(surfaceControl.get()); + return reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); +} + +ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name) { + CHECK_NOT_NULL(parent); + CHECK_NOT_NULL(debug_name); + + SurfaceComposerClient* client = ASurfaceControl_to_SurfaceControl(parent)->getClient().get(); + + SurfaceControl* surfaceControlParent = ASurfaceControl_to_SurfaceControl(parent); + + uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState; + sp<SurfaceControl> surfaceControl = + client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */, + // Format is only relevant for buffer queue layers. + PIXEL_FORMAT_UNKNOWN /* format */, flags, + surfaceControlParent); + if (!surfaceControl) { + return nullptr; + } + + SurfaceControl_acquire(surfaceControl.get()); + return reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); +} + +void ASurfaceControl_release(ASurfaceControl* aSurfaceControl) { + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + + SurfaceControl_release(surfaceControl.get()); +} + +ASurfaceTransaction* ASurfaceTransaction_create() { + Transaction* transaction = new Transaction; + return reinterpret_cast<ASurfaceTransaction*>(transaction); +} + +void ASurfaceTransaction_delete(ASurfaceTransaction* aSurfaceTransaction) { + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + delete transaction; +} + +void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) { + CHECK_NOT_NULL(aSurfaceTransaction); + + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->apply(); +} + +typedef struct ASurfaceControlStats { + int64_t acquireTime; + sp<Fence> previousReleaseFence; +} ASurfaceControlStats; + +struct ASurfaceTransactionStats { + std::unordered_map<ASurfaceControl*, ASurfaceControlStats> aSurfaceControlStats; + int64_t latchTime; + sp<Fence> presentFence; +}; + +int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* aSurfaceTransactionStats) { + CHECK_NOT_NULL(aSurfaceTransactionStats); + return aSurfaceTransactionStats->latchTime; +} + +int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* aSurfaceTransactionStats) { + CHECK_NOT_NULL(aSurfaceTransactionStats); + auto& presentFence = aSurfaceTransactionStats->presentFence; + return (presentFence) ? presentFence->dup() : -1; +} + +void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* aSurfaceTransactionStats, + ASurfaceControl*** outASurfaceControls, + size_t* outASurfaceControlsSize) { + CHECK_NOT_NULL(aSurfaceTransactionStats); + CHECK_NOT_NULL(outASurfaceControls); + CHECK_NOT_NULL(outASurfaceControlsSize); + + size_t size = aSurfaceTransactionStats->aSurfaceControlStats.size(); + + SurfaceControl** surfaceControls = new SurfaceControl*[size]; + ASurfaceControl** aSurfaceControls = reinterpret_cast<ASurfaceControl**>(surfaceControls); + + size_t i = 0; + for (auto& [aSurfaceControl, aSurfaceControlStats] : aSurfaceTransactionStats->aSurfaceControlStats) { + aSurfaceControls[i] = aSurfaceControl; + i++; + } + + *outASurfaceControls = aSurfaceControls; + *outASurfaceControlsSize = size; +} + +int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* aSurfaceTransactionStats, + ASurfaceControl* aSurfaceControl) { + CHECK_NOT_NULL(aSurfaceTransactionStats); + CHECK_NOT_NULL(aSurfaceControl); + + const auto& aSurfaceControlStats = + aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl); + LOG_ALWAYS_FATAL_IF( + aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(), + "ASurfaceControl not found"); + + return aSurfaceControlStats->second.acquireTime; +} + +int ASurfaceTransactionStats_getPreviousReleaseFenceFd( + ASurfaceTransactionStats* aSurfaceTransactionStats, ASurfaceControl* aSurfaceControl) { + CHECK_NOT_NULL(aSurfaceTransactionStats); + CHECK_NOT_NULL(aSurfaceControl); + + const auto& aSurfaceControlStats = + aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl); + LOG_ALWAYS_FATAL_IF( + aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(), + "ASurfaceControl not found"); + + auto& previousReleaseFence = aSurfaceControlStats->second.previousReleaseFence; + return (previousReleaseFence) ? previousReleaseFence->dup() : -1; +} + +void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** aSurfaceControls) { + CHECK_NOT_NULL(aSurfaceControls); + + SurfaceControl** surfaceControls = reinterpret_cast<SurfaceControl**>(aSurfaceControls); + delete[] surfaceControls; +} + +void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, void* context, + ASurfaceTransaction_OnComplete func) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(context); + CHECK_NOT_NULL(func); + + TransactionCompletedCallbackTakesContext callback = [func](void* callback_context, + nsecs_t latchTime, + const sp<Fence>& presentFence, + const std::vector<SurfaceControlStats>& surfaceControlStats) { + ASurfaceTransactionStats aSurfaceTransactionStats; + + aSurfaceTransactionStats.latchTime = latchTime; + aSurfaceTransactionStats.presentFence = presentFence; + + auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats; + + for (const auto& [surfaceControl, acquireTime, previousReleaseFence] : surfaceControlStats) { + ASurfaceControl* aSurfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControl.get()); + aSurfaceControlStats[aSurfaceControl].acquireTime = acquireTime; + aSurfaceControlStats[aSurfaceControl].previousReleaseFence = previousReleaseFence; + } + + (*func)(callback_context, &aSurfaceTransactionStats); + }; + + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->addTransactionCompletedCallback(callback, context); +} + +void ASurfaceTransaction_reparent(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + ASurfaceControl* newParentASurfaceControl) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + sp<SurfaceControl> newParentSurfaceControl = ASurfaceControl_to_SurfaceControl( + newParentASurfaceControl); + sp<IBinder> newParentHandle = (newParentSurfaceControl)? newParentSurfaceControl->getHandle() : nullptr; + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->reparent(surfaceControl, newParentHandle); +} + +void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + int8_t visibility) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + switch (visibility) { + case ASURFACE_TRANSACTION_VISIBILITY_SHOW: + transaction->show(surfaceControl); + break; + case ASURFACE_TRANSACTION_VISIBILITY_HIDE: + transaction->hide(surfaceControl); + break; + default: + LOG_ALWAYS_FATAL("invalid visibility %d", visibility); + } +} + +void ASurfaceTransaction_setZOrder(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + int32_t z_order) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->setLayer(surfaceControl, z_order); +} + +void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + AHardwareBuffer* buffer, int acquire_fence_fd) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + sp<GraphicBuffer> graphic_buffer(reinterpret_cast<GraphicBuffer*>(buffer)); + + transaction->setBuffer(surfaceControl, graphic_buffer); + if (acquire_fence_fd != -1) { + sp<Fence> fence = new Fence(acquire_fence_fd); + transaction->setAcquireFence(surfaceControl, fence); + } +} + +void ASurfaceTransaction_setGeometry(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, const ARect& source, + const ARect& destination, int32_t transform) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + CHECK_VALID_RECT(source); + CHECK_VALID_RECT(destination); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->setCrop(surfaceControl, static_cast<const Rect&>(source)); + transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination)); + transaction->setTransform(surfaceControl, transform); + bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) == + NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; + transaction->setTransformToDisplayInverse(surfaceControl, transformToInverseDisplay); +} + +void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + int8_t transparency) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + uint32_t flags = (transparency == ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE) ? + layer_state_t::eLayerOpaque : 0; + transaction->setFlags(surfaceControl, flags, layer_state_t::eLayerOpaque); +} + +void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + const ARect rects[], uint32_t count) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + Region region; + for (uint32_t i = 0; i < count; ++i) { + region.orSelf(static_cast<const Rect&>(rects[i])); + } + + // Hardware composer interprets a DamageRegion with a single Rect of {0,0,0,0} to be an + // undamaged region and {0,0,-1,-1} to be a fully damaged buffer. This is a confusing + // distinction for a public api. Instead, default both cases to be a fully damaged buffer. + if (count == 1 && region.getBounds().isEmpty()) { + transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION); + return; + } + + transaction->setSurfaceDamageRegion(surfaceControl, region); +} + +void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* aSurfaceTransaction, + int64_t desiredPresentTime) { + CHECK_NOT_NULL(aSurfaceTransaction); + + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->setDesiredPresentTime(static_cast<nsecs_t>(desiredPresentTime)); +} + +void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + float alpha) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + LOG_ALWAYS_FATAL_IF(alpha < 0.0 || alpha > 1.0, "invalid alpha"); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->setAlpha(surfaceControl, alpha); +} + +void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + ADataSpace aDataSpace) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, aDataSpace), "invalid dataspace"); + + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace)); +} + +void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + struct AHdrMetadata_smpte2086* metadata) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + HdrMetadata hdrMetadata; + + if (metadata) { + hdrMetadata.smpte2086.displayPrimaryRed.x = metadata->displayPrimaryRed.x; + hdrMetadata.smpte2086.displayPrimaryRed.y = metadata->displayPrimaryRed.y; + hdrMetadata.smpte2086.displayPrimaryGreen.x = metadata->displayPrimaryGreen.x; + hdrMetadata.smpte2086.displayPrimaryGreen.y = metadata->displayPrimaryGreen.y; + hdrMetadata.smpte2086.displayPrimaryBlue.x = metadata->displayPrimaryBlue.x; + hdrMetadata.smpte2086.displayPrimaryBlue.y = metadata->displayPrimaryBlue.y; + hdrMetadata.smpte2086.whitePoint.x = metadata->whitePoint.x; + hdrMetadata.smpte2086.whitePoint.y = metadata->whitePoint.y; + hdrMetadata.smpte2086.minLuminance = metadata->minLuminance; + hdrMetadata.smpte2086.maxLuminance = metadata->maxLuminance; + + hdrMetadata.validTypes |= HdrMetadata::SMPTE2086; + } else { + hdrMetadata.validTypes &= ~HdrMetadata::SMPTE2086; + } + + transaction->setHdrMetadata(surfaceControl, hdrMetadata); +} + +void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + struct AHdrMetadata_cta861_3* metadata) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + HdrMetadata hdrMetadata; + + if (metadata) { + hdrMetadata.cta8613.maxContentLightLevel = metadata->maxContentLightLevel; + hdrMetadata.cta8613.maxFrameAverageLightLevel = metadata->maxFrameAverageLightLevel; + + hdrMetadata.validTypes |= HdrMetadata::CTA861_3; + } else { + hdrMetadata.validTypes &= ~HdrMetadata::CTA861_3; + } + + transaction->setHdrMetadata(surfaceControl, hdrMetadata); +} + +void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, + ASurfaceControl* aSurfaceControl, + float r, float g, float b, float alpha, + ADataSpace dataspace) { + CHECK_NOT_NULL(aSurfaceTransaction); + CHECK_NOT_NULL(aSurfaceControl); + + sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); + LOG_ALWAYS_FATAL_IF(!isDataSpaceValid(surfaceControl, dataspace), "invalid dataspace"); + Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); + + half3 color; + color.r = r; + color.g = g; + color.b = b; + + transaction->setBackgroundColor(surfaceControl, color, alpha, static_cast<ui::Dataspace>(dataspace)); +} diff --git a/native/android/surface_texture.cpp b/native/android/surface_texture.cpp index b26688190ccd..ced2792775d4 100644 --- a/native/android/surface_texture.cpp +++ b/native/android/surface_texture.cpp @@ -21,15 +21,16 @@ #include <utils/Log.h> -#include <gui/GLConsumer.h> #include <gui/Surface.h> #include <android_runtime/android_graphics_SurfaceTexture.h> +#include "surfacetexture/SurfaceTexture.h" + using namespace android; struct ASurfaceTexture { - sp<GLConsumer> consumer; + sp<SurfaceTexture> consumer; sp<IGraphicBufferProducer> producer; }; diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp new file mode 100644 index 000000000000..9791da63359b --- /dev/null +++ b/native/android/system_fonts.cpp @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2018 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 <jni.h> + +#include <android/font.h> +#include <android/font_matcher.h> +#include <android/system_fonts.h> + +#include <memory> +#include <string> +#include <vector> + +#include <errno.h> +#include <fcntl.h> +#include <libxml/tree.h> +#include <log/log.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <hwui/MinikinSkia.h> +#include <minikin/FontCollection.h> +#include <minikin/LocaleList.h> +#include <minikin/SystemFonts.h> + +struct XmlCharDeleter { + void operator()(xmlChar* b) { xmlFree(b); } +}; + +struct XmlDocDeleter { + void operator()(xmlDoc* d) { xmlFreeDoc(d); } +}; + +using XmlCharUniquePtr = std::unique_ptr<xmlChar, XmlCharDeleter>; +using XmlDocUniquePtr = std::unique_ptr<xmlDoc, XmlDocDeleter>; + +struct ASystemFontIterator { + XmlDocUniquePtr mXmlDoc; + xmlNode* mFontNode; + + // The OEM customization XML. + XmlDocUniquePtr mCustomizationXmlDoc; +}; + +struct AFont { + std::string mFilePath; + std::unique_ptr<std::string> mLocale; + uint16_t mWeight; + bool mItalic; + uint32_t mCollectionIndex; + std::vector<std::pair<uint32_t, float>> mAxes; +}; + +struct AFontMatcher { + minikin::FontStyle mFontStyle; + uint32_t mLocaleListId = 0; // 0 is reserved for empty locale ID. + bool mFamilyVariant = AFAMILY_VARIANT_DEFAULT; +}; + +static_assert(static_cast<uint32_t>(AFAMILY_VARIANT_DEFAULT) == + static_cast<uint32_t>(minikin::FamilyVariant::DEFAULT)); +static_assert(static_cast<uint32_t>(AFAMILY_VARIANT_COMPACT) == + static_cast<uint32_t>(minikin::FamilyVariant::COMPACT)); +static_assert(static_cast<uint32_t>(AFAMILY_VARIANT_ELEGANT) == + static_cast<uint32_t>(minikin::FamilyVariant::ELEGANT)); + +namespace { + +std::string xmlTrim(const std::string& in) { + if (in.empty()) { + return in; + } + const char XML_SPACES[] = "\u0020\u000D\u000A\u0009"; + const size_t start = in.find_first_not_of(XML_SPACES); // inclusive + if (start == std::string::npos) { + return ""; + } + const size_t end = in.find_last_not_of(XML_SPACES); // inclusive + if (end == std::string::npos) { + return ""; + } + return in.substr(start, end - start + 1 /* +1 since end is inclusive */); +} + +const xmlChar* FAMILY_TAG = BAD_CAST("family"); +const xmlChar* FONT_TAG = BAD_CAST("font"); + +xmlNode* firstElement(xmlNode* node, const xmlChar* tag) { + for (xmlNode* child = node->children; child; child = child->next) { + if (xmlStrEqual(child->name, tag)) { + return child; + } + } + return nullptr; +} + +xmlNode* nextSibling(xmlNode* node, const xmlChar* tag) { + while ((node = node->next) != nullptr) { + if (xmlStrEqual(node->name, tag)) { + return node; + } + } + return nullptr; +} + +void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, AFont* out, + const std::string& pathPrefix) { + const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang"); + XmlCharUniquePtr filePathStr( + xmlNodeListGetString(xmlDoc.get(), fontNode->xmlChildrenNode, 1)); + out->mFilePath = pathPrefix + xmlTrim( + std::string(filePathStr.get(), filePathStr.get() + xmlStrlen(filePathStr.get()))); + + const xmlChar* WEIGHT_ATTR_NAME = BAD_CAST("weight"); + XmlCharUniquePtr weightStr(xmlGetProp(fontNode, WEIGHT_ATTR_NAME)); + out->mWeight = weightStr ? + strtol(reinterpret_cast<const char*>(weightStr.get()), nullptr, 10) : 400; + + const xmlChar* STYLE_ATTR_NAME = BAD_CAST("style"); + const xmlChar* ITALIC_ATTR_VALUE = BAD_CAST("italic"); + XmlCharUniquePtr styleStr(xmlGetProp(fontNode, STYLE_ATTR_NAME)); + out->mItalic = styleStr ? xmlStrEqual(styleStr.get(), ITALIC_ATTR_VALUE) : false; + + const xmlChar* INDEX_ATTR_NAME = BAD_CAST("index"); + XmlCharUniquePtr indexStr(xmlGetProp(fontNode, INDEX_ATTR_NAME)); + 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); + + const xmlChar* TAG_ATTR_NAME = BAD_CAST("tag"); + const xmlChar* STYLEVALUE_ATTR_NAME = BAD_CAST("stylevalue"); + const xmlChar* AXIS_TAG = BAD_CAST("axis"); + out->mAxes.clear(); + for (xmlNode* axis = firstElement(fontNode, AXIS_TAG); axis; + axis = nextSibling(axis, AXIS_TAG)) { + XmlCharUniquePtr tagStr(xmlGetProp(axis, TAG_ATTR_NAME)); + if (!tagStr || xmlStrlen(tagStr.get()) != 4) { + continue; // Tag value must be 4 char string + } + + XmlCharUniquePtr styleValueStr(xmlGetProp(axis, STYLEVALUE_ATTR_NAME)); + if (!styleValueStr) { + continue; + } + + uint32_t tag = + static_cast<uint32_t>(tagStr.get()[0] << 24) | + static_cast<uint32_t>(tagStr.get()[1] << 16) | + static_cast<uint32_t>(tagStr.get()[2] << 8) | + static_cast<uint32_t>(tagStr.get()[3]); + float styleValue = strtod(reinterpret_cast<const char*>(styleValueStr.get()), nullptr); + out->mAxes.push_back(std::make_pair(tag, styleValue)); + } +} + +bool isFontFileAvailable(const std::string& filePath) { + std::string fullPath = filePath; + struct stat st = {}; + if (stat(fullPath.c_str(), &st) != 0) { + return false; + } + return S_ISREG(st.st_mode); +} + +xmlNode* findFirstFontNode(const XmlDocUniquePtr& doc) { + xmlNode* familySet = xmlDocGetRootElement(doc.get()); + if (familySet == nullptr) { + return nullptr; + } + xmlNode* family = firstElement(familySet, FAMILY_TAG); + if (family == nullptr) { + return nullptr; + } + + xmlNode* font = firstElement(family, FONT_TAG); + while (font == nullptr) { + family = nextSibling(family, FAMILY_TAG); + if (family == nullptr) { + return nullptr; + } + font = firstElement(family, FONT_TAG); + } + return font; +} + +} // namespace + +ASystemFontIterator* ASystemFontIterator_open() { + std::unique_ptr<ASystemFontIterator> ite(new ASystemFontIterator()); + ite->mXmlDoc.reset(xmlReadFile("/system/etc/fonts.xml", nullptr, 0)); + ite->mCustomizationXmlDoc.reset(xmlReadFile("/product/etc/fonts_customization.xml", nullptr, 0)); + return ite.release(); +} + +void ASystemFontIterator_close(ASystemFontIterator* ite) { + delete ite; +} + +AFontMatcher* _Nonnull AFontMatcher_create() { + return new AFontMatcher(); +} + +void AFontMatcher_destroy(AFontMatcher* matcher) { + delete matcher; +} + +void AFontMatcher_setStyle( + AFontMatcher* _Nonnull matcher, + uint16_t weight, + bool italic) { + matcher->mFontStyle = minikin::FontStyle( + weight, static_cast<minikin::FontStyle::Slant>(italic)); +} + +void AFontMatcher_setLocales( + AFontMatcher* _Nonnull matcher, + const char* _Nonnull languageTags) { + matcher->mLocaleListId = minikin::registerLocaleList(languageTags); +} + +void AFontMatcher_setFamilyVariant(AFontMatcher* _Nonnull matcher, uint32_t familyVariant) { + matcher->mFamilyVariant = familyVariant; +} + +AFont* _Nonnull AFontMatcher_match( + const AFontMatcher* _Nonnull matcher, + const char* _Nonnull familyName, + const uint16_t* _Nonnull text, + const uint32_t textLength, + uint32_t* _Nullable runLength) { + std::shared_ptr<minikin::FontCollection> fc = + minikin::SystemFonts::findFontCollection(familyName); + std::vector<minikin::FontCollection::Run> runs = fc->itemize( + minikin::U16StringPiece(text, textLength), + matcher->mFontStyle, + matcher->mLocaleListId, + static_cast<minikin::FamilyVariant>(matcher->mFamilyVariant), + 1 /* maxRun */); + + const minikin::Font* font = runs[0].fakedFont.font; + std::unique_ptr<AFont> result = std::make_unique<AFont>(); + const android::MinikinFontSkia* minikinFontSkia = + reinterpret_cast<android::MinikinFontSkia*>(font->typeface().get()); + result->mFilePath = minikinFontSkia->getFilePath(); + result->mWeight = font->style().weight(); + result->mItalic = font->style().slant() == minikin::FontStyle::Slant::ITALIC; + result->mCollectionIndex = minikinFontSkia->GetFontIndex(); + const std::vector<minikin::FontVariation>& axes = minikinFontSkia->GetAxes(); + result->mAxes.reserve(axes.size()); + for (auto axis : axes) { + result->mAxes.push_back(std::make_pair(axis.axisTag, axis.value)); + } + if (runLength != nullptr) { + *runLength = runs[0].end; + } + return result.release(); +} + +xmlNode* findNextFontNode(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode) { + if (fontNode == nullptr) { + if (!xmlDoc) { + return nullptr; // Already at the end. + } else { + // First time to query font. + return findFirstFontNode(xmlDoc); + } + } else { + xmlNode* nextNode = nextSibling(fontNode, FONT_TAG); + while (nextNode == nullptr) { + xmlNode* family = nextSibling(fontNode->parent, FAMILY_TAG); + if (family == nullptr) { + break; + } + nextNode = firstElement(family, FONT_TAG); + } + return nextNode; + } +} + +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) { + // 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/"); + if (!isFontFileAvailable(font->mFilePath)) { + return ASystemFontIterator_next(ite); + } + return font.release(); + } + } + if (ite->mCustomizationXmlDoc) { + // TODO: Filter only customizationType="new-named-family" + ite->mFontNode = findNextFontNode(ite->mCustomizationXmlDoc, ite->mFontNode); + if (ite->mFontNode == nullptr) { + // 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/"); + if (!isFontFileAvailable(font->mFilePath)) { + return ASystemFontIterator_next(ite); + } + return font.release(); + } + } + return nullptr; +} + +void AFont_close(AFont* font) { + delete font; +} + +const char* AFont_getFontFilePath(const AFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument"); + return font->mFilePath.c_str(); +} + +uint16_t AFont_getWeight(const AFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument"); + return font->mWeight; +} + +bool AFont_isItalic(const AFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument"); + return font->mItalic; +} + +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(); +} + +size_t AFont_getCollectionIndex(const AFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + return font->mCollectionIndex; +} + +size_t AFont_getAxisCount(const AFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + return font->mAxes.size(); +} + +uint32_t AFont_getAxisTag(const AFont* font, uint32_t axisIndex) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + LOG_ALWAYS_FATAL_IF(axisIndex >= font->mAxes.size(), + "given axis index is out of bounds. (< %zd", font->mAxes.size()); + return font->mAxes[axisIndex].first; +} + +float AFont_getAxisValue(const AFont* font, uint32_t axisIndex) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + LOG_ALWAYS_FATAL_IF(axisIndex >= font->mAxes.size(), + "given axis index is out of bounds. (< %zd", font->mAxes.size()); + return font->mAxes[axisIndex].second; +} diff --git a/native/android/trace.cpp b/native/android/trace.cpp index db522204f96f..9ff5b8a31bb1 100644 --- a/native/android/trace.cpp +++ b/native/android/trace.cpp @@ -28,3 +28,15 @@ void ATrace_beginSection(const char* sectionName) { void ATrace_endSection() { atrace_end(ATRACE_TAG_APP); } + +void ATrace_beginAsyncSection(const char* sectionName, int32_t cookie) { + atrace_async_begin(ATRACE_TAG_APP, sectionName, cookie); +} + +void ATrace_endAsyncSection(const char* sectionName, int32_t cookie) { + atrace_async_end(ATRACE_TAG_APP, sectionName, cookie); +} + +void ATrace_setCounter(const char* counterName, int64_t counterValue) { + atrace_int64(ATRACE_TAG_APP, counterName, counterValue); +}
\ No newline at end of file diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index 0704e3545b62..942eafdbc48d 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -33,9 +33,11 @@ cc_library_shared { arch: { arm: { // TODO: This is to work around b/24465209. Remove after root cause is fixed + pack_relocations: false, ldflags: ["-Wl,--hash-style=both"], }, }, + version_script: "libjnigraphics.map.txt", } // The headers module is in frameworks/native/Android.bp. diff --git a/native/webview/Android.mk b/native/webview/Android.mk deleted file mode 100644 index a2a93d7d664d..000000000000 --- a/native/webview/Android.mk +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (C) 2017 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 all the makefiles for subdirectories. -include $(call all-subdir-makefiles) - diff --git a/native/webview/OWNERS b/native/webview/OWNERS index 00e540a46ab2..580bb0fe8273 100644 --- a/native/webview/OWNERS +++ b/native/webview/OWNERS @@ -1,3 +1,4 @@ +boliu@google.com changwan@google.com tobiasjs@google.com torne@google.com diff --git a/native/webview/loader/Android.bp b/native/webview/loader/Android.bp new file mode 100644 index 000000000000..0ba256facb6d --- /dev/null +++ b/native/webview/loader/Android.bp @@ -0,0 +1,32 @@ +// +// Copyright (C) 2017 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. + +// This package provides the system interfaces required to load WebView. + +// Loader library which handles address space reservation and relro sharing. +// Does NOT link any native chromium code. +cc_library_shared { + name: "libwebviewchromium_loader", + + srcs: ["loader.cpp"], + + cflags: ["-Werror"], + + shared_libs: [ + "libdl", + "liblog", + "libnativeloader", + ], +} diff --git a/native/webview/loader/Android.mk b/native/webview/loader/Android.mk deleted file mode 100644 index e8a7d9743cb9..000000000000 --- a/native/webview/loader/Android.mk +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (C) 2017 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. - -# This package provides the system interfaces required to load WebView. - -LOCAL_PATH := $(call my-dir) - -# Loader library which handles address space reservation and relro sharing. -# Does NOT link any native chromium code. -include $(CLEAR_VARS) - -LOCAL_MODULE:= libwebviewchromium_loader - -LOCAL_SRC_FILES := \ - loader.cpp \ - -LOCAL_CFLAGS := \ - -Werror \ - -LOCAL_SHARED_LIBRARIES += \ - libdl \ - liblog \ - libnativeloader \ - -LOCAL_MODULE_TAGS := optional - -include $(BUILD_SHARED_LIBRARY) - diff --git a/native/webview/loader/loader.cpp b/native/webview/loader/loader.cpp index adb371dde0fc..1265763d47d3 100644 --- a/native/webview/loader/loader.cpp +++ b/native/webview/loader/loader.cpp @@ -26,6 +26,7 @@ #include <string.h> #include <unistd.h> #include <sys/mman.h> +#include <sys/prctl.h> #include <sys/stat.h> #include <sys/types.h> @@ -58,13 +59,15 @@ jboolean DoReserveAddressSpace(jlong size) { vsize, strerror(errno)); return JNI_FALSE; } + prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, addr, vsize, "libwebview reservation"); gReservedAddress = addr; gReservedSize = vsize; ALOGV("Reserved %zd bytes at %p", vsize, addr); return JNI_TRUE; } -jboolean DoCreateRelroFile(const char* lib, const char* relro) { +jboolean DoCreateRelroFile(JNIEnv* env, const char* lib, const char* relro, + jobject clazzLoader) { // Try to unlink the old file, since if this is being called, the old one is // obsolete. if (unlink(relro) != 0 && errno != ENOENT) { @@ -82,11 +85,20 @@ jboolean DoCreateRelroFile(const char* lib, const char* relro) { ALOGE("Failed to create temporary file %s: %s", relro_tmp, strerror(errno)); return JNI_FALSE; } + android_namespace_t* ns = + android::FindNamespaceByClassLoader(env, clazzLoader); + if (ns == NULL) { + ALOGE("Failed to find classloader namespace"); + return JNI_FALSE; + } android_dlextinfo extinfo; - extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO; + extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_WRITE_RELRO | + ANDROID_DLEXT_USE_NAMESPACE | + ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE; extinfo.reserved_addr = gReservedAddress; extinfo.reserved_size = gReservedSize; extinfo.relro_fd = tmp_fd; + extinfo.library_namespace = ns; void* handle = android_dlopen_ext(lib, RTLD_NOW, &extinfo); int close_result = close(tmp_fd); if (handle == NULL) { @@ -120,7 +132,8 @@ jint DoLoadWithRelroFile(JNIEnv* env, const char* lib, const char* relro, } android_dlextinfo extinfo; extinfo.flags = ANDROID_DLEXT_RESERVED_ADDRESS | ANDROID_DLEXT_USE_RELRO | - ANDROID_DLEXT_USE_NAMESPACE; + ANDROID_DLEXT_USE_NAMESPACE | + ANDROID_DLEXT_RESERVED_ADDRESS_RECURSIVE; extinfo.reserved_addr = gReservedAddress; extinfo.reserved_size = gReservedSize; extinfo.relro_fd = relro_fd; @@ -143,13 +156,14 @@ jboolean ReserveAddressSpace(JNIEnv*, jclass, jlong size) { return DoReserveAddressSpace(size); } -jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro) { +jboolean CreateRelroFile(JNIEnv* env, jclass, jstring lib, jstring relro, + jobject clazzLoader) { jboolean ret = JNI_FALSE; const char* lib_utf8 = env->GetStringUTFChars(lib, NULL); if (lib_utf8 != NULL) { const char* relro_utf8 = env->GetStringUTFChars(relro, NULL); if (relro_utf8 != NULL) { - ret = DoCreateRelroFile(lib_utf8, relro_utf8); + ret = DoCreateRelroFile(env, lib_utf8, relro_utf8, clazzLoader); env->ReleaseStringUTFChars(relro, relro_utf8); } env->ReleaseStringUTFChars(lib, lib_utf8); @@ -179,7 +193,7 @@ const JNINativeMethod kJniMethods[] = { { "nativeReserveAddressSpace", "(J)Z", reinterpret_cast<void*>(ReserveAddressSpace) }, { "nativeCreateRelroFile", - "(Ljava/lang/String;Ljava/lang/String;)Z", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)Z", reinterpret_cast<void*>(CreateRelroFile) }, { "nativeLoadWithRelroFile", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)I", diff --git a/native/webview/plat_support/Android.bp b/native/webview/plat_support/Android.bp new file mode 100644 index 000000000000..88decc86c387 --- /dev/null +++ b/native/webview/plat_support/Android.bp @@ -0,0 +1,46 @@ +// +// Copyright (C) 2012 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. +// + +// This package provides the system interfaces allowing WebView to render. + +// Native support library (libwebviewchromium_plat_support.so) - does NOT link +// any native chromium code. +cc_library_shared { + name: "libwebviewchromium_plat_support", + + srcs: [ + "draw_functor.cpp", + "draw_gl_functor.cpp", + "functor_utils.cpp", + "jni_entry_point.cpp", + "graphics_utils.cpp", + "graphic_buffer_impl.cpp", + ], + + shared_libs: [ + "libandroidfw", + "libandroid_runtime", + "libcutils", + "libhwui", + "liblog", + "libui", + "libutils", + "libvulkan", + ], + + // To remove warnings from skia header files + cflags: ["-Wno-unused-parameter"], +} diff --git a/native/webview/plat_support/Android.mk b/native/webview/plat_support/Android.mk deleted file mode 100644 index 6a33fe208416..000000000000 --- a/native/webview/plat_support/Android.mk +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (C) 2012 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. -# - -# This package provides the system interfaces allowing WebView to render. - -LOCAL_PATH := $(call my-dir) - -# Native support library (libwebviewchromium_plat_support.so) - does NOT link -# any native chromium code. -include $(CLEAR_VARS) - -LOCAL_MODULE:= libwebviewchromium_plat_support - -LOCAL_SRC_FILES:= \ - draw_gl_functor.cpp \ - jni_entry_point.cpp \ - graphics_utils.cpp \ - graphic_buffer_impl.cpp \ - -LOCAL_C_INCLUDES:= \ - external/skia/include/core \ - frameworks/base/core/jni/android/graphics \ - frameworks/native/include/ui \ - -LOCAL_SHARED_LIBRARIES += \ - libandroid_runtime \ - liblog \ - libcutils \ - libui \ - libutils \ - libhwui \ - libandroidfw - -LOCAL_MODULE_TAGS := optional - -# To remove warnings from skia header files -LOCAL_CFLAGS := -Wno-unused-parameter - -include $(BUILD_SHARED_LIBRARY) diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h new file mode 100644 index 000000000000..42cad43af8fc --- /dev/null +++ b/native/webview/plat_support/draw_fn.h @@ -0,0 +1,208 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +//****************************************************************************** +// This is a copy of the coresponding android_webview/public/browser header. +// Any changes to the interface should be made there as well. +//****************************************************************************** + +#ifndef ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_ +#define ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_ + +#include <vulkan/vulkan.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// In order to make small changes backwards compatible, all structs passed from +// android to chromium are versioned. +// +// 1 is Android Q. This matches kAwDrawGLInfoVersion version 3. +// 2 Adds transfer_function_* and color_space_toXYZD50 to AwDrawFn_DrawGLParams. +static const int kAwDrawFnVersion = 2; + +struct AwDrawFn_OnSyncParams { + int version; + + bool apply_force_dark; +}; + +struct AwDrawFn_DrawGLParams { + int version; + + // Input: current clip rect in surface coordinates. Reflects the current state + // of the OpenGL scissor rect. Both the OpenGL scissor rect and viewport are + // set by the caller of the draw function and updated during View animations. + int clip_left; + int clip_top; + int clip_right; + int clip_bottom; + + // Input: current width/height of destination surface. + int width; + int height; + + // Used to be is_layer. + bool deprecated_0; + + // Input: current transformation matrix in surface pixels. + // Uses the column-based OpenGL matrix format. + float transform[16]; + + // Input: Color space parameters. + float transfer_function_g; + float transfer_function_a; + float transfer_function_b; + float transfer_function_c; + float transfer_function_d; + float transfer_function_e; + float transfer_function_f; + float color_space_toXYZD50[9]; +}; + +struct AwDrawFn_InitVkParams { + int version; + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + VkQueue queue; + uint32_t graphics_queue_index; + uint32_t api_version; + const char* const* enabled_instance_extension_names; + uint32_t enabled_instance_extension_names_length; + const char* const* enabled_device_extension_names; + uint32_t enabled_device_extension_names_length; + // Only one of device_features and device_features_2 should be non-null. + // If both are null then no features are enabled. + VkPhysicalDeviceFeatures* device_features; + VkPhysicalDeviceFeatures2* device_features_2; +}; + +struct AwDrawFn_DrawVkParams { + int version; + + // Input: current width/height of destination surface. + int width; + int height; + + bool deprecated_0; + + // Input: current transform matrix + float transform[16]; + + // Input WebView should do its main compositing draws into this. It cannot do + // anything that would require stopping the render pass. + VkCommandBuffer secondary_command_buffer; + + // Input: The main color attachment index where secondary_command_buffer will + // eventually be submitted. + uint32_t color_attachment_index; + + // Input: A render pass which will be compatible to the one which the + // secondary_command_buffer will be submitted into. + VkRenderPass compatible_render_pass; + + // Input: Format of the destination surface. + VkFormat format; + + // Input: Color space parameters. + float transfer_function_g; + float transfer_function_a; + float transfer_function_b; + float transfer_function_c; + float transfer_function_d; + float transfer_function_e; + float transfer_function_f; + float color_space_toXYZD50[9]; + + // Input: current clip rect + int clip_left; + int clip_top; + int clip_right; + int clip_bottom; +}; + +struct AwDrawFn_PostDrawVkParams { + int version; +}; + +// Called on render thread while UI thread is blocked. Called for both GL and +// VK. +typedef void AwDrawFn_OnSync(int functor, + void* data, + AwDrawFn_OnSyncParams* params); + +// Called on render thread when either the context is destroyed _or_ when the +// functor's last reference goes away. Will always be called with an active +// context. Called for both GL and VK. +typedef void AwDrawFn_OnContextDestroyed(int functor, void* data); + +// Called on render thread when the last reference to the handle goes away and +// the handle is considered irrevocably destroyed. Will always be preceded by +// a call to OnContextDestroyed if this functor had ever been drawn. Called for +// both GL and VK. +typedef void AwDrawFn_OnDestroyed(int functor, void* data); + +// Only called for GL. +typedef void AwDrawFn_DrawGL(int functor, + void* data, + AwDrawFn_DrawGLParams* params); + +// Initialize vulkan state. Needs to be called again after any +// OnContextDestroyed. Only called for Vulkan. +typedef void AwDrawFn_InitVk(int functor, + void* data, + AwDrawFn_InitVkParams* params); + +// Only called for Vulkan. +typedef void AwDrawFn_DrawVk(int functor, + void* data, + AwDrawFn_DrawVkParams* params); + +// Only called for Vulkan. +typedef void AwDrawFn_PostDrawVk(int functor, + void* data, + AwDrawFn_PostDrawVkParams* params); + +struct AwDrawFnFunctorCallbacks { + // No version here since this is passed from chromium to android. + AwDrawFn_OnSync* on_sync; + AwDrawFn_OnContextDestroyed* on_context_destroyed; + AwDrawFn_OnDestroyed* on_destroyed; + AwDrawFn_DrawGL* draw_gl; + AwDrawFn_InitVk* init_vk; + AwDrawFn_DrawVk* draw_vk; + AwDrawFn_PostDrawVk* post_draw_vk; +}; + +enum AwDrawFnRenderMode { + AW_DRAW_FN_RENDER_MODE_OPENGL_ES = 0, + AW_DRAW_FN_RENDER_MODE_VULKAN = 1, +}; + +// Get the render mode. Result is static for the process. +typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void); + +// Create a functor. |functor_callbacks| should be valid until OnDestroyed. +typedef int AwDrawFn_CreateFunctor(void* data, + AwDrawFnFunctorCallbacks* functor_callbacks); + +// May be called on any thread to signal that the functor should be destroyed. +// The functor will receive an onDestroyed when the last usage of it is +// released, and it should be considered alive & active until that point. +typedef void AwDrawFn_ReleaseFunctor(int functor); + +struct AwDrawFnFunctionTable { + int version; + AwDrawFn_QueryRenderMode* query_render_mode; + AwDrawFn_CreateFunctor* create_functor; + AwDrawFn_ReleaseFunctor* release_functor; +}; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_ diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp new file mode 100644 index 000000000000..7cce61b87d12 --- /dev/null +++ b/native/webview/plat_support/draw_functor.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2018 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 "draw_fn.h" + +#include <jni.h> +#include <private/hwui/WebViewFunctor.h> +#include <utils/Log.h> + +#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) +#define COMPILE_ASSERT(expr, err) \ +__unused static const char (err)[(expr) ? 1 : -1] = ""; + +namespace android { +namespace { + +struct SupportData { + void* const data; + AwDrawFnFunctorCallbacks callbacks; +}; + +void onSync(int functor, void* data, + const uirenderer::WebViewSyncData& syncData) { + AwDrawFn_OnSyncParams params = { + .version = kAwDrawFnVersion, + .apply_force_dark = syncData.applyForceDark, + }; + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.on_sync(functor, support->data, ¶ms); +} + +void onContextDestroyed(int functor, void* data) { + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.on_context_destroyed(functor, support->data); +} + +void onDestroyed(int functor, void* data) { + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.on_destroyed(functor, support->data); + delete support; +} + +void draw_gl(int functor, void* data, + const uirenderer::DrawGlInfo& draw_gl_params) { + float gabcdef[7]; + draw_gl_params.color_space_ptr->transferFn(gabcdef); + AwDrawFn_DrawGLParams params = { + .version = kAwDrawFnVersion, + .clip_left = draw_gl_params.clipLeft, + .clip_top = draw_gl_params.clipTop, + .clip_right = draw_gl_params.clipRight, + .clip_bottom = draw_gl_params.clipBottom, + .width = draw_gl_params.width, + .height = draw_gl_params.height, + .deprecated_0 = false, + .transfer_function_g = gabcdef[0], + .transfer_function_a = gabcdef[1], + .transfer_function_b = gabcdef[2], + .transfer_function_c = gabcdef[3], + .transfer_function_d = gabcdef[4], + .transfer_function_e = gabcdef[5], + .transfer_function_f = gabcdef[6], + }; + COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform), + mismatched_transform_matrix_sizes); + for (int i = 0; i < NELEM(params.transform); ++i) { + params.transform[i] = draw_gl_params.transform[i]; + } + COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3), + gamut_transform_size_mismatch); + draw_gl_params.color_space_ptr->toXYZD50( + reinterpret_cast<skcms_Matrix3x3*>(¶ms.color_space_toXYZD50)); + + SupportData* support = static_cast<SupportData*>(data); + support->callbacks.draw_gl(functor, support->data, ¶ms); +} + +void initializeVk(int functor, void* data, + const uirenderer::VkFunctorInitParams& init_vk_params) { + SupportData* support = static_cast<SupportData*>(data); + VkPhysicalDeviceFeatures2 device_features_2; + if (init_vk_params.device_features_2) + device_features_2 = *init_vk_params.device_features_2; + + AwDrawFn_InitVkParams params{ + .version = kAwDrawFnVersion, + .instance = init_vk_params.instance, + .physical_device = init_vk_params.physical_device, + .device = init_vk_params.device, + .queue = init_vk_params.queue, + .graphics_queue_index = init_vk_params.graphics_queue_index, + .api_version = init_vk_params.api_version, + .enabled_instance_extension_names = + init_vk_params.enabled_instance_extension_names, + .enabled_instance_extension_names_length = + init_vk_params.enabled_instance_extension_names_length, + .enabled_device_extension_names = + init_vk_params.enabled_device_extension_names, + .enabled_device_extension_names_length = + init_vk_params.enabled_device_extension_names_length, + .device_features = nullptr, + .device_features_2 = + init_vk_params.device_features_2 ? &device_features_2 : nullptr, + }; + support->callbacks.init_vk(functor, support->data, ¶ms); +} + +void drawVk(int functor, void* data, const uirenderer::VkFunctorDrawParams& draw_vk_params) { + SupportData* support = static_cast<SupportData*>(data); + float gabcdef[7]; + draw_vk_params.color_space_ptr->transferFn(gabcdef); + AwDrawFn_DrawVkParams params{ + .version = kAwDrawFnVersion, + .width = draw_vk_params.width, + .height = draw_vk_params.height, + .deprecated_0 = false, + .secondary_command_buffer = draw_vk_params.secondary_command_buffer, + .color_attachment_index = draw_vk_params.color_attachment_index, + .compatible_render_pass = draw_vk_params.compatible_render_pass, + .format = draw_vk_params.format, + .transfer_function_g = gabcdef[0], + .transfer_function_a = gabcdef[1], + .transfer_function_b = gabcdef[2], + .transfer_function_c = gabcdef[3], + .transfer_function_d = gabcdef[4], + .transfer_function_e = gabcdef[5], + .transfer_function_f = gabcdef[6], + .clip_left = draw_vk_params.clip_left, + .clip_top = draw_vk_params.clip_top, + .clip_right = draw_vk_params.clip_right, + .clip_bottom = draw_vk_params.clip_bottom, + }; + COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3), + gamut_transform_size_mismatch); + draw_vk_params.color_space_ptr->toXYZD50( + reinterpret_cast<skcms_Matrix3x3*>(¶ms.color_space_toXYZD50)); + COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_vk_params.transform), + mismatched_transform_matrix_sizes); + for (int i = 0; i < NELEM(params.transform); ++i) { + params.transform[i] = draw_vk_params.transform[i]; + } + support->callbacks.draw_vk(functor, support->data, ¶ms); +} + +void postDrawVk(int functor, void* data) { + SupportData* support = static_cast<SupportData*>(data); + AwDrawFn_PostDrawVkParams params{.version = kAwDrawFnVersion}; + support->callbacks.post_draw_vk(functor, support->data, ¶ms); +} + +int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { + static bool callbacks_initialized = false; + static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = { + .onSync = &onSync, + .onContextDestroyed = &onContextDestroyed, + .onDestroyed = &onDestroyed, + }; + if (!callbacks_initialized) { + switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) { + case uirenderer::RenderMode::OpenGL_ES: + webview_functor_callbacks.gles.draw = &draw_gl; + break; + case uirenderer::RenderMode::Vulkan: + webview_functor_callbacks.vk.initialize = &initializeVk; + webview_functor_callbacks.vk.draw = &drawVk; + webview_functor_callbacks.vk.postDraw = &postDrawVk; + break; + } + callbacks_initialized = true; + } + SupportData* support = new SupportData{ + .data = data, + .callbacks = *functor_callbacks, + }; + int functor = uirenderer::WebViewFunctor_create( + support, webview_functor_callbacks, + uirenderer::WebViewFunctor_queryPlatformRenderMode()); + if (functor <= 0) delete support; + return functor; +} + +void ReleaseFunctor(int functor) { + uirenderer::WebViewFunctor_release(functor); +} + +AwDrawFnRenderMode QueryRenderMode(void) { + switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) { + case uirenderer::RenderMode::OpenGL_ES: + return AW_DRAW_FN_RENDER_MODE_OPENGL_ES; + case uirenderer::RenderMode::Vulkan: + return AW_DRAW_FN_RENDER_MODE_VULKAN; + } +} + +jlong GetDrawFnFunctionTable() { + static AwDrawFnFunctionTable function_table = { + .version = kAwDrawFnVersion, + .query_render_mode = &QueryRenderMode, + .create_functor = &CreateFunctor, + .release_functor = &ReleaseFunctor, + }; + return reinterpret_cast<intptr_t>(&function_table); +} + +const char kClassName[] = "com/android/webview/chromium/DrawFunctor"; +const JNINativeMethod kJniMethods[] = { + {"nativeGetFunctionTable", "()J", + reinterpret_cast<void*>(GetDrawFnFunctionTable)}, +}; + +} // namespace + +void RegisterDrawFunctor(JNIEnv* env) { + jclass clazz = env->FindClass(kClassName); + LOG_ALWAYS_FATAL_IF(!clazz, "Unable to find class '%s'", kClassName); + + int res = env->RegisterNatives(clazz, kJniMethods, NELEM(kJniMethods)); + LOG_ALWAYS_FATAL_IF(res < 0, "register native methods failed: res=%d", res); +} + +} // namespace android diff --git a/native/webview/plat_support/draw_gl.h b/native/webview/plat_support/draw_gl.h index c8434b61eba5..de13ed0dec6f 100644 --- a/native/webview/plat_support/draw_gl.h +++ b/native/webview/plat_support/draw_gl.h @@ -43,9 +43,9 @@ struct AwDrawGLInfo { // Input: tells the draw function what action to perform. enum Mode { kModeDraw = 0, - kModeProcess, - kModeProcessNoContext, - kModeSync, + kModeProcess = 1, + kModeProcessNoContext = 2, + kModeSync = 3, } mode; // Input: current clip rect in surface coordinates. Reflects the current state @@ -93,9 +93,9 @@ typedef void (AwDrawGLFunction)(long view_context, AwDrawGLInfo* draw_info, void* spare); enum AwMapMode { - MAP_READ_ONLY, - MAP_WRITE_ONLY, - MAP_READ_WRITE, + MAP_READ_ONLY = 0, + MAP_WRITE_ONLY = 1, + MAP_READ_WRITE = 2, }; // Called to create a GraphicBuffer diff --git a/native/webview/plat_support/draw_gl_functor.cpp b/native/webview/plat_support/draw_gl_functor.cpp index d54f558b9866..be36b6742037 100644 --- a/native/webview/plat_support/draw_gl_functor.cpp +++ b/native/webview/plat_support/draw_gl_functor.cpp @@ -21,16 +21,13 @@ #include "draw_gl.h" -#include <Properties.h> -#include <errno.h> #include <jni.h> #include <private/hwui/DrawGlInfo.h> -#include <string.h> -#include <sys/resource.h> -#include <sys/time.h> #include <utils/Functor.h> #include <utils/Log.h> +#include "functor_utils.h" + #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) #define COMPILE_ASSERT(expr, err) \ __unused static const char (err)[(expr) ? 1 : -1] = ""; @@ -43,10 +40,10 @@ AwDrawGLFunction* g_aw_drawgl_function = NULL; class DrawGLFunctor : public Functor { public: explicit DrawGLFunctor(jlong view_context) : view_context_(view_context) {} - virtual ~DrawGLFunctor() {} + ~DrawGLFunctor() override {} // Functor - virtual status_t operator ()(int what, void* data) { + status_t operator ()(int what, void* data) override { using uirenderer::DrawGlInfo; if (!g_aw_drawgl_function) { ALOGE("Cannot draw: no DrawGL Function installed"); @@ -54,13 +51,7 @@ class DrawGLFunctor : public Functor { } AwDrawGLInfo aw_info; - // TODO(boliu): Remove property check once OpenGL fallback is removed. - auto render_pipeline_type = - android::uirenderer::Properties::getRenderPipelineType(); - aw_info.version = (render_pipeline_type == - android::uirenderer::RenderPipelineType::OpenGL) - ? 2 - : kAwDrawGLInfoVersion; + aw_info.version = kAwDrawGLInfoVersion; switch (what) { case DrawGlInfo::kModeDraw: { aw_info.mode = AwDrawGLInfo::kModeDraw; @@ -105,27 +96,6 @@ class DrawGLFunctor : public Functor { intptr_t view_context_; }; -// Raise the file handle soft limit to the hard limit since gralloc buffers -// uses file handles. -void RaiseFileNumberLimit() { - static bool have_raised_limit = false; - if (have_raised_limit) - return; - - have_raised_limit = true; - struct rlimit limit_struct; - limit_struct.rlim_cur = 0; - limit_struct.rlim_max = 0; - if (getrlimit(RLIMIT_NOFILE, &limit_struct) == 0) { - limit_struct.rlim_cur = limit_struct.rlim_max; - if (setrlimit(RLIMIT_NOFILE, &limit_struct) != 0) { - ALOGE("setrlimit failed: %s", strerror(errno)); - } - } else { - ALOGE("getrlimit failed: %s", strerror(errno)); - } -} - jlong CreateGLFunctor(JNIEnv*, jclass, jlong view_context) { RaiseFileNumberLimit(); return reinterpret_cast<jlong>(new DrawGLFunctor(view_context)); diff --git a/native/webview/plat_support/functor_utils.cpp b/native/webview/plat_support/functor_utils.cpp new file mode 100644 index 000000000000..235762dc2679 --- /dev/null +++ b/native/webview/plat_support/functor_utils.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 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 "functor_utils.h" + +#include <errno.h> +#include <string.h> +#include <sys/resource.h> +#include <utils/Log.h> + +namespace android { + +void RaiseFileNumberLimit() { + static bool have_raised_limit = false; + if (have_raised_limit) + return; + + have_raised_limit = true; + struct rlimit limit_struct; + limit_struct.rlim_cur = 0; + limit_struct.rlim_max = 0; + if (getrlimit(RLIMIT_NOFILE, &limit_struct) == 0) { + limit_struct.rlim_cur = limit_struct.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &limit_struct) != 0) { + ALOGE("setrlimit failed: %s", strerror(errno)); + } + } else { + ALOGE("getrlimit failed: %s", strerror(errno)); + } +} + +} // namespace android diff --git a/native/webview/plat_support/functor_utils.h b/native/webview/plat_support/functor_utils.h new file mode 100644 index 000000000000..76c0bb67d275 --- /dev/null +++ b/native/webview/plat_support/functor_utils.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2018 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. + */ + +#pragma once + +namespace android { + +// Raise the file handle soft limit to the hard limit since gralloc buffers +// uses file handles. +void RaiseFileNumberLimit(); + +} // namespace android diff --git a/native/webview/plat_support/graphics_utils.cpp b/native/webview/plat_support/graphics_utils.cpp index 89beb754b52c..56825cee4520 100644 --- a/native/webview/plat_support/graphics_utils.cpp +++ b/native/webview/plat_support/graphics_utils.cpp @@ -25,8 +25,8 @@ #include <cstdlib> #include <jni.h> #include <utils/Log.h> +#include "android/graphics/GraphicsJNI.h" #include "graphic_buffer_impl.h" -#include "GraphicsJNI.h" #include "SkCanvasStateUtils.h" #include "SkGraphics.h" #include "SkPicture.h" diff --git a/native/webview/plat_support/jni_entry_point.cpp b/native/webview/plat_support/jni_entry_point.cpp index 4771be1bc258..9599fa6da516 100644 --- a/native/webview/plat_support/jni_entry_point.cpp +++ b/native/webview/plat_support/jni_entry_point.cpp @@ -21,6 +21,7 @@ namespace android { +void RegisterDrawFunctor(JNIEnv* env); void RegisterDrawGLFunctor(JNIEnv* env); void RegisterGraphicsUtils(JNIEnv* env); @@ -30,6 +31,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint ret = vm->AttachCurrentThread(&env, NULL); LOG_ALWAYS_FATAL_IF(ret != JNI_OK, "AttachCurrentThread failed"); + android::RegisterDrawFunctor(env); android::RegisterDrawGLFunctor(env); android::RegisterGraphicsUtils(env); |