Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.content.pm; |
| 18 | |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 19 | import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 20 | import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK; |
| 21 | import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; |
| 22 | import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; |
| 23 | |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 24 | import android.content.pm.PackageParser.Package; |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 25 | import android.util.Log; |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 26 | |
| 27 | import com.android.internal.annotations.VisibleForTesting; |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 28 | |
| 29 | import java.util.ArrayList; |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 30 | import java.util.List; |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 31 | import java.util.function.Supplier; |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 32 | |
| 33 | /** |
| 34 | * Modifies {@link Package} in order to maintain backwards compatibility. |
| 35 | * |
| 36 | * @hide |
| 37 | */ |
| 38 | @VisibleForTesting |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 39 | public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { |
| 40 | |
| 41 | private static final String TAG = PackageBackwardCompatibility.class.getSimpleName(); |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 42 | |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 43 | private static final PackageBackwardCompatibility INSTANCE; |
| 44 | |
| 45 | static { |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 46 | final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>(); |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 47 | |
Paul Duffin | 025bfab | 2019-01-08 13:26:40 +0000 | [diff] [blame] | 48 | // Automatically add the org.apache.http.legacy library to the app classpath if the app |
| 49 | // targets < P. |
| 50 | packageUpdaters.add(new OrgApacheHttpLegacyUpdater()); |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 51 | |
Steven Moreland | f36ad62 | 2018-09-04 13:20:22 -0700 | [diff] [blame] | 52 | packageUpdaters.add(new AndroidHidlUpdater()); |
| 53 | |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 54 | // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before |
| 55 | // android.test.mock. |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 56 | packageUpdaters.add(new AndroidTestRunnerSplitUpdater()); |
| 57 | |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 58 | // 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 Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 66 | PackageSharedLibraryUpdater[] updaterArray = packageUpdaters |
| 67 | .toArray(new PackageSharedLibraryUpdater[0]); |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 68 | INSTANCE = new PackageBackwardCompatibility( |
Paul Duffin | 025bfab | 2019-01-08 13:26:40 +0000 | [diff] [blame] | 69 | bootClassPathContainsATB, updaterArray); |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 72 | /** |
| 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 Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 115 | private final boolean mBootClassPathContainsATB; |
| 116 | |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 117 | private final PackageSharedLibraryUpdater[] mPackageUpdaters; |
| 118 | |
Paul Duffin | 025bfab | 2019-01-08 13:26:40 +0000 | [diff] [blame] | 119 | public PackageBackwardCompatibility( |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 120 | boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) { |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 121 | this.mBootClassPathContainsATB = bootClassPathContainsATB; |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 122 | this.mPackageUpdaters = packageUpdaters; |
| 123 | } |
Paul Duffin | 0a227782 | 2017-07-26 14:24:19 +0100 | [diff] [blame] | 124 | |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 125 | /** |
| 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 Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 133 | INSTANCE.updatePackage(pkg); |
| 134 | } |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 135 | |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 136 | @Override |
| 137 | public void updatePackage(Package pkg) { |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 138 | for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) { |
| 139 | packageUpdater.updatePackage(pkg); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | /** |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 144 | * 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 Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 152 | * 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 Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 165 | // 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 Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 167 | prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK); |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 168 | } |
Paul Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 169 | } |
| 170 | |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 171 | /** |
| 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 Duffin | 0a227782 | 2017-07-26 14:24:19 +0100 | [diff] [blame] | 178 | |
Paul Duffin | beee5dc | 2018-01-23 13:39:00 +0000 | [diff] [blame] | 179 | @Override |
| 180 | public void updatePackage(Package pkg) { |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 181 | removeLibrary(pkg, ORG_APACHE_HTTP_LEGACY); |
Paul Duffin | 035820c | 2017-10-02 11:16:25 +0100 | [diff] [blame] | 182 | } |
Paul Duffin | 0692a56 | 2018-01-09 12:35:32 +0000 | [diff] [blame] | 183 | |
Paul Duffin | 035820c | 2017-10-02 11:16:25 +0100 | [diff] [blame] | 184 | } |
Paul Duffin | a3b6921 | 2018-01-25 09:58:32 +0000 | [diff] [blame] | 185 | |
| 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 Duffin | 855d702 | 2017-07-10 15:16:07 +0100 | [diff] [blame] | 199 | } |