blob: b19196a9b636d54ae9a2b2a4fb76f02d874fe352 [file] [log] [blame]
Paul Duffin855d7022017-07-10 15:16:07 +01001/*
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
17package android.content.pm;
18
Paul Duffina3b69212018-01-25 09:58:32 +000019import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
Paul Duffin0692a562018-01-09 12:35:32 +000020import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
21import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
22import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
23
Paul Duffin855d7022017-07-10 15:16:07 +010024import android.content.pm.PackageParser.Package;
Paul Duffinbeee5dc2018-01-23 13:39:00 +000025import android.util.Log;
Paul Duffin855d7022017-07-10 15:16:07 +010026
27import com.android.internal.annotations.VisibleForTesting;
Paul Duffin855d7022017-07-10 15:16:07 +010028
29import java.util.ArrayList;
Paul Duffinbeee5dc2018-01-23 13:39:00 +000030import java.util.List;
Paul Duffin0692a562018-01-09 12:35:32 +000031import java.util.function.Supplier;
Paul Duffin855d7022017-07-10 15:16:07 +010032
33/**
34 * Modifies {@link Package} in order to maintain backwards compatibility.
35 *
36 * @hide
37 */
38@VisibleForTesting
Paul Duffinbeee5dc2018-01-23 13:39:00 +000039public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
40
41 private static final String TAG = PackageBackwardCompatibility.class.getSimpleName();
Paul Duffin855d7022017-07-10 15:16:07 +010042
Paul Duffinbeee5dc2018-01-23 13:39:00 +000043 private static final PackageBackwardCompatibility INSTANCE;
44
45 static {
Paul Duffinbeee5dc2018-01-23 13:39:00 +000046 final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>();
Paul Duffin0692a562018-01-09 12:35:32 +000047
Paul Duffin025bfab2019-01-08 13:26:40 +000048 // Automatically add the org.apache.http.legacy library to the app classpath if the app
49 // targets < P.
50 packageUpdaters.add(new OrgApacheHttpLegacyUpdater());
Paul Duffinbeee5dc2018-01-23 13:39:00 +000051
Steven Morelandf36ad622018-09-04 13:20:22 -070052 packageUpdaters.add(new AndroidHidlUpdater());
53
Paul Duffina3b69212018-01-25 09:58:32 +000054 // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
55 // android.test.mock.
Paul Duffinbeee5dc2018-01-23 13:39:00 +000056 packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
57
Paul Duffina3b69212018-01-25 09:58:32 +000058 // Attempt to load and add the optional updater that will only be available when
59 // REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default updater that
60 // will remove any references to org.apache.http.library from the package so that it does
61 // not try and load the library when it is on the bootclasspath.
62 boolean bootClassPathContainsATB = !addOptionalUpdater(packageUpdaters,
63 "android.content.pm.AndroidTestBaseUpdater",
64 RemoveUnnecessaryAndroidTestBaseLibrary::new);
65
Paul Duffinbeee5dc2018-01-23 13:39:00 +000066 PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
67 .toArray(new PackageSharedLibraryUpdater[0]);
Paul Duffin0692a562018-01-09 12:35:32 +000068 INSTANCE = new PackageBackwardCompatibility(
Paul Duffin025bfab2019-01-08 13:26:40 +000069 bootClassPathContainsATB, updaterArray);
Paul Duffinbeee5dc2018-01-23 13:39:00 +000070 }
71
Paul Duffin0692a562018-01-09 12:35:32 +000072 /**
73 * Add an optional {@link PackageSharedLibraryUpdater} instance to the list, if it could not be
74 * found then add a default instance instead.
75 *
76 * @param packageUpdaters the list to update.
77 * @param className the name of the optional class.
78 * @param defaultUpdater the supplier of the default instance.
79 * @return true if the optional updater was added false otherwise.
80 */
81 private static boolean addOptionalUpdater(List<PackageSharedLibraryUpdater> packageUpdaters,
82 String className, Supplier<PackageSharedLibraryUpdater> defaultUpdater) {
83 Class<? extends PackageSharedLibraryUpdater> clazz;
84 try {
85 clazz = (PackageBackwardCompatibility.class.getClassLoader()
86 .loadClass(className)
87 .asSubclass(PackageSharedLibraryUpdater.class));
88 Log.i(TAG, "Loaded " + className);
89 } catch (ClassNotFoundException e) {
90 Log.i(TAG, "Could not find " + className + ", ignoring");
91 clazz = null;
92 }
93
94 boolean usedOptional = false;
95 PackageSharedLibraryUpdater updater;
96 if (clazz == null) {
97 updater = defaultUpdater.get();
98 } else {
99 try {
100 updater = clazz.getConstructor().newInstance();
101 usedOptional = true;
102 } catch (ReflectiveOperationException e) {
103 throw new IllegalStateException("Could not create instance of " + className, e);
104 }
105 }
106 packageUpdaters.add(updater);
107 return usedOptional;
108 }
109
110 @VisibleForTesting
111 public static PackageSharedLibraryUpdater getInstance() {
112 return INSTANCE;
113 }
114
Paul Duffina3b69212018-01-25 09:58:32 +0000115 private final boolean mBootClassPathContainsATB;
116
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000117 private final PackageSharedLibraryUpdater[] mPackageUpdaters;
118
Paul Duffin025bfab2019-01-08 13:26:40 +0000119 public PackageBackwardCompatibility(
Paul Duffina3b69212018-01-25 09:58:32 +0000120 boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
Paul Duffina3b69212018-01-25 09:58:32 +0000121 this.mBootClassPathContainsATB = bootClassPathContainsATB;
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000122 this.mPackageUpdaters = packageUpdaters;
123 }
Paul Duffin0a2277822017-07-26 14:24:19 +0100124
Paul Duffin855d7022017-07-10 15:16:07 +0100125 /**
126 * Modify the shared libraries in the supplied {@link Package} to maintain backwards
127 * compatibility.
128 *
129 * @param pkg the {@link Package} to modify.
130 */
131 @VisibleForTesting
132 public static void modifySharedLibraries(Package pkg) {
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000133 INSTANCE.updatePackage(pkg);
134 }
Paul Duffin855d7022017-07-10 15:16:07 +0100135
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000136 @Override
137 public void updatePackage(Package pkg) {
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000138 for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) {
139 packageUpdater.updatePackage(pkg);
140 }
141 }
142
143 /**
Paul Duffina3b69212018-01-25 09:58:32 +0000144 * True if the android.test.base is on the bootclasspath, false otherwise.
145 */
146 @VisibleForTesting
147 public static boolean bootClassPathContainsATB() {
148 return INSTANCE.mBootClassPathContainsATB;
149 }
150
151 /**
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000152 * Add android.test.mock dependency for any APK that depends on android.test.runner.
153 *
154 * <p>This is needed to maintain backwards compatibility as in previous versions of Android the
155 * android.test.runner library included the classes from android.test.mock which have since
156 * been split out into a separate library.
157 *
158 * @hide
159 */
160 @VisibleForTesting
161 public static class AndroidTestRunnerSplitUpdater extends PackageSharedLibraryUpdater {
162
163 @Override
164 public void updatePackage(Package pkg) {
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000165 // android.test.runner has a dependency on android.test.mock so if android.test.runner
166 // is present but android.test.mock is not then add android.test.mock.
Paul Duffin0692a562018-01-09 12:35:32 +0000167 prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK);
Paul Duffin855d7022017-07-10 15:16:07 +0100168 }
Paul Duffin855d7022017-07-10 15:16:07 +0100169 }
170
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000171 /**
172 * Remove any usages of org.apache.http.legacy from the shared library as the library is on the
173 * bootclasspath.
174 */
175 @VisibleForTesting
176 public static class RemoveUnnecessaryOrgApacheHttpLegacyLibrary
177 extends PackageSharedLibraryUpdater {
Paul Duffin0a2277822017-07-26 14:24:19 +0100178
Paul Duffinbeee5dc2018-01-23 13:39:00 +0000179 @Override
180 public void updatePackage(Package pkg) {
Paul Duffin0692a562018-01-09 12:35:32 +0000181 removeLibrary(pkg, ORG_APACHE_HTTP_LEGACY);
Paul Duffin035820c2017-10-02 11:16:25 +0100182 }
Paul Duffin0692a562018-01-09 12:35:32 +0000183
Paul Duffin035820c2017-10-02 11:16:25 +0100184 }
Paul Duffina3b69212018-01-25 09:58:32 +0000185
186 /**
187 * Remove any usages of android.test.base from the shared library as the library is on the
188 * bootclasspath.
189 */
190 @VisibleForTesting
191 public static class RemoveUnnecessaryAndroidTestBaseLibrary
192 extends PackageSharedLibraryUpdater {
193
194 @Override
195 public void updatePackage(Package pkg) {
196 removeLibrary(pkg, ANDROID_TEST_BASE);
197 }
198 }
Paul Duffin855d7022017-07-10 15:16:07 +0100199}