diff options
Diffstat (limited to 'native')
| -rw-r--r-- | native/android/Android.bp | 5 | ||||
| -rw-r--r-- | native/android/libandroid.map.txt | 13 | ||||
| -rw-r--r-- | native/android/storage_manager.cpp | 26 | ||||
| -rw-r--r-- | native/android/surface_texture.cpp | 5 | ||||
| -rw-r--r-- | native/android/system_fonts.cpp | 339 | ||||
| -rw-r--r-- | native/webview/OWNERS | 1 | ||||
| -rw-r--r-- | native/webview/loader/loader.cpp | 22 | ||||
| -rw-r--r-- | native/webview/plat_support/draw_gl_functor.cpp | 9 |
8 files changed, 403 insertions, 17 deletions
diff --git a/native/android/Android.bp b/native/android/Android.bp index c26d980aa2fc..5cfb09b9a68c 100644 --- a/native/android/Android.bp +++ b/native/android/Android.bp @@ -49,6 +49,7 @@ cc_library_shared { "sharedmem.cpp", "storage_manager.cpp", "surface_texture.cpp", + "system_fonts.cpp", "trace.cpp", ], @@ -61,9 +62,13 @@ cc_library_shared { "libbinder", "libui", "libgui", + "libharfbuzz_ng", // Only for including hb.h via minikin "libsensor", "libandroid_runtime", + "libminikin", "libnetd_client", + "libhwui", + "libxml2", ], static_libs: [ diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index ac5ded60bf6b..e7e8384c5567 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -212,6 +212,19 @@ LIBANDROID { ASurfaceTexture_getTransformMatrix; # introduced=28 ASurfaceTexture_release; # introduced=28 ASurfaceTexture_updateTexImage; # introduced=28 + ASystemFontIterator_open; # introduced=29 + ASystemFontIterator_close; # introduced=29 + ASystemFontIterator_next; # introduced=29 + ASystemFont_close; # introduced=29 + ASystemFont_getFontFilePath; # introduced=29 + ASystemFont_getWeight; # introduced=29 + ASystemFont_isItalic; # introduced=29 + ASystemFont_getLocale; # introduced=29 + ASystemFont_getCollectionIndex; # introduced=29 + ASystemFont_getAxisCount; # introduced=29 + ASystemFont_getAxisTag; # introduced=29 + ASystemFont_getAxisValue; # introduced=29 + ASystemFont_matchFamilyStyleCharacter; # introduced=29 ATrace_beginSection; # introduced=23 ATrace_endSection; # introduced=23 ATrace_isEnabled; # introduced=23 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_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..4d3d1d66ffda --- /dev/null +++ b/native/android/system_fonts.cpp @@ -0,0 +1,339 @@ +/* + * 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/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 ASystemFont { + 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; +}; + +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, ASystemFont* 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; +} + +ASystemFont* ASystemFont_matchFamilyStyleCharacter( + const char* _Nonnull familyName, + uint16_t weight, + bool italic, + const char* _Nonnull languageTags, + const uint16_t* _Nonnull text, + 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), + minikin::FontStyle(weight, static_cast<minikin::FontStyle::Slant>(italic)), + minikin::registerLocaleList(languageTags), + minikin::FamilyVariant::DEFAULT); + + const minikin::Font* font = runs[0].fakedFont.font; + std::unique_ptr<ASystemFont> result = std::make_unique<ASystemFont>(); + 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; + } +} + +ASystemFont* 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<ASystemFont> font = std::make_unique<ASystemFont>(); + 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<ASystemFont> font = std::make_unique<ASystemFont>(); + copyFont(ite->mCustomizationXmlDoc, ite->mFontNode, font.get(), "/product/fonts/"); + if (!isFontFileAvailable(font->mFilePath)) { + return ASystemFontIterator_next(ite); + } + return font.release(); + } + } + return nullptr; +} + +void ASystemFont_close(ASystemFont* font) { + delete font; +} + +const char* ASystemFont_getFontFilePath(const ASystemFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument"); + return font->mFilePath.c_str(); +} + +uint16_t ASystemFont_getWeight(const ASystemFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument"); + return font->mWeight; +} + +bool ASystemFont_isItalic(const ASystemFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument"); + return font->mItalic; +} + +const char* ASystemFont_getLocale(const ASystemFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + return font->mLocale ? nullptr : font->mLocale->c_str(); +} + +size_t ASystemFont_getCollectionIndex(const ASystemFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + return font->mCollectionIndex; +} + +size_t ASystemFont_getAxisCount(const ASystemFont* font) { + LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument"); + return font->mAxes.size(); +} + +uint32_t ASystemFont_getAxisTag(const ASystemFont* 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 ASystemFont_getAxisValue(const ASystemFont* 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/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/loader.cpp b/native/webview/loader/loader.cpp index adb371dde0fc..7f71f6312f00 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,19 @@ 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; 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) { @@ -143,13 +154,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 +191,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/draw_gl_functor.cpp b/native/webview/plat_support/draw_gl_functor.cpp index d54f558b9866..7cb49da483de 100644 --- a/native/webview/plat_support/draw_gl_functor.cpp +++ b/native/webview/plat_support/draw_gl_functor.cpp @@ -21,7 +21,6 @@ #include "draw_gl.h" -#include <Properties.h> #include <errno.h> #include <jni.h> #include <private/hwui/DrawGlInfo.h> @@ -54,13 +53,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; |