Merge "StorageManagerService: fix names of user lifecycle methods" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 55f5436..f0b7598 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -12,20 +12,29 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+aconfig_srcjars = [
+    ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
+    ":android.nfc.flags-aconfig-java{.generated_srcjars}",
+    ":android.os.flags-aconfig-java{.generated_srcjars}",
+    ":android.security.flags-aconfig-java{.generated_srcjars}",
+    ":com.android.hardware.camera2-aconfig-java{.generated_srcjars}",
+    ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
+    ":com.android.hardware.input-aconfig-java{.generated_srcjars}",
+    ":com.android.text.flags-aconfig-java{.generated_srcjars}",
+]
+
+filegroup {
+    name: "framework-minus-apex-aconfig-srcjars",
+    srcs: aconfig_srcjars,
+}
+
 // Aconfig declarations and libraries for the core framework
 java_defaults {
     name: "framework-minus-apex-aconfig-libraries",
 
     // Add java_aconfig_libraries to here to add them to the core framework
-    srcs: [
-        ":android.os.flags-aconfig-java{.generated_srcjars}",
-        ":android.security.flags-aconfig-java{.generated_srcjars}",
-        ":com.android.hardware.camera2-aconfig-java{.generated_srcjars}",
-        ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
-        ":com.android.hardware.input-aconfig-java{.generated_srcjars}",
-        ":com.android.text.flags-aconfig-java{.generated_srcjars}",
-    ],
     // Add aconfig-annotations-lib as a dependency for the optimization
+    srcs: aconfig_srcjars,
     libs: ["aconfig-annotations-lib"],
 }
 
@@ -102,6 +111,19 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// NFC
+aconfig_declarations {
+    name: "android.nfc.flags-aconfig",
+    package: "android.nfc",
+    srcs: ["core/java/android/nfc/*.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.nfc.flags-aconfig-java",
+    aconfig_declarations: "android.nfc.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // Security
 aconfig_declarations {
     name: "android.security.flags-aconfig",
@@ -122,3 +144,16 @@
     test: true,
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
+
+// Biometrics
+aconfig_declarations {
+    name: "android.hardware.biometrics.flags-aconfig",
+    package: "android.hardware.biometrics",
+    srcs: ["core/java/android/hardware/biometrics/flags.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.hardware.biometrics.flags-aconfig-java",
+    aconfig_declarations: "android.hardware.biometrics.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp
index dc17a78..d15b44f 100644
--- a/api/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -29,6 +29,9 @@
 
 droidstubs {
     name: "api-stubs-docs-non-updatable",
+    srcs: [
+        ":framework-minus-apex-aconfig-srcjars",
+    ],
     defaults: [
         "android-non-updatable-stubs-defaults",
         "module-classpath-stubs-defaults",
@@ -63,6 +66,7 @@
             tag: ".removed-api.txt",
         },
     ],
+    api_surface: "public",
 }
 
 priv_apps = " --show-annotation android.annotation.SystemApi\\(" +
@@ -116,6 +120,7 @@
             tag: ".removed-api.txt",
         },
     ],
+    api_surface: "system",
 }
 
 droidstubs {
@@ -161,6 +166,7 @@
             tag: ".removed-api.txt",
         },
     ],
+    api_surface: "test",
 }
 
 droidstubs {
@@ -200,6 +206,7 @@
             tag: ".removed-api.txt",
         },
     ],
