Merge "Close sockets from ConnectivityService#setFirewallChainEnabled"
diff --git a/.clang-format b/.clang-format
index 03af56d..021d938 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,7 +2,7 @@
 
 AccessModifierOffset: -4
 AlignOperands: false
-AllowShortFunctionsOnASingleLine: Inline
+AllowShortFunctionsOnASingleLine: Empty
 AlwaysBreakBeforeMultilineStrings: false
 ColumnLimit: 100
 CommentPragmas: NOLINT:.*
diff --git a/Android.bp b/Android.bp
index 93d1e4e..b4e02c0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -532,7 +532,7 @@
         "core/java/**/*.logtags",
         "**/package.html",
     ],
-    visibility: ["//visibility:private"],
+    visibility: ["//frameworks/base/api"],
 }
 
 // Defaults for all stubs that include the non-updatable framework. These defaults do not include
@@ -546,12 +546,10 @@
     java_version: "1.8",
     arg_files: [":frameworks-base-core-AndroidManifest.xml"],
     aidl: {
-        local_include_dirs: [
-            "media/aidl",
-            "telephony/java",
-        ],
         include_dirs: [
             "frameworks/av/aidl",
+            "frameworks/base/media/aidl",
+            "frameworks/base/telephony/java",
             "frameworks/native/libs/permission/aidl",
             "packages/modules/Bluetooth/framework/aidl-export",
             "packages/modules/Connectivity/framework/aidl-export",
@@ -583,7 +581,7 @@
     annotations_enabled: true,
     previous_api: ":android.api.public.latest",
     merge_annotations_dirs: ["metalava-manual"],
-    defaults_visibility: ["//visibility:private"],
+    defaults_visibility: ["//frameworks/base/api"],
     visibility: ["//frameworks/base/api"],
 }
 
@@ -611,12 +609,9 @@
         // NOTE: The below can be removed once the prebuilt stub contains IKE.
         "sdk_system_current_android.net.ipsec.ike",
     ],
-    defaults_visibility: ["//visibility:private"],
 }
 
 build = [
-    "StubLibraries.bp",
-    "ApiDocs.bp",
     "ProtoLibraries.bp",
     "TestProtoLibraries.bp",
 ]
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
index b995b06..3910a08 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
@@ -52,7 +52,7 @@
         }
     }
 
-    @Test
+    @Test(timeout = 900)
     public void timeClonedDateFormatTimeInstance() {
         DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/api/Android.bp b/api/Android.bp
index 9d20eca..f40f0c9 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -252,3 +252,8 @@
     out: ["api_fingerprint.txt"],
     cmd: "cat $(in) | md5sum | cut -d' ' -f1 > $(out)",
 }
+
+build = [
+    "ApiDocs.bp",
+    "StubLibraries.bp",
+]
diff --git a/ApiDocs.bp b/api/ApiDocs.bp
similarity index 97%
rename from ApiDocs.bp
rename to api/ApiDocs.bp
index a46ecce..fbcaa52 100644
--- a/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -182,10 +182,10 @@
 // using droiddoc
 /////////////////////////////////////////////////////////////////////
 
-framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+framework_docs_only_args = " -android -manifest $(location :frameworks-base-core-AndroidManifest.xml) " +
     "-metalavaApiSince " +
     "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
-    "-overview $(location core/java/overview.html) " +
+    "-overview $(location :frameworks-base-java-overview) " +
     // Federate Support Library references against local API file.
     "-federate SupportLib https://developer.android.com " +
     "-federationapi SupportLib $(location :current-support-api) " +
@@ -218,16 +218,16 @@
         "sdk.preview 0",
     ],
     arg_files: [
-        "core/res/AndroidManifest.xml",
-        "core/java/overview.html",
+        ":frameworks-base-core-AndroidManifest.xml",
+        ":frameworks-base-java-overview",
         ":current-support-api",
         ":current-androidx-api",
     ],
     // TODO(b/169090544): remove below aidl includes.
     aidl: {
-        local_include_dirs: ["media/aidl"],
         include_dirs: [
             "frameworks/av/aidl",
+            "frameworks/base/media/aidl",
             "frameworks/native/libs/permission/aidl",
         ],
     },
