Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2edcebb authored by Derek Sollenberger's avatar Derek Sollenberger Committed by Android (Google) Code Review
Browse files

Merge "Consolidate AssetManager calls in Font/FontFamily"

parents 20024529 4db7bd28
Loading
Loading
Loading
Loading
+0 −61
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager2.h>
#include "Utils.h"
#include "FontUtils.h"

@@ -212,63 +210,6 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong
    return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
}

static void releaseAsset(const void* ptr, void* context) {
    delete static_cast<Asset*>(context);
}

static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong builderPtr,
        jobject jassetMgr, jstring jpath, jint cookie, jboolean isAsset, jint ttcIndex,
        jint weight, jint isItalic) {
#ifdef __ANDROID__ // Layoutlib does not support native AssetManager
    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
    NPE_CHECK_RETURN_ZERO(env, jpath);

    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
    if (NULL == mgr) {
        builder->axes.clear();
        return false;
    }

    ScopedUtfChars str(env, jpath);
    if (str.c_str() == nullptr) {
        builder->axes.clear();
        return false;
    }

    std::unique_ptr<Asset> asset;
    {
      ScopedLock<AssetManager2> locked_mgr(*mgr);
      if (isAsset) {
          asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
      } else if (cookie > 0) {
          // Valid java cookies are 1-based, but AssetManager cookies are 0-based.
          asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
                  Asset::ACCESS_BUFFER);
      } else {
          asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
      }
    }

    if (nullptr == asset) {
        builder->axes.clear();
        return false;
    }

    const void* buf = asset->getBuffer(false);
    if (NULL == buf) {
        builder->axes.clear();
        return false;
    }

    sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset,
            asset.release()));
    return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
#else
    return false;
#endif
}

static void FontFamily_addAxisValue(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag, jfloat value) {
    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
    builder->axes.push_back({static_cast<minikin::AxisTag>(tag), value});
@@ -284,8 +225,6 @@ static const JNINativeMethod gFontFamilyMethods[] = {
    { "nAddFont",               "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
    { "nAddFontWeightStyle",    "(JLjava/nio/ByteBuffer;III)Z",
            (void*)FontFamily_addFontWeightStyle },
    { "nAddFontFromAssetManager",    "(JLandroid/content/res/AssetManager;Ljava/lang/String;IZIII)Z",
            (void*)FontFamily_addFontFromAssetManager },
    { "nAddAxisValue",         "(JIF)V", (void*)FontFamily_addAxisValue },
};

+0 −63
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@
#include "GraphicsJNI.h"
#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager2.h>
#include "Utils.h"
#include "FontUtils.h"

@@ -48,14 +46,6 @@ static inline NativeFontBuilder* toBuilder(jlong ptr) {
    return reinterpret_cast<NativeFontBuilder*>(ptr);
}

static inline Asset* toAsset(jlong ptr) {
    return reinterpret_cast<Asset*>(ptr);
}

static void releaseAsset(jlong asset) {
    delete toAsset(asset);
}

static void releaseFont(jlong font) {
    delete reinterpret_cast<FontWrapper*>(font);
}
@@ -78,54 +68,6 @@ static void release_global_ref(const void* /*data*/, void* context) {
    env->DeleteGlobalRef(obj);
}

// Regular JNI
static jlong Font_Builder_getNativeAsset(
    JNIEnv* env, jobject clazz, jobject assetMgr, jstring path, jboolean isAsset, jint cookie) {
#ifdef __ANDROID__ // Layoutlib does not support native AssetManager
    NPE_CHECK_RETURN_ZERO(env, assetMgr);
    NPE_CHECK_RETURN_ZERO(env, path);

    Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, assetMgr);
    if (mgr == nullptr) {
        return 0;
    }

    ScopedUtfChars str(env, path);
    if (str.c_str() == nullptr) {
        return 0;
    }

    std::unique_ptr<Asset> asset;
    {
      ScopedLock<AssetManager2> locked_mgr(*mgr);
      if (isAsset) {
          asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
      } else if (cookie > 0) {
          // Valid java cookies are 1-based, but AssetManager cookies are 0-based.
          asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
                  Asset::ACCESS_BUFFER);
      } else {
          asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
      }
    }

    return reinterpret_cast<jlong>(asset.release());
#else
    return 0;
#endif
}

// Regular JNI
static jobject Font_Builder_getAssetBuffer(JNIEnv* env, jobject clazz, jlong nativeAsset) {
    Asset* asset = toAsset(nativeAsset);
    return env->NewDirectByteBuffer(const_cast<void*>(asset->getBuffer(false)), asset->getLength());
}

// CriticalNative
static jlong Font_Builder_getReleaseNativeAssetFunc(CRITICAL_JNI_PARAMS) {
    return reinterpret_cast<jlong>(&releaseAsset);
}

// Regular JNI
static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
    return reinterpret_cast<jlong>(new NativeFontBuilder());
