Merge changes I6f19b810,I0fd91e2a am: 83e62acb23 am: 18f2d1d0bc am: 08c44c420b

Original change: https://android-review.googlesource.com/c/platform/packages/modules/SdkExtensions/+/2060061

Change-Id: I9055b880e37efbde04635e5bc78c9d09742c938b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/README.md b/README.md
index 9741867..eb2c503 100644
--- a/README.md
+++ b/README.md
@@ -49,15 +49,21 @@
 
 ## Developer information
 
-### Adding a new extension version
-For every new Android SDK level a new extension version should be defined. These
-are the steps necessary to do that:
-- Add the new modules in this extension version to the SdkModule enum in
-  sdk.proto.
+### Adding a new extension
+An extension is a way to group a set of modules so that they are versioned
+together. We currently define a new extension for every Android SDK level
+that introduces new modules. Every module shipped in previous versions are
+also part of the new extension. For example, all the R modules are part of
+both the R extensions and the S extensions.
+
+The steps to define a new extension are:
+- Add any new modules to the SdkModule enum in sdk.proto.
+- Add the binary "current sdk version" proto to the apexes of the new modules.
 - Update `derive_sdk.cpp` by:
  * mapping the modules' package names to the new enum values
- * creating a new set with the new enum values
+ * creating a new set with the new enum values of the modules relevant for
+   this extension.
  * set a new sysprop to the value of `GetSdkLevel` with the new enum set
- * add a unit test to `derive_sdk_test.cpp` verifying the new extensions works
+ * add a unit test to `derive_sdk_test.cpp` verifying the new extensions work
 - Make the `SdkExtensions.getExtensionVersion` API support the new extensions.
 - Extend the CTS test to verify the above two behaviors.
diff --git a/derive_sdk/derive_sdk.cpp b/derive_sdk/derive_sdk.cpp
index 44ac7d1..2d1f5e1 100644
--- a/derive_sdk/derive_sdk.cpp
+++ b/derive_sdk/derive_sdk.cpp
@@ -35,11 +35,14 @@
 namespace derivesdk {
 
 static const std::unordered_map<std::string, SdkModule> kApexNameToModule = {
+    {"com.android.adservices", SdkModule::AD_SERVICES},
+    {"com.android.appsearch", SdkModule::APPSEARCH},
     {"com.android.art", SdkModule::ART},
     {"com.android.conscrypt", SdkModule::CONSCRYPT},
     {"com.android.ipsec", SdkModule::IPSEC},
     {"com.android.media", SdkModule::MEDIA},
     {"com.android.mediaprovider", SdkModule::MEDIA_PROVIDER},
+    {"com.android.ondevicepersonalization", SdkModule::ON_DEVICE_PERSONALIZATION},
     {"com.android.permission", SdkModule::PERMISSIONS},
     {"com.android.scheduling", SdkModule::SCHEDULING},
     {"com.android.sdkext", SdkModule::SDK_EXTENSIONS},
@@ -54,6 +57,9 @@
 
 static const std::unordered_set<SdkModule> kSModules = {SdkModule::ART, SdkModule::SCHEDULING};
 
+static const std::unordered_set<SdkModule> kTModules = {
+    SdkModule::AD_SERVICES, SdkModule::APPSEARCH, SdkModule::ON_DEVICE_PERSONALIZATION};
+
 bool ReadDatabase(const std::string& db_path, ExtensionDatabase& db) {
   std::string contents;
   if (!android::base::ReadFileToString(db_path, &contents, true)) {
@@ -174,6 +180,16 @@
     }
   }
 
+  relevant_modules.insert(kTModules.begin(), kTModules.end());
+  if (android::modules::sdklevel::IsAtLeastT()) {
+    int version_T = GetSdkLevel(db, relevant_modules, versions);
+    LOG(INFO) << "T extension version is " << version_T;
+    if (!android::base::SetProperty("build.version.extensions.t", std::to_string(version_T))) {
+      LOG(ERROR) << "failed to set t sdk_info prop";
+      return false;
+    }
+  }
+
   // Consistency check: verify all modules with requirements is included in some dessert
   for (const auto& ext_version : db.versions()) {
     for (const auto& requirement : ext_version.requirements()) {
diff --git a/derive_sdk/derive_sdk_test.cpp b/derive_sdk/derive_sdk_test.cpp
index 1a37342..5beb162 100644
--- a/derive_sdk/derive_sdk_test.cpp
+++ b/derive_sdk/derive_sdk_test.cpp
@@ -85,9 +85,16 @@
     EXPECT_EQ(S, android::modules::sdklevel::IsAtLeastS() ? n : -1);
   }
 
+  void EXPECT_T(int n) {
+    int T = android::base::GetIntProperty("build.version.extensions.t", -1);
+    // Only expect the T extension level to be set on T+ devices.
+    EXPECT_EQ(T, android::modules::sdklevel::IsAtLeastT() ? n : -1);
+  }
+
   void EXPECT_ALL(int n) {
     EXPECT_R(n);
     EXPECT_S(n);
+    EXPECT_T(n);
   }
 
   ExtensionDatabase db_;
@@ -95,7 +102,7 @@
 };
 
 TEST_F(DeriveSdkTest, CurrentSystemImageValue) {
-  EXPECT_ALL(1);
+  EXPECT_ALL(2);
 }
 
 TEST_F(DeriveSdkTest, OneDessert_OneVersion_OneApex) {
diff --git a/gen_sdk/extensions_db.textpb b/gen_sdk/extensions_db.textpb
index 5d54a58..423a221 100644
--- a/gen_sdk/extensions_db.textpb
+++ b/gen_sdk/extensions_db.textpb
@@ -61,3 +61,66 @@
     }
   }
 }