diff --git a/StubLibraries.bp b/api/StubLibraries.bp
similarity index 99%
rename from StubLibraries.bp
rename to api/StubLibraries.bp
index b005591..f08745b 100644
--- a/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -515,6 +515,7 @@
     ],
     api_levels_sdk_type: "public",
     extensions_info_file: ":sdk-extensions-info",
+    visibility: ["//frameworks/base"],
 }
 
 droidstubs {
diff --git a/api/docs b/api/docs
new file mode 120000
index 0000000..a9594bf
--- /dev/null
+++ b/api/docs
@@ -0,0 +1 @@
+../docs
\ No newline at end of file
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 025e862..0100f0e 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -143,12 +143,16 @@
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
     SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler):
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRouting.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler):
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaCodec#setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaCodec.setOnFrameRenderedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaPlayer#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 7df3d1e..8ceea92 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -429,6 +429,11 @@
     },
 }
 
+filegroup {
+    name: "frameworks-base-java-overview",
+    srcs: ["overview.html"],
+}
+
 // Avoid including Parcelable classes as we don't want to have two copies of
 // Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
 // and TeleService app (packages/services/Telephony).
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
index e857c72..80ecaa4 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -3,3 +3,5 @@
 markpun@google.com
 lpeter@google.com
 tymtsai@google.com
+hackz@google.com
+volnov@google.com
\ No newline at end of file
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index a6c79b3..9179f5d 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2228,6 +2228,12 @@
                 } else {
                     List<CaptureResult> partialResults =
                             mFrameNumberTracker.popPartialResults(frameNumber);
+                    if (mBatchOutputMap.containsKey(requestId)) {
+                        int requestCount = mBatchOutputMap.get(requestId);
+                        for (int i = 1; i < requestCount; i++) {
+                            mFrameNumberTracker.popPartialResults(frameNumber - (requestCount - i));
+                        }
+                    }
 
                     final long sensorTimestamp =
                             result.get(CaptureResult.SENSOR_TIMESTAMP);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index bb74e19..89da45b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1360,7 +1360,7 @@
         String formatSize = MemoryProperties.memory_ddr_size().orElse("0KB");
         long memSize = FileUtils.parseSize(formatSize);
 
-        if (memSize == Long.MIN_VALUE) {
+        if (memSize <= 0) {
             return FileUtils.roundStorageSize(getTotalMemory());
         }
 
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
index 462d8be..162e029 100644
--- a/core/java/android/speech/OWNERS
+++ b/core/java/android/speech/OWNERS
@@ -2,3 +2,4 @@
 eugeniom@google.com
 schfan@google.com
 andreaambu@google.com
+hackz@google.com
\ No newline at end of file
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 1a5cb1e4..d1eda96 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -5,3 +5,5 @@
 markpun@google.com
 lpeter@google.com
 tymtsai@google.com
+hackz@google.com
+volnov@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS
index 352c132..2f3bbee 100644
--- a/core/java/com/android/internal/jank/OWNERS
+++ b/core/java/com/android/internal/jank/OWNERS
@@ -3,4 +3,5 @@
 # Jank people
 ahanwu@google.com
 vadimt@google.com
-marcinoc@google.com
\ No newline at end of file
+marcinoc@google.com
+pmuetschard@google.com
\ No newline at end of file
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 6919a76..7c8ea93 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -646,9 +646,7 @@
     char saveResolvedClassesDelayMsOptsBuf[
             sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];
     char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX];
-    char profileMinFirstSaveOptsBuf[
-            sizeof("-Xps-min-first-save-ms:")-1 + PROPERTY_VALUE_MAX];
-    char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX];
+    char profileMinFirstSaveOptsBuf[sizeof("-Xps-min-first-save-ms:") - 1 + PROPERTY_VALUE_MAX];
     char madviseWillNeedFileSizeVdex[
             sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX];
     char madviseWillNeedFileSizeOdex[
@@ -861,13 +859,8 @@
                        jitprithreadweightOptBuf,
                        "-Xjitprithreadweight:");
 
