1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import com.android.internal.annotations.GuardedBy;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.os.Parcel;
24 import android.os.Process;
25 import android.util.ArrayMap;
26 
27 import java.util.ArrayList;
28 
29 /**
30  * This class is used for Parceling Typeface object.
31  * Note: Typeface object can not be passed over the process boundary.
32  *
33  * @hide
34  */
35 public class LeakyTypefaceStorage {
36     private static final Object sLock = new Object();
37 
38     @GuardedBy("sLock")
39     private static final ArrayList<Typeface> sStorage = new ArrayList<>();
40     @GuardedBy("sLock")
41     private static final ArrayMap<Typeface, Integer> sTypefaceMap = new ArrayMap<>();
42 
43     /**
44      * Write typeface to parcel.
45      *
46      * You can't transfer Typeface to a different process. {@link readTypefaceFromParcel} will
47      * return {@code null} if the {@link readTypefaceFromParcel} is called in a different process.
48      *
49      * @param typeface A {@link Typeface} to be written.
50      * @param parcel A {@link Parcel} object.
51      */
writeTypefaceToParcel(@ullable Typeface typeface, @NonNull Parcel parcel)52     public static void writeTypefaceToParcel(@Nullable Typeface typeface, @NonNull Parcel parcel) {
53         parcel.writeInt(Process.myPid());
54         synchronized (sLock) {
55             final int id;
56             final Integer i = sTypefaceMap.get(typeface);
57             if (i != null) {
58                 id = i.intValue();
59             } else {
60                 id = sStorage.size();
61                 sStorage.add(typeface);
62                 sTypefaceMap.put(typeface, id);
63             }
64             parcel.writeInt(id);
65         }
66     }
67 
68     /**
69      * Read typeface from parcel.
70      *
71      * If the {@link Typeface} was created in another process, this method returns null.
72      *
73      * @param parcel A {@link Parcel} object
74      * @return A {@link Typeface} object.
75      */
readTypefaceFromParcel(@onNull Parcel parcel)76     public static @Nullable Typeface readTypefaceFromParcel(@NonNull Parcel parcel) {
77         final int pid = parcel.readInt();
78         final int typefaceId = parcel.readInt();
79         if (pid != Process.myPid()) {
80             return null;  // The Typeface was created and written in another process.
81         }
82         synchronized (sLock) {
83             return sStorage.get(typefaceId);
84         }
85     }
86 }
87