• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.pm.parsing.library;
18 
19 import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
20 import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
21 import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
22 import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
23 
24 import android.util.Log;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.internal.pm.parsing.pkg.ParsedPackage;
28 import com.android.internal.pm.pkg.parsing.ParsingPackage;
29 import com.android.server.SystemConfig;
30 
31 import java.util.ArrayList;
32 import java.util.List;
33 
34 /**
35  * Modifies {@link ParsedPackage} in order to maintain backwards compatibility.
36  *
37  * @hide
38  */
39 @VisibleForTesting
40 public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
41 
42     private static final String TAG = PackageBackwardCompatibility.class.getSimpleName();
43 
44     private static final PackageBackwardCompatibility INSTANCE;
45 
46     static {
47         final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>();
48 
49         // Remove wear-sdk, it is added to boot classpath since Android Baklava.
packageUpdaters.add(new WearSdkUpdater())50         packageUpdaters.add(new WearSdkUpdater());
51 
52         // Remove android.net.ipsec.ike library, it is added to boot classpath since Android S.
packageUpdaters.add(new AndroidNetIpSecIkeUpdater())53         packageUpdaters.add(new AndroidNetIpSecIkeUpdater());
54 
55         // Remove com.google.android.maps library.
packageUpdaters.add(new ComGoogleAndroidMapsUpdater())56         packageUpdaters.add(new ComGoogleAndroidMapsUpdater());
57 
58         // Automatically add the org.apache.http.legacy library to the app classpath if the app
59         // targets < P.
packageUpdaters.add(new OrgApacheHttpLegacyUpdater())60         packageUpdaters.add(new OrgApacheHttpLegacyUpdater());
61 
packageUpdaters.add(new AndroidHidlUpdater())62         packageUpdaters.add(new AndroidHidlUpdater());
63 
64         // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
65         // android.test.mock.
packageUpdaters.add(new AndroidTestRunnerSplitUpdater())66         packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
67 
68         boolean bootClassPathContainsATB = !addUpdaterForAndroidTestBase(packageUpdaters);
69 
70         // ApexSharedLibraryUpdater should be the last one, to allow modifications introduced by
71         // mainline after dessert release.
packageUpdaters.add(new ApexSharedLibraryUpdater( SystemConfig.getInstance().getSharedLibraries()))72         packageUpdaters.add(new ApexSharedLibraryUpdater(
73                 SystemConfig.getInstance().getSharedLibraries()));
74 
75         PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
76                 .toArray(new PackageSharedLibraryUpdater[0]);
77         INSTANCE = new PackageBackwardCompatibility(
78                 bootClassPathContainsATB, updaterArray);
79     }
80 
81     /**
82      * Attempt to load and add the optional updater that will only be available when
83      * REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default updater that
84      * will remove any references to org.apache.http.library from the package so that
85      * it does not try and load the library when it is on the bootclasspath.
86      *
87      * TODO:(b/135203078): Find a better way to do this.
88      */
addUpdaterForAndroidTestBase( List<PackageSharedLibraryUpdater> packageUpdaters)89     private static boolean addUpdaterForAndroidTestBase(
90             List<PackageSharedLibraryUpdater> packageUpdaters) {
91         boolean hasClass = false;
92         String className = "android.content.pm.AndroidTestBaseUpdater";
93         try {
94             Class clazz = ParsingPackage.class.getClassLoader().loadClass(className);
95             hasClass = clazz != null;
96             Log.i(TAG, "Loaded " + className);
97         } catch (ClassNotFoundException e) {
98             Log.i(TAG, "Could not find " + className + ", ignoring");
99         }
100 
101         if (hasClass) {
102             packageUpdaters.add(new AndroidTestBaseUpdater());
103         } else {
104             packageUpdaters.add(new RemoveUnnecessaryAndroidTestBaseLibrary());
105         }
106         return hasClass;
107     }
108 
109     @VisibleForTesting
getInstance()110     public static PackageSharedLibraryUpdater getInstance() {
111         return INSTANCE;
112     }
113 
114     private final boolean mBootClassPathContainsATB;
115 
116     private final PackageSharedLibraryUpdater[] mPackageUpdaters;
117 
118     @VisibleForTesting
getPackageUpdaters()119     PackageSharedLibraryUpdater[] getPackageUpdaters() {
120         return mPackageUpdaters;
121     }
122 
PackageBackwardCompatibility( boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters)123     private PackageBackwardCompatibility(
124             boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
125         this.mBootClassPathContainsATB = bootClassPathContainsATB;
126         this.mPackageUpdaters = packageUpdaters;
127     }
128 
129     /**
130      * Modify the shared libraries in the supplied {@link ParsedPackage} to maintain backwards
131      * compatibility.
132      *
133      * @param parsedPackage the {@link ParsedPackage} to modify.
134      */
135     @VisibleForTesting
modifySharedLibraries(ParsedPackage parsedPackage, boolean isSystemApp, boolean isUpdatedSystemApp)136     public static void modifySharedLibraries(ParsedPackage parsedPackage, boolean isSystemApp,
137             boolean isUpdatedSystemApp) {
138         INSTANCE.updatePackage(parsedPackage, isSystemApp, isUpdatedSystemApp);
139     }
140 
141     @Override
updatePackage(ParsedPackage parsedPackage, boolean isSystemApp, boolean isUpdatedSystemApp)142     public void updatePackage(ParsedPackage parsedPackage, boolean isSystemApp,
143             boolean isUpdatedSystemApp) {
144         for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) {
145             packageUpdater.updatePackage(parsedPackage, isSystemApp, isUpdatedSystemApp);
146         }
147     }
148 
149     /**
150      * True if the android.test.base is on the bootclasspath, false otherwise.
151      */
152     @VisibleForTesting
bootClassPathContainsATB()153     public static boolean bootClassPathContainsATB() {
154         return INSTANCE.mBootClassPathContainsATB;
155     }
156 
157     /**
158      * Add android.test.mock dependency for any APK that depends on android.test.runner.
159      *
160      * <p>This is needed to maintain backwards compatibility as in previous versions of Android the
161      * android.test.runner library included the classes from android.test.mock which have since
162      * been split out into a separate library.
163      *
164      * @hide
165      */
166     @VisibleForTesting
167     public static class AndroidTestRunnerSplitUpdater extends PackageSharedLibraryUpdater {
168 
169         @Override
updatePackage(ParsedPackage parsedPackage, boolean isSystemApp, boolean isUpdatedSystemApp)170         public void updatePackage(ParsedPackage parsedPackage, boolean isSystemApp,
171                 boolean isUpdatedSystemApp) {
172             // android.test.runner has a dependency on android.test.mock so if android.test.runner
173             // is present but android.test.mock is not then add android.test.mock.
174             prefixImplicitDependency(parsedPackage, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK);
175         }
176     }
177 
178     /**
179      * Remove any usages of org.apache.http.legacy from the shared library as the library is on the
180      * bootclasspath.
181      */
182     @VisibleForTesting
183     public static class RemoveUnnecessaryOrgApacheHttpLegacyLibrary
184             extends PackageSharedLibraryUpdater {
185 
186         @Override
updatePackage(ParsedPackage parsedPackage, boolean isSystemApp, boolean isUpdatedSystemApp)187         public void updatePackage(ParsedPackage parsedPackage, boolean isSystemApp,
188                 boolean isUpdatedSystemApp) {
189             removeLibrary(parsedPackage, ORG_APACHE_HTTP_LEGACY);
190         }
191 
192     }
193 
194     /**
195      * Remove any usages of android.test.base from the shared library as the library is on the
196      * bootclasspath.
197      */
198     @VisibleForTesting
199     public static class RemoveUnnecessaryAndroidTestBaseLibrary
200             extends PackageSharedLibraryUpdater {
201 
202         @Override
updatePackage(ParsedPackage parsedPackage, boolean isSystemApp, boolean isUpdatedSystemApp)203         public void updatePackage(ParsedPackage parsedPackage, boolean isSystemApp,
204                 boolean isUpdatedSystemApp) {
205             removeLibrary(parsedPackage, ANDROID_TEST_BASE);
206         }
207     }
208 }
209