-    parseRuntimeOption("dalvik.vm.jittransitionweight",
-                       jittransitionweightOptBuf,
+    parseRuntimeOption("dalvik.vm.jittransitionweight", jittransitionweightOptBuf,
                        "-Xjittransitionweight:");
-    /*
-     * Madvise related options.
-     */
-    parseRuntimeOption("dalvik.vm.madvise-random", madviseRandomOptsBuf, "-XX:MadviseRandomAccess:");
 
     /*
      * Use default platform configuration as limits for madvising,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 277bdf3..35dc8e3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2328,6 +2328,8 @@
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+        android:description="@string/permdesc_nfcTransactionEvent"
+        android:label="@string/permlab_nfcTransactionEvent"
       android:protectionLevel="normal" />
 
     <!-- Allows applications to receive NFC preferred payment service information.
@@ -4237,11 +4239,11 @@
                 android:protectionLevel="internal|preinstalled" />
 
     <!-- Allows an application to subscribe to keyguard locked (i.e., showing) state.
-         <p>Protection level: internal|role
-         <p>Intended for use by ROLE_ASSISTANT only.
+         <p>Protection level: signature|role
+         <p>Intended for use by ROLE_ASSISTANT and signature apps only.
     -->
     <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE"
-                android:protectionLevel="internal|role"/>
+                android:protectionLevel="signature|role"/>
 
     <!-- Must be required by a {@link android.service.autofill.AutofillService},
          to ensure that only the system can bind to it.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4b05f99..031a666 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4475,6 +4475,9 @@
     <!-- Whether or not we should show the option to show battery percentage -->
     <bool name="config_battery_percentage_setting_available">true</bool>
 
+    <!-- Default value set for battery percentage in status bar false = disabled, true = enabled -->
+    <bool name="config_defaultBatteryPercentageSetting">false</bool>
+
     <!-- Whether or not battery saver should be "sticky" when manually enabled. -->
     <bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8a1b74d..5a1e0e8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1604,6 +1604,12 @@
       with Near Field Communication (NFC) tags, cards, and readers.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_nfcTransactionEvent">Secure Element transaction event</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_nfcTransactionEvent">Allows the app to receive information about
+      transactions happening on a Secure Element.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_disableKeyguard">disable your screen lock</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_disableKeyguard">Allows the app to disable the
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ba1030b..716d1bd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2359,6 +2359,7 @@
   <java-symbol type="style" name="Animation.RecentApplications" />
   <java-symbol type="integer" name="dock_enter_exit_duration" />
   <java-symbol type="bool" name="config_battery_percentage_setting_available" />
+  <java-symbol type="bool" name="config_defaultBatteryPercentageSetting" />
   <java-symbol type="string" name="nas_upgrade_notification_title" />
   <java-symbol type="string" name="nas_upgrade_notification_content" />
   <java-symbol type="string" name="nas_upgrade_notification_enable_action" />
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index 52846df..b2ffdc0 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -73,6 +73,7 @@
     }
 
     public void testGetAdvertisedMem() {
+        assertTrue(Process.getAdvertisedMem() > 0);
         assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
     }
 }
diff --git a/libs/androidfw/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h
index 3dbf997d..38ece5c1 100644
--- a/libs/androidfw/include/androidfw/ObbFile.h
+++ b/libs/androidfw/include/androidfw/ObbFile.h
@@ -43,10 +43,6 @@
     bool removeFrom(const char* filename);
     bool removeFrom(int fd);
 
-    const char* getFileName() const {
-        return mFileName;
-    }
-
     const String8 getPackageName() const {
         return mPackageName;
     }
@@ -127,8 +123,6 @@
     /* The encryption salt. */
     unsigned char mSalt[8];
 
-    const char* mFileName;
-
     size_t mFooterStart;
 
     bool parseObbFile(int fd);
diff --git a/mime/java/Android.bp b/mime/java/Android.bp
index 07cada8e..a267d65 100644
--- a/mime/java/Android.bp
+++ b/mime/java/Android.bp
@@ -10,5 +10,8 @@
 filegroup {
     name: "framework-mime-sources",
     srcs: ["**/*.java"],
-    visibility: ["//frameworks/base"],
+    visibility: [
+        "//frameworks/base",
+        "//frameworks/base/api",
+    ],
 }
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index 9e0a6eb..294ca9c 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -86,7 +86,7 @@
             return nullptr;
         }
 