+    api_surface: "module-lib",
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -376,8 +383,8 @@
 java_api_library {
     name: "android-non-updatable.stubs.from-text",
     api_surface: "public",
-    api_files: [
-        ":non-updatable-current.txt",
+    api_contributions: [
+        "api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_from_text_defaults"],
     full_api_surface_stub: "android_stubs_current.from-text",
@@ -386,9 +393,9 @@
 java_api_library {
     name: "android-non-updatable.stubs.system.from-text",
     api_surface: "system",
-    api_files: [
-        ":non-updatable-current.txt",
-        ":non-updatable-system-current.txt",
+    api_contributions: [
+        "api-stubs-docs-non-updatable.api.contribution",
+        "system-api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_from_text_defaults"],
     full_api_surface_stub: "android_system_stubs_current.from-text",
@@ -397,10 +404,10 @@
 java_api_library {
     name: "android-non-updatable.stubs.test.from-text",
     api_surface: "test",
-    api_files: [
-        ":non-updatable-current.txt",
-        ":non-updatable-system-current.txt",
-        ":non-updatable-test-current.txt",
+    api_contributions: [
+        "api-stubs-docs-non-updatable.api.contribution",
+        "system-api-stubs-docs-non-updatable.api.contribution",
+        "test-api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_from_text_defaults"],
     full_api_surface_stub: "android_test_stubs_current.from-text",
@@ -409,10 +416,10 @@
 java_api_library {
     name: "android-non-updatable.stubs.module_lib.from-text",
     api_surface: "module_lib",
-    api_files: [
-        ":non-updatable-current.txt",
-        ":non-updatable-system-current.txt",
-        ":non-updatable-module-lib-current.txt",
+    api_contributions: [
+        "api-stubs-docs-non-updatable.api.contribution",
+        "system-api-stubs-docs-non-updatable.api.contribution",
+        "module-lib-api-stubs-docs-non-updatable.api.contribution",
     ],
     defaults: ["android-non-updatable_from_text_defaults"],
     full_api_surface_stub: "android_module_lib_stubs_current_full.from-text",
@@ -595,7 +602,6 @@
     name: "android_test_stubs_current_contributions",
     api_surface: "test",
     api_contributions: [
-        "test-api-stubs-docs-non-updatable.api.contribution",
         "framework-virtualization.stubs.source.test.api.contribution",
     ],
 }
@@ -661,6 +667,7 @@
     api_contributions: [
         "api-stubs-docs-non-updatable.api.contribution",
         "system-api-stubs-docs-non-updatable.api.contribution",
+        "test-api-stubs-docs-non-updatable.api.contribution",
     ],
     visibility: ["//visibility:public"],
 }
diff --git a/api/api.go b/api/api.go
index e09be03..431d6d8 100644
--- a/api/api.go
+++ b/api/api.go
@@ -429,7 +429,7 @@
 }
 
 // combined_apis bp2build converter
-func (a *CombinedApis) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+func (a *CombinedApis) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) {
 	basePrefix := "non-updatable"
 	scopeToSuffix := map[string]string{
 		"public":        "-current.txt",
diff --git a/core/api/current.txt b/core/api/current.txt
index cba935f..d399e34 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -37935,6 +37935,7 @@
     method @Nullable public java.util.Date getKeyValidityStart();
     method @NonNull public String getKeystoreAlias();
     method public int getMaxUsageCount();
+    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
     method public int getPurposes();
     method @NonNull public String[] getSignaturePaddings();
     method public int getUserAuthenticationType();
@@ -37942,6 +37943,7 @@
     method public boolean isDevicePropertiesAttestationIncluded();
     method @NonNull public boolean isDigestsSpecified();
     method public boolean isInvalidatedByBiometricEnrollment();
+    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
     method public boolean isRandomizedEncryptionRequired();
     method public boolean isStrongBoxBacked();
     method public boolean isUnlockedDeviceRequired();
@@ -37973,6 +37975,7 @@
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int);
+    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@Nullable java.lang.String...);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
     method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
@@ -38077,12 +38080,14 @@
     method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
     method @Nullable public java.util.Date getKeyValidityStart();
     method public int getMaxUsageCount();
+    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
     method public int getPurposes();
     method @NonNull public String[] getSignaturePaddings();
     method public int getUserAuthenticationType();
     method public int getUserAuthenticationValidityDurationSeconds();
     method public boolean isDigestsSpecified();
     method public boolean isInvalidatedByBiometricEnrollment();
+    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
     method public boolean isRandomizedEncryptionRequired();
     method public boolean isUnlockedDeviceRequired();
     method public boolean isUserAuthenticationRequired();
@@ -38104,6 +38109,7 @@
     method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
     method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
     method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int);
+    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
     method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
     method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
     method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 26c72f0..8cf921c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2976,6 +2976,7 @@
     field public static final String SYSTEM_CONFIG_SERVICE = "system_config";
     field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
     field public static final String TETHERING_SERVICE = "tethering";
+    field public static final String THREAD_NETWORK_SERVICE = "thread_network";
     field public static final String TRANSLATION_MANAGER_SERVICE = "translation";
     field public static final String UI_TRANSLATION_SERVICE = "ui_translation";
     field public static final String UWB_SERVICE = "uwb";
@@ -9139,6 +9140,73 @@
 
 }
 
+package android.nfc.cardemulation {
+
+  @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public final class AidGroup implements android.os.Parcelable {
+    ctor @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public AidGroup(@NonNull java.util.List<java.lang.String>, @Nullable String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @Nullable public static android.nfc.cardemulation.AidGroup createFromXml(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public int describeContents();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void dump(@NonNull android.util.proto.ProtoOutputStream);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public java.util.List<java.lang.String> getAids();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getCategory();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void writeAsXml(@NonNull org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.AidGroup> CREATOR;
+  }
+
+  @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public final class ApduServiceInfo implements android.os.Parcelable {
+    ctor @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public ApduServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo, boolean) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public int describeContents();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void dump(@NonNull android.os.ParcelFileDescriptor, @NonNull java.io.PrintWriter, @NonNull String[]);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void dumpDebug(@NonNull android.util.proto.ProtoOutputStream);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public java.util.List<android.nfc.cardemulation.AidGroup> getAidGroups();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public java.util.List<java.lang.String> getAids();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getCategoryForAid(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public android.content.ComponentName getComponent();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getDescription();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public android.nfc.cardemulation.AidGroup getDynamicAidGroupForCategory(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @Nullable public String getOffHostSecureElement();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public java.util.List<java.lang.String> getPrefixAids();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getSettingsActivityName();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public java.util.List<java.lang.String> getSubsetAids();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public int getUid();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public boolean hasCategory(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public boolean isOnHost();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public CharSequence loadAppLabel(@NonNull android.content.pm.PackageManager);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public android.graphics.drawable.Drawable loadBanner(@NonNull android.content.pm.PackageManager);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public android.graphics.drawable.Drawable loadIcon(@NonNull android.content.pm.PackageManager);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public CharSequence loadLabel(@NonNull android.content.pm.PackageManager);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public boolean removeDynamicAidGroupForCategory(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public boolean requiresScreenOn();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public boolean requiresUnlock();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void resetOffHostSecureElement();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void setOffHostSecureElement(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.ApduServiceInfo> CREATOR;
+  }
+
+  @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public final class NfcFServiceInfo implements android.os.Parcelable {
+    ctor @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public NfcFServiceInfo(@NonNull android.content.pm.PackageManager, @NonNull android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public int describeContents();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void dump(@NonNull android.os.ParcelFileDescriptor, @NonNull java.io.PrintWriter, @NonNull String[]);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void dumpDebug(@NonNull android.util.proto.ProtoOutputStream);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public android.content.ComponentName getComponent();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getDescription();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getNfcid2();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getSystemCode();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public String getT3tPmm();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public int getUid();
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public android.graphics.drawable.Drawable loadIcon(@NonNull android.content.pm.PackageManager);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public CharSequence loadLabel(@NonNull android.content.pm.PackageManager);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void setDynamicNfcid2(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void setDynamicSystemCode(@NonNull String);
+    method @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.NfcFServiceInfo> CREATOR;
+  }
+
+}
+
 package android.os {
 
   public class BatteryManager {
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 0100f0e..71c02dc 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -225,3 +225,16 @@
     SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addTouchExplorationStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
     SAM-compatible parameters (such as parameter 2, "filePathCallback", in android.webkit.WebChromeClient.onShowFileChooser) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+
+UnflaggedApi: android.nfc.cardemulation.AidGroup#CONTENTS_FILE_DESCRIPTOR:
+    New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.AidGroup.CONTENTS_FILE_DESCRIPTOR
+UnflaggedApi: android.nfc.cardemulation.AidGroup#PARCELABLE_WRITE_RETURN_VALUE:
+    New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.AidGroup.PARCELABLE_WRITE_RETURN_VALUE
+UnflaggedApi: android.nfc.cardemulation.ApduServiceInfo#CONTENTS_FILE_DESCRIPTOR:
+    New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.ApduServiceInfo.CONTENTS_FILE_DESCRIPTOR
+UnflaggedApi: android.nfc.cardemulation.ApduServiceInfo#PARCELABLE_WRITE_RETURN_VALUE:
+    New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.ApduServiceInfo.PARCELABLE_WRITE_RETURN_VALUE
+UnflaggedApi: android.nfc.cardemulation.NfcFServiceInfo#CONTENTS_FILE_DESCRIPTOR:
+    New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.NfcFServiceInfo.CONTENTS_FILE_DESCRIPTOR
+UnflaggedApi: android.nfc.cardemulation.NfcFServiceInfo#PARCELABLE_WRITE_RETURN_VALUE:
+    New API must be flagged with @FlaggedApi: field android.nfc.cardemulation.NfcFServiceInfo.PARCELABLE_WRITE_RETURN_VALUE
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d04d8be..518234f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3825,6 +3825,7 @@
             VIBRATOR_MANAGER_SERVICE,
             VIBRATOR_SERVICE,
             //@hide: STATUS_BAR_SERVICE,
+            THREAD_NETWORK_SERVICE,
             CONNECTIVITY_SERVICE,
             PAC_PROXY_SERVICE,
             VCN_MANAGEMENT_SERVICE,
@@ -4496,6 +4497,20 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.net.thread.ThreadNetworkManager}.
+     *
+     * <p>On devices without {@link PackageManager#FEATURE_THREAD_NETWORK} system feature
+     * the {@link #getSystemService(String)} will return {@code null}.
+     *
+     * @see #getSystemService(String)
+     * @see android.net.thread.ThreadNetworkManager
+     * @hide
+     */
+    @SystemApi
+    public static final String THREAD_NETWORK_SERVICE = "thread_network";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.net.IpSecManager} for encrypting Sockets or Networks with
      * IPSec.
      *
diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig
new file mode 100644
index 0000000..0924e0d1
--- /dev/null
+++ b/core/java/android/hardware/biometrics/flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.hardware.biometrics"
+
+flag {
+  name: "add_key_agreement_crypto_object"
+  namespace: "biometrics"
+  description: "Feature flag for adding KeyAgreement api to CryptoObject."
+  bug: "282058146"
+}
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 2436e57..958669e 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -16,7 +16,11 @@
 
 package android.nfc.cardemulation;
 
-import android.compat.annotation.UnsupportedAppUsage;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.nfc.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -29,6 +33,11 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
+
+/**********************************************************************
+ * This file is not a part of the NFC mainline module                 *
+ * *******************************************************************/
 
 /**
  * The AidGroup class represents a group of Application Identifiers (AIDs).
@@ -39,28 +48,30 @@
  *
  * @hide
  */
+@SystemApi
+@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
 public final class AidGroup implements Parcelable {
     /**
      * The maximum number of AIDs that can be present in any one group.
      */
-    public static final int MAX_NUM_AIDS = 256;
+    private static final int MAX_NUM_AIDS = 256;
 
-    static final String TAG = "AidGroup";
+    private static final String TAG = "AidGroup";
 
-    @UnsupportedAppUsage
-    final List<String> aids;
-    @UnsupportedAppUsage
-    final String category;
-    @UnsupportedAppUsage
-    final String description;
+
+    private final List<String> mAids;
+    private final String mCategory;
+    @SuppressWarnings("unused") // Unused as of now, but part of the XML input.
+    private final String mDescription;
 
     /**
      * Creates a new AidGroup object.
      *
-     * @param aids The list of AIDs present in the group
-     * @param category The category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
+     * @param aids list of AIDs present in the group
+     * @param category category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
      */
-    public AidGroup(List<String> aids, String category) {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public AidGroup(@NonNull List<String> aids, @Nullable String category) {
         if (aids == null || aids.size() == 0) {
             throw new IllegalArgumentException("No AIDS in AID group.");
         }
@@ -73,45 +84,55 @@
             }
         }
         if (isValidCategory(category)) {
-            this.category = category;
+            this.mCategory = category;
         } else {
-            this.category = CardEmulation.CATEGORY_OTHER;
+            this.mCategory = CardEmulation.CATEGORY_OTHER;
         }
-        this.aids = new ArrayList<String>(aids.size());
+        this.mAids = new ArrayList<String>(aids.size());
         for (String aid : aids) {
-            this.aids.add(aid.toUpperCase());
+            this.mAids.add(aid.toUpperCase(Locale.US));
         }
-        this.description = null;
-    }
-
-    @UnsupportedAppUsage
-    AidGroup(String category, String description) {
-        this.aids = new ArrayList<String>();
-        this.category = category;
-        this.description = description;
+        this.mDescription = null;
     }
 
     /**
+     * Creates a new AidGroup object.
+     *
+     * @param category category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
+     * @param description description of this group
+     */
+    AidGroup(@NonNull String category, @NonNull String description) {
+        this.mAids = new ArrayList<String>();
+        this.mCategory = category;
+        this.mDescription = description;
+    }
+
+    /**
+     * Returns the category of this group.
      * @return the category of this AID group
      */
-    @UnsupportedAppUsage
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getCategory() {
-        return category;
+        return mCategory;
     }
 
     /**
+     * Returns the list of AIDs in this group.
+     *
      * @return the list of AIDs in this group
      */
-    @UnsupportedAppUsage
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public List<String> getAids() {
-        return aids;
+        return mAids;
     }
 
     @Override
     public String toString() {
-        StringBuilder out = new StringBuilder("Category: " + category +
-                  ", AIDs:");
-        for (String aid : aids) {
+        StringBuilder out = new StringBuilder("Category: " + mCategory
+                + ", AIDs:");
+        for (String aid : mAids) {
             out.append(aid);
             out.append(", ");
         }
@@ -119,41 +140,44 @@
     }
 
     /**
-     * Dump debugging info as AidGroupProto
+     * Dump debugging info as AidGroupProto.
      *
      * If the output belongs to a sub message, the caller is responsible for wrapping this function
      * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
      *
      * @param proto the ProtoOutputStream to write to
      */
-    public void dump(ProtoOutputStream proto) {
-        proto.write(AidGroupProto.CATEGORY, category);
-        for (String aid : aids) {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void dump(@NonNull ProtoOutputStream proto) {
+        proto.write(AidGroupProto.CATEGORY, mCategory);
+        for (String aid : mAids) {
             proto.write(AidGroupProto.AIDS, aid);
         }
     }
 
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     @Override
     public int describeContents() {
         return 0;
     }
 
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(category);
-        dest.writeInt(aids.size());
-        if (aids.size() > 0) {
-            dest.writeStringList(aids);
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mCategory);
+        dest.writeInt(mAids.size());
+        if (mAids.size() > 0) {
+            dest.writeStringList(mAids);
         }
     }
 
-    @UnsupportedAppUsage
-    public static final @android.annotation.NonNull Parcelable.Creator<AidGroup> CREATOR =
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public static final @NonNull Parcelable.Creator<AidGroup> CREATOR =
             new Parcelable.Creator<AidGroup>() {
 
         @Override
         public AidGroup createFromParcel(Parcel source) {
-            String category = source.readString();
+            String category = source.readString8();
             int listSize = source.readInt();
             ArrayList<String> aidList = new ArrayList<String>();
             if (listSize > 0) {
@@ -168,8 +192,17 @@
         }
     };
 
-    @UnsupportedAppUsage
-    static public AidGroup createFromXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+    /**
+     * Create an instance of AID group from XML file.
+     *
+     * @param parser input xml parser stream
+     * @throws XmlPullParserException If an error occurs parsing the element.
+     * @throws IOException If an error occurs reading the element.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @Nullable
+    public static AidGroup createFromXml(@NonNull XmlPullParser parser)
+            throws XmlPullParserException, IOException {
         String category = null;
         ArrayList<String> aids = new ArrayList<String>();
         AidGroup group = null;
@@ -210,11 +243,16 @@
         return group;
     }
 
-    @UnsupportedAppUsage
-    public void writeAsXml(XmlSerializer out) throws IOException {
+    /**
+     * Serialize instance of AID group to XML file.
+     * @param out XML serializer stream
+     * @throws IOException If an error occurs reading the element.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void writeAsXml(@NonNull XmlSerializer out) throws IOException {
         out.startTag(null, "aid-group");
-        out.attribute(null, "category", category);
-        for (String aid : aids) {
+        out.attribute(null, "category", mCategory);
+        for (String aid : mAids) {
             out.startTag(null, "aid");
             out.attribute(null, "value", aid);
             out.endTag(null, "aid");
@@ -222,7 +260,7 @@
         out.endTag(null, "aid-group");
     }
 
-    static boolean isValidCategory(String category) {
+    private static boolean isValidCategory(String category) {
         return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
                 CardEmulation.CATEGORY_OTHER.equals(category);
     }
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 793a70e..18ec914 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -14,10 +14,16 @@
  * limitations under the License.
  */
 
+/**********************************************************************
+ * This file is not a part of the NFC mainline module                 *
+ * *******************************************************************/
+
 package android.nfc.cardemulation;
 
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
+import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -28,7 +34,9 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
+import android.nfc.Flags;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -38,7 +46,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -47,82 +54,82 @@
 import java.util.Map;
 
 /**
+ * Class holding APDU service info.
+ *
  * @hide
  */
+@SystemApi
+@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
 public final class ApduServiceInfo implements Parcelable {
-    static final String TAG = "ApduServiceInfo";
+    private static final String TAG = "ApduServiceInfo";
 
     /**
      * The service that implements this
      */
-    @UnsupportedAppUsage
-    final ResolveInfo mService;
+    private final ResolveInfo mService;
 
     /**
      * Description of the service
      */
-    final String mDescription;
+    private final String mDescription;
 
     /**
      * Whether this service represents AIDs running on the host CPU
      */
-    final boolean mOnHost;
+    private final boolean mOnHost;
 
     /**
      * Offhost reader name.
      * eg: SIM, eSE etc
      */
-    String mOffHostName;
+    private String mOffHostName;
 
     /**
      * Offhost reader name from manifest file.
-     * Used for unsetOffHostSecureElement()
+     * Used for resetOffHostSecureElement()
      */
-    final String mStaticOffHostName;
+    private final String mStaticOffHostName;
 
     /**
      * Mapping from category to static AID group
      */
-    @UnsupportedAppUsage
-    final HashMap<String, AidGroup> mStaticAidGroups;
+    private final HashMap<String, AidGroup> mStaticAidGroups;
 
     /**
      * Mapping from category to dynamic AID group
      */
-    @UnsupportedAppUsage
-    final HashMap<String, AidGroup> mDynamicAidGroups;
+    private final HashMap<String, AidGroup> mDynamicAidGroups;
 
     /**
      * Whether this service should only be started when the device is unlocked.
      */
-    final boolean mRequiresDeviceUnlock;
+    private final boolean mRequiresDeviceUnlock;
 
     /**
      * Whether this service should only be started when the device is screen on.
      */
-    final boolean mRequiresDeviceScreenOn;
+    private final boolean mRequiresDeviceScreenOn;
 
     /**
      * The id of the service banner specified in XML.
      */
-    final int mBannerResourceId;
+    private final int mBannerResourceId;
 
     /**
      * The uid of the package the service belongs to
      */
-    final int mUid;
+    private final int mUid;
 
     /**
      * Settings Activity for this service
      */
-    final String mSettingsActivityName;
+    private final String mSettingsActivityName;
 
     /**
      * @hide
      */
-    @UnsupportedAppUsage
     public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
-            ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
+            List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
             boolean requiresUnlock, int bannerResource, int uid,
             String settingsActivityName, String offHost, String staticOffHost) {
         this(info, onHost, description, staticAidGroups, dynamicAidGroups,
@@ -134,7 +141,7 @@
      * @hide
      */
     public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
-            ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
+            List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
             boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid,
             String settingsActivityName, String offHost, String staticOffHost) {
         this.mService = info;
@@ -147,19 +154,28 @@
         this.mRequiresDeviceUnlock = requiresUnlock;
         this.mRequiresDeviceScreenOn = requiresScreenOn;
         for (AidGroup aidGroup : staticAidGroups) {
-            this.mStaticAidGroups.put(aidGroup.category, aidGroup);
+            this.mStaticAidGroups.put(aidGroup.getCategory(), aidGroup);
         }
         for (AidGroup aidGroup : dynamicAidGroups) {
-            this.mDynamicAidGroups.put(aidGroup.category, aidGroup);
+            this.mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
         }
         this.mBannerResourceId = bannerResource;
         this.mUid = uid;
         this.mSettingsActivityName = settingsActivityName;
     }
 
-    @UnsupportedAppUsage
-    public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost) throws
-            XmlPullParserException, IOException {
+    /**
+     * Creates a new ApduServiceInfo object.
+     *
+     * @param pm packageManager instance
+     * @param info app component info
+     * @param onHost whether service is on host or not (secure element)
+     * @throws XmlPullParserException If an error occurs parsing the element.
+     * @throws IOException If an error occurs reading the element.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public ApduServiceInfo(@NonNull PackageManager pm, @NonNull ResolveInfo info, boolean onHost)
+            throws XmlPullParserException, IOException {
         ServiceInfo si = info.serviceInfo;
         XmlResourceParser parser = null;
         try {
@@ -277,9 +293,9 @@
                     groupAttrs.recycle();
                 } else if (eventType == XmlPullParser.END_TAG && "aid-group".equals(tagName) &&
                         currentGroup != null) {
-                    if (currentGroup.aids.size() > 0) {
-                        if (!mStaticAidGroups.containsKey(currentGroup.category)) {
-                            mStaticAidGroups.put(currentGroup.category, currentGroup);
+                    if (currentGroup.getAids().size() > 0) {
+                        if (!mStaticAidGroups.containsKey(currentGroup.getCategory())) {
+                            mStaticAidGroups.put(currentGroup.getCategory(), currentGroup);
                         }
                     } else {
                         Log.e(TAG, "Not adding <aid-group> with empty or invalid AIDs");
@@ -291,8 +307,8 @@
                             com.android.internal.R.styleable.AidFilter);
                     String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
                             toUpperCase();
-                    if (CardEmulation.isValidAid(aid) && !currentGroup.aids.contains(aid)) {
-                        currentGroup.aids.add(aid);
+                    if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+                        currentGroup.getAids().add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
                     }
@@ -305,8 +321,8 @@
                             toUpperCase();
                     // Add wildcard char to indicate prefix
                     aid = aid.concat("*");
-                    if (CardEmulation.isValidAid(aid) && !currentGroup.aids.contains(aid)) {
-                        currentGroup.aids.add(aid);
+                    if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+                        currentGroup.getAids().add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
                     }
@@ -319,8 +335,8 @@
                             toUpperCase();
                     // Add wildcard char to indicate suffix
                     aid = aid.concat("#");
-                    if (CardEmulation.isValidAid(aid) && !currentGroup.aids.contains(aid)) {
-                        currentGroup.aids.add(aid);
+                    if (CardEmulation.isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
+                        currentGroup.getAids().add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
                     }
@@ -336,11 +352,25 @@
         mUid = si.applicationInfo.uid;
     }
 
+    /**
+     * Returns the app component corresponding to this APDU service.
+     *
+     * @return app component for this service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public ComponentName getComponent() {
         return new ComponentName(mService.serviceInfo.packageName,
                 mService.serviceInfo.name);
     }
 
+    /**
+     * Returns the offhost secure element name (if the service is offhost).
+     *
+     * @return offhost secure element name for offhost services
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @Nullable
     public String getOffHostSecureElement() {
         return mOffHostName;
     }
@@ -353,18 +383,30 @@
      * for that category.
      * @return List of AIDs registered by the service
      */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public List<String> getAids() {
         final ArrayList<String> aids = new ArrayList<String>();
         for (AidGroup group : getAidGroups()) {
-            aids.addAll(group.aids);
+            aids.addAll(group.getAids());
         }
         return aids;
     }
 
+    /**
+     * Returns a consolidated list of AIDs with prefixes from the AID groups
+     * registered by this service. Note that if a service has both
+     * a static (manifest-based) AID group for a category and a dynamic
+     * AID group, only the dynamically registered AIDs will be returned
+     * for that category.
+     * @return List of prefix AIDs registered by the service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public List<String> getPrefixAids() {
         final ArrayList<String> prefixAids = new ArrayList<String>();
         for (AidGroup group : getAidGroups()) {
-            for (String aid : group.aids) {
+            for (String aid : group.getAids()) {
                 if (aid.endsWith("*")) {
                     prefixAids.add(aid);
                 }
@@ -373,10 +415,20 @@
         return prefixAids;
     }
 
+    /**
+     * Returns a consolidated list of AIDs with subsets from the AID groups
+     * registered by this service. Note that if a service has both
+     * a static (manifest-based) AID group for a category and a dynamic
+     * AID group, only the dynamically registered AIDs will be returned
+     * for that category.
+     * @return List of prefix AIDs registered by the service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public List<String> getSubsetAids() {
         final ArrayList<String> subsetAids = new ArrayList<String>();
         for (AidGroup group : getAidGroups()) {
-            for (String aid : group.aids) {
+            for (String aid : group.getAids()) {
                 if (aid.endsWith("#")) {
                     subsetAids.add(aid);
                 }
@@ -384,14 +436,28 @@
         }
         return subsetAids;
     }
+
     /**
      * Returns the registered AID group for this category.
+     *
+     * @param category category name
+     * @return {@link AidGroup} instance for the provided category
      */
-    public AidGroup getDynamicAidGroupForCategory(String category) {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public AidGroup getDynamicAidGroupForCategory(@NonNull String category) {
         return mDynamicAidGroups.get(category);
     }
 
-    public boolean removeDynamicAidGroupForCategory(String category) {
+    /**
+     * Removes the registered AID group for this category.
+     *
+     * @param category category name
+     * @return {@code true} if an AID group existed
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public boolean removeDynamicAidGroupForCategory(@NonNull String category) {
         return (mDynamicAidGroups.remove(category) != null);
     }
 
@@ -403,7 +469,9 @@
      * for that category.
      * @return List of AIDs registered by the service
      */
-    public ArrayList<AidGroup> getAidGroups() {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public List<AidGroup> getAidGroups() {
         final ArrayList<AidGroup> groups = new ArrayList<AidGroup>();
         for (Map.Entry<String, AidGroup> entry : mDynamicAidGroups.entrySet()) {
             groups.add(entry.getValue());
@@ -421,49 +489,83 @@
     /**
      * Returns the category to which this service has attributed the AID that is passed in,
      * or null if we don't know this AID.
+     * @param aid AID to lookup for
+     * @return category name corresponding to this AID
      */
-    public String getCategoryForAid(String aid) {
-        ArrayList<AidGroup> groups = getAidGroups();
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public String getCategoryForAid(@NonNull String aid) {
+        List<AidGroup> groups = getAidGroups();
         for (AidGroup group : groups) {
-            if (group.aids.contains(aid.toUpperCase())) {
-                return group.category;
+            if (group.getAids().contains(aid.toUpperCase())) {
+                return group.getCategory();
             }
         }
         return null;
     }
 
-    public boolean hasCategory(String category) {
+    /**
+     * Returns whether there is any AID group for this category.
+     * @param category category name
+     * @return {@code true} if an AID group exists
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public boolean hasCategory(@NonNull String category) {
         return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Returns whether the service is on host or not.
+     * @return true if the service is on host (not secure element)
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public boolean isOnHost() {
         return mOnHost;
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Returns whether the service requires device unlock.
+     * @return whether the service requires device unlock
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public boolean requiresUnlock() {
         return mRequiresDeviceUnlock;
     }
 
     /**
      * Returns whether this service should only be started when the device is screen on.
+     * @return whether the service requires screen on
      */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public boolean requiresScreenOn() {
         return mRequiresDeviceScreenOn;
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Returns description of service.
+     * @return user readable description of service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getDescription() {
         return mDescription;
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Returns uid of service.
+     * @return uid of the service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public int getUid() {
         return mUid;
     }
 
-    public void setOrReplaceDynamicAidGroup(AidGroup aidGroup) {
+    /**
+     * Add or replace an AID group to this service.
+     * @param aidGroup instance of aid group to set or replace
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void setDynamicAidGroup(@NonNull AidGroup aidGroup) {
         mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
     }
 
@@ -476,7 +578,8 @@
      *                  TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be eSE[number]
      *                                    (e.g. eSE/eSE1, eSE2, etc.).
      */
-    public void setOffHostSecureElement(String offHost) {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void setOffHostSecureElement(@NonNull String offHost) {
         mOffHostName = offHost;
     }
 
@@ -484,15 +587,30 @@
      * Resets the off host Secure Element to statically defined
      * by the service in the manifest file.
      */
-    public void unsetOffHostSecureElement() {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void resetOffHostSecureElement() {
         mOffHostName = mStaticOffHostName;
     }
 
-    public CharSequence loadLabel(PackageManager pm) {
+    /**
+     * Load label for this service.
+     * @param pm packagemanager instance
+     * @return label name corresponding to service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public CharSequence loadLabel(@NonNull PackageManager pm) {
         return mService.loadLabel(pm);
     }
 
-    public CharSequence loadAppLabel(PackageManager pm) {
+    /**
+     * Load application label for this service.
+     * @param pm packagemanager instance
+     * @return app label name corresponding to service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public CharSequence loadAppLabel(@NonNull PackageManager pm) {
         try {
             return pm.getApplicationLabel(pm.getApplicationInfo(
                     mService.resolvePackageName, PackageManager.GET_META_DATA));
@@ -501,12 +619,25 @@
         }
     }
 
-    public Drawable loadIcon(PackageManager pm) {
+    /**
+     * Load application icon for this service.
+     * @param pm packagemanager instance
+     * @return app icon corresponding to service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public Drawable loadIcon(@NonNull PackageManager pm) {
         return mService.loadIcon(pm);
     }
 
-    @UnsupportedAppUsage
-    public Drawable loadBanner(PackageManager pm) {
+    /**
+     * Load application banner for this service.
+     * @param pm packagemanager instance
+     * @return app banner corresponding to service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public Drawable loadBanner(@NonNull PackageManager pm) {
         Resources res;
         try {
             res = pm.getResourcesForApplication(mService.serviceInfo.packageName);
@@ -521,7 +652,12 @@
         }
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Load activity name for this service.
+     * @return activity name for this service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getSettingsActivityName() { return mSettingsActivityName; }
 
     @Override
@@ -556,14 +692,15 @@
         return getComponent().hashCode();
     }
 
-
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     @Override
     public int describeContents() {
         return 0;
     }
 
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         mService.writeToParcel(dest, flags);
         dest.writeString(mDescription);
         dest.writeInt(mOnHost ? 1 : 0);
@@ -584,8 +721,8 @@
         dest.writeString(mSettingsActivityName);
     };
 
-    @UnsupportedAppUsage
-    public static final @android.annotation.NonNull Parcelable.Creator<ApduServiceInfo> CREATOR =
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public static final @NonNull Parcelable.Creator<ApduServiceInfo> CREATOR =
             new Parcelable.Creator<ApduServiceInfo>() {
         @Override
         public ApduServiceInfo createFromParcel(Parcel source) {
@@ -620,7 +757,15 @@
         }
     };
 
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    /**
+     * Dump contents for debugging.
+     * @param fd parcelfiledescriptor instance
+     * @param pw printwriter instance
+     * @param args args for dumping
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void dump(@NonNull ParcelFileDescriptor fd, @NonNull PrintWriter pw,
+                     @NonNull String[] args) {
         pw.println("    " + getComponent()
                 + " (Description: " + getDescription() + ")"
                 + " (UID: " + getUid() + ")");
@@ -633,15 +778,15 @@
         }
         pw.println("    Static AID groups:");
         for (AidGroup group : mStaticAidGroups.values()) {
-            pw.println("        Category: " + group.category);
-            for (String aid : group.aids) {
+            pw.println("        Category: " + group.getCategory());
+            for (String aid : group.getAids()) {
                 pw.println("            AID: " + aid);
             }
         }
         pw.println("    Dynamic AID groups:");
         for (AidGroup group : mDynamicAidGroups.values()) {
-            pw.println("        Category: " + group.category);
-            for (String aid : group.aids) {
+            pw.println("        Category: " + group.getCategory());
+            for (String aid : group.getAids()) {
                 pw.println("            AID: " + aid);
             }
         }
@@ -651,7 +796,7 @@
     }
 
     /**
-     * Dump debugging info as ApduServiceInfoProto
+     * Dump debugging info as ApduServiceInfoProto.
      *
      * If the output belongs to a sub message, the caller is responsible for wrapping this function
      * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
@@ -659,7 +804,8 @@
      *
      * @param proto the ProtoOutputStream to write to
      */
-    public void dumpDebug(ProtoOutputStream proto) {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void dumpDebug(@NonNull ProtoOutputStream proto) {
         Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
         proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index 7a36b26..ec919e4 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
+/**********************************************************************
+ * This file is not a part of the NFC mainline module                 *
+ * *******************************************************************/
+
 package android.nfc.cardemulation;
 
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -26,7 +33,9 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
+import android.nfc.Flags;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -36,13 +45,16 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
 
 /**
+ * Class to hold NfcF service info.
+ *
  * @hide
  */
+@SystemApi
+@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
 public final class NfcFServiceInfo implements Parcelable {
     static final String TAG = "NfcFServiceInfo";
 
@@ -51,42 +63,42 @@
     /**
      * The service that implements this
      */
-    final ResolveInfo mService;
+    private final ResolveInfo mService;
 
     /**
      * Description of the service
      */
-    final String mDescription;
+    private final String mDescription;
 
     /**
      * System Code of the service
      */
-    final String mSystemCode;
+    private final String mSystemCode;
 
     /**
      * System Code of the service registered by API
      */
-    String mDynamicSystemCode;
+    private String mDynamicSystemCode;
 
     /**
      * NFCID2 of the service
      */
-    final String mNfcid2;
+    private final String mNfcid2;
 
     /**
      * NFCID2 of the service registered by API
      */
-    String mDynamicNfcid2;
+    private String mDynamicNfcid2;
 
     /**
      * The uid of the package the service belongs to
      */
-    final int mUid;
+    private final int mUid;
 
     /**
      * LF_T3T_PMM of the service
      */
-    final String mT3tPmm;
+    private final String mT3tPmm;
 
     /**
      * @hide
@@ -104,7 +116,16 @@
         this.mT3tPmm = t3tPmm;
     }
 
-    public NfcFServiceInfo(PackageManager pm, ResolveInfo info)
+    /**
+     * Creates a new NfcFServiceInfo object.
+     *
+     * @param pm packageManager instance
+     * @param info app component info
+     * @throws XmlPullParserException If an error occurs parsing the element.
+     * @throws IOException If an error occurs reading the element.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public NfcFServiceInfo(@NonNull PackageManager pm, @NonNull ResolveInfo info)
             throws XmlPullParserException, IOException {
         ServiceInfo si = info.serviceInfo;
         XmlResourceParser parser = null;
@@ -192,44 +213,107 @@
         mUid = si.applicationInfo.uid;
     }
 
+    /**
+     * Returns the app component corresponding to this NFCF service.
+     *
+     * @return app component for this service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public ComponentName getComponent() {
         return new ComponentName(mService.serviceInfo.packageName,
                 mService.serviceInfo.name);
     }
 
+    /**
+     * Returns the system code corresponding to this service.
+     *
+     * @return system code for this service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getSystemCode() {
         return (mDynamicSystemCode == null ? mSystemCode : mDynamicSystemCode);
     }
 
-    public void setOrReplaceDynamicSystemCode(String systemCode) {
+    /**
+     * Add or replace a system code to this service.
+     * @param systemCode system code to set or replace
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void setDynamicSystemCode(@NonNull String systemCode) {
         mDynamicSystemCode = systemCode;
     }
 
+    /**
+     * Returns NFC ID2.
+     *
+     * @return nfc id2 to return
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getNfcid2() {
         return (mDynamicNfcid2 == null ? mNfcid2 : mDynamicNfcid2);
     }
 
-    public void setOrReplaceDynamicNfcid2(String nfcid2) {
+    /**
+     * Set or replace NFC ID2
+     *
+     * @param nfcid2 NFC ID2 string
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void setDynamicNfcid2(@NonNull String nfcid2) {
         mDynamicNfcid2 = nfcid2;
     }
 
+    /**
+     * Returns description of service.
+     * @return user readable description of service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getDescription() {
         return mDescription;
     }
 
+    /**
+     * Returns uid of service.
+     * @return uid of the service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     public int getUid() {
         return mUid;
     }
 
+    /**
+     * Returns LF_T3T_PMM of the service
+     * @return returns LF_T3T_PMM of the service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
     public String getT3tPmm() {
         return mT3tPmm;
     }
 
-    public CharSequence loadLabel(PackageManager pm) {
+    /**
+     * Load application label for this service.
+     * @param pm packagemanager instance
+     * @return label name corresponding to service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public CharSequence loadLabel(@NonNull PackageManager pm) {
         return mService.loadLabel(pm);
     }
 
-    public Drawable loadIcon(PackageManager pm) {
+    /**
+     * Load application icon for this service.
+     * @param pm packagemanager instance
+     * @return app icon corresponding to service
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    @NonNull
+    public Drawable loadIcon(@NonNull PackageManager pm) {
         return mService.loadIcon(pm);
     }
 
@@ -270,13 +354,15 @@
         return getComponent().hashCode();
     }
 
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     @Override
     public int describeContents() {
         return 0;
     }
 
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         mService.writeToParcel(dest, flags);
         dest.writeString(mDescription);
         dest.writeString(mSystemCode);
@@ -293,7 +379,8 @@
         dest.writeString(mT3tPmm);
     };
 
-    public static final @android.annotation.NonNull Parcelable.Creator<NfcFServiceInfo> CREATOR =
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public static final @NonNull Parcelable.Creator<NfcFServiceInfo> CREATOR =
             new Parcelable.Creator<NfcFServiceInfo>() {
         @Override
         public NfcFServiceInfo createFromParcel(Parcel source) {
@@ -322,7 +409,15 @@
         }
     };
 
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    /**
+     * Dump contents of the service for debugging.
+     * @param fd parcelfiledescriptor instance
+     * @param pw printwriter instance
+     * @param args args for dumping
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void dump(@NonNull ParcelFileDescriptor fd, @NonNull PrintWriter pw,
+                     @NonNull String[] args) {
         pw.println("    " + getComponent()
                 + " (Description: " + getDescription() + ")"
                 + " (UID: " + getUid() + ")");
@@ -332,14 +427,15 @@
     }
 
     /**
-     * Dump debugging info as NfcFServiceInfoProto
+     * Dump debugging info as NfcFServiceInfoProto.
      *
      * If the output belongs to a sub message, the caller is responsible for wrapping this function
      * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
      *
      * @param proto the ProtoOutputStream to write to
      */
-    public void dumpDebug(ProtoOutputStream proto) {
+    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
+    public void dumpDebug(@NonNull ProtoOutputStream proto) {
         Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
         proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
@@ -347,4 +443,3 @@
         proto.write(NfcFServiceInfoProto.T3T_PMM, getT3tPmm());
     }
 }
-
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
new file mode 100644
index 0000000..e3faf39
--- /dev/null
+++ b/core/java/android/nfc/flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.nfc"
+
+flag {
+    name: "enable_nfc_mainline"
+    namespace: "nfc"
+    description: "Flag for NFC mainline changes"
+    bug: "292140387"
+}
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 3f04ca4..8e60102 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -186,6 +186,8 @@
     /**
      * Get the binder transaction observer for this process.
      *
+     * TODO(b/299356196): only applies to Java code, not C++/Rust
+     *
      * @hide
      */
     public static void setObserver(@Nullable BinderInternal.Observer observer) {
@@ -202,6 +204,8 @@
      * that require a result must be sent as {@link IBinder#FLAG_ONEWAY} calls
      * which deliver results through a callback interface.
      *
+     * TODO(b/299355525): only applies to Java code, not C++/Rust
+     *
      * @hide
      */
     public static void setWarnOnBlocking(boolean warnOnBlocking) {
@@ -218,6 +222,8 @@
      * interfaces hosted by package that could be upgraded or replaced,
      * otherwise you risk system instability if that remote interface wedges.
      *
+     * TODO(b/299355525): only applies to Java code, not C++/Rust
+     *
      * @hide
      */
     public static IBinder allowBlocking(IBinder binder) {
@@ -1307,6 +1313,8 @@
             int callingUid) {
         // Make sure the observer won't change while processing a transaction.
         final BinderInternal.Observer observer = sObserver;
+
+        // TODO(b/299356196): observer should also observe transactions in native code
         final CallSession callSession =
                 observer != null ? observer.callStarted(this, code, UNSET_WORKSOURCE) : null;
         // Theoretically, we should call transact, which will call onTransact,
@@ -1329,7 +1337,7 @@
 
         final boolean tracingEnabled = tagEnabled && transactionTraceName != null;
         try {
-            // TODO - this logic should not be in Java - it should be in native
+            // TODO(b/299356201) - this logic should not be in Java - it should be in native
             // code in libbinder so that it works for all binder users.
             final BinderCallHeavyHitterWatcher heavyHitterWatcher = sHeavyHitterWatcher;
             if (heavyHitterWatcher != null && callingUid != -1) {
@@ -1340,9 +1348,9 @@
                 Trace.traceBegin(Trace.TRACE_TAG_AIDL, transactionTraceName);
             }
 
-            // TODO - this logic should not be in Java - it should be in native
-            // code in libbinder so that it works for all binder users. Further,
-            // this should not re-use flags.
+            // TODO(b/299353919) - this logic should not be in Java - it should be
+            // in native code in libbinder so that it works for all binder users.
+            // Further, this should not re-use flags.
             if ((flags & FLAG_COLLECT_NOTED_APP_OPS) != 0 && callingUid != -1) {
                 AppOpsManager.startNotedAppOpsCollection(callingUid);
                 try {
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 1929a4d..5196b17 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -32,7 +32,9 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -613,15 +615,35 @@
      */
     public native boolean transactNative(int code, Parcel data, Parcel reply,
             int flags) throws RemoteException;
+
+    /* This list is to hold strong reference to the death recipients that are waiting for the death
+     * of binder that this proxy references. Previously, the death recipients were strongy
+     * referenced from JNI, but that can cause memory leak (b/298374304) when the application has a
+     * strong reference from the death recipient to the proxy object. The JNI reference is now weak.
+     * And this strong reference is to keep death recipients at least until the proxy is GC'ed. */
+    private List<DeathRecipient> mDeathRecipients = Collections.synchronizedList(new ArrayList<>());
+
     /**
      * See {@link IBinder#linkToDeath(DeathRecipient, int)}
      */
-    public native void linkToDeath(DeathRecipient recipient, int flags)
-            throws RemoteException;
+    public void linkToDeath(DeathRecipient recipient, int flags)
+            throws RemoteException {
+        linkToDeathNative(recipient, flags);
+        mDeathRecipients.add(recipient);
+    }
+
     /**
      * See {@link IBinder#unlinkToDeath}
      */
-    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
+    public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
+        mDeathRecipients.remove(recipient);
+        return unlinkToDeathNative(recipient, flags);
+    }
+
+    private native void linkToDeathNative(DeathRecipient recipient, int flags)
+            throws RemoteException;
+
+    private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags);
 
     /**
      * Perform a dump on the remote object
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index ece069f..c4660c4 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -111,7 +111,7 @@
     /**
      *  Regular expression to match all IANA top-level domains.
      *
-     *  List accurate as of 2015/11/24.  List taken from:
+     *  List accurate as of 2023/09/11.  List taken from:
      *  http://data.iana.org/TLD/tlds-alpha-by-domain.txt
      *  This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
      *
@@ -119,121 +119,167 @@
      */
     static final String IANA_TOP_LEVEL_DOMAINS =
         "(?:"
-        + "(?:aaa|aarp|abb|abbott|abogado|academy|accenture|accountant|accountants|aco|active"
-        + "|actor|ads|adult|aeg|aero|afl|agency|aig|airforce|airtel|allfinanz|alsace|amica|amsterdam"
-        + "|android|apartments|app|apple|aquarelle|aramco|archi|army|arpa|arte|asia|associates"
-        + "|attorney|auction|audio|auto|autos|axa|azure|a[cdefgilmoqrstuwxz])"
-        + "|(?:band|bank|bar|barcelona|barclaycard|barclays|bargains|bauhaus|bayern|bbc|bbva"
-        + "|bcn|beats|beer|bentley|berlin|best|bet|bharti|bible|bid|bike|bing|bingo|bio|biz|black"
-        + "|blackfriday|bloomberg|blue|bms|bmw|bnl|bnpparibas|boats|bom|bond|boo|boots|boutique"
-        + "|bradesco|bridgestone|broadway|broker|brother|brussels|budapest|build|builders|business"
-        + "|buzz|bzh|b[abdefghijmnorstvwyz])"
-        + "|(?:cab|cafe|cal|camera|camp|cancerresearch|canon|capetown|capital|car|caravan|cards"
-        + "|care|career|careers|cars|cartier|casa|cash|casino|cat|catering|cba|cbn|ceb|center|ceo"
-        + "|cern|cfa|cfd|chanel|channel|chat|cheap|chloe|christmas|chrome|church|cipriani|cisco"
-        + "|citic|city|cityeats|claims|cleaning|click|clinic|clothing|cloud|club|clubmed|coach"
-        + "|codes|coffee|college|cologne|com|commbank|community|company|computer|comsec|condos"
-        + "|construction|consulting|contractors|cooking|cool|coop|corsica|country|coupons|courses"
-        + "|credit|creditcard|creditunion|cricket|crown|crs|cruises|csc|cuisinella|cymru|cyou|c[acdfghiklmnoruvwxyz])"
-        + "|(?:dabur|dad|dance|date|dating|datsun|day|dclk|deals|degree|delivery|dell|delta"
-        + "|democrat|dental|dentist|desi|design|dev|diamonds|diet|digital|direct|directory|discount"
-        + "|dnp|docs|dog|doha|domains|doosan|download|drive|durban|dvag|d[ejkmoz])"
-        + "|(?:earth|eat|edu|education|email|emerck|energy|engineer|engineering|enterprises"
-        + "|epson|equipment|erni|esq|estate|eurovision|eus|events|everbank|exchange|expert|exposed"
-        + "|express|e[cegrstu])"
-        + "|(?:fage|fail|fairwinds|faith|family|fan|fans|farm|fashion|feedback|ferrero|film"
-        + "|final|finance|financial|firmdale|fish|fishing|fit|fitness|flights|florist|flowers|flsmidth"
-        + "|fly|foo|football|forex|forsale|forum|foundation|frl|frogans|fund|furniture|futbol|fyi"
-        + "|f[ijkmor])"
-        + "|(?:gal|gallery|game|garden|gbiz|gdn|gea|gent|genting|ggee|gift|gifts|gives|giving"
-        + "|glass|gle|global|globo|gmail|gmo|gmx|gold|goldpoint|golf|goo|goog|google|gop|gov|grainger"
-        + "|graphics|gratis|green|gripe|group|gucci|guge|guide|guitars|guru|g[abdefghilmnpqrstuwy])"
-        + "|(?:hamburg|hangout|haus|healthcare|help|here|hermes|hiphop|hitachi|hiv|hockey|holdings"
-        + "|holiday|homedepot|homes|honda|horse|host|hosting|hoteles|hotmail|house|how|hsbc|hyundai"
-        + "|h[kmnrtu])"
-        + "|(?:ibm|icbc|ice|icu|ifm|iinet|immo|immobilien|industries|infiniti|info|ing|ink|institute"
-        + "|insure|int|international|investments|ipiranga|irish|ist|istanbul|itau|iwc|i[delmnoqrst])"
-        + "|(?:jaguar|java|jcb|jetzt|jewelry|jlc|jll|jobs|joburg|jprs|juegos|j[emop])"
-        + "|(?:kaufen|kddi|kia|kim|kinder|kitchen|kiwi|koeln|komatsu|krd|kred|kyoto|k[eghimnprwyz])"
-        + "|(?:lacaixa|lancaster|land|landrover|lasalle|lat|latrobe|law|lawyer|lds|lease|leclerc"
-        + "|legal|lexus|lgbt|liaison|lidl|life|lifestyle|lighting|limited|limo|linde|link|live"
-        + "|lixil|loan|loans|lol|london|lotte|lotto|love|ltd|ltda|lupin|luxe|luxury|l[abcikrstuvy])"
-        + "|(?:madrid|maif|maison|man|management|mango|market|marketing|markets|marriott|mba"
-        + "|media|meet|melbourne|meme|memorial|men|menu|meo|miami|microsoft|mil|mini|mma|mobi|moda"
-        + "|moe|moi|mom|monash|money|montblanc|mormon|mortgage|moscow|motorcycles|mov|movie|movistar"
-        + "|mtn|mtpc|mtr|museum|mutuelle|m[acdeghklmnopqrstuvwxyz])"
-        + "|(?:nadex|nagoya|name|navy|nec|net|netbank|network|neustar|new|news|nexus|ngo|nhk"
-        + "|nico|ninja|nissan|nokia|nra|nrw|ntt|nyc|n[acefgilopruz])"
-        + "|(?:obi|office|okinawa|omega|one|ong|onl|online|ooo|oracle|orange|org|organic|osaka"
-        + "|otsuka|ovh|om)"
-        + "|(?:page|panerai|paris|partners|parts|party|pet|pharmacy|philips|photo|photography"
-        + "|photos|physio|piaget|pics|pictet|pictures|ping|pink|pizza|place|play|playstation|plumbing"
-        + "|plus|pohl|poker|porn|post|praxi|press|pro|prod|productions|prof|properties|property"
-        + "|protection|pub|p[aefghklmnrstwy])"
-        + "|(?:qpon|quebec|qa)"
-        + "|(?:racing|realtor|realty|recipes|red|redstone|rehab|reise|reisen|reit|ren|rent|rentals"
-        + "|repair|report|republican|rest|restaurant|review|reviews|rich|ricoh|rio|rip|rocher|rocks"
-        + "|rodeo|rsvp|ruhr|run|rwe|ryukyu|r[eosuw])"
-        + "|(?:saarland|sakura|sale|samsung|sandvik|sandvikcoromant|sanofi|sap|sapo|sarl|saxo"
-        + "|sbs|sca|scb|schmidt|scholarships|school|schule|schwarz|science|scor|scot|seat|security"
-        + "|seek|sener|services|seven|sew|sex|sexy|shiksha|shoes|show|shriram|singles|site|ski"
-        + "|sky|skype|sncf|soccer|social|software|sohu|solar|solutions|sony|soy|space|spiegel|spreadbetting"
-        + "|srl|stada|starhub|statoil|stc|stcgroup|stockholm|studio|study|style|sucks|supplies"
-        + "|supply|support|surf|surgery|suzuki|swatch|swiss|sydney|systems|s[abcdeghijklmnortuvxyz])"
-        + "|(?:tab|taipei|tatamotors|tatar|tattoo|tax|taxi|team|tech|technology|tel|telefonica"
-        + "|temasek|tennis|thd|theater|theatre|tickets|tienda|tips|tires|tirol|today|tokyo|tools"
-        + "|top|toray|toshiba|tours|town|toyota|toys|trade|trading|training|travel|trust|tui|t[cdfghjklmnortvwz])"
-        + "|(?:ubs|university|uno|uol|u[agksyz])"
-        + "|(?:vacations|vana|vegas|ventures|versicherung|vet|viajes|video|villas|vin|virgin"
-        + "|vision|vista|vistaprint|viva|vlaanderen|vodka|vote|voting|voto|voyage|v[aceginu])"
-        + "|(?:wales|walter|wang|watch|webcam|website|wed|wedding|weir|whoswho|wien|wiki|williamhill"
-        + "|win|windows|wine|wme|work|works|world|wtc|wtf|w[fs])"
-        + "|(?:\u03b5\u03bb|\u0431\u0435\u043b|\u0434\u0435\u0442\u0438|\u043a\u043e\u043c|\u043c\u043a\u0434"
+        + "(?:aaa|aarp|abb|abbott|abbvie|abc|able|abogado|abudhabi|academy|accenture|accountant"
+        + "|accountants|aco|actor|ads|adult|aeg|aero|aetna|afl|africa|agakhan|agency|aig|airbus"
+        + "|airforce|airtel|akdn|alibaba|alipay|allfinanz|allstate|ally|alsace|alstom|amazon|americanexpress"
+        + "|americanfamily|amex|amfam|amica|amsterdam|analytics|android|anquan|anz|aol|apartments"
+        + "|app|apple|aquarelle|arab|aramco|archi|army|arpa|art|arte|asda|asia|associates|athleta"
+        + "|attorney|auction|audi|audible|audio|auspost|author|auto|autos|avianca|aws|axa|azure"
+        + "|a[cdefgilmoqrstuwxz])"
+        + "|(?:baby|baidu|banamex|bananarepublic|band|bank|bar|barcelona|barclaycard|barclays"
+        + "|barefoot|bargains|baseball|basketball|bauhaus|bayern|bbc|bbt|bbva|bcg|bcn|beats|beauty"
+        + "|beer|bentley|berlin|best|bestbuy|bet|bharti|bible|bid|bike|bing|bingo|bio|biz|black"
+        + "|blackfriday|blockbuster|blog|bloomberg|blue|bms|bmw|bnpparibas|boats|boehringer|bofa"
+        + "|bom|bond|boo|book|booking|bosch|bostik|boston|bot|boutique|box|bradesco|bridgestone"
+        + "|broadway|broker|brother|brussels|build|builders|business|buy|buzz|bzh|b[abdefghijmnorstvwyz])"
+        + "|(?:cab|cafe|cal|call|calvinklein|cam|camera|camp|canon|capetown|capital|capitalone"
+        + "|car|caravan|cards|care|career|careers|cars|casa|case|cash|casino|cat|catering|catholic"
+        + "|cba|cbn|cbre|cbs|center|ceo|cern|cfa|cfd|chanel|channel|charity|chase|chat|cheap|chintai"
+        + "|christmas|chrome|church|cipriani|circle|cisco|citadel|citi|citic|city|cityeats|claims"
+        + "|cleaning|click|clinic|clinique|clothing|cloud|club|clubmed|coach|codes|coffee|college"
+        + "|cologne|com|comcast|commbank|community|company|compare|computer|comsec|condos|construction"
+        + "|consulting|contact|contractors|cooking|cool|coop|corsica|country|coupon|coupons|courses"
+        + "|cpa|credit|creditcard|creditunion|cricket|crown|crs|cruise|cruises|cuisinella|cymru"
+        + "|cyou|c[acdfghiklmnoruvwxyz])"
+        + "|(?:dabur|dad|dance|data|date|dating|datsun|day|dclk|dds|deal|dealer|deals|degree"
+        + "|delivery|dell|deloitte|delta|democrat|dental|dentist|desi|design|dev|dhl|diamonds|diet"
+        + "|digital|direct|directory|discount|discover|dish|diy|dnp|docs|doctor|dog|domains|dot"
+        + "|download|drive|dtv|dubai|dunlop|dupont|durban|dvag|dvr|d[ejkmoz])"
+        + "|(?:earth|eat|eco|edeka|edu|education|email|emerck|energy|engineer|engineering|enterprises"
+        + "|epson|equipment|ericsson|erni|esq|estate|etisalat|eurovision|eus|events|exchange|expert"
+        + "|exposed|express|extraspace|e[cegrstu])"
+        + "|(?:fage|fail|fairwinds|faith|family|fan|fans|farm|farmers|fashion|fast|fedex|feedback"
+        + "|ferrari|ferrero|fidelity|fido|film|final|finance|financial|fire|firestone|firmdale"
+        + "|fish|fishing|fit|fitness|flickr|flights|flir|florist|flowers|fly|foo|food|football"
+        + "|ford|forex|forsale|forum|foundation|fox|free|fresenius|frl|frogans|frontdoor|frontier"
+        + "|ftr|fujitsu|fun|fund|furniture|futbol|fyi|f[ijkmor])"
+        + "|(?:gal|gallery|gallo|gallup|game|games|gap|garden|gay|gbiz|gdn|gea|gent|genting"
+        + "|george|ggee|gift|gifts|gives|giving|glass|gle|global|globo|gmail|gmbh|gmo|gmx|godaddy"
+        + "|gold|goldpoint|golf|goo|goodyear|goog|google|gop|got|gov|grainger|graphics|gratis|green"
+        + "|gripe|grocery|group|guardian|gucci|guge|guide|guitars|guru|g[abdefghilmnpqrstuwy])"
+        + "|(?:hair|hamburg|hangout|haus|hbo|hdfc|hdfcbank|health|healthcare|help|helsinki|here"
+        + "|hermes|hiphop|hisamitsu|hitachi|hiv|hkt|hockey|holdings|holiday|homedepot|homegoods"
+        + "|homes|homesense|honda|horse|hospital|host|hosting|hot|hotels|hotmail|house|how|hsbc"
+        + "|hughes|hyatt|hyundai|h[kmnrtu])"
+        + "|(?:ibm|icbc|ice|icu|ieee|ifm|ikano|imamat|imdb|immo|immobilien|inc|industries|infiniti"
+        + "|info|ing|ink|institute|insurance|insure|int|international|intuit|investments|ipiranga"
+        + "|irish|ismaili|ist|istanbul|itau|itv|i[delmnoqrst])"
+        + "|(?:jaguar|java|jcb|jeep|jetzt|jewelry|jio|jll|jmp|jnj|jobs|joburg|jot|joy|jpmorgan"
+        + "|jprs|juegos|juniper|j[emop])"
+        + "|(?:kaufen|kddi|kerryhotels|kerrylogistics|kerryproperties|kfh|kia|kids|kim|kinder"
+        + "|kindle|kitchen|kiwi|koeln|komatsu|kosher|kpmg|kpn|krd|kred|kuokgroup|kyoto|k[eghimnprwyz])"
+        + "|(?:lacaixa|lamborghini|lamer|lancaster|land|landrover|lanxess|lasalle|lat|latino"
+        + "|latrobe|law|lawyer|lds|lease|leclerc|lefrak|legal|lego|lexus|lgbt|lidl|life|lifeinsurance"
+        + "|lifestyle|lighting|like|lilly|limited|limo|lincoln|link|lipsy|live|living|llc|llp|loan"
+        + "|loans|locker|locus|lol|london|lotte|lotto|love|lpl|lplfinancial|ltd|ltda|lundbeck|luxe"
+        + "|luxury|l[abcikrstuvy])"
+        + "|(?:madrid|maif|maison|makeup|man|management|mango|map|market|marketing|markets|marriott"
+        + "|marshalls|mattel|mba|mckinsey|med|media|meet|melbourne|meme|memorial|men|menu|merckmsd"
+        + "|miami|microsoft|mil|mini|mint|mit|mitsubishi|mlb|mls|mma|mobi|mobile|moda|moe|moi|mom"
+        + "|monash|money|monster|mormon|mortgage|moscow|moto|motorcycles|mov|movie|msd|mtn|mtr"
+        + "|museum|music|m[acdeghklmnopqrstuvwxyz])"
+        + "|(?:nab|nagoya|name|natura|navy|nba|nec|net|netbank|netflix|network|neustar|new|news"
+        + "|next|nextdirect|nexus|nfl|ngo|nhk|nico|nike|nikon|ninja|nissan|nissay|nokia|norton"
+        + "|now|nowruz|nowtv|nra|nrw|ntt|nyc|n[acefgilopruz])"
+        + "|(?:obi|observer|office|okinawa|olayan|olayangroup|oldnavy|ollo|omega|one|ong|onl"
+        + "|online|ooo|open|oracle|orange|org|organic|origins|osaka|otsuka|ott|ovh|om)"
+        + "|(?:page|panasonic|paris|pars|partners|parts|party|pay|pccw|pet|pfizer|pharmacy|phd"
+        + "|philips|phone|photo|photography|photos|physio|pics|pictet|pictures|pid|pin|ping|pink"
+        + "|pioneer|pizza|place|play|playstation|plumbing|plus|pnc|pohl|poker|politie|porn|post"
+        + "|pramerica|praxi|press|prime|pro|prod|productions|prof|progressive|promo|properties"
+        + "|property|protection|pru|prudential|pub|pwc|p[aefghklmnrstwy])"
+        + "|(?:qpon|quebec|quest|qa)"
+        + "|(?:racing|radio|read|realestate|realtor|realty|recipes|red|redstone|redumbrella"
+        + "|rehab|reise|reisen|reit|reliance|ren|rent|rentals|repair|report|republican|rest|restaurant"
+        + "|review|reviews|rexroth|rich|richardli|ricoh|ril|rio|rip|rocher|rocks|rodeo|rogers|room"
+        + "|rsvp|rugby|ruhr|run|rwe|ryukyu|r[eosuw])"
+        + "|(?:saarland|safe|safety|sakura|sale|salon|samsclub|samsung|sandvik|sandvikcoromant"
+        + "|sanofi|sap|sarl|sas|save|saxo|sbi|sbs|sca|scb|schaeffler|schmidt|scholarships|school"
+        + "|schule|schwarz|science|scot|search|seat|secure|security|seek|select|sener|services"
+        + "|seven|sew|sex|sexy|sfr|shangrila|sharp|shaw|shell|shia|shiksha|shoes|shop|shopping"
+        + "|shouji|show|showtime|silk|sina|singles|site|ski|skin|sky|skype|sling|smart|smile|sncf"
+        + "|soccer|social|softbank|software|sohu|solar|solutions|song|sony|soy|spa|space|sport"
+        + "|spot|srl|stada|staples|star|statebank|statefarm|stc|stcgroup|stockholm|storage|store"
+        + "|stream|studio|study|style|sucks|supplies|supply|support|surf|surgery|suzuki|swatch"
+        + "|swiss|sydney|systems|s[abcdeghijklmnorstuvxyz])"
+        + "|(?:tab|taipei|talk|taobao|target|tatamotors|tatar|tattoo|tax|taxi|tci|tdk|team|tech"
+        + "|technology|tel|temasek|tennis|teva|thd|theater|theatre|tiaa|tickets|tienda|tips|tires"
+        + "|tirol|tjmaxx|tjx|tkmaxx|tmall|today|tokyo|tools|top|toray|toshiba|total|tours|town"
+        + "|toyota|toys|trade|trading|training|travel|travelers|travelersinsurance|trust|trv|tube"
+        + "|tui|tunes|tushu|tvs|t[cdfghjklmnortvwz])"
+        + "|(?:ubank|ubs|unicom|university|uno|uol|ups|u[agksyz])"
+        + "|(?:vacations|vana|vanguard|vegas|ventures|verisign|versicherung|vet|viajes|video"
+        + "|vig|viking|villas|vin|vip|virgin|visa|vision|viva|vivo|vlaanderen|vodka|volkswagen"
+        + "|volvo|vote|voting|voto|voyage|v[aceginu])"
+        + "|(?:wales|walmart|walter|wang|wanggou|watch|watches|weather|weatherchannel|webcam"
+        + "|weber|website|wed|wedding|weibo|weir|whoswho|wien|wiki|williamhill|win|windows|wine"
+        + "|winners|wme|wolterskluwer|woodside|work|works|world|wow|wtc|wtf|w[fs])"
+        + "|(?:\u03b5\u03bb|\u03b5\u03c5|\u0431\u0433|\u0431\u0435\u043b|\u0434\u0435\u0442\u0438"
+        + "|\u0435\u044e|\u043a\u0430\u0442\u043e\u043b\u0438\u043a|\u043a\u043e\u043c|\u043c\u043a\u0434"
         + "|\u043c\u043e\u043d|\u043c\u043e\u0441\u043a\u0432\u0430|\u043e\u043d\u043b\u0430\u0439\u043d"
         + "|\u043e\u0440\u0433|\u0440\u0443\u0441|\u0440\u0444|\u0441\u0430\u0439\u0442|\u0441\u0440\u0431"
-        + "|\u0443\u043a\u0440|\u049b\u0430\u0437|\u0570\u0561\u0575|\u05e7\u05d5\u05dd|\u0627\u0631\u0627\u0645\u0643\u0648"
-        + "|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629"
-        + "|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0627\u06cc\u0631\u0627\u0646"
-        + "|\u0628\u0627\u0632\u0627\u0631|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633"
-        + "|\u0633\u0648\u062f\u0627\u0646|\u0633\u0648\u0631\u064a\u0629|\u0634\u0628\u0643\u0629"
-        + "|\u0639\u0631\u0627\u0642|\u0639\u0645\u0627\u0646|\u0641\u0644\u0633\u0637\u064a\u0646"
-        + "|\u0642\u0637\u0631|\u0643\u0648\u0645|\u0645\u0635\u0631|\u0645\u0644\u064a\u0633\u064a\u0627"
-        + "|\u0645\u0648\u0642\u0639|\u0915\u0949\u092e|\u0928\u0947\u091f|\u092d\u093e\u0930\u0924"
-        + "|\u0938\u0902\u0917\u0920\u0928|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4"
-        + "|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd"
-        + "|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e04\u0e2d\u0e21|\u0e44\u0e17\u0e22"
-        + "|\u10d2\u10d4|\u307f\u3093\u306a|\u30b0\u30fc\u30b0\u30eb|\u30b3\u30e0|\u4e16\u754c"
-        + "|\u4e2d\u4fe1|\u4e2d\u56fd|\u4e2d\u570b|\u4e2d\u6587\u7f51|\u4f01\u4e1a|\u4f5b\u5c71"
-        + "|\u4fe1\u606f|\u5065\u5eb7|\u516b\u5366|\u516c\u53f8|\u516c\u76ca|\u53f0\u6e7e|\u53f0\u7063"
-        + "|\u5546\u57ce|\u5546\u5e97|\u5546\u6807|\u5728\u7ebf|\u5927\u62ff|\u5a31\u4e50|\u5de5\u884c"
-        + "|\u5e7f\u4e1c|\u6148\u5584|\u6211\u7231\u4f60|\u624b\u673a|\u653f\u52a1|\u653f\u5e9c"
-        + "|\u65b0\u52a0\u5761|\u65b0\u95fb|\u65f6\u5c1a|\u673a\u6784|\u6de1\u9a6c\u9521|\u6e38\u620f"
-        + "|\u70b9\u770b|\u79fb\u52a8|\u7ec4\u7ec7\u673a\u6784|\u7f51\u5740|\u7f51\u5e97|\u7f51\u7edc"
-        + "|\u8c37\u6b4c|\u96c6\u56e2|\u98de\u5229\u6d66|\u9910\u5385|\u9999\u6e2f|\ub2f7\ub137"
-        + "|\ub2f7\ucef4|\uc0bc\uc131|\ud55c\uad6d|xbox"
-        + "|xerox|xin|xn\\-\\-11b4c3d|xn\\-\\-1qqw23a|xn\\-\\-30rr7y|xn\\-\\-3bst00m|xn\\-\\-3ds443g"
-        + "|xn\\-\\-3e0b707e|xn\\-\\-3pxu8k|xn\\-\\-42c2d9a|xn\\-\\-45brj9c|xn\\-\\-45q11c|xn\\-\\-4gbrim"
-        + "|xn\\-\\-55qw42g|xn\\-\\-55qx5d|xn\\-\\-6frz82g|xn\\-\\-6qq986b3xl|xn\\-\\-80adxhks"
-        + "|xn\\-\\-80ao21a|xn\\-\\-80asehdb|xn\\-\\-80aswg|xn\\-\\-90a3ac|xn\\-\\-90ais|xn\\-\\-9dbq2a"
-        + "|xn\\-\\-9et52u|xn\\-\\-b4w605ferd|xn\\-\\-c1avg|xn\\-\\-c2br7g|xn\\-\\-cg4bki|xn\\-\\-clchc0ea0b2g2a9gcd"
-        + "|xn\\-\\-czr694b|xn\\-\\-czrs0t|xn\\-\\-czru2d|xn\\-\\-d1acj3b|xn\\-\\-d1alf|xn\\-\\-efvy88h"
-        + "|xn\\-\\-estv75g|xn\\-\\-fhbei|xn\\-\\-fiq228c5hs|xn\\-\\-fiq64b|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s"
-        + "|xn\\-\\-fjq720a|xn\\-\\-flw351e|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-gecrj9c"
-        + "|xn\\-\\-h2brj9c|xn\\-\\-hxt814e|xn\\-\\-i1b6b1a6a2e|xn\\-\\-imr513n|xn\\-\\-io0a7i"
-        + "|xn\\-\\-j1aef|xn\\-\\-j1amh|xn\\-\\-j6w193g|xn\\-\\-kcrx77d1x4a|xn\\-\\-kprw13d|xn\\-\\-kpry57d"
+        + "|\u0443\u043a\u0440|\u049b\u0430\u0437|\u0570\u0561\u0575|\u05d9\u05e9\u05e8\u05d0\u05dc"
+        + "|\u05e7\u05d5\u05dd|\u0627\u0628\u0648\u0638\u0628\u064a|\u0627\u062a\u0635\u0627\u0644\u0627\u062a"
+        + "|\u0627\u0631\u0627\u0645\u0643\u0648|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u0628\u062d\u0631\u064a\u0646"
+        + "|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629"
+        + "|\u0627\u0644\u0639\u0644\u064a\u0627\u0646|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a"
+        + "|\u0627\u06cc\u0631\u0627\u0646|\u0628\u0627\u0631\u062a|\u0628\u0627\u0632\u0627\u0631"
+        + "|\u0628\u064a\u062a\u0643|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u062f\u0627\u0646"
+        + "|\u0633\u0648\u0631\u064a\u0629|\u0634\u0628\u0643\u0629|\u0639\u0631\u0627\u0642|\u0639\u0631\u0628"
+        + "|\u0639\u0645\u0627\u0646|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0643\u0627\u062b\u0648\u0644\u064a\u0643"
+        + "|\u0643\u0648\u0645|\u0645\u0635\u0631|\u0645\u0644\u064a\u0633\u064a\u0627|\u0645\u0648\u0631\u064a\u062a\u0627\u0646\u064a\u0627"
+        + "|\u0645\u0648\u0642\u0639|\u0647\u0645\u0631\u0627\u0647|\u067e\u0627\u06a9\u0633\u062a\u0627\u0646"
+        + "|\u0680\u0627\u0631\u062a|\u0915\u0949\u092e|\u0928\u0947\u091f|\u092d\u093e\u0930\u0924"
+        + "|\u092d\u093e\u0930\u0924\u092e\u094d|\u092d\u093e\u0930\u094b\u0924|\u0938\u0902\u0917\u0920\u0928"
+        + "|\u09ac\u09be\u0982\u09b2\u09be|\u09ad\u09be\u09b0\u09a4|\u09ad\u09be\u09f0\u09a4|\u0a2d\u0a3e\u0a30\u0a24"
+        + "|\u0aad\u0abe\u0ab0\u0aa4|\u0b2d\u0b3e\u0b30\u0b24|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe"
+        + "|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd"
+        + "|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0cad\u0cbe\u0cb0\u0ca4|\u0d2d\u0d3e\u0d30\u0d24\u0d02"
+        + "|\u0dbd\u0d82\u0d9a\u0dcf|\u0e04\u0e2d\u0e21|\u0e44\u0e17\u0e22|\u0ea5\u0eb2\u0ea7|\u10d2\u10d4"
+        + "|\u307f\u3093\u306a|\u30a2\u30de\u30be\u30f3|\u30af\u30e9\u30a6\u30c9|\u30b0\u30fc\u30b0\u30eb"
+        + "|\u30b3\u30e0|\u30b9\u30c8\u30a2|\u30bb\u30fc\u30eb|\u30d5\u30a1\u30c3\u30b7\u30e7\u30f3"
+        + "|\u30dd\u30a4\u30f3\u30c8|\u4e16\u754c|\u4e2d\u4fe1|\u4e2d\u56fd|\u4e2d\u570b|\u4e2d\u6587\u7f51"
+        + "|\u4e9a\u9a6c\u900a|\u4f01\u4e1a|\u4f5b\u5c71|\u4fe1\u606f|\u5065\u5eb7|\u516b\u5366"
+        + "|\u516c\u53f8|\u516c\u76ca|\u53f0\u6e7e|\u53f0\u7063|\u5546\u57ce|\u5546\u5e97|\u5546\u6807"
+        + "|\u5609\u91cc|\u5609\u91cc\u5927\u9152\u5e97|\u5728\u7ebf|\u5927\u62ff|\u5929\u4e3b\u6559"
+        + "|\u5a31\u4e50|\u5bb6\u96fb|\u5e7f\u4e1c|\u5fae\u535a|\u6148\u5584|\u6211\u7231\u4f60"
+        + "|\u624b\u673a|\u62db\u8058|\u653f\u52a1|\u653f\u5e9c|\u65b0\u52a0\u5761|\u65b0\u95fb"
+        + "|\u65f6\u5c1a|\u66f8\u7c4d|\u673a\u6784|\u6de1\u9a6c\u9521|\u6e38\u620f|\u6fb3\u9580"
+        + "|\u70b9\u770b|\u79fb\u52a8|\u7ec4\u7ec7\u673a\u6784|\u7f51\u5740|\u7f51\u5e97|\u7f51\u7ad9"
+        + "|\u7f51\u7edc|\u8054\u901a|\u8c37\u6b4c|\u8d2d\u7269|\u901a\u8ca9|\u96c6\u56e2|\u96fb\u8a0a\u76c8\u79d1"
+        + "|\u98de\u5229\u6d66|\u98df\u54c1|\u9910\u5385|\u9999\u683c\u91cc\u62c9|\u9999\u6e2f"
+        + "|\ub2f7\ub137|\ub2f7\ucef4|\uc0bc\uc131|\ud55c\uad6d"
+        + "|xbox|xerox|xfinity|xihuan|xin|xn\\-\\-11b4c3d|xn\\-\\-1ck2e1b|xn\\-\\-1qqw23a|xn\\-\\-2scrj9c"
+        + "|xn\\-\\-30rr7y|xn\\-\\-3bst00m|xn\\-\\-3ds443g|xn\\-\\-3e0b707e|xn\\-\\-3hcrj9c|xn\\-\\-3pxu8k"
+        + "|xn\\-\\-42c2d9a|xn\\-\\-45br5cyl|xn\\-\\-45brj9c|xn\\-\\-45q11c|xn\\-\\-4dbrk0ce|xn\\-\\-4gbrim"
+        + "|xn\\-\\-54b7fta0cc|xn\\-\\-55qw42g|xn\\-\\-55qx5d|xn\\-\\-5su34j936bgsg|xn\\-\\-5tzm5g"
+        + "|xn\\-\\-6frz82g|xn\\-\\-6qq986b3xl|xn\\-\\-80adxhks|xn\\-\\-80ao21a|xn\\-\\-80aqecdr1a"
+        + "|xn\\-\\-80asehdb|xn\\-\\-80aswg|xn\\-\\-8y0a063a|xn\\-\\-90a3ac|xn\\-\\-90ae|xn\\-\\-90ais"
+        + "|xn\\-\\-9dbq2a|xn\\-\\-9et52u|xn\\-\\-9krt00a|xn\\-\\-b4w605ferd|xn\\-\\-bck1b9a5dre4c"
+        + "|xn\\-\\-c1avg|xn\\-\\-c2br7g|xn\\-\\-cck2b3b|xn\\-\\-cckwcxetd|xn\\-\\-cg4bki|xn\\-\\-clchc0ea0b2g2a9gcd"
+        + "|xn\\-\\-czr694b|xn\\-\\-czrs0t|xn\\-\\-czru2d|xn\\-\\-d1acj3b|xn\\-\\-d1alf|xn\\-\\-e1a4c"
+        + "|xn\\-\\-eckvdtc9d|xn\\-\\-efvy88h|xn\\-\\-fct429k|xn\\-\\-fhbei|xn\\-\\-fiq228c5hs"
+        + "|xn\\-\\-fiq64b|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fjq720a|xn\\-\\-flw351e|xn\\-\\-fpcrj9c3d"
+        + "|xn\\-\\-fzc2c9e2c|xn\\-\\-fzys8d69uvgm|xn\\-\\-g2xx48c|xn\\-\\-gckr3f0f|xn\\-\\-gecrj9c"
+        + "|xn\\-\\-gk3at1e|xn\\-\\-h2breg3eve|xn\\-\\-h2brj9c|xn\\-\\-h2brj9c8c|xn\\-\\-hxt814e"
+        + "|xn\\-\\-i1b6b1a6a2e|xn\\-\\-imr513n|xn\\-\\-io0a7i|xn\\-\\-j1aef|xn\\-\\-j1amh|xn\\-\\-j6w193g"
+        + "|xn\\-\\-jlq480n2rg|xn\\-\\-jvr189m|xn\\-\\-kcrx77d1x4a|xn\\-\\-kprw13d|xn\\-\\-kpry57d"
         + "|xn\\-\\-kput3i|xn\\-\\-l1acc|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgb9awbf|xn\\-\\-mgba3a3ejt"
-        + "|xn\\-\\-mgba3a4f16a|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbab2bd|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e"
-        + "|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-mgbpl2fh|xn\\-\\-mgbtx2b|xn\\-\\-mgbx4cd0ab"
-        + "|xn\\-\\-mk1bu44c|xn\\-\\-mxtq1m|xn\\-\\-ngbc5azd|xn\\-\\-node|xn\\-\\-nqv7f|xn\\-\\-nqv7fs00ema"
-        + "|xn\\-\\-nyqy26a|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1acf|xn\\-\\-p1ai|xn\\-\\-pgbs0dh"
-        + "|xn\\-\\-pssy2u|xn\\-\\-q9jyb4c|xn\\-\\-qcka1pmc|xn\\-\\-qxam|xn\\-\\-rhqv96g|xn\\-\\-s9brj9c"
-        + "|xn\\-\\-ses554g|xn\\-\\-t60b56a|xn\\-\\-tckwe|xn\\-\\-unup4y|xn\\-\\-vermgensberater\\-ctb"
-        + "|xn\\-\\-vermgensberatung\\-pwb|xn\\-\\-vhquv|xn\\-\\-vuq861b|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a"
+        + "|xn\\-\\-mgba3a4f16a|xn\\-\\-mgba7c0bbn0a|xn\\-\\-mgbaakc7dvf|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbab2bd"
+        + "|xn\\-\\-mgbah1a3hjkrd|xn\\-\\-mgbai9azgqp6j|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a|xn\\-\\-mgbbh1a71e"
+        + "|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgbca7dzdo|xn\\-\\-mgbcpq6gpa1a|xn\\-\\-mgberp4a5d4ar|xn\\-\\-mgbgu82a"
+        + "|xn\\-\\-mgbi4ecexp|xn\\-\\-mgbpl2fh|xn\\-\\-mgbt3dhd|xn\\-\\-mgbtx2b|xn\\-\\-mgbx4cd0ab"
+        + "|xn\\-\\-mix891f|xn\\-\\-mk1bu44c|xn\\-\\-mxtq1m|xn\\-\\-ngbc5azd|xn\\-\\-ngbe9e0a|xn\\-\\-ngbrx"
+        + "|xn\\-\\-node|xn\\-\\-nqv7f|xn\\-\\-nqv7fs00ema|xn\\-\\-nyqy26a|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl"
+        + "|xn\\-\\-otu796d|xn\\-\\-p1acf|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-pssy2u|xn\\-\\-q7ce6a"
+        + "|xn\\-\\-q9jyb4c|xn\\-\\-qcka1pmc|xn\\-\\-qxa6a|xn\\-\\-qxam|xn\\-\\-rhqv96g|xn\\-\\-rovu88b"
+        + "|xn\\-\\-rvc1e0am3e|xn\\-\\-s9brj9c|xn\\-\\-ses554g|xn\\-\\-t60b56a|xn\\-\\-tckwe|xn\\-\\-tiq49xqyj"
+        + "|xn\\-\\-unup4y|xn\\-\\-vermgensberater\\-ctb|xn\\-\\-vermgensberatung\\-pwb|xn\\-\\-vhquv"
+        + "|xn\\-\\-vuq861b|xn\\-\\-w4r85el8fhu5dnra|xn\\-\\-w4rs40l|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a"
         + "|xn\\-\\-xhq521b|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-y9a3aq|xn\\-\\-yfro4i67o"
-        + "|xn\\-\\-ygbi2ammx|xn\\-\\-zfr164b|xperia|xxx|xyz)"
-        + "|(?:yachts|yamaxun|yandex|yodobashi|yoga|yokohama|youtube|y[et])"
-        + "|(?:zara|zip|zone|zuerich|z[amw]))";
-
+        + "|xn\\-\\-ygbi2ammx|xn\\-\\-zfr164b|xxx|xyz)"
+        + "|(?:yachts|yahoo|yamaxun|yandex|yodobashi|yoga|yokohama|you|youtube|yun|y[et])"
+        + "|(?:zappos|zara|zero|zip|zone|zuerich|z[amw]))";
     /**
      * Kept for backward compatibility reasons.
      *
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 73c93ac..81c3255 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -15,7 +15,19 @@
     ],
 }
 
-cc_library_shared {
+soong_config_module_type {
+    name: "cc_library_shared_for_libandroid_runtime",
+    module_type: "cc_library_shared",
+    config_namespace: "ANDROID",
+    bool_variables: [
+        "release_binder_death_recipient_weak_from_jni",
+    ],
+    properties: [
+        "cflags",
+    ],
+}
+
+cc_library_shared_for_libandroid_runtime {
     name: "libandroid_runtime",
     host_supported: true,
     cflags: [
@@ -46,6 +58,12 @@
         },
     },
 
+    soong_config_variables: {
+        release_binder_death_recipient_weak_from_jni: {
+            cflags: ["-DBINDER_DEATH_RECIPIENT_WEAK_FROM_JNI"],
+        },
+    },
+
     cpp_std: "gnu++20",
 
     srcs: [
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 6ed0a8a..55382cc 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -17,19 +17,8 @@
 #define LOG_TAG "JavaBinder"
 //#define LOG_NDEBUG 0
 
-#include "android_os_Parcel.h"
 #include "android_util_Binder.h"
 
-#include <atomic>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <mutex>
-#include <stdio.h>
-#include <string>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
 #include <android-base/stringprintf.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
@@ -40,7 +29,16 @@
 #include <binder/Stability.h>
 #include <binderthreadstate/CallerUtils.h>
 #include <cutils/atomic.h>
+#include <fcntl.h>
+#include <inttypes.h>
 #include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 #include <utils/KeyedVector.h>
 #include <utils/List.h>
 #include <utils/Log.h>
@@ -48,10 +46,11 @@
 #include <utils/SystemClock.h>
 #include <utils/threads.h>
 
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
-#include <nativehelper/ScopedUtfChars.h>
+#include <atomic>
+#include <mutex>
+#include <string>
 
+#include "android_os_Parcel.h"
 #include "core_jni_helpers.h"
 
 //#undef ALOGV
@@ -557,14 +556,48 @@
 };
 
 // ----------------------------------------------------------------------------
+#ifdef BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
+#if __BIONIC__
+#include <android/api-level.h>
+static bool target_sdk_is_at_least_vic() {
+    return android_get_application_target_sdk_version() >= __ANDROID_API_V__;
+}
+#else
+static constexpr bool target_sdk_is_at_least_vic() {
+    // If not built for Android (i.e. glibc host), follow the latest behavior as there's no compat
+    // requirement there.
+    return true;
+}
+#endif // __BIONIC__
+#endif // BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
 
 class JavaDeathRecipient : public IBinder::DeathRecipient
 {
 public:
     JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
-        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
-          mObjectWeak(NULL), mList(list)
-    {
+          : mVM(jnienv_to_javavm(env)), mObject(NULL), mObjectWeak(NULL), mList(list) {
+        // b/298374304: For apps targeting Android V or beyond, we no longer hold the global JNI ref
+        // to the death recipient objects. This is to prevent the memory leak which can happen when
+        // the death recipient object internally has a strong reference to the proxy object. Under
+        // the old behavior, you were unable to kill the binder service by dropping all references
+        // to the proxy object - because it is still strong referenced from JNI (here). The only way
+        // to cut the strong reference was to call unlinkDeath(), but it was easy to forget.
+        //
+        // Now, the strong reference to the death recipient is held in the Java-side proxy object.
+        // See BinderProxy.mDeathRecipients. From JNI, only the weak reference is kept. An
+        // implication of this is that you may not receive binderDied() if you drop all references
+        // to the proxy object before the service dies. This should be okay for most cases because
+        // you normally are not interested in the death of a binder service which you don't have any
+        // reference to. If however you want to get binderDied() regardless of the proxy object's
+        // lifecycle, keep a strong reference to the death recipient object by yourself.
+#ifdef BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
+        if (target_sdk_is_at_least_vic()) {
+            mObjectWeak = env->NewWeakGlobalRef(object);
+        } else
+#endif
+        {
+            mObject = env->NewGlobalRef(object);
+        }
         // These objects manage their own lifetimes so are responsible for final bookkeeping.
         // The list holds a strong reference to this object.
         LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
@@ -577,26 +610,49 @@
     void binderDied(const wp<IBinder>& who)
     {
         LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
-        if (mObject != NULL) {
-            JNIEnv* env = javavm_to_jnienv(mVM);
-            ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
-            env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
-                                      gBinderProxyOffsets.mSendDeathNotice, mObject,
-                                      jBinderProxy.get());
-            if (env->ExceptionCheck()) {
-                jthrowable excep = env->ExceptionOccurred();
-                binder_report_exception(env, excep,
-                                        "*** Uncaught exception returned from death notification!");
-            }
+        if (mObject == NULL && mObjectWeak == NULL) {
+            return;
+        }
+        JNIEnv* env = javavm_to_jnienv(mVM);
+        ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
 
-            // Serialize with our containing DeathRecipientList so that we can't
-            // delete the global ref on mObject while the list is being iterated.
+        // Hold a local reference to the recipient. This may fail if the recipient is weakly
+        // referenced, in which case we can't deliver the death notice.
+        ScopedLocalRef<jobject> jRecipient(env,
+                                           env->NewLocalRef(mObject != NULL ? mObject
+                                                                            : mObjectWeak));
+        if (jRecipient.get() == NULL) {
+            ALOGW("Binder died, but death recipient is already garbage collected. If your target "
+                  "sdk level is at or above 35, this can happen when you dropped all references to "
+                  "the binder service before it died. If you want to get a death notice for a "
+                  "binder service which you have no reference to, keep a strong reference to the "
+                  "death recipient by yourself.");
+            return;
+        }
+
+        if (mFired) {
+            ALOGW("Received multiple death notices for the same binder object. Binder driver bug?");
+            return;
+        }
+        mFired = true;
+
+        env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mSendDeathNotice,
+                                  jRecipient.get(), jBinderProxy.get());
+        if (env->ExceptionCheck()) {
+            jthrowable excep = env->ExceptionOccurred();
+            binder_report_exception(env, excep,
+                                    "*** Uncaught exception returned from death notification!");
+        }
+
+        // Demote from strong ref (if exists) to weak after binderDied() has been delivered, to
+        // allow the DeathRecipient and BinderProxy to be GC'd if no longer needed. Do this in sync
+        // with our containing DeathRecipientList so that we can't delete the global ref on mObject
+        // while the list is being iterated.
+        if (mObject != NULL) {
             sp<DeathRecipientList> list = mList.promote();
             if (list != NULL) {
                 AutoMutex _l(list->lock());
 
-                // Demote from strong ref to weak after binderDied() has been delivered,
-                // to allow the DeathRecipient and BinderProxy to be GC'd if no longer needed.
                 mObjectWeak = env->NewWeakGlobalRef(mObject);
                 env->DeleteGlobalRef(mObject);
                 mObject = NULL;
@@ -663,9 +719,19 @@
 
 private:
     JavaVM* const mVM;
-    jobject mObject;  // Initial strong ref to Java-side DeathRecipient. Cleared on binderDied().
-    jweak mObjectWeak; // Weak ref to the same Java-side DeathRecipient after binderDied().
+
+    // If target sdk version < 35, the Java-side DeathRecipient is strongly referenced from mObject
+    // upon linkToDeath() and then after binderDied() is called, the strong reference is demoted to
+    // a weak reference (mObjectWeak).
+    // If target sdk version >= 35, the strong reference is never made here (i.e. mObject == NULL
+    // always). Instead, the strong reference to the Java-side DeathRecipient is made in
+    // BinderProxy.mDeathRecipients. In the native world, only the weak reference is kept.
+    jobject mObject;
+    jweak mObjectWeak;
     wp<DeathRecipientList> mList;
+
+    // Whether binderDied was called or not.
+    bool mFired = false;
 };
 
 // ----------------------------------------------------------------------------
@@ -1452,17 +1518,19 @@
 
 // ----------------------------------------------------------------------------
 
+// clang-format off
 static const JNINativeMethod gBinderProxyMethods[] = {
      /* name, signature, funcPtr */
     {"pingBinder",          "()Z", (void*)android_os_BinderProxy_pingBinder},
     {"isBinderAlive",       "()Z", (void*)android_os_BinderProxy_isBinderAlive},
     {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
     {"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
-    {"linkToDeath",         "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
-    {"unlinkToDeath",       "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
+    {"linkToDeathNative",   "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
+    {"unlinkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
     {"getNativeFinalizer",  "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
     {"getExtension",        "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
 };
+// clang-format on
 
 const char* const kBinderProxyPathName = "android/os/BinderProxy";
 
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 3b099e8..af8c69e 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -216,6 +216,9 @@
     <!-- Pakistan -->
     <shortcode country="pk" pattern="\\d{1,5}" free="2057" />
 
+    <!-- Palestine: 5 digits, known premium codes listed -->
+    <shortcode country="ps" pattern="\\d{1,5}" free="37477" />
+
     <!-- Poland: 4-5 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="pl" pattern="\\d{4,5}" premium="74240|79(?:10|866)|92525" free="116\\d{3}|8012|80921" />
 
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index 6cea2f3..dd8f73f 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -399,7 +399,7 @@
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchUrlsWithoutProtocolAndWithUnknownTld()
             throws Exception {
-        String url = "thank.you";
+        String url = "thank.unknowntld";
         assertFalse("Should not match URL that does not start with a protocol and " +
                 "does not contain a known TLD",
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
@@ -422,7 +422,7 @@
     @SmallTest
     public void testAutoLinkWebUrl_doesNotMatchUrlsWithEmojiWithoutProtocolAndWithoutKnownTld()
             throws Exception {
-        String url = "Thank\u263A.you";
+        String url = "Thank\u263A.unknowntld";
         assertFalse("Should not match URLs containing emoji and with unknown TLD",
                 Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
     }
diff --git a/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java b/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
index b5e5b25..cb98855 100644
--- a/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
+++ b/core/tests/fuzzers/ParcelFuzzer/ReadUtils.java
@@ -364,6 +364,12 @@
                         TestClassLoader loader = new TestClassLoader();
                         parcel.readParcelableArray(loader);
                     },
+                    (parcel, provider) -> {
+                        parcel.readParcelable(null);
+                    },
+                    (parcel, provider) -> {
+                        parcel.readParcelableArray(null);
+                    },
 
                     // read lists
                     (parcel, provider) -> {
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 9eed904..6db1832 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -16,6 +16,7 @@
 
 package android.security.keystore;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -34,7 +35,10 @@
 import java.security.Signature;
 import java.security.cert.Certificate;
 import java.security.spec.AlgorithmParameterSpec;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.crypto.Cipher;
 import javax.crypto.KeyGenerator;
@@ -300,6 +304,7 @@
     private final Date mKeyValidityForConsumptionEnd;
     private final @KeyProperties.PurposeEnum int mPurposes;
     private final @KeyProperties.DigestEnum String[] mDigests;
+    private final @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests;
     private final @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
     private final @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
     private final @KeyProperties.BlockModeEnum String[] mBlockModes;
@@ -343,6 +348,7 @@
             Date keyValidityForConsumptionEnd,
             @KeyProperties.PurposeEnum int purposes,
             @KeyProperties.DigestEnum String[] digests,
+            @KeyProperties.DigestEnum Set<String> mgf1Digests,
             @KeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
             @KeyProperties.SignaturePaddingEnum String[] signaturePaddings,
             @KeyProperties.BlockModeEnum String[] blockModes,
@@ -401,6 +407,9 @@
         mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
         mPurposes = purposes;
         mDigests = ArrayUtils.cloneIfNotEmpty(digests);
+        // No need to copy the input parameter because the Builder class passes in an immutable
+        // collection.
+        mMgf1Digests = mgf1Digests != null ? mgf1Digests : Collections.emptySet();
         mEncryptionPaddings =
                 ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
         mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
@@ -562,7 +571,7 @@
 
     /**
      * Returns the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384} with which the
-     * key can be used or {@code null} if not specified.
+     * key can be used.
      *
      * <p>See {@link KeyProperties}.{@code DIGEST} constants.
      *
@@ -590,6 +599,40 @@
     }
 
     /**
+     * Returns the set of digests that can be used by the MGF1 mask generation function
+     * (e.g., {@code SHA-256}, {@code SHA-384}) with the key. Useful with the {@code RSA-OAEP}
+     * scheme.
+     * If not explicitly specified during key generation, the default {@code SHA-1} digest is
+     * used and may be specified when using the key.
+     *
+     * <p>See {@link KeyProperties}.{@code DIGEST} constants.
+     *
+     * @throws IllegalStateException if this set has not been specified.
+     *
+     * @see #isMgf1DigestsSpecified()
+     */
+    @NonNull
+    @FlaggedApi("MGF1_DIGEST_SETTER")
+    public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
+        if (mMgf1Digests.isEmpty()) {
+            throw new IllegalStateException("Mask generation function (MGF) not specified");
+        }
+        return new HashSet(mMgf1Digests);
+    }
+
+    /**
+     * Returns {@code true} if the set of digests for the MGF1 mask generation function,
+     * with which the key can be used, has been specified. Useful with the {@code RSA-OAEP} scheme.
+     *
+     * @see #getMgf1Digests()
+     */
+    @NonNull
+    @FlaggedApi("MGF1_DIGEST_SETTER")
+    public boolean isMgf1DigestsSpecified() {
+        return !mMgf1Digests.isEmpty();
+    }
+
+    /**
      * Returns the set of padding schemes (e.g., {@code PKCS7Padding}, {@code OEAPPadding},
      * {@code PKCS1Padding}, {@code NoPadding}) with which the key can be used when
      * encrypting/decrypting. Attempts to use the key with any other padding scheme will be
@@ -899,6 +942,8 @@
         private Date mKeyValidityForOriginationEnd;
         private Date mKeyValidityForConsumptionEnd;
         private @KeyProperties.DigestEnum String[] mDigests;
+        private @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests =
+                Collections.emptySet();
         private @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
         private @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
         private @KeyProperties.BlockModeEnum String[] mBlockModes;
@@ -968,6 +1013,9 @@
             if (sourceSpec.isDigestsSpecified()) {
                 mDigests = sourceSpec.getDigests();
             }
+            if (sourceSpec.isMgf1DigestsSpecified()) {
+                mMgf1Digests = sourceSpec.getMgf1Digests();
+            }
             mEncryptionPaddings = sourceSpec.getEncryptionPaddings();
             mSignaturePaddings = sourceSpec.getSignaturePaddings();
             mBlockModes = sourceSpec.getBlockModes();
@@ -1214,6 +1262,30 @@
         }
 
         /**
+         * Sets the set of hash functions (e.g., {@code SHA-256}, {@code SHA-384}) which could be
+         * used by the mask generation function MGF1 (which is used for certain operations with
+         * the key). Attempts to use the key with any other digest for the mask generation
+         * function will be rejected.
+         *
+         * <p>This can only be specified for signing/verification keys and RSA encryption/decryption
+         * keys used with RSA OAEP padding scheme because these operations involve a mask generation
+         * function (MGF1) with a digest.
+         * The default digest for MGF1 is {@code SHA-1}, which will be specified during key creation
+         * time if no digests have been explicitly provided.
+         * When using the key, the caller may not specify any digests that were not provided during
+         * key creation time. The caller may specify the default digest, {@code SHA-1}, if no
+         * digests were explicitly provided during key creation (but it is not necessary to do so).
+         *
+         * <p>See {@link KeyProperties}.{@code DIGEST} constants.
+         */
+        @NonNull
+        @FlaggedApi("MGF1_DIGEST_SETTER")
+        public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
+            mMgf1Digests = Set.of(mgf1Digests);
+            return this;
+        }
+
+        /**
          * Sets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code OAEPPadding},
          * {@code PKCS1Padding}, {@code NoPadding}) with which the key can be used when
          * encrypting/decrypting. Attempts to use the key with any other padding scheme will be
@@ -1745,6 +1817,7 @@
                     mKeyValidityForConsumptionEnd,
                     mPurposes,
                     mDigests,
+                    mMgf1Digests,
                     mEncryptionPaddings,
                     mSignaturePaddings,
                     mBlockModes,
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index c14c3c5..1262a53 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -16,6 +16,7 @@
 
 package android.security.keystore;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -30,7 +31,10 @@
 import java.security.KeyStore.ProtectionParameter;
 import java.security.Signature;
 import java.security.cert.Certificate;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
 
 import javax.crypto.Cipher;
 import javax.crypto.Mac;
@@ -223,6 +227,7 @@
     private final @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
     private final @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
     private final @KeyProperties.DigestEnum String[] mDigests;
+    private final @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests;
     private final @KeyProperties.BlockModeEnum String[] mBlockModes;
     private final boolean mRandomizedEncryptionRequired;
     private final boolean mUserAuthenticationRequired;
@@ -246,6 +251,7 @@
             @KeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
             @KeyProperties.SignaturePaddingEnum String[] signaturePaddings,
             @KeyProperties.DigestEnum String[] digests,
+            @KeyProperties.DigestEnum Set<String> mgf1Digests,
             @KeyProperties.BlockModeEnum String[] blockModes,
             boolean randomizedEncryptionRequired,
             boolean userAuthenticationRequired,
@@ -269,6 +275,7 @@
         mSignaturePaddings =
                 ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
         mDigests = ArrayUtils.cloneIfNotEmpty(digests);
+        mMgf1Digests = mgf1Digests;
         mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
         mRandomizedEncryptionRequired = randomizedEncryptionRequired;
         mUserAuthenticationRequired = userAuthenticationRequired;
@@ -378,6 +385,40 @@
     }
 
     /**
+     * Returns the set of digests that can be used by the MGF1 mask generation function
+     * (e.g., {@code SHA-256}, {@code SHA-384}) with the key. Useful with the {@code RSA-OAEP}
+     * scheme.
+     * If not explicitly specified  during key generation, the default {@code SHA-1} digest is
+     * used and may be specified.
+     *
+     * <p>See {@link KeyProperties}.{@code DIGEST} constants.
+     *
+     * @throws IllegalStateException if this set has not been specified.
+     *
+     * @see #isMgf1DigestsSpecified()
+     */
+    @NonNull
+    @FlaggedApi("MGF1_DIGEST_SETTER")
+    public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
+        if (mMgf1Digests.isEmpty()) {
+            throw new IllegalStateException("Mask generation function (MGF) not specified");
+        }
+        return new HashSet(mMgf1Digests);
+    }
+
+    /**
+     * Returns {@code true} if the set of digests for the MGF1 mask generation function,
+     * with which the key can be used, has been specified. Useful with the {@code RSA-OAEP} scheme.
+     *
+     * @see #getMgf1Digests()
+     */
+    @NonNull
+    @FlaggedApi("MGF1_DIGEST_SETTER")
+    public boolean isMgf1DigestsSpecified() {
+        return !mMgf1Digests.isEmpty();
+    }
+
+    /**
      * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
      * when encrypting/decrypting. Attempts to use the key with any other block modes will be
      * rejected.
@@ -574,6 +615,8 @@
         private @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
         private @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
         private @KeyProperties.DigestEnum String[] mDigests;
+        private @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests =
+                Collections.emptySet();
         private @KeyProperties.BlockModeEnum String[] mBlockModes;
         private boolean mRandomizedEncryptionRequired = true;
         private boolean mUserAuthenticationRequired;
@@ -724,6 +767,30 @@
         }
 
         /**
+         * Sets the set of hash functions (e.g., {@code SHA-256}, {@code SHA-384}) which could be
+         * used by the mask generation function MGF1 (which is used for certain operations with
+         * the key). Attempts to use the key with any other digest for the mask generation
+         * function will be rejected.
+         *
+         * <p>This can only be specified for signing/verification keys and RSA encryption/decryption
+         * keys used with RSA OAEP padding scheme because these operations involve a mask generation
+         * function (MGF1) with a digest.
+         * The default digest for MGF1 is {@code SHA-1}, which will be specified during key import
+         * time if no digests have been explicitly provided.
+         * When using the key, the caller may not specify any digests that were not provided during
+         * key import time. The caller may specify the default digest, {@code SHA-1}, if no
+         * digests were explicitly provided during key import (but it is not necessary to do so).
+         *
+         * <p>See {@link KeyProperties}.{@code DIGEST} constants.
+         */
+        @NonNull
+        @FlaggedApi("MGF1_DIGEST_SETTER")
+        public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
+            mMgf1Digests = Set.of(mgf1Digests);
+            return this;
+        }
+
+        /**
          * Sets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be
          * used when encrypting/decrypting. Attempts to use the key with any other block modes will
          * be rejected.
@@ -1111,6 +1178,7 @@
                     mEncryptionPaddings,
                     mSignaturePaddings,
                     mDigests,
+                    mMgf1Digests,
                     mBlockModes,
                     mRandomizedEncryptionRequired,
                     mUserAuthenticationRequired,
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index a6e3366..30b3b5c 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -23,7 +23,11 @@
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.ECGenParameterSpec;
 import java.security.spec.RSAKeyGenParameterSpec;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
+import java.util.Set;
 
 import javax.security.auth.x500.X500Principal;
 
@@ -91,6 +95,11 @@
         } else {
             out.writeStringArray(null);
         }
+        if (mSpec.isMgf1DigestsSpecified()) {
+            out.writeStringList(List.copyOf(mSpec.getMgf1Digests()));
+        } else {
+            out.writeStringList(null);
+        }
         out.writeStringArray(mSpec.getEncryptionPaddings());
         out.writeStringArray(mSpec.getSignaturePaddings());
         out.writeStringArray(mSpec.getBlockModes());
@@ -152,6 +161,7 @@
         final Date keyValidityForOriginationEnd = readDateOrNull(in);
         final Date keyValidityForConsumptionEnd = readDateOrNull(in);
         final String[] digests = in.createStringArray();
+        final ArrayList<String> mgf1Digests = in.createStringArrayList();
         final String[] encryptionPaddings = in.createStringArray();
         final String[] signaturePaddings = in.createStringArray();
         final String[] blockModes = in.createStringArray();
@@ -189,6 +199,7 @@
                 keyValidityForConsumptionEnd,
                 purposes,
                 digests,
+                mgf1Digests != null ? Set.copyOf(mgf1Digests) : Collections.emptySet(),
                 encryptionPaddings,
                 signaturePaddings,
                 blockModes,
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index 9ac0f6d..101a10e 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -24,6 +24,7 @@
 import android.security.KeyStoreException;
 import android.security.KeyStoreOperation;
 import android.security.keymaster.KeymasterDefs;
+import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyStoreCryptoOperation;
 import android.system.keystore2.Authorization;
 
@@ -71,7 +72,7 @@
  */
 abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation {
     private static final String TAG = "AndroidKeyStoreCipherSpiBase";
-    public static final String DEFAULT_MGF1_DIGEST = "SHA-1";
+    public static final String DEFAULT_MGF1_DIGEST = KeyProperties.DIGEST_SHA1;
 
     // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
     // doFinal finishes.
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 1398da3..ed4b485 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -188,6 +188,7 @@
     private int[] mKeymasterEncryptionPaddings;
     private int[] mKeymasterSignaturePaddings;
     private int[] mKeymasterDigests;
+    private int[] mKeymasterMgf1Digests;
 
     private Long mRSAPublicExponent;
 
@@ -323,6 +324,21 @@
                 } else {
                     mKeymasterDigests = EmptyArray.INT;
                 }
+                if (spec.isMgf1DigestsSpecified()) {
+                    // User-specified digests: Add all of them and do _not_ add the SHA-1
+                    // digest by default (stick to what the user provided).
+                    Set<String> mgfDigests = spec.getMgf1Digests();
+                    mKeymasterMgf1Digests = new int[mgfDigests.size()];
+                    int offset = 0;
+                    for (String digest : mgfDigests) {
+                        mKeymasterMgf1Digests[offset] = KeyProperties.Digest.toKeymaster(digest);
+                        offset++;
+                    }
+                } else {
+                    // No user-specified digests: Add the SHA-1 default.
+                    mKeymasterMgf1Digests = new int[]{
+                            KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)};
+                }
 
                 // Check that user authentication related parameters are acceptable. This method
                 // will throw an IllegalStateException if there are issues (e.g., secure lock screen
@@ -544,6 +560,7 @@
         mKeymasterEncryptionPaddings = null;
         mKeymasterSignaturePaddings = null;
         mKeymasterDigests = null;
+        mKeymasterMgf1Digests = null;
         mKeySizeBits = 0;
         mSpec = null;
         mRSAPublicExponent = null;
@@ -831,24 +848,11 @@
                     KeymasterDefs.KM_TAG_PADDING, padding
             ));
             if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) {
-                final boolean[] hasDefaultMgf1DigestBeenAdded = {false};
-                ArrayUtils.forEach(mKeymasterDigests, (digest) -> {
+                ArrayUtils.forEach(mKeymasterMgf1Digests, (mgf1Digest) -> {
                     params.add(KeyStore2ParameterUtils.makeEnum(
-                            KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest
+                            KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mgf1Digest
                     ));
-                    hasDefaultMgf1DigestBeenAdded[0] |=
-                            digest.equals(KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST));
                 });
-                /* Because of default MGF1 digest is SHA-1. It has to be added in Key
-                 * characteristics. Otherwise, crypto operations will fail with Incompatible
-                 * MGF1 digest.
-                 */
-                if (!hasDefaultMgf1DigestBeenAdded[0]) {
-                    params.add(KeyStore2ParameterUtils.makeEnum(
-                            KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
-                            KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
-                    ));
-                }
             }
         });
         ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index eef8179..d3d9701 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -526,25 +526,22 @@
                         padding
                 ));
                 if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) {
-                    if (spec.isDigestsSpecified()) {
-                        boolean hasDefaultMgf1DigestBeenAdded = false;
-                        for (String digest : spec.getDigests()) {
+                    if (spec.isMgf1DigestsSpecified()) {
+                        for (String mgf1Digest : spec.getMgf1Digests()) {
                             importArgs.add(KeyStore2ParameterUtils.makeEnum(
                                     KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
-                                    KeyProperties.Digest.toKeymaster(digest)
+                                    KeyProperties.Digest.toKeymaster(mgf1Digest)
                             ));
-                            hasDefaultMgf1DigestBeenAdded |= digest.equals(DEFAULT_MGF1_DIGEST);
                         }
+                    } else {
                         /* Because of default MGF1 digest is SHA-1. It has to be added in Key
                          * characteristics. Otherwise, crypto operations will fail with Incompatible
                          * MGF1 digest.
                          */
-                        if (!hasDefaultMgf1DigestBeenAdded) {
-                            importArgs.add(KeyStore2ParameterUtils.makeEnum(
-                                    KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
-                                    KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
-                            ));
-                        }
+                        importArgs.add(KeyStore2ParameterUtils.makeEnum(
+                                KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,
+                                KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)
+                        ));
                     }
                 }
             }
diff --git a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
index 2ae61ab..d4e2dbc 100644
--- a/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/ParcelableKeyGenParameterSpecTest.java
@@ -17,6 +17,7 @@
 package android.security;
 
 import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
@@ -101,6 +102,7 @@
         assertThat(spec.getKeyValidityForOriginationEnd(), is(KEY_VALIDITY_FOR_ORIG_END));
         assertThat(spec.getKeyValidityForConsumptionEnd(), is(KEY_VALIDITY_FOR_CONSUMPTION_END));
         assertThat(spec.getDigests(), is(new String[] {DIGEST}));
+        assertThat(spec.isMgf1DigestsSpecified(), is(false));
         assertThat(spec.getEncryptionPaddings(), is(new String[] {ENCRYPTION_PADDING}));
         assertThat(spec.getSignaturePaddings(), is(new String[] {SIGNATURE_PADDING}));
         assertThat(spec.getBlockModes(), is(new String[] {BLOCK_MODE}));
@@ -189,4 +191,19 @@
         ECGenParameterSpec parcelSpec = (ECGenParameterSpec) fromParcel.getAlgorithmParameterSpec();
         assertEquals(parcelSpec.getName(), ecSpec.getName());
     }
+
+    @Test
+    public void testParcelingMgf1Digests() {
+        String[] mgf1Digests =
+                new String[] {KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA256};
+
+        ParcelableKeyGenParameterSpec spec = new ParcelableKeyGenParameterSpec(
+                new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
+                        .setMgf1Digests(mgf1Digests)
+                        .build());
+        Parcel parcel = parcelForReading(spec);
+        KeyGenParameterSpec fromParcel =
+                ParcelableKeyGenParameterSpec.CREATOR.createFromParcel(parcel).getSpec();
+        assertArrayEquals(fromParcel.getMgf1Digests().toArray(), mgf1Digests);
+    }
 }
diff --git a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
index ddbb1d8..da5e8bf 100644
--- a/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
+++ b/keystore/tests/src/android/security/keystore/KeyGenParameterSpecTest.java
@@ -16,9 +16,12 @@
 
 package android.security.keystore;
 
+import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
 
 import android.security.ParcelableKeyGenParameterSpecTest;
 
@@ -61,4 +64,54 @@
 
         assertEquals(copiedSpec.getAttestationChallenge(), null);
     }
+
+    @Test
+    public void testMgf1DigestsNotSpecifiedByDefault() {
+        KeyGenParameterSpec spec = ParcelableKeyGenParameterSpecTest.configureDefaultSpec();
+        assertThat(spec.isMgf1DigestsSpecified(), is(false));
+        assertThrows(IllegalStateException.class, () -> {
+            spec.getMgf1Digests();
+        });
+    }
+
+    @Test
+    public void testMgf1DigestsCanBeSpecified() {
+        String[] mgf1Digests =
+                new String[] {KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA256};
+        KeyGenParameterSpec spec =  new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
+                .setMgf1Digests(mgf1Digests)
+                .build();
+        assertThat(spec.isMgf1DigestsSpecified(), is(true));
+        assertThat(spec.getMgf1Digests(), containsInAnyOrder(mgf1Digests));
+
+        KeyGenParameterSpec copiedSpec = new KeyGenParameterSpec.Builder(spec).build();
+        assertThat(copiedSpec.isMgf1DigestsSpecified(), is(true));
+        assertThat(copiedSpec.getMgf1Digests(), containsInAnyOrder(mgf1Digests));
+    }
+
+    @Test
+    public void testMgf1DigestsAreNotModified() {
+        String[] mgf1Digests =
+                new String[] {KeyProperties.DIGEST_SHA1, KeyProperties.DIGEST_SHA256};
+        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
+                .setMgf1Digests(mgf1Digests);
+
+        KeyGenParameterSpec firstSpec =  builder.build();
+        assertArrayEquals(mgf1Digests, firstSpec.getMgf1Digests().toArray());
+
+        String[] otherDigests = new String[] {KeyProperties.DIGEST_SHA224};
+        KeyGenParameterSpec secondSpec =  builder.setMgf1Digests(otherDigests).build();
+        assertThat(secondSpec.getMgf1Digests(), containsInAnyOrder(otherDigests));
+
+        // Now check that the first spec created hasn't changed.
+        assertThat(firstSpec.getMgf1Digests(), containsInAnyOrder(mgf1Digests));
+    }
+
+    @Test
+    public void testEmptyMgf1DigestsCanBeSet() {
+        KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(ALIAS, KEY_PURPOSES)
+                .setMgf1Digests(new String[] {}).build();
+
+        assertThat(spec.isMgf1DigestsSpecified(), is(false));
+    }
 }
diff --git a/mime/Android.bp b/mime/Android.bp
index a3ea65c..757862b 100644
--- a/mime/Android.bp
+++ b/mime/Android.bp
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 package {
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
@@ -125,6 +124,6 @@
     srcs: [
         "java-res/vendor.mime.types",
     ],
-    //    strip comments            normalize whitepace       drop empty lines   prepend ? to fields that are missing it
-    cmd: "awk '{gsub(/#.*$$/,\"\"); $$1=$$1; print;}' $(in) | grep ' '         | awk '{for(i=1;i<=NF;i++) { sub(/^\\??/, \"?\", $$i); }; print}' > $(out)",
+    //    strip comments            normalize whitepace       drop empty lines           prepend ? to fields that are missing it
+    cmd: "awk '{gsub(/#.*$$/,\"\"); $$1=$$1; print;}' $(in) | (grep ' ' || echo -n '') | awk '{for(i=1;i<=NF;i++) { sub(/^\\??/, \"?\", $$i); }; print}' > $(out)",
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
index c9f645d..f2d6e1f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
@@ -34,7 +34,7 @@
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.withContext
 
 @SysUISingleton
@@ -59,16 +59,21 @@
         get() = R.drawable.ic_camera
 
     override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
-        get() =
-            flowOf(
-                KeyguardQuickAffordanceConfig.LockScreenState.Visible(
-                    icon =
-                        Icon.Resource(
-                            R.drawable.ic_camera,
-                            ContentDescription.Resource(R.string.accessibility_camera_button)
-                        )
-                )
+        get() = flow {
+            emit(
+                if (isLaunchable()) {
+                    KeyguardQuickAffordanceConfig.LockScreenState.Visible(
+                        icon =
+                            Icon.Resource(
+                                R.drawable.ic_camera,
+                                ContentDescription.Resource(R.string.accessibility_camera_button)
+                            )
+                    )
+                } else {
+                    KeyguardQuickAffordanceConfig.LockScreenState.Hidden
+                }
             )
+        }
 
     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
         return if (isLaunchable()) {
diff --git a/services/Android.bp b/services/Android.bp
index eb56c25..5b15392f 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -255,4 +255,5 @@
             tag: ".removed-api.txt",
         },
     ],
+    api_surface: "system-server",
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b837688..1d028c8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4201,21 +4201,6 @@
                         profile.addPss(mi.getTotalPss(),
                                 mi.getTotalUss(), mi.getTotalRss(), false,
                                 ProcessStats.ADD_PSS_EXTERNAL_SLOW, duration);
-                        proc.getPkgList().forEachPackageProcessStats(holder -> {
-                            final ProcessState state = holder.state;
-                            FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
-                                    proc.info.uid,
-                                    state != null ? state.getName() : proc.processName,
-                                    state != null ? state.getPackage() : proc.info.packageName,
-                                    mi.getTotalPss(),
-                                    mi.getTotalUss(),
-                                    mi.getTotalRss(),
-                                    ProcessStats.ADD_PSS_EXTERNAL_SLOW,
-                                    duration,
-                                    holder.appVersion,
-                                    profile.getCurrentHostingComponentTypes(),
-                                    profile.getHistoricalHostingComponentTypes());
-                        });
                     }
                 }
             }
@@ -4262,20 +4247,6 @@
                         // Record this for posterity if the process has been stable.
                         profile.addPss(pi, tmpUss[0], tmpUss[2], false,
                                 ProcessStats.ADD_PSS_EXTERNAL, duration);
-                        proc.getPkgList().forEachPackageProcessStats(holder -> {
-                            FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
-                                    proc.info.uid,
-                                    holder.state.getName(),
-                                    holder.state.getPackage(),
-                                    pi,
-                                    tmpUss[0],
-                                    tmpUss[2],
-                                    ProcessStats.ADD_PSS_EXTERNAL,
-                                    duration,
-                                    holder.appVersion,
-                                    profile.getCurrentHostingComponentTypes(),
-                                    profile.getHistoricalHostingComponentTypes());
-                        });
                     }
                 }
             }
@@ -11411,17 +11382,6 @@
                         // Record this for posterity if the process has been stable.
                         r.mProfile.addPss(myTotalPss, myTotalUss, myTotalRss, true,
                                 reportType, endTime - startTime);
-                        r.getPkgList().forEachPackageProcessStats(holder -> {
-                            FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
-                                    r.info.uid,
-                                    holder.state.getName(),
-                                    holder.state.getPackage(),
-                                    myTotalPss, myTotalUss, myTotalRss, reportType,
-                                    endTime-startTime,
-                                    holder.appVersion,
-                                    r.mProfile.getCurrentHostingComponentTypes(),
-                                    r.mProfile.getHistoricalHostingComponentTypes());
-                        });
                     }
                 }
 
@@ -12057,16 +12017,6 @@
                     // Record this for posterity if the process has been stable.
                     r.mProfile.addPss(myTotalPss, myTotalUss, myTotalRss, true,
                                 reportType, endTime - startTime);
-                    r.getPkgList().forEachPackageProcessStats(holder -> {
-                        FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
-                                r.info.uid,
-                                holder.state.getName(),
-                                holder.state.getPackage(),
-                                myTotalPss, myTotalUss, myTotalRss, reportType, endTime-startTime,
-                                holder.appVersion,
-                                r.mProfile.getCurrentHostingComponentTypes(),
-                                r.mProfile.getHistoricalHostingComponentTypes());
-                    });
                 }
             }
 
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 15efb7d..7c04a57 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -567,17 +567,6 @@
                 swapPss * 1024, rss * 1024, statType, procState, pssDuration);
         profile.setLastPssTime(now);
         profile.addPss(pss, uss, rss, true, statType, pssDuration);
-        proc.getPkgList().forEachPackageProcessStats(holder -> {
-            FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
-                    proc.info.uid,
-                    holder.state.getName(),
-                    holder.state.getPackage(),
-                    pss, uss, rss,
-                    statType, pssDuration,
-                    holder.appVersion,
-                    profile.getCurrentHostingComponentTypes(),
-                    profile.getHistoricalHostingComponentTypes());
-        });
         if (DEBUG_PSS) {
             Slog.d(TAG_PSS,
                     "pss of " + proc.toShortString() + ": " + pss
diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS
index fcaa957..9439eaa 100644
--- a/services/core/java/com/android/server/display/OWNERS
+++ b/services/core/java/com/android/server/display/OWNERS
@@ -6,5 +6,6 @@
 flc@google.com
 wilczynskip@google.com
 brup@google.com
+petsjonkin@google.com
 
 per-file ColorDisplayService.java=christyfranks@google.com
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 10e72f5..13b4f7f 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1480,12 +1480,9 @@
         if (dir.isDirectory() && dir.canRead()) {
             Collections.addAll(ret, dir.listFiles());
         }
-        // For IoT devices, we check the oem partition for default permissions for each app.
-        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED, 0)) {
-            dir = new File(Environment.getOemDirectory(), "etc/default-permissions");
-            if (dir.isDirectory() && dir.canRead()) {
-                Collections.addAll(ret, dir.listFiles());
-            }
+        dir = new File(Environment.getOemDirectory(), "etc/default-permissions");
+        if (dir.isDirectory() && dir.canRead()) {
+            Collections.addAll(ret, dir.listFiles());
         }
         return ret.isEmpty() ? null : ret.toArray(new File[0]);
     }
diff --git a/services/foldables/devicestateprovider/OWNERS b/services/foldables/devicestateprovider/OWNERS
new file mode 100644
index 0000000..5732844
--- /dev/null
+++ b/services/foldables/devicestateprovider/OWNERS
@@ -0,0 +1,6 @@
+akulian@google.com
+jiamingliu@google.com
+kchyn@google.com
+kennethford@google.com
+nickchameyev@google.com
+nicomazz@google.com
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index 94f88ab..5674101 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -18,6 +18,8 @@
 
 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
 
+import static com.android.compatibility.common.util.PollingCheck.waitFor;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
@@ -40,6 +42,7 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.compatibility.common.util.PollingCheck;
 import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowProcessController;
 
@@ -73,6 +76,8 @@
 
     private static final int FAKE_PROCESS_ID = 100;
 
+    private static final int TIMEOUT = 2000;
+
     private TestDeviceStatePolicy mPolicy;
     private TestDeviceStateProvider mProvider;
     private DeviceStateManagerService mService;
@@ -106,6 +111,10 @@
         }
     }
 
+    private void waitAndAssert(PollingCheck.PollingCheckCondition condition) {
+        waitFor(TIMEOUT, condition);
+    }
+
     @Test
     public void baseStateChanged() {
         assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
@@ -272,37 +281,34 @@
         mService.getBinderService().registerCallback(callback);
 
         mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
-        flushHandler();
-        assertEquals(callback.getLastNotifiedInfo().baseState,
-                OTHER_DEVICE_STATE.getIdentifier());
-        assertEquals(callback.getLastNotifiedInfo().currentState,
-                OTHER_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+                == OTHER_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+                == OTHER_DEVICE_STATE.getIdentifier());
 
         mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
-        flushHandler();
-        assertEquals(callback.getLastNotifiedInfo().baseState,
-                DEFAULT_DEVICE_STATE.getIdentifier());
-        assertEquals(callback.getLastNotifiedInfo().currentState,
-                DEFAULT_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+                == DEFAULT_DEVICE_STATE.getIdentifier());
+
+        waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+                == DEFAULT_DEVICE_STATE.getIdentifier());
 
         mPolicy.blockConfigure();
         mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
-        flushHandler();
         // The callback should not have been notified of the state change as the policy is still
         // pending callback.
-        assertEquals(callback.getLastNotifiedInfo().baseState,
-                DEFAULT_DEVICE_STATE.getIdentifier());
-        assertEquals(callback.getLastNotifiedInfo().currentState,
-                DEFAULT_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+                == DEFAULT_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+                == DEFAULT_DEVICE_STATE.getIdentifier());
 
         mPolicy.resumeConfigure();
-        flushHandler();
         // Now that the policy is finished processing the callback should be notified of the state
         // change.
-        assertEquals(callback.getLastNotifiedInfo().baseState,
-                OTHER_DEVICE_STATE.getIdentifier());
-        assertEquals(callback.getLastNotifiedInfo().currentState,
-                OTHER_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+                == OTHER_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().currentState
+                == OTHER_DEVICE_STATE.getIdentifier());
     }
 
     @Test
@@ -329,13 +335,9 @@
 
         mService.getBinderService().requestState(token, OTHER_DEVICE_STATE.getIdentifier(),
                 0 /* flags */);
-        // Flush the handler twice. The first flush ensures the request is added and the policy is
-        // notified, while the second flush ensures the callback is notified once the change is
-        // committed.
-        flushHandler(2 /* count */);
 
-        assertEquals(callback.getLastNotifiedStatus(token),
-                TestDeviceStateManagerCallback.STATUS_ACTIVE);
+        waitAndAssert(() -> callback.getLastNotifiedStatus(token)
+                == TestDeviceStateManagerCallback.STATUS_ACTIVE);
         // Committed state changes as there is a requested override.
         assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
         assertEquals(mSysPropSetter.getValue(),
@@ -352,12 +354,11 @@
                 OTHER_DEVICE_STATE.getIdentifier());
 
         mService.getBinderService().cancelStateRequest();
-        flushHandler();
 
-        assertEquals(callback.getLastNotifiedStatus(token),
-                TestDeviceStateManagerCallback.STATUS_CANCELED);
+        waitAndAssert(() -> callback.getLastNotifiedStatus(token)
+                == TestDeviceStateManagerCallback.STATUS_CANCELED);
         // Committed state is set back to the requested state once the override is cleared.
-        assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
+        waitAndAssert(() -> mService.getCommittedState().equals(Optional.of(DEFAULT_DEVICE_STATE)));
         assertEquals(mSysPropSetter.getValue(),
                 DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
         assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
@@ -600,13 +601,9 @@
         mService.getBinderService().requestBaseStateOverride(token,
                 OTHER_DEVICE_STATE.getIdentifier(),
                 0 /* flags */);
-        // Flush the handler twice. The first flush ensures the request is added and the policy is
-        // notified, while the second flush ensures the callback is notified once the change is
-        // committed.
-        flushHandler(2 /* count */);
 
-        assertEquals(callback.getLastNotifiedStatus(token),
-                TestDeviceStateManagerCallback.STATUS_ACTIVE);
+        waitAndAssert(() -> callback.getLastNotifiedStatus(token)
+                == TestDeviceStateManagerCallback.STATUS_ACTIVE);
         // Committed state changes as there is a requested override.
         assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
         assertEquals(mSysPropSetter.getValue(),
@@ -624,12 +621,11 @@
                 OTHER_DEVICE_STATE.getIdentifier());
 
         mService.getBinderService().cancelBaseStateOverride();
-        flushHandler();
 
-        assertEquals(callback.getLastNotifiedStatus(token),
-                TestDeviceStateManagerCallback.STATUS_CANCELED);
+        waitAndAssert(() -> callback.getLastNotifiedStatus(token)
+                == TestDeviceStateManagerCallback.STATUS_CANCELED);
         // Committed state is set back to the requested state once the override is cleared.
-        assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
+        waitAndAssert(() -> mService.getCommittedState().equals(Optional.of(DEFAULT_DEVICE_STATE)));
         assertEquals(mSysPropSetter.getValue(),
                 DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
         assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
@@ -638,8 +634,8 @@
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 DEFAULT_DEVICE_STATE.getIdentifier());
 
-        assertEquals(callback.getLastNotifiedInfo().baseState,
-                DEFAULT_DEVICE_STATE.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+                == DEFAULT_DEVICE_STATE.getIdentifier());
         assertEquals(callback.getLastNotifiedInfo().currentState,
                 DEFAULT_DEVICE_STATE.getIdentifier());
     }
@@ -660,13 +656,9 @@
         mService.getBinderService().requestBaseStateOverride(token,
                 OTHER_DEVICE_STATE.getIdentifier(),
                 0 /* flags */);
-        // Flush the handler twice. The first flush ensures the request is added and the policy is
-        // notified, while the second flush ensures the callback is notified once the change is
-        // committed.
-        flushHandler(2 /* count */);
 
-        assertEquals(callback.getLastNotifiedStatus(token),
-                TestDeviceStateManagerCallback.STATUS_ACTIVE);
+        waitAndAssert(() -> callback.getLastNotifiedStatus(token)
+                == TestDeviceStateManagerCallback.STATUS_ACTIVE);
         // Committed state changes as there is a requested override.
         assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
         assertEquals(mSysPropSetter.getValue(),
@@ -684,12 +676,11 @@
                 OTHER_DEVICE_STATE.getIdentifier());
 
         mProvider.setState(testDeviceState.getIdentifier());
-        flushHandler();
 
-        assertEquals(callback.getLastNotifiedStatus(token),
-                TestDeviceStateManagerCallback.STATUS_CANCELED);
+        waitAndAssert(() -> callback.getLastNotifiedStatus(token)
+                == TestDeviceStateManagerCallback.STATUS_CANCELED);
         // Committed state is set to the new base state once the override is cleared.
-        assertEquals(mService.getCommittedState(), Optional.of(testDeviceState));
+        waitAndAssert(() -> mService.getCommittedState().equals(Optional.of(testDeviceState)));
         assertEquals(mSysPropSetter.getValue(),
                 testDeviceState.getIdentifier() + ":" + testDeviceState.getName());
         assertEquals(mService.getBaseState(), Optional.of(testDeviceState));
@@ -698,8 +689,8 @@
         assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
                 testDeviceState.getIdentifier());
 
-        assertEquals(callback.getLastNotifiedInfo().baseState,
-                testDeviceState.getIdentifier());
+        waitAndAssert(() -> callback.getLastNotifiedInfo().baseState
+                == testDeviceState.getIdentifier());
         assertEquals(callback.getLastNotifiedInfo().currentState,
                 testDeviceState.getIdentifier());
     }
diff --git a/tests/BinderLeakTest/Android.bp b/tests/BinderLeakTest/Android.bp
new file mode 100644
index 0000000..78b0ede
--- /dev/null
+++ b/tests/BinderLeakTest/Android.bp
@@ -0,0 +1,40 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "binder_leak_test_aidl",
+    srcs: ["**/*.aidl"],
+    path: "aidl",
+}
+
+java_defaults {
+    name: "BinderTest.defaults",
+    srcs: [
+        "**/*.java",
+        ":binder_leak_test_aidl",
+    ],
+    static_libs: [
+        "androidx.test.ext.junit",
+        "androidx.test.rules",
+        "androidx.test.runner",
+    ],
+}
+
+// Built with target_sdk_version: current
+android_test {
+    name: "BinderLeakTest",
+    defaults: ["BinderTest.defaults"],
+}
+
+// Built with target_sdk_version: 33
+android_test {
+    name: "BinderLeakTest_legacy",
+    defaults: ["BinderTest.defaults"],
+    manifest: "AndroidManifest_legacy.xml",
+}
diff --git a/tests/BinderLeakTest/AndroidManifest.xml b/tests/BinderLeakTest/AndroidManifest.xml
new file mode 100644
index 0000000..756def7
--- /dev/null
+++ b/tests/BinderLeakTest/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.test.binder">
+    <application>
+        <service
+            android:name=".MyService"
+            android:enabled="true"
+            android:exported="true"
+            android:process=":service">
+        </service>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.test.binder"
+        android:label="Binder leak test">
+    </instrumentation>
+</manifest>
diff --git a/tests/BinderLeakTest/AndroidManifest_legacy.xml b/tests/BinderLeakTest/AndroidManifest_legacy.xml
new file mode 100644
index 0000000..03d1dfd
--- /dev/null
+++ b/tests/BinderLeakTest/AndroidManifest_legacy.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.test.binder">
+    <uses-sdk android:minSdkVersion="33"
+          android:targetSdkVersion="33"
+          android:maxSdkVersion="33" />
+    <application>
+        <service
+            android:name=".MyService"
+            android:enabled="true"
+            android:exported="true"
+            android:process=":service">
+        </service>
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.test.binder"
+        android:label="Binder leak test">
+    </instrumentation>
+</manifest>
diff --git a/tests/BinderLeakTest/aidl/com/android/test/binder/IFoo.aidl b/tests/BinderLeakTest/aidl/com/android/test/binder/IFoo.aidl
new file mode 100644
index 0000000..a721959
--- /dev/null
+++ b/tests/BinderLeakTest/aidl/com/android/test/binder/IFoo.aidl
@@ -0,0 +1,5 @@
+package com.android.test.binder;
+
+interface IFoo {
+
+}
diff --git a/tests/BinderLeakTest/aidl/com/android/test/binder/IFooProvider.aidl b/tests/BinderLeakTest/aidl/com/android/test/binder/IFooProvider.aidl
new file mode 100644
index 0000000..b487f51
--- /dev/null
+++ b/tests/BinderLeakTest/aidl/com/android/test/binder/IFooProvider.aidl
@@ -0,0 +1,10 @@
+package com.android.test.binder;
+import com.android.test.binder.IFoo;
+
+interface IFooProvider {
+    IFoo createFoo();
+
+    boolean isFooGarbageCollected();
+
+    oneway void killProcess();
+}
diff --git a/tests/BinderLeakTest/java/com/android/test/binder/BinderTest.java b/tests/BinderLeakTest/java/com/android/test/binder/BinderTest.java
new file mode 100644
index 0000000..f07317f
--- /dev/null
+++ b/tests/BinderLeakTest/java/com/android/test/binder/BinderTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.binder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.rule.ServiceTestRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class BinderTest {
+    @Rule
+    public final ServiceTestRule serviceRule = new ServiceTestRule();
+
+    @Test
+    public void testDeathRecipientLeaksOrNot()
+            throws RemoteException, TimeoutException, InterruptedException {
+        Intent intent = new Intent(ApplicationProvider.getApplicationContext(), MyService.class);
+        IFooProvider provider = IFooProvider.Stub.asInterface(serviceRule.bindService(intent));
+        FooHolder holder = new FooHolder(provider.createFoo());
+
+        // ref will get enqueued right after holder is finalized for gc.
+        ReferenceQueue<FooHolder> refQueue = new ReferenceQueue<>();
+        PhantomReference<FooHolder> ref = new PhantomReference<>(holder, refQueue);
+
+        DeathRecorder deathRecorder = new DeathRecorder();
+        holder.registerDeathRecorder(deathRecorder);
+
+        if (getSdkVersion() >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+            /////////////////////////////////////////////
+            // New behavior
+            //
+            // Reference chain at this moment:
+            // holder --(java strong ref)--> FooHolder
+            // FooHolder.mProxy --(java strong ref)--> IFoo.Proxy
+            // IFoo.Proxy.mRemote --(java strong ref)--> BinderProxy
+            // BinderProxy --(binder ref)--> Foo.Stub
+            // In other words, the variable "holder" is the root of the reference chain.
+
+            // By setting the variable to null, we make FooHolder, IFoo.Proxy, BinderProxy, and even
+            // Foo.Stub unreachable.
+            holder = null;
+
+            // Ensure that the objects are garbage collected
+            forceGc();
+            assertEquals(ref, refQueue.poll());
+            assertTrue(provider.isFooGarbageCollected());
+
+            // The binder has died, but we don't get notified since the death recipient is GC'ed.
+            provider.killProcess();
+            Thread.sleep(1000); // give some time for the service process to die and reaped
+            assertFalse(deathRecorder.deathRecorded);
+        } else {
+            /////////////////////////////////////////////
+            // Legacy behavior
+            //
+            // Reference chain at this moment:
+            // JavaDeathRecipient --(JNI strong ref)--> FooHolder
+            // holder --(java strong ref)--> FooHolder
+            // FooHolder.mProxy --(java strong ref)--> IFoo.Proxy
+            // IFoo.Proxy.mRemote --(java strong ref)--> BinderProxy
+            // BinderProxy --(binder ref)--> Foo.Stub
+            // So, BOTH JavaDeathRecipient and holder are roots of the reference chain.
+
+            // Even if we set holder to null, it doesn't make other objects unreachable; they are
+            // still reachable via the JNI strong ref.
+            holder = null;
+
+            // Check that objects are not garbage collected
+            forceGc();
+            assertNotEquals(ref, refQueue.poll());
+            assertFalse(provider.isFooGarbageCollected());
+
+            // The legacy behavior is getting notified even when there's no reference
+            provider.killProcess();
+            Thread.sleep(1000); // give some time for the service process to die and reaped
+            assertTrue(deathRecorder.deathRecorded);
+        }
+    }
+
+    static class FooHolder implements IBinder.DeathRecipient {
+        private IFoo mProxy;
+        private DeathRecorder mDeathRecorder;
+
+        FooHolder(IFoo proxy) throws RemoteException {
+            proxy.asBinder().linkToDeath(this, 0);
+
+            // A strong reference from DeathRecipient(this) to the binder proxy is created here
+            mProxy = proxy;
+        }
+
+        public void registerDeathRecorder(DeathRecorder dr) {
+            mDeathRecorder = dr;
+        }
+
+        @Override
+        public void binderDied() {
+            if (mDeathRecorder != null) {
+                mDeathRecorder.deathRecorded = true;
+            }
+        }
+    }
+
+    static class DeathRecorder {
+        public boolean deathRecorded = false;
+    }
+
+    // Try calling System.gc() until an orphaned object is confirmed to be finalized
+    private static void forceGc() {
+        Object obj = new Object();
+        ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
+        PhantomReference<Object> ref = new PhantomReference<>(obj, refQueue);
+        obj = null; // make it an orphan
+        while (refQueue.poll() != ref) {
+            System.gc();
+        }
+    }
+
+    private static int getSdkVersion() {
+        return ApplicationProvider.getApplicationContext().getApplicationInfo().targetSdkVersion;
+    }
+}
diff --git a/tests/BinderLeakTest/java/com/android/test/binder/MyService.java b/tests/BinderLeakTest/java/com/android/test/binder/MyService.java
new file mode 100644
index 0000000..c701253
--- /dev/null
+++ b/tests/BinderLeakTest/java/com/android/test/binder/MyService.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.binder;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+
+public class MyService extends Service {
+    @Override
+    public IBinder onBind(Intent intent) {
+        return new IFooProvider.Stub() {
+            ReferenceQueue<IFoo> mRefQueue = new ReferenceQueue<>();
+            PhantomReference<IFoo> mRef;
+
+            @Override
+            public IFoo createFoo() throws RemoteException {
+                IFoo binder = new IFoo.Stub() {};
+                mRef = new PhantomReference<>(binder, mRefQueue);
+                return binder;
+            }
+
+            @Override
+            public boolean isFooGarbageCollected() throws RemoteException {
+                forceGc();
+                return mRefQueue.poll() == mRef;
+            }
+
+            @Override
+            public void killProcess() throws RemoteException {
+                android.os.Process.killProcess(android.os.Process.myPid());
+            }
+        };
+    }
+
+    private static void forceGc() {
+        Object obj = new Object();
+        ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
+        PhantomReference<Object> ref = new PhantomReference<>(obj, refQueue);
+        obj = null; // make it an orphan
+        while (refQueue.poll() != ref) {
+            System.gc();
+        }
+    }
+}
diff --git a/tests/NetworkSecurityConfigTest/res/raw/ca_certs_der.der b/tests/NetworkSecurityConfigTest/res/raw/ca_certs_der.der
index 235bd47..fd888ec 100644
--- a/tests/NetworkSecurityConfigTest/res/raw/ca_certs_der.der
+++ b/tests/NetworkSecurityConfigTest/res/raw/ca_certs_der.der
Binary files differ
diff --git a/tests/NetworkSecurityConfigTest/res/raw/ca_certs_pem.pem b/tests/NetworkSecurityConfigTest/res/raw/ca_certs_pem.pem
index 413e3c0..66f7bfd 100644
--- a/tests/NetworkSecurityConfigTest/res/raw/ca_certs_pem.pem
+++ b/tests/NetworkSecurityConfigTest/res/raw/ca_certs_pem.pem
@@ -1,35 +1,31 @@
 -----BEGIN CERTIFICATE-----
-MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw
-WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE
-AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m
-OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu
-T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c
-JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR
-Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz
-PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm
-aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM
-TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g
-LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO
-BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv
-dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB
-AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL
-NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W
-b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
-BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
-I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
-CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
-2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
-2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
+MIIFYjCCBEqgAwIBAgIQd70NbNs2+RrqIQ/E8FjTDTANBgkqhkiG9w0BAQsFADBX
+MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEQMA4GA1UE
+CxMHUm9vdCBDQTEbMBkGA1UEAxMSR2xvYmFsU2lnbiBSb290IENBMB4XDTIwMDYx
+OTAwMDA0MloXDTI4MDEyODAwMDA0MlowRzELMAkGA1UEBhMCVVMxIjAgBgNVBAoT
+GUdvb2dsZSBUcnVzdCBTZXJ2aWNlcyBMTEMxFDASBgNVBAMTC0dUUyBSb290IFIx
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAthECix7joXebO9y/lD63
+ladAPKH9gvl9MgaCcfb2jH/76Nu8ai6Xl6OMS/kr9rH5zoQdsfnFl97vufKj6bwS
+iV6nqlKr+CMny6SxnGPb15l+8Ape62im9MZaRw1NEDPjTrETo8gYbEvs/AmQ351k
+KSUjB6G00j0uYODP0gmHu81I8E3CwnqIiru6z1kZ1q+PsAewnjHxgsHA3y6mbWwZ
+DrXYfiYaRQM9sHmklCitD38m5agI/pboPGiUU+6DOogrFZYJsuB6jC511pzrp1Zk
+j5ZPaK49l8KEj8C8QMALXL32h7M1bKwYUH+E4EzNktMg6TO8UpmvMrUpsyUqtEj5
+cuHKZPfmghCN6J3Cioj6OGaK/GP5Afl4/Xtcd/p2h/rs37EOeZVXtL0m79YB0esW
+CruOC7XFxYpVq9Os6pFLKcwZpDIlTirxZUTQAs6qzkm06p98g7BAe+dDq6dso499
+iYH6TKX/1Y7DzkvgtdizjkXPdsDtQCv9Uw+wp9U7DbGKogPeMa3Md+pvez7W35Ei
+Eua++tgy/BBjFFFy3l3WFpO9KWgz7zpm7AeKJt8T11dleCfeXkkUAKIAf5qoIbap
+sZWwpbkNFhHax2xIPEDgfg1azVY80ZcFuctL7TlLnMQ/0lUTbiSw1nH69MG6zO0b
+9f6BQdgAmD06yK56mDcYBZUCAwEAAaOCATgwggE0MA4GA1UdDwEB/wQEAwIBhjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTkrysmcRorSCeFL1JmLO/wiRNxPjAf
+BgNVHSMEGDAWgBRge2YaRQ2XyolQL30EzTSo//z9SzBgBggrBgEFBQcBAQRUMFIw
+JQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnBraS5nb29nL2dzcjEwKQYIKwYBBQUH
+MAKGHWh0dHA6Ly9wa2kuZ29vZy9nc3IxL2dzcjEuY3J0MDIGA1UdHwQrMCkwJ6Al
+oCOGIWh0dHA6Ly9jcmwucGtpLmdvb2cvZ3NyMS9nc3IxLmNybDA7BgNVHSAENDAy
+MAgGBmeBDAECATAIBgZngQwBAgIwDQYLKwYBBAHWeQIFAwIwDQYLKwYBBAHWeQIF
+AwMwDQYJKoZIhvcNAQELBQADggEBADSkHrEoo9C0dhemMXoh6dFSPsjbdBZBiLg9
+NR3t5P+T4Vxfq7vqfM/b5A3Ri1fyJm9bvhdGaJQ3b2t6yMAYN/olUazsaL+yyEn9
+WprKASOshIArAoyZl+tJaox118fessmXn1hIVw41oeQa1v1vg4Fv74zPl6/AhSrw
+9U5pCZEt4Wi4wStz6dTZ/CLANx8LZh1J7QJVj2fhMtfTJr9w4z30Z209fOU0iOMy
++qduBmpvvYuR7hZL6Dupszfnw0Skfths18dG9ZKb59UhvmaSGZRVbNQpsg3BZlvi
+d0lIKO2d1xozclOzgjXPYovJJIultzkMu34qQb9Sz/yilrbCgj8=
 -----END CERTIFICATE-----
diff --git a/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml b/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml
index 5d23d36e..99106ad 100644
--- a/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml
+++ b/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml
@@ -5,7 +5,7 @@
     </domain>
     <domain>   developer.android.com    </domain>
     <pin-set>
-      <pin digest="SHA-256">  7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=  </pin>
+      <pin digest="SHA-256">  zCTnfLwLKbS9S2sbp+uFz4KZOocFvXxkV06Ce9O5M2w=  </pin>
     </pin-set>
   </domain-config>
 </network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/nested_domains.xml b/tests/NetworkSecurityConfigTest/res/xml/nested_domains.xml
index d45fd77..232f88f 100644
--- a/tests/NetworkSecurityConfigTest/res/xml/nested_domains.xml
+++ b/tests/NetworkSecurityConfigTest/res/xml/nested_domains.xml
@@ -9,7 +9,7 @@
       <domain-config>
           <domain>developer.android.com</domain>
           <pin-set>
-              <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
+              <pin digest="SHA-256">zCTnfLwLKbS9S2sbp+uFz4KZOocFvXxkV06Ce9O5M2w=</pin>
           </pin-set>
       </domain-config>
     </domain-config>
diff --git a/tests/NetworkSecurityConfigTest/res/xml/pins1.xml b/tests/NetworkSecurityConfigTest/res/xml/pins1.xml
index 1773d280..7cc81b0 100644
--- a/tests/NetworkSecurityConfigTest/res/xml/pins1.xml
+++ b/tests/NetworkSecurityConfigTest/res/xml/pins1.xml
@@ -3,7 +3,7 @@
   <domain-config>
     <domain>android.com</domain>
     <pin-set>
-      <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
+      <pin digest="SHA-256">zCTnfLwLKbS9S2sbp+uFz4KZOocFvXxkV06Ce9O5M2w=</pin>
     </pin-set>
   </domain-config>
 </network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
index 047be16..0494f17 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/NetworkSecurityConfigTests.java
@@ -22,23 +22,17 @@
 import android.test.ActivityUnitTestCase;
 import android.util.ArraySet;
 import android.util.Pair;
+
+import com.android.org.conscrypt.TrustedCertificateStore;
+
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.Socket;
-import java.net.URL;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.TrustManager;
 
-import com.android.org.conscrypt.TrustedCertificateStore;
+import javax.net.ssl.SSLContext;
 
 public class NetworkSecurityConfigTests extends ActivityUnitTestCase<Activity> {
 
@@ -46,9 +40,9 @@
         super(Activity.class);
     }
 
-    // SHA-256 of the G2 intermediate CA for android.com (as of 10/2015).
-    private static final byte[] G2_SPKI_SHA256
-            = hexToBytes("ec722969cb64200ab6638f68ac538e40abab5b19a6485661042a1061c4612776");
+    // SHA-256 of the GTS intermediate CA (CN = GTS CA 1C3) for android.com (as of 09/2023).
+    private static final byte[] GTS_INTERMEDIATE_SPKI_SHA256 =
+        hexToBytes("cc24e77cbc0b29b4bd4b6b1ba7eb85cf82993a8705bd7c64574e827bd3b9336c");
 
     private static final byte[] TEST_CA_BYTES
             = hexToBytes(
@@ -161,7 +155,7 @@
 
     public void testGoodPin() throws Exception {
         ArraySet<Pin> pins = new ArraySet<Pin>();
-        pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
+        pins.add(new Pin("SHA-256", GTS_INTERMEDIATE_SPKI_SHA256));
         NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
                 .setPinSet(new PinSet(pins, Long.MAX_VALUE))
                 .addCertificatesEntryRef(
@@ -247,7 +241,7 @@
 
     public void testWithUrlConnection() throws Exception {
         ArraySet<Pin> pins = new ArraySet<Pin>();
-        pins.add(new Pin("SHA-256", G2_SPKI_SHA256));
+        pins.add(new Pin("SHA-256", GTS_INTERMEDIATE_SPKI_SHA256));
         NetworkSecurityConfig domain = new NetworkSecurityConfig.Builder()
                 .setPinSet(new PinSet(pins, Long.MAX_VALUE))
                 .addCertificatesEntryRef(
@@ -304,7 +298,7 @@
         } finally {
             // Delete the user added CA. We don't know the alias so just delete them all.
             for (String alias : store.aliases()) {
-                if (store.isUser(alias)) {
+                if (TrustedCertificateStore.isUser(alias)) {
                     try {
                         store.deleteCertificateEntry(alias);
                     } catch (Exception ignored) {
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java
index 9dec21b..39b5cb4c 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/TestUtils.java
@@ -16,19 +16,20 @@
 
 package android.security.net.config;
 
+import static org.junit.Assert.fail;
+
 import android.content.pm.ApplicationInfo;
 import android.os.Build;
-import java.net.Socket;
+
 import java.net.URL;
+
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.TrustManager;
+import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManagerFactory;
 
-import junit.framework.Assert;
-
-public final class TestUtils extends Assert {
+public final class TestUtils {
 
     private TestUtils() {
     }
@@ -36,8 +37,8 @@
     public static void assertConnectionFails(SSLContext context, String host, int port)
             throws Exception {
         try {
-            Socket s = context.getSocketFactory().createSocket(host, port);
-            s.getInputStream();
+            SSLSocket s = (SSLSocket) context.getSocketFactory().createSocket(host, port);
+            s.startHandshake();
             fail("Expected connection to " + host + ":" + port + " to fail.");
         } catch (SSLHandshakeException expected) {
         }
@@ -45,7 +46,8 @@
 
     public static void assertConnectionSucceeds(SSLContext context, String host, int port)
             throws Exception {
-        Socket s = context.getSocketFactory().createSocket(host, port);
+        SSLSocket s = (SSLSocket) context.getSocketFactory().createSocket(host, port);
+        s.startHandshake();
         s.getInputStream();
     }
 
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index 4b7a014..81e05c1 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -16,26 +16,18 @@
 
 package android.security.net.config;
 
-import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
-import android.util.ArraySet;
-import android.util.Pair;
+
 import java.io.IOException;
 import java.net.InetAddress;
-import java.net.Socket;
-import java.net.URL;
 import java.security.KeyStore;
 import java.security.Provider;
-import java.security.Security;
 import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Set;
-import javax.net.ssl.HttpsURLConnection;
+
 import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLSocket;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
@@ -52,7 +44,7 @@
         NetworkSecurityConfig config = appConfig.getConfigForHostname("");
         assertNotNull(config);
         // Check defaults.
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
         assertFalse(config.getTrustAnchors().isEmpty());
         PinSet pinSet = config.getPins();
@@ -72,7 +64,7 @@
         NetworkSecurityConfig config = appConfig.getConfigForHostname("");
         assertNotNull(config);
         // Check defaults.
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
         assertTrue(config.getTrustAnchors().isEmpty());
         PinSet pinSet = config.getPins();
@@ -91,14 +83,14 @@
         NetworkSecurityConfig config = appConfig.getConfigForHostname("");
         assertNotNull(config);
         // Check defaults.
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
         assertTrue(config.getTrustAnchors().isEmpty());
         PinSet pinSet = config.getPins();
         assertTrue(pinSet.pins.isEmpty());
         // Check android.com.
         config = appConfig.getConfigForHostname("android.com");
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
         assertFalse(config.getTrustAnchors().isEmpty());
         pinSet = config.getPins();
@@ -188,7 +180,7 @@
         ApplicationConfig appConfig = new ApplicationConfig(source);
         assertTrue(appConfig.hasPerDomainConfigs());
         NetworkSecurityConfig config = appConfig.getConfigForHostname("android.com");
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
         assertFalse(config.getTrustAnchors().isEmpty());
         PinSet pinSet = config.getPins();
@@ -250,9 +242,9 @@
         ApplicationConfig appConfig = new ApplicationConfig(source);
         // Check android.com.
         NetworkSecurityConfig config = appConfig.getConfigForHostname("android.com");
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
-        assertEquals(2, config.getTrustAnchors().size());
+        assertEquals(1, config.getTrustAnchors().size());
         // Try connections.
         SSLContext context = TestUtils.getSSLContext(source);
         TestUtils.assertConnectionSucceeds(context, "android.com", 443);
@@ -267,9 +259,9 @@
         ApplicationConfig appConfig = new ApplicationConfig(source);
         // Check android.com.
         NetworkSecurityConfig config = appConfig.getConfigForHostname("android.com");
-        assertTrue(config.isCleartextTrafficPermitted());
+        assertFalse(config.isCleartextTrafficPermitted());
         assertFalse(config.isHstsEnforced());
-        assertEquals(2, config.getTrustAnchors().size());
+        assertEquals(1, config.getTrustAnchors().size());
         // Try connections.
         SSLContext context = TestUtils.getSSLContext(source);
         TestUtils.assertConnectionSucceeds(context, "android.com", 443);
diff --git a/tools/lint/fix/Android.bp b/tools/lint/fix/Android.bp
index 43f2122..ddacf57 100644
--- a/tools/lint/fix/Android.bp
+++ b/tools/lint/fix/Android.bp
@@ -25,6 +25,11 @@
     name: "lint_fix",
     main: "soong_lint_fix.py",
     srcs: ["soong_lint_fix.py"],
+    version: {
+        py3: {
+            embedded_launcher: true,
+        },
+    },
 }
 
 python_library_host {
diff --git a/tools/lint/fix/soong_lint_fix.py b/tools/lint/fix/soong_lint_fix.py
index acc0ad0..4a2e37e 100644
--- a/tools/lint/fix/soong_lint_fix.py
+++ b/tools/lint/fix/soong_lint_fix.py
@@ -64,27 +64,27 @@
 
 class SoongLintFix:
     """
-    This class creates a command line tool that will
-    apply lint fixes to the platform via the necessary
-    combination of soong and shell commands.
+    This class creates a command line tool that will apply lint fixes to the
+    platform via the necessary combination of soong and shell commands.
 
-    It breaks up these operations into a few "private" methods
-    that are intentionally exposed so experimental code can tweak behavior.
+    It breaks up these operations into a few "private" methods that are
+    intentionally exposed so experimental code can tweak behavior.
 
-    The entry point, `run`, will apply lint fixes using the
-    intermediate `suggested-fixes` directory that soong creates during its
-    invocation of lint.
+    The entry point, `run`, will apply lint fixes using the intermediate
+    `suggested-fixes` directory that soong creates during its invocation of
+    lint.
 
     Basic usage:
     ```
     from soong_lint_fix import SoongLintFix
 
-    SoongLintFix().run()
+    opts = SoongLintFixOptions()
+    opts.parse_args(sys.argv)
+    SoongLintFix(opts).run()
     ```
     """
-    def __init__(self):
-        self._parser = _setup_parser()
-        self._args = None
+    def __init__(self, opts):
+        self._opts = opts
         self._kwargs = None
         self._modules = []
 
@@ -96,19 +96,18 @@
         self._find_modules()
         self._lint()
 
-        if not self._args.no_fix:
+        if not self._opts.no_fix:
             self._fix()
 
-        if self._args.print:
+        if self._opts.print:
             self._print()
 
     def _setup(self):
-        self._args = self._parser.parse_args()
         env = os.environ.copy()
-        if self._args.check:
-            env["ANDROID_LINT_CHECK"] = self._args.check
-        if self._args.lint_module:
-            env["ANDROID_LINT_CHECK_EXTRA_MODULES"] = self._args.lint_module
+        if self._opts.check:
+            env["ANDROID_LINT_CHECK"] = self._opts.check
+        if self._opts.lint_module:
+            env["ANDROID_LINT_CHECK_EXTRA_MODULES"] = self._opts.lint_module
 
         self._kwargs = {
             "env": env,
@@ -131,7 +130,7 @@
         with open(f"{ANDROID_PRODUCT_OUT}/module-info.json") as f:
             module_info = json.load(f)
 
-        for module_name in self._args.modules:
+        for module_name in self._opts.modules:
             module = SoongModule(module_name)
             module.find(module_info)
             self._modules.append(module)
@@ -169,6 +168,20 @@
                 print(f.read())
 
 
+class SoongLintFixOptions:
+    """Options for SoongLintFix"""
+
+    def __init__(self):
+        self.modules = []
+        self.check = None
+        self.lint_module = None
+        self.no_fix = False
+        self.print = False
+
+    def parse_args(self, args=None):
+        _setup_parser().parse_args(args, self)
+
+
 def _setup_parser():
     parser = argparse.ArgumentParser(description="""
         This is a python script that applies lint fixes to the platform:
@@ -199,4 +212,6 @@
     return parser
 
 if __name__ == "__main__":
-    SoongLintFix().run()
+    opts = SoongLintFixOptions()
+    opts.parse_args()
+    SoongLintFix(opts).run()
diff --git a/tools/lint/utils/Android.bp b/tools/lint/utils/Android.bp
index 75e8d68..439c86d 100644
--- a/tools/lint/utils/Android.bp
+++ b/tools/lint/utils/Android.bp
@@ -43,3 +43,9 @@
         "AndroidUtilsLintChecker",
     ],
 }
+
+python_binary_host {
+    name: "enforce_permission_counter",
+    srcs: ["enforce_permission_counter.py"],
+    libs: ["soong_lint_fix"],
+}
diff --git a/tools/lint/utils/enforce_permission_counter.py b/tools/lint/utils/enforce_permission_counter.py
new file mode 100644
index 0000000..b5c2ffe
--- /dev/null
+++ b/tools/lint/utils/enforce_permission_counter.py
@@ -0,0 +1,82 @@
+#  Copyright (C) 2023 The Android Open Source Project
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+import re
+
+import soong_lint_fix
+
+# Libraries that constitute system_server.
+# It is non-trivial to keep in sync with services/Android.bp as some
+# module are post-processed (e.g, services.core).
+TARGETS = [
+        "services.core.unboosted",
+        "services.accessibility",
+        "services.appprediction",
+        "services.appwidget",
+        "services.autofill",
+        "services.backup",
+        "services.companion",
+        "services.contentcapture",
+        "services.contentsuggestions",
+        "services.coverage",
+        "services.devicepolicy",
+        "services.midi",
+        "services.musicsearch",
+        "services.net",
+        "services.people",
+        "services.print",
+        "services.profcollect",
+        "services.restrictions",
+        "services.searchui",
+        "services.smartspace",
+        "services.systemcaptions",
+        "services.translation",
+        "services.texttospeech",
+        "services.usage",
+        "services.usb",
+        "services.voiceinteraction",
+        "services.wallpapereffectsgeneration",
+        "services.wifi",
+]
+
+
+class EnforcePermissionMigratedCounter:
+    """Wrapper around lint_fix to count the number of AIDL methods annotated."""
+    def run(self):
+        opts = soong_lint_fix.SoongLintFixOptions()
+        opts.check = "AnnotatedAidlCounter"
+        opts.lint_module = "AndroidUtilsLintChecker"
+        opts.no_fix = True
+        opts.modules = TARGETS
+
+        self.linter = soong_lint_fix.SoongLintFix(opts)
+        self.linter.run()
+        self.parse_lint_reports()
+
+    def parse_lint_reports(self):
+        counts = { "unannotated": 0, "enforced": 0, "notRequired": 0 }
+        for module in self.linter._modules:
+            with open(module.lint_report, "r") as f:
+                content = f.read()
+                keys = dict(re.findall(r'(\w+)=(\d+)', content))
+                for key in keys:
+                    counts[key] += int(keys[key])
+        print(counts)
+        total = sum(counts.values())
+        annotated_percent = (1 - (counts["unannotated"] / total)) * 100
+        print("Annotated methods = %.2f%%" % (annotated_percent))
+
+
+if __name__ == "__main__":
+    EnforcePermissionMigratedCounter().run()