1 /*
2  * Copyright (C) 2020 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 com.android.server.pm.parsing.library;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 
21 import com.android.internal.annotations.VisibleForTesting;
22 import com.android.internal.util.ArrayUtils;
23 import com.android.server.pm.parsing.pkg.ParsedPackage;
24 
25 import java.util.ArrayList;
26 import java.util.List;
27 
28 /**
29  * Base for classes that update a {@link ParsedPackage}'s shared libraries.
30  *
31  * @hide
32  */
33 @VisibleForTesting
34 public abstract class PackageSharedLibraryUpdater {
35 
36     /**
37      * Update the package's shared libraries.
38      *
39      * @param parsedPackage the package to update.
40      */
updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp)41     public abstract void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp);
42 
removeLibrary(ParsedPackage parsedPackage, String libraryName)43     static void removeLibrary(ParsedPackage parsedPackage, String libraryName) {
44         parsedPackage.removeUsesLibrary(libraryName)
45                 .removeUsesOptionalLibrary(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(List<String> usesLibraries, List<String> usesOptionalLibraries, String apacheHttpLegacy)57     private static boolean isLibraryPresent(List<String> usesLibraries,
58             List<String> usesOptionalLibraries, String apacheHttpLegacy) {
59         return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
60                 || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
61     }
62 
63     /**
64      * Add an implicit dependency.
65      *
66      * <p>If the package has an existing dependency on {@code existingLibrary} then prefix it with
67      * the {@code implicitDependency} if it is not already in the list of libraries.
68      *
69      * @param parsedPackage the {@link ParsedPackage} to update.
70      * @param existingLibrary the existing library.
71      * @param implicitDependency the implicit dependency to add
72      */
prefixImplicitDependency(ParsedPackage parsedPackage, String existingLibrary, String implicitDependency)73     void prefixImplicitDependency(ParsedPackage parsedPackage, String existingLibrary,
74             String implicitDependency) {
75         List<String> usesLibraries = parsedPackage.getUsesLibraries();
76         List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries();
77 
78         if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) {
79             if (ArrayUtils.contains(usesLibraries, existingLibrary)) {
80                 parsedPackage.addUsesLibrary(0, implicitDependency);
81             } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) {
82                 parsedPackage.addUsesOptionalLibrary(0, implicitDependency);
83             }
84         }
85     }
86 
prefixRequiredLibrary(ParsedPackage parsedPackage, String libraryName)87     void prefixRequiredLibrary(ParsedPackage parsedPackage, String libraryName) {
88         List<String> usesLibraries = parsedPackage.getUsesLibraries();
89         List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries();
90 
91         boolean alreadyPresent = isLibraryPresent(
92                 usesLibraries, usesOptionalLibraries, libraryName);
93         if (!alreadyPresent) {
94             parsedPackage.addUsesLibrary(0, libraryName);
95         }
96     }
97 }
98