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