-        String16 fileName(obbFile->getFileName());
+        String16 fileName(canonicalPath);
         String16 packageName(obbFile->getPackageName());
         size_t length;
         const unsigned char* salt = obbFile->getSalt(&length);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 879181f..2d958a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -6,6 +6,7 @@
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothCsipSetCoordinator;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -162,14 +163,21 @@
                     resources, ((BitmapDrawable) pair.first).getBitmap()), pair.second);
         }
 
+        int hashCode;
+        if ((cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) {
+            hashCode = new Integer(cachedDevice.getGroupId()).hashCode();
+        } else {
+            hashCode = cachedDevice.getAddress().hashCode();
+        }
+
         return new Pair<>(buildBtRainbowDrawable(context,
-                pair.first, cachedDevice.getAddress().hashCode()), pair.second);
+                pair.first, hashCode), pair.second);
     }
 
     /**
      * Build Bluetooth device icon with rainbow
      */
-    public static Drawable buildBtRainbowDrawable(Context context, Drawable drawable,
+    private static Drawable buildBtRainbowDrawable(Context context, Drawable drawable,
             int hashCode) {
         final Resources resources = context.getResources();
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 6748e9c..6ef5d73 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1502,8 +1502,7 @@
             refresh();
         }
 
-        return new Pair<>(BluetoothUtils.buildBtRainbowDrawable(
-                        mContext, pair.first, getAddress().hashCode()), pair.second);
+        return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this);
     }
 
     void releaseLruCache() {
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 03d999f..9f948a7 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -325,7 +325,9 @@
         // TODO(b/140051051)
         final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
                 .getIntForUser(getContext().getContentResolver(),
-                SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT));
+                SHOW_BATTERY_PERCENT, getContext().getResources().getBoolean(
+                com.android.internal.R.bool.config_defaultBatteryPercentageSetting)
+                ? 1 : 0, UserHandle.USER_CURRENT));
         boolean shouldShow =
                 (mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
                 || mShowPercentMode == MODE_ON
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 175f6c1..148688f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10784,6 +10784,13 @@
                 pw.println("\n\n** Cache info for pid " + pid + " [" + r.processName + "] **");
                 pw.flush();
                 try {
+                    if (pid == Process.myPid()) {
+                        // Directly dump to target fd for local dump to avoid hang.
+                        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fd.getInt$())) {
+                            thread.dumpCacheInfo(pfd, args);
+                        }
+                        continue;
+                    }
                     TransferPipe tp = new TransferPipe();
                     try {
                         thread.dumpCacheInfo(tp.getWriteFd(), args);
diff --git a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
index ff78355..6268082 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
@@ -338,7 +338,7 @@
                 pw.print(prefix);
                 pw.print(mKeyNumOfEventsThreshold);
                 pw.print('=');
-                pw.println(mDefaultNumOfEventsThreshold);
+                pw.println(mNumOfEventsThreshold);
             }
             pw.print(prefix);
             pw.print("event_time_slot_size=");
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c678a92..4208a12 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -3677,8 +3677,11 @@
                     encapType = IkeSessionParams.ESP_ENCAP_TYPE_NONE;
                     break;
                 default:
-                    ipVersion = IkeSessionParams.ESP_IP_VERSION_AUTO;
-                    encapType = IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
+                    // By default, PREFERRED_IKE_PROTOCOL_IPV4_UDP is used for safety. This is
+                    // because some carriers' networks do not support IPv6 very well, and using
+                    // IPv4 can help to prevent problems.
+                    ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV4;
+                    encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP;
                     break;
             }
             return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index dcf1906..d285337 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -220,6 +220,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
@@ -801,6 +802,16 @@
             }
             return buckets;
         }
+
+        /** Require IPC call. Don't call when holding a lock. */
+        int getDefaultDataSubId() {
+            return SubscriptionManager.getDefaultDataSubscriptionId();
+        }
+
+        /** Require IPC call. Don't call when holding a lock. */
+        int getActivateDataSubId() {
+            return SubscriptionManager.getActiveDataSubscriptionId();
+        }
     }
 
     @VisibleForTesting
@@ -828,7 +839,7 @@
 
         mSuppressDefaultPolicy = suppressDefaultPolicy;
         mDeps = Objects.requireNonNull(deps, "missing Dependencies");