@@ -196,11 +138,6 @@ static const JNINativeMethod gFontBuilderMethods[] = {
    { "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
    { "nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;IZI)J", (void*) Font_Builder_build },
    { "nGetReleaseNativeFont", "()J", (void*) Font_Builder_getReleaseNativeFont },

    { "nGetNativeAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;ZI)J",
      (void*) Font_Builder_getNativeAsset },
    { "nGetAssetBuffer", "(J)Ljava/nio/ByteBuffer;", (void*) Font_Builder_getAssetBuffer },
    { "nGetReleaseNativeAssetFunc", "()J", (void*) Font_Builder_getReleaseNativeAssetFunc },
};

int register_android_graphics_fonts_Font(JNIEnv* env) {
+7 −13
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.graphics;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontVariationAxis;
import android.os.Build;
import android.text.TextUtils;
@@ -195,18 +196,13 @@ public class FontFamily {
        if (mBuilderPtr == 0) {
            throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
        }
        if (axes != null) {
            for (FontVariationAxis axis : axes) {
                nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
            }
        }
        return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
                isItalic);
    }

    // TODO: Remove once internal user stop using private API.
    private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
        return nAddFont(builderPtr, font, ttcIndex, -1, -1);
        try {
            ByteBuffer buffer =  Font.Builder.createBuffer(mgr, path, isAsset, cookie);
            return addFontFromBuffer(buffer, ttcIndex, axes, weight, isItalic);
        } catch (IOException e) {
            return false;
        }
    }

    private static native long nInitBuilder(String langs, int variant);
@@ -225,8 +221,6 @@ public class FontFamily {
            int weight, int isItalic);
    private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
            int ttcIndex, int weight, int isItalic);
    private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
            String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);

    // The added axis values are only valid for the next nAddFont* method call.
    @CriticalNative
+68 −36
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.graphics.fonts;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.LocaleList;
@@ -35,7 +36,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Objects;
@@ -54,10 +57,6 @@ public final class Font {
     * A builder class for creating new Font.
     */
    public static final class Builder {
        private static final NativeAllocationRegistry sAssetByteBufferRegistry =
                NativeAllocationRegistry.createMalloced(ByteBuffer.class.getClassLoader(),
                    nGetReleaseNativeAssetFunc());

        private static final NativeAllocationRegistry sFontRegistry =
                NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
                    nGetReleaseNativeFont());
@@ -151,7 +150,11 @@ public final class Font {
         * @param path the file name of the font data in the asset directory
         */
        public Builder(@NonNull AssetManager am, @NonNull String path) {
            this(am, path, true /* is asset */, 0 /* cookie */);
            try {
                mBuffer = createBuffer(am, path, true /* is asset */, 0 /* cookie */);
            } catch (IOException e) {
                mException = e;
            }
        }

        /**
@@ -165,18 +168,11 @@ public final class Font {
         */
        public Builder(@NonNull AssetManager am, @NonNull String path, boolean isAsset,
                int cookie) {
            final long nativeAsset = nGetNativeAsset(am, path, isAsset, cookie);
            if (nativeAsset == 0) {
                mException = new FileNotFoundException("Unable to open " + path);
                return;
            }
            final ByteBuffer b = nGetAssetBuffer(nativeAsset);
            sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
            if (b == null) {
                mException = new FileNotFoundException(path + " not found");
                return;
            try {
                mBuffer = createBuffer(am, path, isAsset, cookie);
            } catch (IOException e) {
                mException = e;
            }
            mBuffer = b;
        }

        /**
@@ -199,19 +195,64 @@ public final class Font {
                mException = new FileNotFoundException(resId + " must be font file.");
                return;
            }
            final long nativeAsset = nGetNativeAsset(res.getAssets(), str, false /* is asset */,
                    value.assetCookie);
            if (nativeAsset == 0) {
                mException = new FileNotFoundException("Unable to open " + str);
                return;

            try {
                mBuffer = createBuffer(res.getAssets(), str, false, value.assetCookie);
            } catch (IOException e) {
                mException = e;
            }
            final ByteBuffer b = nGetAssetBuffer(nativeAsset);
            sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
            if (b == null) {
                mException = new FileNotFoundException(str + " not found");
                return;
        }
            mBuffer = b;

        /**
         * Creates a buffer containing font data using the assetManager and other
         * provided inputs.
         *
         * @param am the application's asset manager
         * @param path the file name of the font data in the asset directory
         * @param isAsset true if the undelying data is in asset
         * @param cookie set asset cookie
         * @return buffer containing the contents of the file
         *
         * @hide
         */
        public static ByteBuffer createBuffer(@NonNull AssetManager am, @NonNull String path,
                                              boolean isAsset, int cookie) throws IOException {
            Preconditions.checkNotNull(am, "assetManager can not be null");
            Preconditions.checkNotNull(path, "path can not be null");

            if (!isAsset) {
                // Attempt to open as FD, which should work unless the asset is compressed
                AssetFileDescriptor assetFD;
                try {
                    if (cookie > 0) {
                        assetFD = am.openNonAssetFd(cookie, path);
                    } else {
                        assetFD = am.openNonAssetFd(path);
                    }

                    try (FileInputStream fis = assetFD.createInputStream()) {
                        final FileChannel fc = fis.getChannel();
                        return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
                    }
                } catch (IOException e) {
                    // failed to open as FD so now we will attempt to open as an input stream
                }
            }

            try (InputStream assetStream = isAsset ? am.open(path, AssetManager.ACCESS_BUFFER)
                    : am.openNonAsset(cookie, path, AssetManager.ACCESS_BUFFER)) {

                int capacity = assetStream.available();
                ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
                buffer.order(ByteOrder.nativeOrder());
                assetStream.read(buffer.array(), buffer.arrayOffset(), assetStream.available());

                if (assetStream.read() != -1) {
                    throw new IOException("Unable to access full contents of " + path);
                }

                return buffer;
            }
        }

        /**
@@ -395,15 +436,6 @@ public final class Font {
            return font;
        }

        /**
         * Native methods for accessing underlying buffer in Asset
         */
        private static native long nGetNativeAsset(
                @NonNull AssetManager am, @NonNull String path, boolean isAsset, int cookie);
        private static native ByteBuffer nGetAssetBuffer(long nativeAsset);
        @CriticalNative
        private static native long nGetReleaseNativeAssetFunc();

        /**
         * Native methods for creating Font
         */