1298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka/*
2298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * Copyright (C) 2017 The Android Open Source Project
3298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka *
4298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License");
5298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * you may not use this file except in compliance with the License.
6298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * You may obtain a copy of the License at
7298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka *
8298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka *      http://www.apache.org/licenses/LICENSE-2.0
9298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka *
10298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * Unless required by applicable law or agreed to in writing, software
11298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS,
12298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * See the License for the specific language governing permissions and
14298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * limitations under the License.
15298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka */
16298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
17298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakapackage android.graphics;
18298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
19298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport com.android.internal.annotations.GuardedBy;
20298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
21298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport android.annotation.NonNull;
22298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport android.annotation.Nullable;
23298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport android.os.Parcel;
24298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport android.os.Process;
25298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport android.util.ArrayMap;
26298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
27298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakaimport java.util.ArrayList;
28298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
29298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka/**
30298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * This class is used for Parceling Typeface object.
31298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * Note: Typeface object can not be passed over the process boundary.
32298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka *
33298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka * @hide
34298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka */
35298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonakapublic class LeakyTypefaceStorage {
36298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    private static final Object sLock = new Object();
37298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
38298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    @GuardedBy("sLock")
39298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    private static final ArrayList<Typeface> sStorage = new ArrayList<>();
40298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    @GuardedBy("sLock")
41298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    private static final ArrayMap<Typeface, Integer> sTypefaceMap = new ArrayMap<>();
42298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
43298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    /**
44298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * Write typeface to parcel.
45298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     *
46298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * You can't transfer Typeface to a different process. {@link readTypefaceFromParcel} will
47298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * return {@code null} if the {@link readTypefaceFromParcel} is called in a different process.
48298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     *
49298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * @param typeface A {@link Typeface} to be written.
50298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * @param parcel A {@link Parcel} object.
51298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     */
52298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    public static void writeTypefaceToParcel(@Nullable Typeface typeface, @NonNull Parcel parcel) {
53298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        parcel.writeInt(Process.myPid());
54298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        synchronized (sLock) {
55298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            final int id;
56298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            final Integer i = sTypefaceMap.get(typeface);
57298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            if (i != null) {
58298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka                id = i.intValue();
59298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            } else {
60298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka                id = sStorage.size();
61298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka                sStorage.add(typeface);
62298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka                sTypefaceMap.put(typeface, id);
63298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            }
64298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            parcel.writeInt(id);
65298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        }
66298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    }
67298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka
68298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    /**
69298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * Read typeface from parcel.
70298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     *
71298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * If the {@link Typeface} was created in another process, this method returns null.
72298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     *
73298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * @param parcel A {@link Parcel} object
74298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     * @return A {@link Typeface} object.
75298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka     */
76298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    public static @Nullable Typeface readTypefaceFromParcel(@NonNull Parcel parcel) {
77298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        final int pid = parcel.readInt();
78298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        final int typefaceId = parcel.readInt();
79298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        if (pid != Process.myPid()) {
80298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            return null;  // The Typeface was created and written in another process.
81298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        }
82298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        synchronized (sLock) {
83298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka            return sStorage.get(typefaceId);
84298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka        }
85298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka    }
86298bb2995b7544793006c0f93953c7aac2f08d61Seigo Nonaka}
87