-
+        mActiveDataSubIdListener = new ActiveDataSubIdListener();
         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
 
         mAppOps = context.getSystemService(AppOpsManager.class);
@@ -1088,6 +1099,10 @@
                         }
                     });
 
+            // Listen for active data sub Id change, upon which data notifications is shown/hidden.
+            mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor,
+                    mActiveDataSubIdListener);
+
             // tell systemReady() that the service has been initialized
             initCompleteSignal.countDown();
         } finally {
@@ -1257,6 +1272,38 @@
     };
 
     /**
+     * Listener that watches for active data sub Id change, upon which data notifications are
+     * shown/hidden.
+     */
+    private final ActiveDataSubIdListener mActiveDataSubIdListener;
+    private class ActiveDataSubIdListener extends TelephonyCallback implements
+            TelephonyCallback.ActiveDataSubscriptionIdListener {
+        /**
+         * In most cases active data sub is the same as the default data sub, but if user enabled
+         * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH},
+         * active data sub could be the non-default data sub.
+         *
+         * If the listener is initialized before the phone process is up, the IPC call to the
+         * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned,
+         * indicating the phone process is unable to determine a valid data sub Id at this point, in
+         * which case no data notifications should be shown anyway. Later on when an active data
+         * sub is known, notifications will be re-evaluated by this callback.
+         */
+        private int mDefaultDataSubId = mDeps.getDefaultDataSubId();
+        private int mActiveDataSubId = mDeps.getActivateDataSubId();
+        // Only listen to active data sub change is sufficient because default data sub change
+        // leads to active data sub change as well.
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveDataSubId = subId;
+            mDefaultDataSubId = mDeps.getDefaultDataSubId();
+            synchronized (mNetworkPoliciesSecondLock) {
+                updateNotificationsNL();
+            }
+        }
+    }
+
+    /**
      * Listener that watches for {@link NetworkStatsManager} updates, which
      * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}.
      */
@@ -1445,6 +1492,9 @@
 
             // ignore policies that aren't relevant to user
             if (subId == INVALID_SUBSCRIPTION_ID) continue;
