aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-10 09:06:53 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-10 09:06:53 +0000
commitaf05d31dd14df47931440054328471ee39062dea (patch)
tree488f9fad5730da262340f0a106de7c3c0387cff5
parent437a9ffd0c5c96a2171419194e8608f11ef64d2b (diff)
parent017c7f9328abb6c72aec5aa425517c7c69c343b9 (diff)
downloadplatform_packages_modules_SdkExtensions-main-cg-testing-release.tar.gz
platform_packages_modules_SdkExtensions-main-cg-testing-release.tar.bz2
platform_packages_modules_SdkExtensions-main-cg-testing-release.zip
Snap for 7810574 from 017c7f9328abb6c72aec5aa425517c7c69c343b9 to main-cg-testing-releasemain-cg-testing-release
Change-Id: If7d9f93034ab2f4a885b752219c367ceb7646901
-rw-r--r--README.md2
-rw-r--r--derive_classpath/derive_classpath.cpp98
-rw-r--r--derive_classpath/derive_classpath.h16
-rw-r--r--derive_classpath/derive_classpath_test.cpp70
-rw-r--r--derive_classpath/main.cpp60
-rw-r--r--derive_sdk/derive_sdk.cpp3
-rw-r--r--derive_sdk/derive_sdk_test.cpp4
-rw-r--r--framework/java/android/os/ext/SdkExtensions.java5
-rw-r--r--gen_sdk/extensions_db.textpb63
-rw-r--r--tests/cts/Classpaths/src/android/os/ext/classpath/cts/ClasspathsTest.java7
-rw-r--r--tests/cts/Extensions/src/android/os/ext/cts/SdkExtensionsTest.java11
-rw-r--r--tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s12.xml2
-rw-r--r--tests/e2e/Extensions/apps-with-reqs/AndroidManifest-s45.xml2
-rw-r--r--tests/e2e/Extensions/test-src/com/android/tests/apex/sdkextensions/SdkExtensionsHostTest.java4
14 files changed, 262 insertions, 85 deletions
diff --git a/README.md b/README.md
index 45862a2..9741867 100644
--- a/README.md
+++ b/README.md
@@ -61,5 +61,3 @@ are the steps necessary to do that:
* add a unit test to `derive_sdk_test.cpp` verifying the new extensions works
- Make the `SdkExtensions.getExtensionVersion` API support the new extensions.
- Extend the CTS test to verify the above two behaviors.
-- Update `RollbackManagerServiceImpl#getExtensionVersions` to account for the
- new extension version.
diff --git a/derive_classpath/derive_classpath.cpp b/derive_classpath/derive_classpath.cpp
index d379a40..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;
}
}
@@ -188,33 +205,24 @@ bool ParseFragments(const std::string& globPatternPrefix, Classpaths& classpaths
// Generates /data/system/environ/classpath exports file by globing and merging individual
// classpaths.proto config fragments. The exports file is read by init.rc to setenv *CLASSPATH
// environ variables at runtime.
-bool GenerateClasspathExports(std::string_view output_path) {
- // Outside of tests use actual config fragments.
- return GenerateClasspathExports("", output_path);
-}
-
-// Internal implementation of GenerateClasspathExports that allows putting config fragments in
-// temporary directories. `globPatternPrefix` is appended to each glob pattern from
-// kBootclasspathFragmentGlobPatterns and kSystemserverclasspathFragmentGlobPatterns, which allows
-// adding mock configs in /data/local/tmp for example.
-bool GenerateClasspathExports(const std::string& globPatternPrefix, std::string_view output_path) {
+bool GenerateClasspathExports(const Args& args) {
// Parse all known classpath fragments
CHECK(android::modules::sdklevel::IsAtLeastS())
<< "derive_classpath must only be run on Android 12 or above";
Classpaths classpaths;
- if (!ParseFragments(globPatternPrefix, classpaths, /*boot_jars=*/true)) {
+ if (!ParseFragments(args, classpaths, /*boot_jars=*/true)) {
LOG(ERROR) << "Failed to parse BOOTCLASSPATH fragments";
return false;
}
- if (!ParseFragments(globPatternPrefix, classpaths, /*boot_jars=*/false)) {
+ if (!ParseFragments(args, classpaths, /*boot_jars=*/false)) {
LOG(ERROR) << "Failed to parse SYSTEMSERVERCLASSPATH fragments";
return false;
}
// Write export actions for init.rc
- if (!WriteClasspathExports(classpaths, output_path)) {
- PLOG(ERROR) << "Failed to write " << output_path;
+ if (!WriteClasspathExports(classpaths, args.output_path)) {
+ PLOG(ERROR) << "Failed to write " << args.output_path;
return false;
}
return true;
diff --git a/derive_classpath/derive_classpath.h b/derive_classpath/derive_classpath.h
index a99e561..b0716f3 100644
--- a/derive_classpath/derive_classpath.h
+++ b/derive_classpath/derive_classpath.h
@@ -24,11 +24,19 @@ namespace derive_classpath {
constexpr std::string_view kGeneratedClasspathExportsFilepath = "/data/system/environ/classpath";
-bool GenerateClasspathExports(std::string_view output_path = kGeneratedClasspathExportsFilepath);
+struct Args {
+ std::string_view output_path;
-// This must only be used in tests.
-bool GenerateClasspathExports(const std::string& globPatternPrefix,
- std::string_view output_path = kGeneratedClasspathExportsFilepath);
+ // 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;
+};
+
+bool GenerateClasspathExports(const Args& args);
} // namespace derive_classpath
} // namespace android
diff --git a/derive_classpath/derive_classpath_test.cpp b/derive_classpath/derive_classpath_test.cpp
index 97e2581..6e503f3 100644
--- a/derive_classpath/derive_classpath_test.cpp
+++ b/derive_classpath/derive_classpath_test.cpp
@@ -49,7 +49,7 @@ class DeriveClasspathTest : public ::testing::Test {
~DeriveClasspathTest() override {
// Not really needed, as a test device will re-generate a proper classpath on reboot,
// but it's better to leave it in a clean state after a test.
- GenerateClasspathExports();
+ GenerateClasspathExports(default_args_);
}
const std::string working_dir() { return std::string(temp_dir_.path); }
@@ -115,7 +115,16 @@ class DeriveClasspathTest : public ::testing::Test {
ASSERT_TRUE(android::base::WriteStringToFile(buf, fragment_path, true));
}
- TemporaryDir temp_dir_;
+ const TemporaryDir temp_dir_;
+
+ const Args default_args_ = {
+ .output_path = kGeneratedClasspathExportsFilepath,
+ };
+
+ const Args default_args_with_test_dir_ = {
+ .output_path = kGeneratedClasspathExportsFilepath,
+ .glob_pattern_prefix = temp_dir_.path,
+ };
};
using DeriveClasspathDeathTest = DeriveClasspathTest;
@@ -123,7 +132,7 @@ using DeriveClasspathDeathTest = DeriveClasspathTest;
// Check only known *CLASSPATH variables are exported.
TEST_F(DeriveClasspathTest, DefaultNoUnknownClasspaths) {
// Re-generate default on device classpaths
- GenerateClasspathExports();
+ GenerateClasspathExports(default_args_);
const std::vector<std::string> exportLines = ParseExportsFile();
// The first three lines are tested above.
@@ -138,7 +147,7 @@ TEST_F(DeriveClasspathTest, TempConfig) {
AddJarToClasspath("/apex/com.android.baz", "/apex/com.android.baz/javalib/baz",
SYSTEMSERVERCLASSPATH);
- ASSERT_TRUE(GenerateClasspathExports(working_dir()));
+ ASSERT_TRUE(GenerateClasspathExports(default_args_with_test_dir_));
const std::vector<std::string> exportLines = ParseExportsFile();
@@ -160,7 +169,7 @@ TEST_F(DeriveClasspathTest, ModulesAreSorted) {
AddJarToClasspath("/apex/com.android.bar", "/apex/com.android.bar/javalib/bar", BOOTCLASSPATH);
AddJarToClasspath("/apex/com.android.baz", "/apex/com.android.baz/javalib/baz", BOOTCLASSPATH);
- ASSERT_TRUE(GenerateClasspathExports(working_dir()));
+ ASSERT_TRUE(GenerateClasspathExports(default_args_with_test_dir_));
const std::vector<std::string> exportLines = ParseExportsFile();
const std::vector<std::string> splitExportLine = SplitClasspathExportLine(exportLines[0]);
@@ -187,7 +196,11 @@ TEST_F(DeriveClasspathTest, CustomOutputLocation) {
android::base::unique_fd fd(memfd_create("temp_file", MFD_CLOEXEC));
ASSERT_TRUE(fd.ok()) << "Unable to open temp-file";
const std::string file_name = android::base::StringPrintf("/proc/self/fd/%d", fd.get());
- ASSERT_TRUE(GenerateClasspathExports(working_dir(), file_name));
+ Args args = {
+ .output_path = file_name,
+ .glob_pattern_prefix = working_dir(),
+ };
+ ASSERT_TRUE(GenerateClasspathExports(args));
const std::vector<std::string> exportLines = ParseExportsFile(file_name.c_str());
const std::vector<std::string> splitExportLine = SplitClasspathExportLine(exportLines[0]);
@@ -203,12 +216,50 @@ 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);
AddJarToClasspath("/system", "/system/framework/jar", BOOTCLASSPATH);
- ASSERT_FALSE(GenerateClasspathExports(working_dir(), "/system/non_writable_path"));
+ Args args = {
+ .output_path = "/system/non_writable_path",
+ .glob_pattern_prefix = working_dir(),
+ };
+ ASSERT_FALSE(GenerateClasspathExports(args));
}
// Test apexes only export their own jars.
@@ -220,7 +271,8 @@ TEST_F(DeriveClasspathDeathTest, ApexJarsBelongToApex) {
AddJarToClasspath("/apex/com.android.foo", "/apex/com.android.foo/javalib/foo", BOOTCLASSPATH);
AddJarToClasspath("/apex/com.android.bar", "/apex/wrong/path/bar", BOOTCLASSPATH);
- EXPECT_DEATH(GenerateClasspathExports(working_dir()), "must not export a jar.*wrong/path/bar");
+ EXPECT_DEATH(GenerateClasspathExports(default_args_with_test_dir_),
+ "must not export a jar.*wrong/path/bar");
}
// Test classpath fragments export jars for themselves.
@@ -251,7 +303,7 @@ TEST_F(DeriveClasspathDeathTest, WrongClasspathInFragments) {
ASSERT_EQ(0, system(cmd.c_str()));
ASSERT_TRUE(android::base::WriteStringToFile(buf, fragment_path, true));
- EXPECT_DEATH(GenerateClasspathExports(working_dir()),
+ EXPECT_DEATH(GenerateClasspathExports(default_args_with_test_dir_),
"must not export a jar for SYSTEMSERVERCLASSPATH");
}
diff --git a/derive_classpath/main.cpp b/derive_classpath/main.cpp
index b896eb9..8807cdb 100644
--- a/derive_classpath/main.cpp
+++ b/derive_classpath/main.cpp
@@ -15,22 +15,66 @@
*/
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <cstdlib>
#include <string_view>
#include "derive_classpath.h"
-int main(int argc, char** argv) {
- std::string_view output_location;
- if (argc == 1) {
- output_location = android::derive_classpath::kGeneratedClasspathExportsFilepath;
- } else if (argc == 2) {
- output_location = argv[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 (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(output_location)) {
+ if (!android::derive_classpath::GenerateClasspathExports(args)) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
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 f36a3f6..ac1929e 100644
--- a/framework/java/android/os/ext/SdkExtensions.java
+++ b/framework/java/android/os/ext/SdkExtensions.java
@@ -43,14 +43,11 @@ 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;
static {
- // Note: when adding more extension versions, the logic that records current
- // extension versions when saving a rollback must also be updated.
- // At the time of writing this is in RollbackManagerServiceImpl#getExtensionVersions()
R_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.r", 0);
S_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.s", 0);
Map<Integer, Integer> extensions = new HashMap<Integer, Integer>();
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));
}