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 isSystemApp, boolean isUpdatedSystemApp)41     public abstract void updatePackage(ParsedPackage parsedPackage, boolean isSystemApp,
42             boolean isUpdatedSystemApp);
43 
removeLibrary(ParsedPackage parsedPackage, String libraryName)44     static void removeLibrary(ParsedPackage parsedPackage, String libraryName) {
45         parsedPackage.removeUsesLibrary(libraryName)
46                 .removeUsesOptionalLibrary(libraryName);
47     }
48 
49     static @NonNull
prefix(@ullable ArrayList<T> cur, T val)50             <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
51         if (cur == null) {
52             cur = new ArrayList<>();
53         }
54         cur.add(0, val);
55         return cur;
56     }
57 
isLibraryPresent(List<String> usesLibraries, List<String> usesOptionalLibraries, String apacheHttpLegacy)58     private static boolean isLibraryPresent(List<String> usesLibraries,
59             List<String> usesOptionalLibraries, String apacheHttpLegacy) {
60         return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
61                 || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
62     }
63 
64     /**
65      * Add an implicit dependency.
66      *
67      * <p>If the package has an existing dependency on {@code existingLibrary} then prefix it with
68      * the {@code implicitDependency} if it is not already in the list of libraries.
69      *
70      * @param parsedPackage the {@link ParsedPackage} to update.
71      * @param existingLibrary the existing library.
72      * @param implicitDependency the implicit dependency to add
73      */
prefixImplicitDependency(ParsedPackage parsedPackage, String existingLibrary, String implicitDependency)74     void prefixImplicitDependency(ParsedPackage parsedPackage, String existingLibrary,
75             String implicitDependency) {
76         List<String> usesLibraries = parsedPackage.getUsesLibraries();
77         List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries();
78 
79         if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) {
80             if (ArrayUtils.contains(usesLibraries, existingLibrary)) {
81                 parsedPackage.addUsesLibrary(0, implicitDependency);
82             } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) {
83                 parsedPackage.addUsesOptionalLibrary(0, implicitDependency);
84             }
85         }
86     }
87 
prefixRequiredLibrary(ParsedPackage parsedPackage, String libraryName)88     void prefixRequiredLibrary(ParsedPackage parsedPackage, String libraryName) {
89         List<String> usesLibraries = parsedPackage.getUsesLibraries();
90         List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries();
91 
92         boolean alreadyPresent = isLibraryPresent(
93                 usesLibraries, usesOptionalLibraries, libraryName);
94         if (!alreadyPresent) {
95             parsedPackage.addUsesLibrary(0, libraryName);
96         }
97     }
98 }
99