+            // ignore if the data sub is neither default nor active for data at the moment.
+            if (subId != mActiveDataSubIdListener.mDefaultDataSubId
+                    && subId != mActiveDataSubIdListener.mActiveDataSubId) continue;
             if (!policy.hasCycle()) continue;
 
             final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 035249e..a4a35dc 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -344,6 +344,7 @@
         assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_succeedsWithCertFile() throws Exception {
         int uid = Binder.getCallingUid();
@@ -365,6 +366,7 @@
         assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_updatesShouldCreatesnapshotOnCertUpdate() throws Exception {
         int uid = Binder.getCallingUid();
@@ -392,6 +394,7 @@
         assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_triesToFilterRootAlias() throws Exception {
         int uid = Binder.getCallingUid();
@@ -413,6 +416,7 @@
 
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_usesProdCertificateForEmptyRootAlias() throws Exception {
         int uid = Binder.getCallingUid();
@@ -433,6 +437,7 @@
         assertThat(activeRootAlias).isEqualTo(DEFAULT_ROOT_CERT_ALIAS);
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_usesProdCertificateForNullRootAlias() throws Exception {
         int uid = Binder.getCallingUid();
@@ -453,6 +458,7 @@
         assertThat(activeRootAlias).isEqualTo(DEFAULT_ROOT_CERT_ALIAS);
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_regeneratesCounterId() throws Exception {
         int uid = Binder.getCallingUid();
@@ -483,6 +489,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_updatesWithLargerSerial() throws Exception {
         int uid = Binder.getCallingUid();
@@ -500,6 +507,7 @@
         assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_throwsExceptionOnSmallerSerial() throws Exception {
         int uid = Binder.getCallingUid();
@@ -565,6 +573,7 @@
                         TestData.getInsecureCertPathForEndpoint1());
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryService_ignoresTheSameSerial() throws Exception {
         int uid = Binder.getCallingUid();
@@ -615,6 +624,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryServiceWithSigFile_succeeds() throws Exception {
         int uid = Binder.getCallingUid();
@@ -630,6 +640,7 @@
         assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void initRecoveryServiceWithSigFile_usesProdCertificateForNullRootAlias()
             throws Exception {
@@ -723,6 +734,7 @@
                         eq(Manifest.permission.RECOVER_KEYSTORE), any());
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void startRecoverySessionWithCertPath_storesTheSessionInfo() throws Exception {
         mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
@@ -740,6 +752,7 @@
         assertEquals(KEY_CLAIMANT_LENGTH_BYTES, entry.getKeyClaimant().length);
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void startRecoverySessionWithCertPath_checksPermissionFirst() throws Exception {
         mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
@@ -809,6 +822,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void startRecoverySession_throwsIfBadNumberOfSecrets() throws Exception {
         try {
@@ -825,6 +839,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void startRecoverySession_throwsIfPublicKeysMismatch() throws Exception {
         byte[] vaultParams = TEST_VAULT_PARAMS.clone();
@@ -843,6 +858,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void startRecoverySessionWithCertPath_throwsIfBadNumberOfSecrets() throws Exception {
         try {
@@ -860,6 +876,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/281583079")
     @Test
     public void startRecoverySessionWithCertPath_throwsIfPublicKeysMismatch() throws Exception {
         byte[] vaultParams = TEST_VAULT_PARAMS.clone();
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 7c7e2ee..012596e 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -151,6 +151,7 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
@@ -241,6 +242,7 @@
     private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey";
     private static final String TEST_IMSI = "310210";
     private static final int TEST_SUB_ID = 42;
+    private static final int TEST_SUB_ID2 = 24;
     private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS);
 
     private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI)
@@ -282,6 +284,8 @@
     private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
             ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
 
+    private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener;
+
     private ActivityManagerInternal mActivityManagerInternal;
     private PackageManagerInternal mPackageManagerInternal;
 
@@ -357,6 +361,8 @@
 
     private class TestDependencies extends NetworkPolicyManagerService.Dependencies {
         private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>();
+        private int mMockDefaultDataSubId;
+        private int mMockedActiveDataSubId;
 
         TestDependencies(Context context) {
             super(context);
@@ -394,6 +400,21 @@
             final NetworkStats.Bucket bucket = mMockedStats.get(uid);
             setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes);
         }
+
+        void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) {
+            mMockDefaultDataSubId = defaultDataSubId;
+            mMockedActiveDataSubId = activeDataSubId;
+        }
+
+        @Override
+        int getDefaultDataSubId() {
+            return mMockDefaultDataSubId;
+        }
+
+        @Override
+        int getActivateDataSubId() {
+            return mMockedActiveDataSubId;
+        }
     }
 
     @Before
@@ -551,6 +572,14 @@
         NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, "");
         mDefaultWarningBytes = defaultPolicy.warningBytes;
         mDefaultLimitBytes = defaultPolicy.limitBytes;
+
+        // Catch TelephonyCallback during systemReady().
+        ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor =
+                ArgumentCaptor.forClass(TelephonyCallback.class);
+        verify(mTelephonyManager).registerTelephonyCallback(any(),
+                telephonyCallbackArgumentCaptor.capture());
+        mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener)
+                telephonyCallbackArgumentCaptor.getValue();
     }
 
     @After
@@ -1243,6 +1272,7 @@
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1258,6 +1288,7 @@
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1275,6 +1306,7 @@
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
             expectDefaultCarrierConfig();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1291,6 +1323,7 @@
 
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.updateNetworks();
 
@@ -1304,6 +1337,7 @@
         {
             reset(mTelephonyManager, mNetworkManager, mNotifManager);
             TelephonyManager tmSub = expectMobileDefaults();
+            clearInvocations(mNotifManager);
 
             mService.snoozeLimit(sTemplateCarrierMetered);
             mService.updateNetworks();
@@ -1314,6 +1348,31 @@
             verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
                     isA(Notification.class), eq(UserHandle.ALL));
         }
+        // The sub is no longer used for data(e.g. user uses another sub), hide the notifications.
+        {
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+            notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2);
+            verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED));
+        }
+        // The sub is not active for data(e.g. due to auto data switch), but still default for data,
+        // show notification.
+        {
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+            notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2);
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+                    isA(Notification.class), eq(UserHandle.ALL));
+        }
+        // The sub is active for data, but not the default(e.g. due to auto data switch),
+        // show notification.
+        {
+            reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+            notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID);
+            verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+                    isA(Notification.class), eq(UserHandle.ALL));
+        }
     }
 
     @Test
@@ -2377,6 +2436,7 @@
             String subscriberId) {
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
                 createSubscriptionInfoList(subscriptionId));
