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

Commit 0a7096dc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Remove Typeface.create" into oc-dev

parents 257ba894 5a09c643
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -13777,7 +13777,6 @@ package android.graphics {
  }
  public class Typeface {
    method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
    method public static android.graphics.Typeface create(java.lang.String, int);
    method public static android.graphics.Typeface create(android.graphics.Typeface, int);
    method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13812,17 +13811,6 @@ package android.graphics {
    method public android.graphics.Typeface.Builder setWeight(int);
  }
  public static abstract deprecated interface Typeface.FontRequestCallback {
    method public abstract void onTypefaceRequestFailed(int);
    method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
    field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
    field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
    field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
    field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
    field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
    field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
  }
  public class Xfermode {
    ctor public Xfermode();
  }
+0 −12
Original line number Diff line number Diff line
@@ -14552,7 +14552,6 @@ package android.graphics {
  }
  public class Typeface {
    method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
    method public static android.graphics.Typeface create(java.lang.String, int);
    method public static android.graphics.Typeface create(android.graphics.Typeface, int);
    method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -14587,17 +14586,6 @@ package android.graphics {
    method public android.graphics.Typeface.Builder setWeight(int);
  }
  public static abstract deprecated interface Typeface.FontRequestCallback {
    method public abstract void onTypefaceRequestFailed(int);
    method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
    field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
    field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
    field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
    field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
    field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
    field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
  }
  public class Xfermode {
    ctor public Xfermode();
  }
+0 −12
Original line number Diff line number Diff line
@@ -13819,7 +13819,6 @@ package android.graphics {
  }
  public class Typeface {
    method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
    method public static android.graphics.Typeface create(java.lang.String, int);
    method public static android.graphics.Typeface create(android.graphics.Typeface, int);
    method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13854,17 +13853,6 @@ package android.graphics {
    method public android.graphics.Typeface.Builder setWeight(int);
  }
  public static abstract deprecated interface Typeface.FontRequestCallback {
    method public abstract void onTypefaceRequestFailed(int);
    method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
    field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
    field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
    field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
    field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
    field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
    field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
  }
  public class Xfermode {
    ctor public Xfermode();
  }
+33 −59
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.content.pm.Signature;
import android.database.Cursor;
import android.graphics.Typeface;
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
import android.os.Bundle;
@@ -43,6 +42,7 @@ import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.ResultReceiver;
import android.util.ArraySet;
import android.util.Log;
import android.util.LruCache;

@@ -64,6 +64,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Utility class to deal with Font ContentProviders.
@@ -181,6 +182,8 @@ public class FontsContract {
    private Handler mHandler;
    @GuardedBy("mLock")
    private HandlerThread mThread;
    @GuardedBy("mLock")
    private Set<String> mInQueueSet;

    private static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16);

@@ -330,81 +333,54 @@ public class FontsContract {
                    mThread.quitSafely();
                    mThread = null;
                    mHandler = null;
                    mInQueueSet = null;
                }
            }
        }
    };

    /** @hide */
    public void getFont(FontRequest request, ResultReceiver receiver) {
    public Typeface getFontOrWarmUpCache(FontRequest request) {
        final String id = request.getIdentifier();
        Typeface cachedTypeface = sTypefaceCache.get(id);
        if (cachedTypeface != null) {
            return cachedTypeface;
        }

        // Unfortunately the typeface is not available at this time, but requesting from the font
        // provider takes too much time. For now, request the font data to ensure it is in the cache
        // next time and return.
        synchronized (mLock) {
            if (mHandler == null) {
                mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND);
                mThread.start();
                mHandler = new Handler(mThread.getLooper());
                mInQueueSet = new ArraySet<String>();
            }
            mHandler.post(() -> {
                ProviderInfo providerInfo;
                try {
                    providerInfo = getProvider(mPackageManager, request);
                    if (providerInfo == null) {
                        receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
                        return;
                    }
                } catch (PackageManager.NameNotFoundException e) {
                    receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
                    return;
                }
                FontInfo[] fonts;
                try {
                    fonts = getFontFromProvider(mContext, request, providerInfo.authority,
                            null /* cancellation signal */);
                } catch (InvalidFormatException e) {
                    receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
                    return;
            if (mInQueueSet.contains(id)) {
                return null;  // Already requested.
            }

                ArrayList<FontResult> result = new ArrayList<>();
                int resultCode = -1;
                for (FontInfo font : fonts) {
                    try {
                        resultCode = font.getResultCode();
                        if (resultCode != Columns.RESULT_CODE_OK) {
                            if (resultCode < 0) {
                                // Negative values are reserved for the internal errors.
                                resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND;
            mInQueueSet.add(id);
            mHandler.post(() -> {
                synchronized (mLock) {
                    mInQueueSet.remove(id);
                }
                            for (int i = 0; i < result.size(); ++i) {
                try {
                                    result.get(i).getFileDescriptor().close();
                                } catch (IOException e) {
                                    // Ignore, as we are closing fds for cleanup.
                    FontFamilyResult result = fetchFonts(mContext, null, request);
                    if (result.getStatusCode() == FontFamilyResult.STATUS_OK) {
                        Typeface typeface = buildTypeface(mContext, null, result.getFonts());
                        if (typeface != null) {
                            sTypefaceCache.put(id, typeface);
                        }
                    }
                            receiver.send(resultCode, null);
                            return;
                        }
                        ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(
                                font.getUri(), "r");
                        result.add(new FontResult(pfd, font.getTtcIndex(),
                                FontVariationAxis.toFontVariationSettings(font.getAxes()),
                                font.getWeight(), font.isItalic()));
                    } catch (FileNotFoundException e) {
                        Log.e(TAG, "FileNotFoundException raised when interacting with content "
                                + "provider " + providerInfo.authority, e);
                    }
                }
                if (!result.isEmpty()) {
                    Bundle bundle = new Bundle();
                    bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
                    receiver.send(Columns.RESULT_CODE_OK, bundle);
                    return;
                } catch (NameNotFoundException e) {
                    // Ignore.
                }
                receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null);
            });
            mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable);
            mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
        }
        return null;
    }

    /**
@@ -452,16 +428,14 @@ public class FontsContract {
        public FontRequestCallback() {}

        /**
         * Called then a Typeface request done via {@link Typeface#create(FontRequest,
         * FontRequestCallback)} is complete. Note that this method will not be called if
         * {@link #onTypefaceRequestFailed(int)} is called instead.
         * Called then a Typeface request done via {@link #requestFont} is complete. Note that this
         * method will not be called if {@link #onTypefaceRequestFailed(int)} is called instead.
         * @param typeface  The Typeface object retrieved.
         */
        public void onTypefaceRetrieved(Typeface typeface) {}

        /**
         * Called when a Typeface request done via {@link Typeface#create(FontRequest,
         * FontRequestCallback)} fails.
         * Called when a Typeface request done via {@link #requestFont}} fails.
         * @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
         *               {@link #FAIL_REASON_FONT_NOT_FOUND},
         *               {@link #FAIL_REASON_FONT_LOAD_ERROR},
+7 −217
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.FontListParser;
import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontResult;
import android.graphics.fonts.FontVariationAxis;
import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
import android.net.Uri;
@@ -102,8 +101,6 @@ public class Typeface {
            new LongSparseArray<>(3);
    @GuardedBy("sLock")
    private static FontsContract sFontsContract;
    @GuardedBy("sLock")
    private static Handler sHandler;

    /**
     * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
@@ -205,16 +202,9 @@ public class Typeface {
    public static Typeface createFromResources(
            FamilyResourceEntry entry, AssetManager mgr, String path) {
        if (sFallbackFonts != null) {
            Typeface typeface = findFromCache(mgr, path);
            if (typeface != null) return typeface;

            if (entry instanceof ProviderResourceEntry) {
                final ProviderResourceEntry providerEntry = (ProviderResourceEntry) entry;
                // Downloadable font
                typeface = findFromCache(providerEntry.getAuthority(), providerEntry.getQuery());
                if (typeface != null) {
                    return typeface;
                }
                List<List<String>> givenCerts = providerEntry.getCerts();
                List<List<byte[]>> certs = new ArrayList<>();
                if (givenCerts != null) {
@@ -229,11 +219,15 @@ public class Typeface {
                }
                // Downloaded font and it wasn't cached, request it again and return a
                // default font instead (nothing we can do now).
                create(new FontRequest(providerEntry.getAuthority(), providerEntry.getPackage(),
                        providerEntry.getQuery(), certs), NO_OP_REQUEST_CALLBACK);
                return DEFAULT;
                FontRequest request = new FontRequest(providerEntry.getAuthority(),
                        providerEntry.getPackage(), providerEntry.getQuery(), certs);
                Typeface typeface = sFontsContract.getFontOrWarmUpCache(request);
                return typeface == null ? DEFAULT : typeface;
            }

            Typeface typeface = findFromCache(mgr, path);
            if (typeface != null) return typeface;

            // family is FontFamilyFilesResourceEntry
            final FontFamilyFilesResourceEntry filesEntry =
                    (FontFamilyFilesResourceEntry) entry;
@@ -291,213 +285,9 @@ public class Typeface {
        synchronized (sLock) {
            if (sFontsContract == null) {
                sFontsContract = new FontsContract(context);
                sHandler = new Handler();
            }
        }
    }

    /**
     * Create a typeface object given a font request. The font will be asynchronously fetched,
     * therefore the result is delivered to the given callback. See {@link FontRequest}.
     * Only one of the methods in callback will be invoked, depending on whether the request
     * succeeds or fails. These calls will happen on the main thread.
     * @param request A {@link FontRequest} object that identifies the provider and query for the
     *                request. May not be null.
     * @param callback A callback that will be triggered when results are obtained. May not be null.
     */
    @Deprecated
    public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) {
        // Check the cache first
        // TODO: would the developer want to avoid a cache hit and always ask for the freshest
        // result?
        Typeface cachedTypeface = findFromCache(
                request.getProviderAuthority(), request.getQuery());
        if (cachedTypeface != null) {
            sHandler.post(() -> callback.onTypefaceRetrieved(cachedTypeface));
            return;
        }
        synchronized (sLock) {
            if (sFontsContract == null) {
                throw new RuntimeException("Context not initialized, can't query provider");
            }
            final ResultReceiver receiver = new ResultReceiver(null) {
                @Override
                public void onReceiveResult(int resultCode, Bundle resultData) {
                    sHandler.post(() -> receiveResult(request, callback, resultCode, resultData));
                }
            };
            sFontsContract.getFont(request, receiver);
        }
    }

    private static Typeface findFromCache(String providerAuthority, String query) {
        synchronized (sDynamicTypefaceCache) {
            final String key = createProviderUid(providerAuthority, query);
            Typeface typeface = sDynamicTypefaceCache.get(key);
            if (typeface != null) {
                return typeface;
            }
        }
        return null;
    }

    private static void receiveResult(FontRequest request, FontRequestCallback callback,
            int resultCode, Bundle resultData) {
        Typeface cachedTypeface = findFromCache(
                request.getProviderAuthority(), request.getQuery());
        if (cachedTypeface != null) {
            // We already know the result.
            // Probably the requester requests the same font again in a short interval.
            callback.onTypefaceRetrieved(cachedTypeface);
            return;
        }
        if (resultCode != FontsContract.Columns.RESULT_CODE_OK) {
            callback.onTypefaceRequestFailed(resultCode);
            return;
        }
        if (resultData == null) {
            callback.onTypefaceRequestFailed(
                    FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND);
            return;
        }
        List<FontResult> resultList =
                resultData.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
        if (resultList == null || resultList.isEmpty()) {
            callback.onTypefaceRequestFailed(
                    FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND);
            return;
        }
        FontFamily fontFamily = new FontFamily();
        for (int i = 0; i < resultList.size(); ++i) {
            FontResult result = resultList.get(i);
            ParcelFileDescriptor fd = result.getFileDescriptor();
            if (fd == null) {
                callback.onTypefaceRequestFailed(
                        FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
                return;
            }
            try (FileInputStream is = new FileInputStream(fd.getFileDescriptor())) {
                FileChannel fileChannel = is.getChannel();
                long fontSize = fileChannel.size();
                ByteBuffer fontBuffer = fileChannel.map(
                        FileChannel.MapMode.READ_ONLY, 0, fontSize);
                int weight = result.getWeight();
                int italic = result.getItalic() ? STYLE_ITALIC : STYLE_NORMAL;
                FontVariationAxis[] axes = null;
                try {
                    axes = FontVariationAxis.fromFontVariationSettings(
                            result.getFontVariationSettings());
                } catch (FontVariationAxis.InvalidFormatException e) {
                    // TODO: Nice to pass FontVariationAxis[] directly instead of string.
                }
                if (!fontFamily.addFontFromBuffer(fontBuffer, result.getTtcIndex(),
                        axes, weight, italic)) {
                    Log.e(TAG, "Error creating font " + request.getQuery());
                    callback.onTypefaceRequestFailed(
                            FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
                    return;
                }
            } catch (IOException e) {
                Log.e(TAG, "Error reading font " + request.getQuery(), e);
                callback.onTypefaceRequestFailed(
                        FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
                return;
            } finally {
                IoUtils.closeQuietly(fd);
    }
        }
        if (!fontFamily.freeze()) {
            callback.onTypefaceRequestFailed(
                    FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
            return;
        }
        Typeface typeface = Typeface.createFromFamiliesWithDefault(
                new FontFamily[] { fontFamily },
                RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
        synchronized (sDynamicTypefaceCache) {
            String key = createProviderUid(request.getProviderAuthority(), request.getQuery());
            sDynamicTypefaceCache.put(key, typeface);
        }
        callback.onTypefaceRetrieved(typeface);
    }

    /**
     * Interface used to receive asynchronously fetched typefaces.
     */
    @Deprecated
    public interface FontRequestCallback {
        /**
         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
         * provider was not found on the device.
         */
        int FAIL_REASON_PROVIDER_NOT_FOUND = FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND;
        /**
         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
         * provider must be authenticated and the given certificates do not match its signature.
         */
        int FAIL_REASON_WRONG_CERTIFICATES = FontsContract.RESULT_CODE_WRONG_CERTIFICATES;
        /**
         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
         * returned by the provider was not loaded properly.
         */
        int FAIL_REASON_FONT_LOAD_ERROR = -3;
        /**
         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
         * provider did not return any results for the given query.
         */
        int FAIL_REASON_FONT_NOT_FOUND = FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
        /**
         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
         * provider found the queried font, but it is currently unavailable.
         */
        int FAIL_REASON_FONT_UNAVAILABLE = FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
        /**
         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
         * query was not supported by the provider.
         */
        int FAIL_REASON_MALFORMED_QUERY = FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;

        /** @hide */
        @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
                FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE,
                FAIL_REASON_MALFORMED_QUERY })
        @Retention(RetentionPolicy.SOURCE)
        @interface FontRequestFailReason {}

        /**
         * Called then a Typeface request done via {@link Typeface#create(FontRequest,
         * FontRequestCallback)} is complete. Note that this method will not be called if
         * {@link #onTypefaceRequestFailed(int)} is called instead.
         * @param typeface  The Typeface object retrieved.
         */
        void onTypefaceRetrieved(Typeface typeface);

        /**
         * Called when a Typeface request done via {@link Typeface#create(FontRequest,
         * FontRequestCallback)} fails.
         * @param reason May be one of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
         *               {@link #FAIL_REASON_FONT_NOT_FOUND},
         *               {@link #FAIL_REASON_FONT_LOAD_ERROR},
         *               {@link #FAIL_REASON_FONT_UNAVAILABLE} or
         *               {@link #FAIL_REASON_MALFORMED_QUERY} if returned by the system. May also be
         *               a positive value greater than 0 defined by the font provider as an
         *               additional error code. Refer to the provider's documentation for more
         *               information on possible returned error codes.
         */
        void onTypefaceRequestFailed(@FontRequestFailReason int reason);
    }

    private static final FontRequestCallback NO_OP_REQUEST_CALLBACK = new FontRequestCallback() {
        @Override
        public void onTypefaceRetrieved(Typeface typeface) {
            // Do nothing.
        }

        @Override
        public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {
            // Do nothing.
        }
    };

    /**
     * A builder class for creating new Typeface instance.
Loading