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.content.pm;
18 
19 import android.annotation.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.TestApi;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Objects;
34 
35 /**
36  * This class provides information for a shared library. There are
37  * four types of shared libraries: builtin - non-updatable part of
38  * the OS; dynamic - updatable backwards-compatible dynamically linked;
39  * static - non backwards-compatible emulating static linking;
40  * SDK - updatable backwards-incompatible dynamically loaded.
41  */
42 public final class SharedLibraryInfo implements Parcelable {
43 
44     /** @hide */
45     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
46             TYPE_BUILTIN,
47             TYPE_DYNAMIC,
48             TYPE_STATIC,
49             TYPE_SDK_PACKAGE,
50     })
51     @Retention(RetentionPolicy.SOURCE)
52     public @interface Type{}
53 
54     /**
55      * Shared library type: this library is a part of the OS
56      * and cannot be updated or uninstalled.
57      */
58     public static final int TYPE_BUILTIN = 0;
59 
60     /**
61      * Shared library type: this library is backwards-compatible, can
62      * be updated, and updates can be uninstalled. Clients link against
63      * the latest version of the library.
64      */
65     public static final int TYPE_DYNAMIC = 1;
66 
67     /**
68      * Shared library type: this library is <strong>not</strong> backwards
69      * -compatible, can be updated and updates can be uninstalled. Clients
70      * link against a specific version of the library.
71      *
72      * Static shared libraries simulate static linking while allowing for
73      * multiple clients to reuse the same instance of the library.
74      */
75     public static final int TYPE_STATIC = 2;
76 
77     /**
78      * SDK package shared library type: this library is <strong>not</strong>
79      * compatible between versions, can be updated and updates can be
80      * uninstalled. Clients depend on a specific version of the library.
81      *
82      * SDK packages are not loaded automatically by the OS and rely
83      * e.g. on 3P libraries to make them available for the clients.
84      */
85     public static final int TYPE_SDK_PACKAGE = 3;
86 
87     /**
88      * Constant for referring to an undefined version.
89      */
90     public static final int VERSION_UNDEFINED = -1;
91 
92     private final String mPath;
93     private final String mPackageName;
94     private final String mName;
95     private final List<String> mCodePaths;
96 
97     private final long mVersion;
98     private final @Type int mType;
99     private final boolean mIsNative;
100     private final VersionedPackage mDeclaringPackage;
101     private final List<VersionedPackage> mDependentPackages;
102     private List<SharedLibraryInfo> mDependencies;
103 
104     /**
105      * Creates a new instance.
106      *
107      * @param codePaths For a non {@link #TYPE_BUILTIN builtin} library, the locations of jars of
108      *                  this shared library. Null for builtin library.
109      * @param name The lib name.
110      * @param version The lib version if not builtin.
111      * @param type The lib type.
112      * @param declaringPackage The package that declares the library.
113      * @param dependentPackages The packages that depend on the library.
114      * @param isNative indicate if this shared lib is a native lib or not (i.e. java)
115      *
116      * @hide
117      */
SharedLibraryInfo(String path, String packageName, List<String> codePaths, String name, long version, int type, VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages, List<SharedLibraryInfo> dependencies, boolean isNative)118     public SharedLibraryInfo(String path, String packageName, List<String> codePaths,
119             String name, long version, int type,
120             VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
121             List<SharedLibraryInfo> dependencies, boolean isNative) {
122         mPath = path;
123         mPackageName = packageName;
124         mCodePaths = codePaths;
125         mName = name;
126         mVersion = version;
127         mType = type;
128         mDeclaringPackage = declaringPackage;
129         mDependentPackages = dependentPackages;
130         mDependencies = dependencies;
131         mIsNative = isNative;
132     }
133 
SharedLibraryInfo(Parcel parcel)134     private SharedLibraryInfo(Parcel parcel) {
135         mPath = parcel.readString8();
136         mPackageName = parcel.readString8();
137         if (parcel.readInt() != 0) {
138             mCodePaths = Arrays.asList(parcel.createString8Array());
139         } else {
140             mCodePaths = null;
141         }
142         mName = parcel.readString8();
143         mVersion = parcel.readLong();
144         mType = parcel.readInt();
145         mDeclaringPackage = parcel.readParcelable(null, android.content.pm.VersionedPackage.class);
146         mDependentPackages = parcel.readArrayList(null, android.content.pm.VersionedPackage.class);
147         mDependencies = parcel.createTypedArrayList(SharedLibraryInfo.CREATOR);
148         mIsNative = parcel.readBoolean();
149     }
150 
151     /**
152      * Gets the type of this library.
153      *
154      * @return The library type.
155      */
getType()156     public @Type int getType() {
157         return mType;
158     }
159 
160     /**
161      * Tells whether this library is a native shared library or not.
162      *
163      * @hide
164      */
165     @TestApi
isNative()166     public boolean isNative() {
167         return mIsNative;
168     }
169 
170     /**
171      * Gets the library name an app defines in its manifest
172      * to depend on the library.
173      *
174      * @return The name.
175      */
getName()176     public String getName() {
177         return mName;
178     }
179 
180     /**
181      * If the shared library is a jar file, returns the path of that jar. Null otherwise.
182      * Only libraries with TYPE_BUILTIN are in jar files.
183      *
184      * @return The path.
185      *
186      * @hide
187      */
getPath()188     public @Nullable String getPath() {
189         return mPath;
190     }
191 
192     /**
193      * If the shared library is an apk, returns the package name. Null otherwise.
194      * Only libraries with TYPE_DYNAMIC or TYPE_STATIC are in apks.
195      *
196      * @return The package name.
197      *
198      * @hide
199      */
getPackageName()200     public @Nullable String getPackageName() {
201         return mPackageName;
202     }
203 
204     /**
205      * Get all code paths for that library.
206      *
207      * @return All code paths.
208      *
209      * @hide
210      */
211     @TestApi
getAllCodePaths()212     public @NonNull List<String> getAllCodePaths() {
213         if (getPath() != null) {
214             // Builtin library.
215             ArrayList<String> list = new ArrayList<>();
216             list.add(getPath());
217             return list;
218         } else {
219             // Static or dynamic library.
220             return Objects.requireNonNull(mCodePaths);
221         }
222     }
223 
224     /**
225      * Add a library dependency to that library. Note that this
226      * should be called under the package manager lock.
227      *
228      * @hide
229      */
addDependency(@ullable SharedLibraryInfo info)230     public void addDependency(@Nullable SharedLibraryInfo info) {
231         if (info == null) {
232             // For convenience of the caller, allow null to be passed.
233             // This can happen when we create the dependencies of builtin
234             // libraries.
235             return;
236         }
237         if (mDependencies == null) {
238             mDependencies = new ArrayList<>();
239         }
240         mDependencies.add(info);
241     }
242 
243     /**
244      * Clear all dependencies.
245      *
246      * @hide
247      */
clearDependencies()248     public void clearDependencies() {
249         mDependencies = null;
250     }
251 
252     /**
253      * Gets the libraries this library directly depends on. Note that
254      * the package manager prevents recursive dependencies when installing
255      * a package.
256      *
257      * @return The dependencies.
258      *
259      * @hide
260      */
getDependencies()261     public @Nullable List<SharedLibraryInfo> getDependencies() {
262         return mDependencies;
263     }
264 
265     /**
266      * @deprecated Use {@link #getLongVersion()} instead.
267      */
268     @Deprecated
getVersion()269     public @IntRange(from = -1) int getVersion() {
270         return mVersion < 0 ? (int) mVersion : (int) (mVersion & 0x7fffffff);
271     }
272 
273     /**
274      * Gets the version of the library. For {@link #TYPE_STATIC static} libraries
275      * this is the declared version and for {@link #TYPE_DYNAMIC dynamic} and
276      * {@link #TYPE_BUILTIN builtin} it is {@link #VERSION_UNDEFINED} as these
277      * are not versioned.
278      *
279      * @return The version.
280      */
getLongVersion()281     public @IntRange(from = -1) long getLongVersion() {
282         return mVersion;
283     }
284 
285     /**
286      * @removed
287      */
isBuiltin()288     public boolean isBuiltin() {
289         return mType == TYPE_BUILTIN;
290     }
291 
292     /**
293      * @removed
294      */
isDynamic()295     public boolean isDynamic() {
296         return mType == TYPE_DYNAMIC;
297     }
298 
299     /**
300      * @removed
301      */
isStatic()302     public boolean isStatic() {
303         return mType == TYPE_STATIC;
304     }
305 
306     /**
307      * @hide
308      */
isSdk()309     public boolean isSdk() {
310         return mType == TYPE_SDK_PACKAGE;
311     }
312 
313     /**
314      * Gets the package that declares the library.
315      *
316      * @return The package declaring the library.
317      */
getDeclaringPackage()318     public @NonNull VersionedPackage getDeclaringPackage() {
319         return mDeclaringPackage;
320     }
321 
322     /**
323      * Gets the packages that depend on the library.
324      *
325      * @return The dependent packages.
326      */
getDependentPackages()327     public @NonNull List<VersionedPackage> getDependentPackages() {
328         if (mDependentPackages == null) {
329             return Collections.emptyList();
330         }
331         return mDependentPackages;
332     }
333 
334     @Override
describeContents()335     public int describeContents() {
336         return 0;
337     }
338 
339     @Override
toString()340     public String toString() {
341         return "SharedLibraryInfo{name:" + mName + ", type:" + typeToString(mType)
342                 + ", version:" + mVersion + (!getDependentPackages().isEmpty()
343                 ? " has dependents" : "") + "}";
344     }
345 
346     @Override
writeToParcel(Parcel parcel, int flags)347     public void writeToParcel(Parcel parcel, int flags) {
348         parcel.writeString8(mPath);
349         parcel.writeString8(mPackageName);
350         if (mCodePaths != null) {
351             parcel.writeInt(1);
352             parcel.writeString8Array(mCodePaths.toArray(new String[mCodePaths.size()]));
353         } else {
354             parcel.writeInt(0);
355         }
356         parcel.writeString8(mName);
357         parcel.writeLong(mVersion);
358         parcel.writeInt(mType);
359         parcel.writeParcelable(mDeclaringPackage, flags);
360         parcel.writeList(mDependentPackages);
361         parcel.writeTypedList(mDependencies);
362         parcel.writeBoolean(mIsNative);
363     }
364 
typeToString(int type)365     private static String typeToString(int type) {
366         switch (type) {
367             case TYPE_BUILTIN: {
368                 return "builtin";
369             }
370             case TYPE_DYNAMIC: {
371                 return "dynamic";
372             }
373             case TYPE_STATIC: {
374                 return "static";
375             }
376             case TYPE_SDK_PACKAGE: {
377                 return "sdk";
378             }
379             default: {
380                 return "unknown";
381             }
382         }
383     }
384 
385     public static final @android.annotation.NonNull Parcelable.Creator<SharedLibraryInfo> CREATOR =
386             new Parcelable.Creator<SharedLibraryInfo>() {
387         public SharedLibraryInfo createFromParcel(Parcel source) {
388             return new SharedLibraryInfo(source);
389         }
390 
391         public SharedLibraryInfo[] newArray(int size) {
392             return new SharedLibraryInfo[size];
393         }
394     };
395 }
396