+        notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId);
 
         TelephonyManager subTelephonyManager;
         subTelephonyManager = mock(TelephonyManager.class);
@@ -2388,6 +2448,16 @@
     }
 
     /**
+     * Telephony Manager callback notifies data sub Id changes.
+     * @param defaultDataSubId The mock default data sub Id.
+     * @param activeDataSubId The mock active data sub Id.
+     */
+    private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) {
+        mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId);
+        mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId);
+    }
+
+    /**
      * Creates mock {@link SubscriptionInfo} from subscription id.
      */
     private List<SubscriptionInfo> createSubscriptionInfoList(int subId) {
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 0170c4a..2f5d8d1 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -206,6 +206,11 @@
     AddOptionalFlag("--compile-sdk-version-name",
         "Version name to inject into the AndroidManifest.xml if none is present.",
         &options_.manifest_fixer_options.compile_sdk_version_codename);
+    AddOptionalSwitch(
+        "--no-compile-sdk-metadata",
+        "Suppresses output of compile SDK-related attributes in AndroidManifest.xml,\n"
+        "including android:compileSdkVersion and platformBuildVersion.",
+        &options_.manifest_fixer_options.no_compile_sdk_metadata);
     AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
         &shared_lib_);
     AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 4219191..f8e7347 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -635,7 +635,7 @@
     root->InsertChild(0, std::move(uses_sdk));
   }
 
-  if (options_.compile_sdk_version) {
+  if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) {
     xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
 
     // Make sure we un-compile the value if it was set to something else.
@@ -647,10 +647,9 @@
     // Make sure we un-compile the value if it was set to something else.
     attr->compiled_value = {};
     attr->value = options_.compile_sdk_version.value();
-
   }
 
-  if (options_.compile_sdk_version_codename) {
+  if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) {
     xml::Attribute* attr =
         root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
 
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index a8707d9..70bfcfc 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -68,11 +68,12 @@
   std::optional<std::string> revision_code_default;
 
   // The version of the framework being compiled against to set for 'android:compileSdkVersion' in
-  // the <manifest> tag.
+  // the <manifest> tag. Not used if no_compile_sdk_metadata is set.
   std::optional<std::string> compile_sdk_version;
 
   // The version codename of the framework being compiled against to set for
-  // 'android:compileSdkVersionCodename' in the <manifest> tag.
+  // 'android:compileSdkVersionCodename' in the <manifest> tag. Not used if no_compile_sdk_metadata
+  // is set.
   std::optional<std::string> compile_sdk_version_codename;
 
   // Whether validation errors should be treated only as warnings. If this is 'true', then an
@@ -85,6 +86,9 @@
 
   // Whether to replace the manifest version with the the command line version
   bool replace_version = false;
+
+  // Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes.
+  bool no_compile_sdk_metadata = false;
 };
 
 // Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 098d0be..9204d22 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -892,6 +892,35 @@
   EXPECT_THAT(attr->value, StrEq("P"));
 }
 
+TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) {
+  std::string input = R"(<manifest package="com.pkg" />)";
+  ManifestFixerOptions options;
+  options.no_compile_sdk_metadata = true;
+  options.compile_sdk_version = {"28"};
+  options.compile_sdk_version_codename = {"P"};
+
+  std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
+  ASSERT_THAT(manifest, NotNull());
+
+  // There should be a declaration of kSchemaAndroid, even when the input
+  // didn't have one.
+  EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
+  EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
+  EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
+
+  xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+  ASSERT_THAT(attr, IsNull());
+
+  attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+  ASSERT_THAT(attr, IsNull());
+
+  attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+  ASSERT_THAT(attr, IsNull());
+
+  attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+  ASSERT_THAT(attr, IsNull());
+}
+
 TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
   std::string input = R"(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"