1 /*
2  * Copyright (C) 2018 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 package android.content.pm;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.os.Build;
21 
22 import com.android.internal.annotations.VisibleForTesting;
23 import com.android.internal.util.ArrayUtils;
24 
25 import java.util.ArrayList;
26 
27 /**
28  * Base for classes that update a {@link PackageParser.Package}'s shared libraries.
29  *
30  * @hide
31  */
32 @VisibleForTesting
33 public abstract class PackageSharedLibraryUpdater {
34 
35     /**
36      * Update the package's shared libraries.
37      *
38      * @param pkg the package to update.
39      */
updatePackage(PackageParser.Package pkg)40     public abstract void updatePackage(PackageParser.Package pkg);
41 
removeLibrary(PackageParser.Package pkg, String libraryName)42     static void removeLibrary(PackageParser.Package pkg, String libraryName) {
43         pkg.usesLibraries = ArrayUtils.remove(pkg.usesLibraries, libraryName);
44         pkg.usesOptionalLibraries =
45                 ArrayUtils.remove(pkg.usesOptionalLibraries, libraryName);
46     }
47 
48     static @NonNull
prefix(@ullable ArrayList<T> cur, T val)49             <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
50         if (cur == null) {
51             cur = new ArrayList<>();
52         }
53         cur.add(0, val);
54         return cur;
55     }
56 
isLibraryPresent(ArrayList<String> usesLibraries, ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy)57     private static boolean isLibraryPresent(ArrayList<String> usesLibraries,
58             ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) {
59         return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
60                 || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
61     }
62 
apkTargetsApiLevelLessThanOrEqualToOMR1(PackageParser.Package pkg)63     static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(PackageParser.Package pkg) {
64         int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
65         return targetSdkVersion < Build.VERSION_CODES.P;
66     }
67 
68     /**
69      * Add an implicit dependency.
70      *
71      * <p>If the package has an existing dependency on {@code existingLibrary} then prefix it with
72      * the {@code implicitDependency} if it is not already in the list of libraries.
73      *
74      * @param pkg the {@link PackageParser.Package} to update.
75      * @param existingLibrary the existing library.
76      * @param implicitDependency the implicit dependency to add
77      */
prefixImplicitDependency(PackageParser.Package pkg, String existingLibrary, String implicitDependency)78     void prefixImplicitDependency(PackageParser.Package pkg, String existingLibrary,
79             String implicitDependency) {
80         ArrayList<String> usesLibraries = pkg.usesLibraries;
81         ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
82 
83         if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) {
84             if (ArrayUtils.contains(usesLibraries, existingLibrary)) {
85                 prefix(usesLibraries, implicitDependency);
86             } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) {
87                 prefix(usesOptionalLibraries, implicitDependency);
88             }
89 
90             pkg.usesLibraries = usesLibraries;
91             pkg.usesOptionalLibraries = usesOptionalLibraries;
92         }
93     }
94 
prefixRequiredLibrary(PackageParser.Package pkg, String libraryName)95     void prefixRequiredLibrary(PackageParser.Package pkg, String libraryName) {
96         ArrayList<String> usesLibraries = pkg.usesLibraries;
97         ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
98 
99         boolean alreadyPresent = isLibraryPresent(
100                 usesLibraries, usesOptionalLibraries, libraryName);
101         if (!alreadyPresent) {
102             usesLibraries = prefix(usesLibraries, libraryName);
103 
104             pkg.usesLibraries = usesLibraries;
105         }
106     }
107 }
108