+versions {
+  version: 2
+  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: 2
+    }
+  }
+  requirements {
+    module: PERMISSIONS
+    version {
+      version: 1
+    }
+  }
+  requirements {
+    module: SCHEDULING
+    version {
+      version: 1
+    }
+  }
+  requirements {
+    module: SDK_EXTENSIONS
+    version {
+      version: 2
+    }
+  }
+  requirements {
+    module: STATSD
+    version {
+      version: 1
+    }
+  }
+  requirements {
+    module: TETHERING
+    version {
+      version: 1
+    }
+  }
+}
diff --git a/java/android/os/ext/SdkExtensions.java b/java/android/os/ext/SdkExtensions.java
index cb4c541..3ce6a5a 100644
--- a/java/android/os/ext/SdkExtensions.java
+++ b/java/android/os/ext/SdkExtensions.java
@@ -44,15 +44,20 @@
 
     private static final int R_EXTENSION_INT;
     private static final int S_EXTENSION_INT;
+    private static final int T_EXTENSION_INT;
     private static final Map<Integer, Integer> ALL_EXTENSION_INTS;
     static {
         R_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.r", 0);
         S_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.s", 0);
+        T_EXTENSION_INT = SystemProperties.getInt("build.version.extensions.t", 0);
         Map<Integer, Integer> extensions = new HashMap<Integer, Integer>();
         extensions.put(VERSION_CODES.R, R_EXTENSION_INT);
         if (SdkLevel.isAtLeastS()) {
             extensions.put(VERSION_CODES.S, S_EXTENSION_INT);
         }
+        if (SdkLevel.isAtLeastT()) {
+            extensions.put(VERSION_CODES.TIRAMISU, T_EXTENSION_INT);
+        }
         ALL_EXTENSION_INTS = Collections.unmodifiableMap(extensions);
     }
 
@@ -60,7 +65,7 @@
      * Values suitable as parameters for {@link #getExtensionVersion(int)}.
      * @hide
      */
-    @IntDef(value = { VERSION_CODES.R, VERSION_CODES.S })
+    @IntDef(value = { VERSION_CODES.R, VERSION_CODES.S, VERSION_CODES.TIRAMISU })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Extension {}
 
@@ -91,6 +96,9 @@
         if (extension == VERSION_CODES.S) {
             return S_EXTENSION_INT;
         }
+        if (extension == VERSION_CODES.TIRAMISU) {
+            return T_EXTENSION_INT;
+        }
         return 0;
     }
 
diff --git a/java/com/android/os/ext/testing/CurrentVersion.java b/java/com/android/os/ext/testing/CurrentVersion.java
index d559709..7086ebe 100644
--- a/java/com/android/os/ext/testing/CurrentVersion.java
+++ b/java/com/android/os/ext/testing/CurrentVersion.java
@@ -25,7 +25,7 @@
 public class CurrentVersion {
 
     /** The current extension version */
-    public static final int V = 1;
+    public static final int V = 2;
 
     /**
      * The current SDK Extension versions to expect / allow in CTS.
@@ -37,8 +37,7 @@
      * new version.
      */
     public static final Set<Integer> ALLOWED_VERSIONS = Collections.unmodifiableSet(Set.of(
-        V,
-        2
+        V
     ));
 
 }
diff --git a/javatests/com/android/os/ext/SdkExtensionsTest.java b/javatests/com/android/os/ext/SdkExtensionsTest.java
index 84ed2a0..f8cbacf 100644
--- a/javatests/com/android/os/ext/SdkExtensionsTest.java
+++ b/javatests/com/android/os/ext/SdkExtensionsTest.java
@@ -65,8 +65,10 @@
         assertCorrectVersion(true, SdkExtensions.getExtensionVersion(VERSION_CODES.R));
         assertCorrectVersion(
             SdkLevel.isAtLeastS(), SdkExtensions.getExtensionVersion(VERSION_CODES.S));
+        assertCorrectVersion(
+            SdkLevel.isAtLeastT(), SdkExtensions.getExtensionVersion(VERSION_CODES.TIRAMISU));
 
-        int firstUnassigned = VERSION_CODES.S + 1;
+        int firstUnassigned = VERSION_CODES.TIRAMISU + 1;
         for (int sdk = firstUnassigned; sdk <= 1_000_000; sdk++) {
             // No extension SDKs yet.
             assertEquals(0, SdkExtensions.getExtensionVersion(sdk));
@@ -78,6 +80,8 @@
         assertCorrectVersion(true, SystemProperties.get("build.version.extensions.r"));
         assertCorrectVersion(
             SdkLevel.isAtLeastS(), SystemProperties.get("build.version.extensions.s"));
+        assertCorrectVersion(
+            SdkLevel.isAtLeastT(), SystemProperties.get("build.version.extensions.t"));
     }
 
     public void testExtensionVersions() throws Exception {
@@ -89,6 +93,10 @@
             assertCorrectVersion(versions.get(VERSION_CODES.S));
             expectedSize++;
         }
+        if (SdkLevel.isAtLeastT()) {
+            assertCorrectVersion(versions.get(VERSION_CODES.TIRAMISU));
+            expectedSize++;
+        }
         assertEquals(expectedSize, versions.size());
     }