diff options
| author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-10-14 01:07:08 +0000 |
|---|---|---|
| committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-10-14 01:07:08 +0000 |
| commit | b41df2be0fdfd03aeecd55fb9679abdd4f7d94e8 (patch) | |
| tree | 488f9fad5730da262340f0a106de7c3c0387cff5 | |
| parent | 6d89bc0b8a6e5ae0e79c1af298a50c161bf6f872 (diff) | |
| parent | 017c7f9328abb6c72aec5aa425517c7c69c343b9 (diff) | |
| download | platform_packages_modules_SdkExtensions-sdk-release.tar.gz platform_packages_modules_SdkExtensions-sdk-release.tar.bz2 platform_packages_modules_SdkExtensions-sdk-release.zip | |
Snap for 7821744 from 017c7f9328abb6c72aec5aa425517c7c69c343b9 to sdk-releasesdk-release
Change-Id: Ib64c3d07ce9052f1f79a4f221b055c2e241d084d
| -rw-r--r-- | derive_classpath/derive_classpath.cpp | 83 | ||||
| -rw-r--r-- | derive_classpath/derive_classpath.h | 4 | ||||
| -rw-r--r-- | derive_classpath/derive_classpath_test.cpp | 34 | ||||
| -rw-r--r-- | derive_classpath/main.cpp | 59 | ||||
| -rw-r--r-- | derive_sdk/derive_sdk.cpp | 3 | ||||
| -rw-r--r-- | derive_sdk/derive_sdk_test.cpp | 4 | ||||
| -rw-r--r-- | framework/java/android/os/ext/SdkExtensions.java | 2 | ||||
| -rw-r--r-- | gen_sdk/extensions_db.textpb | 63 | ||||
| -rw-r--r-- | tests/cts/Classpaths/src/android/os/ext/classpath/cts/ClasspathsTest.java | 7 | ||||
| -rw-r--r-- | tests/cts/Extensions/src/android/os/ext/cts/SdkExtensionsTest.java | 11 | ||||
| -rw-r--r-- | tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s12.xml | 2 | ||||
| -rw-r--r-- | tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s45.xml | 2 | ||||
| -rw-r--r-- | tests/e2e/Extensions/test-src/com/android/tests/apex/sdkextensions/SdkExtensionsHostTest.java | 4 |
13 files changed, 221 insertions, 57 deletions
diff --git a/derive_classpath/derive_classpath.cpp b/derive_classpath/derive_classpath.cpp index 0ff246c..0c9c361 100644 --- a/derive_classpath/derive_classpath.cpp +++ b/derive_classpath/derive_classpath.cpp @@ -34,34 +34,51 @@ using Classpaths = std::unordered_map<Classpath, Filepaths>; static const std::regex kBindMountedApex("^/apex/[^/]+@[0-9]+/"); static const std::regex kApexPathRegex("(/apex/[^/]+)/"); -// Defines the order of individual fragments to be merged for BOOTCLASSPATH: -// 1. Jars in ART module always come first; -// 2. Jars defined as part of /system/etc/classpaths; -// 3. Jars defined in all non-ART apexes that expose /apex/*/etc/classpaths fragments. -// -// Notes: -// - Relative order in the individual fragment files is not changed when merging. -// - If a fragment file is matched by multiple globs, the first one is used; i.e. ART module -// fragment is only parsed once, even if there is a "/apex/*/" pattern later. -// - If there are multiple files matched for a glob pattern with wildcards, the results are sorted -// by pathname (default glob behaviour); i.e. all fragment files are sorted within a single -// "pattern block". -static const std::vector<std::string> kBootclasspathFragmentGlobPatterns = { - // ART module is a special case and must come first before any other classpath entries. - "/apex/com.android.art/etc/classpaths/bootclasspath.pb", - "/system/etc/classpaths/bootclasspath.pb", - "/apex/*/etc/classpaths/bootclasspath.pb", -}; +std::vector<std::string> getBootclasspathFragmentGlobPatterns(const Args& args) { + // Defines the order of individual fragments to be merged for BOOTCLASSPATH: + // 1. Jars in ART module always come first; + // 2. Jars defined as part of /system/etc/classpaths; + // 3. Jars defined in all non-ART apexes that expose /apex/*/etc/classpaths fragments. + // + // Notes: + // - Relative order in the individual fragment files is not changed when merging. + // - If a fragment file is matched by multiple globs, the first one is used; i.e. ART module + // fragment is only parsed once, even if there is a "/apex/*/" pattern later. + // - If there are multiple files matched for a glob pattern with wildcards, the results are sorted + // by pathname (default glob behaviour); i.e. all fragment files are sorted within a single + // "pattern block". + std::vector<std::string> patterns = { + // ART module is a special case and must come first before any other classpath entries. + "/apex/com.android.art/etc/classpaths/bootclasspath.pb", + }; + if (args.system_bootclasspath_fragment.empty()) { + patterns.emplace_back("/system/etc/classpaths/bootclasspath.pb"); + } else { + // TODO: Avoid applying glob(3) expansion later to this path. Although the caller should not + // provide a path that contains '*', it can technically happen. Instead of checking the string + // format, we should just avoid the glob(3) for this string. + patterns.emplace_back(args.system_bootclasspath_fragment); + } + patterns.emplace_back("/apex/*/etc/classpaths/bootclasspath.pb"); + return patterns; +} -// Defines the order of individual fragments to be merged for SYSTEMSERVERCLASSPATH. -// -// ART system server jars are not special in this case, and are considered to be part of all the -// other apexes that may expose system server jars. -// -// All notes from kBootclasspathFragmentGlobPatterns apply here. -static const std::vector<std::string> kSystemserverclasspathFragmentGlobPatterns = { - "/system/etc/classpaths/systemserverclasspath.pb", - "/apex/*/etc/classpaths/systemserverclasspath.pb", +std::vector<std::string> getSystemserverclasspathFragmentGlobPatterns(const Args& args) { + // Defines the order of individual fragments to be merged for SYSTEMSERVERCLASSPATH. + // + // ART system server jars are not special in this case, and are considered to be part of all the + // other apexes that may expose system server jars. + // + // All notes from getBootclasspathFragmentGlobPatterns apply here. + std::vector<std::string> patterns; + if (args.system_systemserverclasspath_fragment.empty()) { + patterns.emplace_back("/system/etc/classpaths/systemserverclasspath.pb"); + } else { + // TODO: Avoid applying glob(3) expansion later to this path. See above. + patterns.emplace_back(args.system_systemserverclasspath_fragment); + } + patterns.emplace_back("/apex/*/etc/classpaths/systemserverclasspath.pb"); + return patterns; }; // Finds all classpath fragment files that match the glob pattern and appends them to `fragments`. @@ -149,15 +166,15 @@ std::string GetAllowedJarPathPrefix(const std::string& fragment_path) { } // Finds and parses all classpath fragments on device matching given glob patterns. -bool ParseFragments(const std::string& globPatternPrefix, Classpaths& classpaths, bool boot_jars) { +bool ParseFragments(const Args& args, Classpaths& classpaths, bool boot_jars) { LOG(INFO) << "ParseFragments for " << (boot_jars ? "bootclasspath" : "systemserverclasspath"); - auto glob_patterns = - boot_jars ? kBootclasspathFragmentGlobPatterns : kSystemserverclasspathFragmentGlobPatterns; + auto glob_patterns = boot_jars ? getBootclasspathFragmentGlobPatterns(args) + : getSystemserverclasspathFragmentGlobPatterns(args); Filepaths fragments; for (const auto& pattern : glob_patterns) { - if (!GlobClasspathFragments(&fragments, globPatternPrefix + pattern)) { + if (!GlobClasspathFragments(&fragments, args.glob_pattern_prefix + pattern)) { return false; } } @@ -194,11 +211,11 @@ bool GenerateClasspathExports(const Args& args) { << "derive_classpath must only be run on Android 12 or above"; Classpaths classpaths; - if (!ParseFragments(args.glob_pattern_prefix, classpaths, /*boot_jars=*/true)) { + if (!ParseFragments(args, classpaths, /*boot_jars=*/true)) { LOG(ERROR) << "Failed to parse BOOTCLASSPATH fragments"; return false; } - if (!ParseFragments(args.glob_pattern_prefix, classpaths, /*boot_jars=*/false)) { + if (!ParseFragments(args, classpaths, /*boot_jars=*/false)) { LOG(ERROR) << "Failed to parse SYSTEMSERVERCLASSPATH fragments"; return false; } diff --git a/derive_classpath/derive_classpath.h b/derive_classpath/derive_classpath.h index 9b53254..b0716f3 100644 --- a/derive_classpath/derive_classpath.h +++ b/derive_classpath/derive_classpath.h @@ -27,6 +27,10 @@ constexpr std::string_view kGeneratedClasspathExportsFilepath = "/data/system/en struct Args { std::string_view output_path; + // Alternative *classpath.pb files if provided. + std::string system_bootclasspath_fragment; + std::string system_systemserverclasspath_fragment; + // Test only. glob_pattern_prefix is appended to each glob pattern to allow adding mock configs in // /data/local/tmp for example. std::string glob_pattern_prefix; diff --git a/derive_classpath/derive_classpath_test.cpp b/derive_classpath/derive_classpath_test.cpp index 277a452..6e503f3 100644 --- a/derive_classpath/derive_classpath_test.cpp +++ b/derive_classpath/derive_classpath_test.cpp @@ -216,6 +216,40 @@ TEST_F(DeriveClasspathTest, CustomOutputLocation) { EXPECT_EQ(expectedJars, exportValue); } +// Test alternative .pb for bootclasspath and systemclasspath. +TEST_F(DeriveClasspathTest, CustomInputLocation) { + AddJarToClasspath("/other", "/other/bcp-jar", BOOTCLASSPATH); + AddJarToClasspath("/other", "/other/systemserver-jar", SYSTEMSERVERCLASSPATH); + AddJarToClasspath("/apex/com.android.art", "/apex/com.android.art/javalib/art", BOOTCLASSPATH); + AddJarToClasspath("/apex/com.android.foo", "/apex/com.android.foo/javalib/foo", BOOTCLASSPATH); + AddJarToClasspath("/apex/com.android.baz", "/apex/com.android.baz/javalib/baz", + SYSTEMSERVERCLASSPATH); + + Args args = default_args_with_test_dir_; + args.system_bootclasspath_fragment = "/other/etc/classpaths/bootclasspath.pb"; + args.system_systemserverclasspath_fragment = "/other/etc/classpaths/systemserverclasspath.pb"; + + ASSERT_TRUE(GenerateClasspathExports(args)); + + const std::vector<std::string> exportLines = ParseExportsFile(); + + std::vector<std::string> splitExportLine; + splitExportLine = SplitClasspathExportLine(exportLines[0]); + EXPECT_EQ("BOOTCLASSPATH", splitExportLine[1]); + const std::string expectedBcpJars( + "/apex/com.android.art/javalib/art" + ":/other/bcp-jar" + ":/apex/com.android.foo/javalib/foo"); + EXPECT_EQ(expectedBcpJars, splitExportLine[2]); + + splitExportLine = SplitClasspathExportLine(exportLines[2]); + EXPECT_EQ("SYSTEMSERVERCLASSPATH", splitExportLine[1]); + const std::string expectedSystemServerJars( + "/other/systemserver-jar" + ":/apex/com.android.baz/javalib/baz"); + EXPECT_EQ(expectedSystemServerJars, splitExportLine[2]); +} + // Test output location that can't be written to. TEST_F(DeriveClasspathTest, NonWriteableOutputLocation) { AddJarToClasspath("/apex/com.android.art", "/apex/com.android.art/javalib/art", BOOTCLASSPATH); diff --git a/derive_classpath/main.cpp b/derive_classpath/main.cpp index d589680..8807cdb 100644 --- a/derive_classpath/main.cpp +++ b/derive_classpath/main.cpp @@ -21,18 +21,57 @@ #include "derive_classpath.h" -int main(int argc, char** argv) { - // Default args - android::derive_classpath::Args args = { - .output_path = android::derive_classpath::kGeneratedClasspathExportsFilepath, - .glob_pattern_prefix = "", - }; - if (argc == 1) { +bool ArgumentMatches(std::string_view argument, std::string_view prefix, std::string_view* value) { + if (android::base::StartsWith(argument, prefix)) { + *value = argument.substr(prefix.size()); + return true; + } + return false; +} + +// Command line flags need to be considered as a de facto API since there may be callers outside +// of the SdkExtensions APEX, which needs to run on older Android versions. For example, otapreopt +// currently executes derive_classpath with a single output file. When changing the flags, make sure +// it won't break on older Android. +bool ParseArgs(android::derive_classpath::Args& args, int argc, char** argv) { + // Parse flags + std::vector<std::string_view> positional_args; + for (int i = 1; i < argc; ++i) { + const std::string_view arg = argv[i]; + std::string_view value; + if (ArgumentMatches(arg, "--bootclasspath-fragment=", &value)) { + if (!args.system_bootclasspath_fragment.empty()) { + LOG(ERROR) << "Duplicated flag --bootclasspath-fragment is specified"; + return false; + } + args.system_bootclasspath_fragment = value; + } else if (ArgumentMatches(arg, "--systemserverclasspath-fragment=", &value)) { + if (!args.system_bootclasspath_fragment.empty()) { + LOG(ERROR) << "Duplicated flag --systemserverclasspath-fragment is specified"; + return false; + } + args.system_systemserverclasspath_fragment = value; + } else { + positional_args.emplace_back(arg); + } + } + + // Handle positional args + if (positional_args.size() == 0) { args.output_path = android::derive_classpath::kGeneratedClasspathExportsFilepath; - } else if (argc == 2) { - args.output_path = argv[1]; + } else if (positional_args.size() == 1) { + args.output_path = positional_args[0]; } else { - LOG(ERROR) << "too many arguments " << argc; + LOG(ERROR) << "Unrecognized positional arguments: " + << android::base::Join(positional_args, ' '); + return false; + } + return true; +} + +int main(int argc, char** argv) { + android::derive_classpath::Args args; + if (!ParseArgs(args, argc, argv)) { return EXIT_FAILURE; } if (!android::derive_classpath::GenerateClasspathExports(args)) { diff --git a/derive_sdk/derive_sdk.cpp b/derive_sdk/derive_sdk.cpp index 29cfca5..0b503de 100644 --- a/derive_sdk/derive_sdk.cpp +++ b/derive_sdk/derive_sdk.cpp @@ -41,6 +41,7 @@ static const std::unordered_map<std::string, SdkModule> kApexNameToModule = { {"com.android.media", SdkModule::MEDIA}, {"com.android.mediaprovider", SdkModule::MEDIA_PROVIDER}, {"com.android.permission", SdkModule::PERMISSIONS}, + {"com.android.scheduling", SdkModule::SCHEDULING}, {"com.android.sdkext", SdkModule::SDK_EXTENSIONS}, {"com.android.os.statsd", SdkModule::STATSD}, {"com.android.tethering", SdkModule::TETHERING}, @@ -51,7 +52,7 @@ static const std::unordered_set<SdkModule> kRModules = { SdkModule::PERMISSIONS, SdkModule::SDK_EXTENSIONS, SdkModule::STATSD, SdkModule::TETHERING, }; -static const std::unordered_set<SdkModule> kSModules = {SdkModule::ART}; +static const std::unordered_set<SdkModule> kSModules = {SdkModule::ART, SdkModule::SCHEDULING}; bool ReadDatabase(const std::string& db_path, ExtensionDatabase& db) { std::string contents; diff --git a/derive_sdk/derive_sdk_test.cpp b/derive_sdk/derive_sdk_test.cpp index 70d7dff..580544e 100644 --- a/derive_sdk/derive_sdk_test.cpp +++ b/derive_sdk/derive_sdk_test.cpp @@ -88,8 +88,8 @@ class DeriveSdkTest : public ::testing::Test { }; TEST_F(DeriveSdkTest, CurrentSystemImageValue) { - EXPECT_R(0); - EXPECT_S(0); + EXPECT_R(1); + EXPECT_S(1); } TEST_F(DeriveSdkTest, OneDessert_OneVersion_OneApex) { diff --git a/framework/java/android/os/ext/SdkExtensions.java b/framework/java/android/os/ext/SdkExtensions.java index 3d9a4b0..ac1929e 100644 --- a/framework/java/android/os/ext/SdkExtensions.java +++ b/framework/java/android/os/ext/SdkExtensions.java @@ -43,7 +43,7 @@ import java.util.Map; public class SdkExtensions { // S_VERSION_CODE is a separate field to simplify management across branches. - private static final int VERSION_CODE_S = VERSION_CODES.CUR_DEVELOPMENT; + private static final int VERSION_CODE_S = VERSION_CODES.S; private static final int R_EXTENSION_INT; private static final int S_EXTENSION_INT; private static final Map<Integer, Integer> ALL_EXTENSION_INTS; diff --git a/gen_sdk/extensions_db.textpb b/gen_sdk/extensions_db.textpb index e69de29..5d54a58 100644 --- a/gen_sdk/extensions_db.textpb +++ b/gen_sdk/extensions_db.textpb @@ -0,0 +1,63 @@ +versions { + version: 1 + requirements { + module: ART + version { + version: 1 + } + } + requirements { + module: CONSCRYPT + version { + version: 1 + } + } + requirements { + module: IPSEC + version { + version: 1 + } + } + requirements { + module: MEDIA + version { + version: 1 + } + } + requirements { + module: MEDIA_PROVIDER + version { + version: 1 + } + } + requirements { + module: PERMISSIONS + version { + version: 1 + } + } + requirements { + module: SCHEDULING + version { + version: 1 + } + } + requirements { + module: SDK_EXTENSIONS + version { + version: 1 + } + } + requirements { + module: STATSD + version { + version: 1 + } + } + requirements { + module: TETHERING + version { + version: 1 + } + } +} diff --git a/tests/cts/Classpaths/src/android/os/ext/classpath/cts/ClasspathsTest.java b/tests/cts/Classpaths/src/android/os/ext/classpath/cts/ClasspathsTest.java index 11d901f..93e7b2e 100644 --- a/tests/cts/Classpaths/src/android/os/ext/classpath/cts/ClasspathsTest.java +++ b/tests/cts/Classpaths/src/android/os/ext/classpath/cts/ClasspathsTest.java @@ -89,7 +89,6 @@ public class ClasspathsTest extends BaseHostJUnit4Test { "/apex/com.android.art/", "/system/", "/system_ext/", - "/apex/com.android.i18n/", "/apex/"); assertThat(jars) .prefixesMatch(expectedPrefixes) @@ -116,7 +115,7 @@ public class ClasspathsTest extends BaseHostJUnit4Test { assertThat(bootJars).containsAtLeastElementsIn(jars); ImmutableList<String> expectedPrefixes = ImmutableList.of( - "/apex/com.android.art/", "/system/", "/system_ext/", "/apex/com.android.i18n/"); + "/apex/com.android.art/", "/system/", "/system_ext/"); assertThat(jars) .prefixesMatch(expectedPrefixes) .inOrder(); @@ -201,6 +200,10 @@ public class ClasspathsTest extends BaseHostJUnit4Test { boolean ordered = true; int currentPrefixIndex = expected.isEmpty() ? -1 : 0; for (String jar : actual) { + if (ICU4J_JAR.equals(jar)) { + // TODO(b/191127295): ICU4j appears out of order, ignore it until fixed + continue; + } int prefixIndex = findFirstMatchingPrefix(jar, expected); if (prefixIndex == -1) { unexpectedJars.add(jar); diff --git a/tests/cts/Extensions/src/android/os/ext/cts/SdkExtensionsTest.java b/tests/cts/Extensions/src/android/os/ext/cts/SdkExtensionsTest.java index ea310c7..c3a42e8 100644 --- a/tests/cts/Extensions/src/android/os/ext/cts/SdkExtensionsTest.java +++ b/tests/cts/Extensions/src/android/os/ext/cts/SdkExtensionsTest.java @@ -38,7 +38,8 @@ public class SdkExtensionsTest extends TestCase { /** Verifies that getExtensionVersion only return existing versions */ public void testValidValues() throws Exception { - for (int sdk = Build.VERSION_CODES.R; sdk <= 1_000_000; sdk++) { + int firstUnassigned = Build.VERSION_CODES.S + 1; + for (int sdk = firstUnassigned; sdk <= 1_000_000; sdk++) { // No extension SDKs versions yet. assertEquals(0, SdkExtensions.getExtensionVersion(sdk)); } @@ -46,18 +47,20 @@ public class SdkExtensionsTest extends TestCase { /** Verifies that the public sysprops are set as expected */ public void testSystemProperties() throws Exception { - assertEquals("0", SystemProperties.get("build.version.extensions.r")); - String expectedS = SdkLevel.isAtLeastS() ? "0" : ""; + assertEquals("1", SystemProperties.get("build.version.extensions.r")); + String expectedS = SdkLevel.isAtLeastS() ? "1" : ""; assertEquals(expectedS, SystemProperties.get("build.version.extensions.s")); } public void testExtensionVersions() throws Exception { Map<Integer, Integer> versions = SdkExtensions.getAllExtensionVersions(); int expectedSize = 1; + assertEquals(1, (int) versions.get(Build.VERSION_CODES.R)); + if (SdkLevel.isAtLeastS()) { + assertEquals(1, (int) versions.get(Build.VERSION_CODES.S)); expectedSize++; } - assertEquals(0, (int) versions.get(Build.VERSION_CODES.R)); assertEquals(expectedSize, versions.size()); } diff --git a/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s12.xml b/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s12.xml index fc5995c..6331c66 100644 --- a/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s12.xml +++ b/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s12.xml @@ -18,7 +18,7 @@ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29"> <extension-sdk android:sdkVersion="30" android:minExtensionVersion="12" /> - <extension-sdk android:sdkVersion="10000" android:minExtensionVersion="12" /> + <extension-sdk android:sdkVersion="31" android:minExtensionVersion="12" /> </uses-sdk> <application android:hasCode="false"></application> diff --git a/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s45.xml b/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s45.xml index 478553c..e05772e 100644 --- a/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s45.xml +++ b/tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s45.xml @@ -18,7 +18,7 @@ <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29"> <extension-sdk android:sdkVersion="30" android:minExtensionVersion="45" /> - <extension-sdk android:sdkVersion="10000" android:minExtensionVersion="45" /> + <extension-sdk android:sdkVersion="31" android:minExtensionVersion="45" /> </uses-sdk> <application android:hasCode="false"></application> diff --git a/tests/e2e/Extensions/test-src/com/android/tests/apex/sdkextensions/SdkExtensionsHostTest.java b/tests/e2e/Extensions/test-src/com/android/tests/apex/sdkextensions/SdkExtensionsHostTest.java index e3f83c7..5a4839a 100644 --- a/tests/e2e/Extensions/test-src/com/android/tests/apex/sdkextensions/SdkExtensionsHostTest.java +++ b/tests/e2e/Extensions/test-src/com/android/tests/apex/sdkextensions/SdkExtensionsHostTest.java @@ -174,8 +174,8 @@ public class SdkExtensionsHostTest extends BaseHostJUnit4Test { } private void assertVersionDefault() throws Exception { - assertRVersionEquals(0); - assertSVersionEquals(0); + assertRVersionEquals(1); + assertSVersionEquals(1); assertTrue(broadcastForBoolean("MAKE_CALLS_DEFAULT", null)); } |
