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