Merge "Do not use @SystemApi(client = MODULE_APPS) (documents/settings)"
diff --git a/apex/Android.bp b/apex/Android.bp
index c3b0014..362cf95 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -26,6 +26,19 @@
     "--hide Typo " +
     "--hide UnavailableSymbol "
 
+// TODO: remove this server classes are cleaned up.
+mainline_stubs_args += "--hide-package com.android.server "
+
+priv_apps = " " +
+    "--show-annotation android.annotation.SystemApi\\(" +
+        "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
+    "\\) "
+
+module_libs = " " +
+    " --show-annotation android.annotation.SystemApi\\(" +
+        "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES," +
+    "\\) "
+
 stubs_defaults {
     name: "framework-module-stubs-defaults-publicapi",
     args: mainline_stubs_args,
@@ -34,36 +47,23 @@
 
 stubs_defaults {
     name: "framework-module-stubs-defaults-systemapi",
-    args: mainline_stubs_args +
-    " --show-annotation android.annotation.SystemApi\\(" +
-    "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
-    "process=android.annotation.SystemApi.Process.ALL\\) ",
+    args: mainline_stubs_args + priv_apps,
     installable: false,
 }
 
+// The defaults for module_libs comes in two parts - defaults for API checks
+// and defaults for stub generation. This is because we want the API txt
+// files to *only* include the module_libs_api, but the stubs to include
+// module_libs_api as well as priv_apps.
+
 stubs_defaults {
-    name: "framework-module-stubs-defaults-module_apps_api",
-    args: mainline_stubs_args +
-    " --show-annotation android.annotation.SystemApi\\(" +
-    "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
-    "process=android.annotation.SystemApi.Process.ALL\\) " +
-    " --show-annotation android.annotation.SystemApi\\(" +
-    "client=android.annotation.SystemApi.Client.MODULE_APPS," +
-    "process=android.annotation.SystemApi.Process.ALL\\) ",
+    name: "framework-module-api-defaults-module_libs_api",
+    args: mainline_stubs_args + module_libs,
     installable: false,
 }
 
 stubs_defaults {
     name: "framework-module-stubs-defaults-module_libs_api",
-    args: mainline_stubs_args +
-    " --show-annotation android.annotation.SystemApi\\(" +
-    "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS," +
-    "process=android.annotation.SystemApi.Process.ALL\\) " +
-    " --show-annotation android.annotation.SystemApi\\(" +
-    "client=android.annotation.SystemApi.Client.MODULE_APPS," +
-    "process=android.annotation.SystemApi.Process.ALL\\) " +
-    " --show-annotation android.annotation.SystemApi\\(" +
-    "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES," +
-    "process=android.annotation.SystemApi.Process.ALL\\) ",
+    args: mainline_stubs_args + module_libs + priv_apps,
     installable: false,
 }
diff --git a/api/system-current.txt b/api/system-current.txt
index 5f17b32..f8f0036 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6515,13 +6515,13 @@
 
   public class UpdateEngine {
     ctor public UpdateEngine();
-    method @NonNull public android.os.UpdateEngine.AllocateSpaceResult allocateSpace(@NonNull String, @NonNull String[]);
+    method @NonNull @WorkerThread public android.os.UpdateEngine.AllocateSpaceResult allocateSpace(@NonNull String, @NonNull String[]);
     method public void applyPayload(String, long, long, String[]);
     method public void applyPayload(@NonNull android.content.res.AssetFileDescriptor, @NonNull String[]);
     method public boolean bind(android.os.UpdateEngineCallback, android.os.Handler);
     method public boolean bind(android.os.UpdateEngineCallback);
     method public void cancel();
-    method public int cleanupAppliedPayload();
+    method @WorkerThread public int cleanupAppliedPayload();
     method public void resetStatus();
     method public void resume();
     method public void suspend();
@@ -6530,8 +6530,8 @@
   }
 
   public static final class UpdateEngine.AllocateSpaceResult {
-    method public int errorCode();
-    method public long freeSpaceRequired();
+    method public int getErrorCode();
+    method public long getFreeSpaceRequired();
   }
 
   public static final class UpdateEngine.ErrorCodeConstants {
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index 50de7385..da51ce2 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -29,10 +29,18 @@
 import java.util.Objects;
 
 /**
- * A time signal from a manual (user provided) source. The value consists of the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime
- * clock when that number was established. The elapsed realtime clock is considered accurate but
- * volatile, so time signals must not be persisted across device resets.
+ * A time signal from a manual (user provided) source.
+ *
+ * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
+ * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
+ * elapsed realtime clock when the {@code utcTime.value} was established.
+ * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
+ * suggestions cannot be persisted across device resets.
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists and how it was entered. This information exists only to aid in
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
+ * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
  *
  * @hide
  */
@@ -49,10 +57,8 @@
                 }
             };
 
-    @NonNull
-    private final TimestampedValue<Long> mUtcTime;
-    @Nullable
-    private ArrayList<String> mDebugInfo;
+    @NonNull private final TimestampedValue<Long> mUtcTime;
+    @Nullable private ArrayList<String> mDebugInfo;
 
     public ManualTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
         mUtcTime = Objects.requireNonNull(utcTime);
diff --git a/core/java/android/app/timedetector/NetworkTimeSuggestion.java b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
index 17e9c5a..89fd6f31 100644
--- a/core/java/android/app/timedetector/NetworkTimeSuggestion.java
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
@@ -29,10 +29,18 @@
 import java.util.Objects;
 
 /**
- * A time signal from a network time source like NTP. The value consists of the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime
- * clock when that number was established. The elapsed realtime clock is considered accurate but
- * volatile, so time signals must not be persisted across device resets.
+ * A time signal from a network time source like NTP.
+ *
+ * <p>{@code utcTime} contains the suggested time. The {@code utcTime.value} is the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the
+ * value of the elapsed realtime clock when the {@code utcTime.value} was established.
+ * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
+ * suggestions cannot be persisted across device resets.
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists and how it was determined. This information exists only to aid
+ * in debugging and therefore is used by {@link #toString()}, but it is not for use in detection
+ * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
  *
  * @hide
  */
@@ -49,10 +57,8 @@
                 }
             };
 
-    @NonNull
-    private final TimestampedValue<Long> mUtcTime;
-    @Nullable
-    private ArrayList<String> mDebugInfo;
+    @NonNull private final TimestampedValue<Long> mUtcTime;
+    @Nullable private ArrayList<String> mDebugInfo;
 
     public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
         mUtcTime = Objects.requireNonNull(utcTime);
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index eab8838..16288e8 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -32,12 +32,22 @@
  * A time suggestion from an identified telephony source. e.g. from NITZ information from a specific
  * radio.
  *
- * <p>The time value can be {@code null} to indicate that the telephony source has entered an
- * "un-opinionated" state and any previous suggestions from the source are being withdrawn. When not
- * {@code null}, the value consists of the number of milliseconds elapsed since 1/1/1970 00:00:00
- * UTC and the time according to the elapsed realtime clock when that number was established. The
- * elapsed realtime clock is considered accurate but volatile, so time suggestions must not be
- * persisted across device resets.
+ * <p>{@code slotIndex} identifies the suggestion source. This enables detection logic to identify
+ * suggestions from the same source when there are several in use.
+ *
+ * <p>{@code utcTime}. When not {@code null}, the {@code utcTime.value} is the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the
+ * value of the elapsed realtime clock when the {@code utcTime.value} was established.
+ * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
+ * suggestions cannot be persisted across device resets. {@code utcTime} can be {@code null} to
+ * indicate that the telephony source has entered an "un-opinionated" state and any previous
+ * suggestion from the source is being withdrawn.
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists, e.g. what triggered it to be made and what heuristic was used
+ * to determine the time or its absence. This information exists only to aid in debugging and
+ * therefore is used by {@link #toString()}, but it is not for use in detection logic and is not
+ * considered in {@link #hashCode()} or {@link #equals(Object)}.
  *
  * @hide
  */
@@ -93,16 +103,18 @@
     }
 
     /**
-     * Returns an identifier for the source of this suggestion. When a device has several sim slots
-     * or equivalent, it is used to identify which one the suggestion is from.
+     * Returns an identifier for the source of this suggestion.
+     *
+     * <p>See {@link PhoneTimeSuggestion} for more information about {@code slotIndex}.
      */
     public int getSlotIndex() {
         return mSlotIndex;
     }
 
     /**
-     * Returns the suggestion. {@code null} means that the caller is no longer sure what time it
-     * is.
+     * Returns the suggested time or {@code null} if there isn't one.
+     *
+     * <p>See {@link PhoneTimeSuggestion} for more information about {@code utcTime}.
      */
     @Nullable
     public TimestampedValue<Long> getUtcTime() {
@@ -110,8 +122,9 @@
     }
 
     /**
-     * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
-     * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+     * Returns debug metadata for the suggestion.
+     *
+     * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
      */
     @NonNull
     public List<String> getDebugInfo() {
@@ -120,9 +133,9 @@
     }
 
     /**
-     * Associates information with the instance that can be useful for debugging / logging. The
-     * information is present in {@link #toString()} but is not considered for
-     * {@link #equals(Object)} and {@link #hashCode()}.
+     * Associates information with the instance that can be useful for debugging / logging.
+     *
+     * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
      */
     public void addDebugInfo(@NonNull String debugInfo) {
         if (mDebugInfo == null) {
@@ -132,9 +145,9 @@
     }
 
     /**
-     * Associates information with the instance that can be useful for debugging / logging. The
-     * information is present in {@link #toString()} but is not considered for
-     * {@link #equals(Object)} and {@link #hashCode()}.
+     * Associates information with the instance that can be useful for debugging / logging.
+     *
+     * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
      */
     public void addDebugInfo(@NonNull List<String> debugInfo) {
         if (mDebugInfo == null) {
@@ -181,12 +194,20 @@
         @Nullable private TimestampedValue<Long> mUtcTime;
         @Nullable private List<String> mDebugInfo;
 
-        /** Creates a builder with the specified {@code slotIndex}. */
+        /**
+         * Creates a builder with the specified {@code slotIndex}.
+         *
+         * <p>See {@link PhoneTimeSuggestion} for more information about {@code slotIndex}.
+         */
         public Builder(int slotIndex) {
             mSlotIndex = slotIndex;
         }
 
-        /** Returns the builder for call chaining. */
+        /**
+         * Returns the builder for call chaining.
+         *
+         * <p>See {@link PhoneTimeSuggestion} for more information about {@code utcTime}.
+         */
         @NonNull
         public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
             if (utcTime != null) {
@@ -198,7 +219,11 @@
             return this;
         }
 
-        /** Returns the builder for call chaining. */
+        /**
+         * Returns the builder for call chaining.
+         *
+         * <p>See {@link PhoneTimeSuggestion} for more information about {@code debugInfo}.
+         */
         @NonNull
         public Builder addDebugInfo(@NonNull String debugInfo) {
             if (mDebugInfo == null) {
diff --git a/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
index a6b953b..3a9adc7 100644
--- a/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
@@ -28,10 +28,14 @@
 import java.util.Objects;
 
 /**
- * A time signal from a manual (user provided) source. The value consists of the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime
- * clock when that number was established. The elapsed realtime clock is considered accurate but
- * volatile, so time signals must not be persisted across device resets.
+ * A time signal from a manual (user provided) source.
+ *
+ * <p>{@code zoneId} contains the suggested time zone ID, e.g. "America/Los_Angeles".
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists and how it was entered. This information exists only to aid in
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection logic
+ * and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
  *
  * @hide
  */
@@ -48,10 +52,8 @@
                 }
             };
 
-    @NonNull
-    private final String mZoneId;
-    @Nullable
-    private ArrayList<String> mDebugInfo;
+    @NonNull private final String mZoneId;
+    @Nullable private ArrayList<String> mDebugInfo;
 
     public ManualTimeZoneSuggestion(@NonNull String zoneId) {
         mZoneId = Objects.requireNonNull(zoneId);
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
index ebaf951..0544ccd 100644
--- a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
@@ -34,10 +34,14 @@
  * A time zone suggestion from an identified telephony source, e.g. from MCC and NITZ information
  * associated with a specific radio.
  *
- * <p>The time zone ID can be {@code null} to indicate that the telephony source has entered an
- * "un-opinionated" state and any previous suggestions from that source are being withdrawn.
- * When not {@code null}, the value consists of a suggested time zone ID and metadata that can be
- * used to judge quality / certainty of the suggestion.
+ * <p>{@code slotIndex} identifies the suggestion source. This enables detection logic to identify
+ * suggestions from the same source when there are several in use.
+ *
+ * <p>{@code zoneId}. When not {@code null}, {@code zoneId} contains the suggested time zone ID,
+ * e.g. "America/Los_Angeles". Suggestion metadata like {@code matchType} and {@code quality} can be
+ * used to judge quality / certainty of the suggestion. {@code zoneId} can be {@code null} to
+ * indicate that the telephony source has entered an "un-opinionated" state and any previous
+ * suggestion from the same source is being withdrawn.
  *
  * <p>{@code matchType} must be set to {@link #MATCH_TYPE_NA} when {@code zoneId} is {@code null},
  * and one of the other {@code MATCH_TYPE_} values when it is not {@code null}.
@@ -45,6 +49,12 @@
  * <p>{@code quality} must be set to {@link #QUALITY_NA} when {@code zoneId} is {@code null},
  * and one of the other {@code QUALITY_} values when it is not {@code null}.
  *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists, e.g. what triggered it to be made and what heuristic was used
+ * to determine the time zone or its absence. This information exists only to aid in debugging and
+ * therefore is used by {@link #toString()}, but it is not for use in detection logic and is not
+ * considered in {@link #hashCode()} or {@link #equals(Object)}.
+ *
  * @hide
  */
 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@@ -131,38 +141,11 @@
      */
     public static final int QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS = 3;
 
-    /**
-     * The ID of the phone this suggestion is associated with. For multiple-sim devices this
-     * helps to establish source so filtering / stickiness can be implemented.
-     */
     private final int mSlotIndex;
-
-    /**
-     * The suggestion. {@code null} means there is no current suggestion and any previous suggestion
-     * should be forgotten.
-     */
-    @Nullable
-    private final String mZoneId;
-
-    /**
-     * The type of "match" used to establish the time zone.
-     */
-    @MatchType
-    private final int mMatchType;
-
-    /**
-     * A measure of the quality of the time zone suggestion, i.e. how confident one could be in
-     * it.
-     */
-    @Quality
-    private final int mQuality;
-
-    /**
-     * Free-form debug information about how the suggestion was derived. Used for debug only,
-     * intentionally not used in equals(), etc.
-     */
-    @Nullable
-    private List<String> mDebugInfo;
+    @Nullable private final String mZoneId;
+    @MatchType private final int mMatchType;
+    @Quality private final int mQuality;
+    @Nullable private List<String> mDebugInfo;
 
     private PhoneTimeZoneSuggestion(Builder builder) {
         mSlotIndex = builder.mSlotIndex;
@@ -203,8 +186,9 @@
     }
 
     /**
-     * Returns an identifier for the source of this suggestion. When a device has several sim slots
-     * or equivalent, it is used to identify which one the suggestion is from.
+     * Returns an identifier for the source of this suggestion.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code slotIndex}.
      */
     public int getSlotIndex() {
         return mSlotIndex;
@@ -212,8 +196,9 @@
 
     /**
      * Returns the suggested time zone Olson ID, e.g. "America/Los_Angeles". {@code null} means that
-     * the caller is no longer sure what the current time zone is. See
-     * {@link PhoneTimeZoneSuggestion} for the associated {@code matchType} / {@code quality} rules.
+     * the caller is no longer sure what the current time zone is.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code zoneId}.
      */
     @Nullable
     public String getZoneId() {
@@ -222,8 +207,9 @@
 
     /**
      * Returns information about how the suggestion was determined which could be used to rank
-     * suggestions when several are available from different sources. See
-     * {@link PhoneTimeZoneSuggestion} for the associated rules.
+     * suggestions when several are available from different sources.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code matchType}.
      */
     @MatchType
     public int getMatchType() {
@@ -231,8 +217,9 @@
     }
 
     /**
-     * Returns information about the likelihood of the suggested zone being correct.  See
-     * {@link PhoneTimeZoneSuggestion} for the associated rules.
+     * Returns information about the likelihood of the suggested zone being correct.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code quality}.
      */
     @Quality
     public int getQuality() {
@@ -240,8 +227,9 @@
     }
 
     /**
-     * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
-     * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+     * Returns debug metadata for the suggestion.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
      */
     @NonNull
     public List<String> getDebugInfo() {
@@ -250,9 +238,9 @@
     }
 
     /**
-     * Associates information with the instance that can be useful for debugging / logging. The
-     * information is present in {@link #toString()} but is not considered for
-     * {@link #equals(Object)} and {@link #hashCode()}.
+     * Associates information with the instance that can be useful for debugging / logging.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
      */
     public void addDebugInfo(@NonNull String debugInfo) {
         if (mDebugInfo == null) {
@@ -262,9 +250,9 @@
     }
 
     /**
-     * Associates information with the instance that can be useful for debugging / logging. The
-     * information is present in {@link #toString()} but is not considered for
-     * {@link #equals(Object)} and {@link #hashCode()}.
+     * Associates information with the instance that can be useful for debugging / logging.
+     *
+     * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
      */
     public void addDebugInfo(@NonNull List<String> debugInfo) {
         if (mDebugInfo == null) {
@@ -317,12 +305,19 @@
         @Quality private int mQuality;
         @Nullable private List<String> mDebugInfo;
 
+        /**
+         * Creates a builder with the specified {@code slotIndex}.
+         *
+         * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code slotIndex}.
+         */
         public Builder(int slotIndex) {
             mSlotIndex = slotIndex;
         }
 
         /**
          * Returns the builder for call chaining.
+         *
+         * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code zoneId}.
          */
         @NonNull
         public Builder setZoneId(@Nullable String zoneId) {
@@ -330,21 +325,33 @@
             return this;
         }
 
-        /** Returns the builder for call chaining. */
+        /**
+         * Returns the builder for call chaining.
+         *
+         * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code matchType}.
+         */
         @NonNull
         public Builder setMatchType(@MatchType int matchType) {
             mMatchType = matchType;
             return this;
         }
 
-        /** Returns the builder for call chaining. */
+        /**
+         * Returns the builder for call chaining.
+         *
+         * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code quality}.
+         */
         @NonNull
         public Builder setQuality(@Quality int quality) {
             mQuality = quality;
             return this;
         }
 
-        /** Returns the builder for call chaining. */
+        /**
+         * Returns the builder for call chaining.
+         *
+         * <p>See {@link PhoneTimeZoneSuggestion} for more information about {@code debugInfo}.
+         */
         @NonNull
         public Builder addDebugInfo(@NonNull String debugInfo) {
             if (mDebugInfo == null) {
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index b13e4b7..140363c 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -25,13 +25,16 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
+import android.os.RemoteException;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 
 /**
@@ -57,6 +60,11 @@
  * </ul>
  */
 public class ConnectivityDiagnosticsManager {
+    /** @hide */
+    @VisibleForTesting
+    public static final Map<ConnectivityDiagnosticsCallback, ConnectivityDiagnosticsBinder>
+            sCallbacks = new ConcurrentHashMap<>();
+
     private final Context mContext;
     private final IConnectivityManager mService;
 
@@ -631,8 +639,9 @@
     /**
      * Registers a ConnectivityDiagnosticsCallback with the System.
      *
-     * <p>Only apps that offer network connectivity to the user are allowed to register callbacks.
-     * This includes:
+     * <p>Only apps that offer network connectivity to the user should be registering callbacks.
+     * These are the only apps whose callbacks will be invoked by the system. Apps considered to
+     * meet these conditions include:
      *
      * <ul>
      *   <li>Carrier apps with active subscriptions
@@ -640,15 +649,14 @@
      *   <li>WiFi Suggesters
      * </ul>
      *
-     * <p>Callbacks will be limited to receiving notifications for networks over which apps provide
-     * connectivity.
+     * <p>Callbacks registered by apps not meeting the above criteria will not be invoked.
      *
      * <p>If a registering app loses its relevant permissions, any callbacks it registered will
      * silently stop receiving callbacks.
      *
-     * <p>Each register() call <b>MUST</b> use a unique ConnectivityDiagnosticsCallback instance. If
-     * a single instance is registered with multiple NetworkRequests, an IllegalArgumentException
-     * will be thrown.
+     * <p>Each register() call <b>MUST</b> use a ConnectivityDiagnosticsCallback instance that is
+     * not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with
+     * multiple NetworkRequests, an IllegalArgumentException will be thrown.
      *
      * @param request The NetworkRequest that will be used to match with Networks for which
      *     callbacks will be fired
@@ -657,15 +665,21 @@
      *     System
      * @throws IllegalArgumentException if the same callback instance is registered with multiple
      *     NetworkRequests
-     * @throws SecurityException if the caller does not have appropriate permissions to register a
-     *     callback
      */
     public void registerConnectivityDiagnosticsCallback(
             @NonNull NetworkRequest request,
             @NonNull Executor e,
             @NonNull ConnectivityDiagnosticsCallback callback) {
-        // TODO(b/143187964): implement ConnectivityDiagnostics functionality
-        throw new UnsupportedOperationException("registerCallback() not supported yet");
+        final ConnectivityDiagnosticsBinder binder = new ConnectivityDiagnosticsBinder(callback, e);
+        if (sCallbacks.putIfAbsent(callback, binder) != null) {
+            throw new IllegalArgumentException("Callback is currently registered");
+        }
+
+        try {
+            mService.registerConnectivityDiagnosticsCallback(binder, request);
+        } catch (RemoteException exception) {
+            exception.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -678,7 +692,15 @@
      */
     public void unregisterConnectivityDiagnosticsCallback(
             @NonNull ConnectivityDiagnosticsCallback callback) {
-        // TODO(b/143187964): implement ConnectivityDiagnostics functionality
-        throw new UnsupportedOperationException("registerCallback() not supported yet");
+        // unconditionally removing from sCallbacks prevents race conditions here, since remove() is
+        // atomic.
+        final ConnectivityDiagnosticsBinder binder = sCallbacks.remove(callback);
+        if (binder == null) return;
+
+        try {
+            mService.unregisterConnectivityDiagnosticsCallback(binder);
+        } catch (RemoteException exception) {
+            exception.rethrowFromSystemServer();
+        }
     }
 }
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 73e1adf..223f920 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.WorkerThread;
 import android.content.res.AssetFileDescriptor;
 import android.os.IUpdateEngine;
 import android.os.IUpdateEngineCallback;
@@ -478,7 +479,7 @@
          * </ul>
          */
         @ErrorCode
-        public int errorCode() {
+        public int getErrorCode() {
             return mErrorCode;
         }
 
@@ -492,14 +493,15 @@
          *
          * @return The following values:
          * <ul>
-         * <li>zero if {@link #errorCode} returns {@link ErrorCodeConstants#SUCCESS}</li>
-         * <li>non-zero if {@link #errorCode} returns {@link ErrorCodeConstants#NOT_ENOUGH_SPACE}.
+         * <li>zero if {@link #getErrorCode} returns {@link ErrorCodeConstants#SUCCESS}</li>
+         * <li>non-zero if {@link #getErrorCode} returns
+         * {@link ErrorCodeConstants#NOT_ENOUGH_SPACE}.
          * Value is the estimated total space required on userdata partition.</li>
          * </ul>
-         * @throws IllegalStateException if {@link #errorCode} is not one of the above.
+         * @throws IllegalStateException if {@link #getErrorCode} is not one of the above.
          *
          */
-        public long freeSpaceRequired() {
+        public long getFreeSpaceRequired() {
             if (mErrorCode == ErrorCodeConstants.SUCCESS) {
                 return 0;
             }
@@ -507,7 +509,7 @@
                 return mFreeSpaceRequired;
             }
             throw new IllegalStateException(String.format(
-                    "freeSpaceRequired() is not available when error code is %d", mErrorCode));
+                    "getFreeSpaceRequired() is not available when error code is %d", mErrorCode));
         }
     }
 
@@ -531,8 +533,10 @@
      *
      * @param payloadMetadataFilename See {@link #verifyPayloadMetadata}.
      * @param headerKeyValuePairs See {@link #applyPayload}.
-     * @return See {@link AllocateSpaceResult}.
+     * @return See {@link AllocateSpaceResult#getErrorCode} and
+     *             {@link AllocateSpaceResult#getFreeSpaceRequired}.
      */
+    @WorkerThread
     @NonNull
     public AllocateSpaceResult allocateSpace(
                 @NonNull String payloadMetadataFilename,
@@ -583,6 +587,7 @@
      * @throws ServiceSpecificException if other transient errors has occurred.
      * A reboot may or may not help resolving the issue.
      */
+    @WorkerThread
     @ErrorCode
     public int cleanupAppliedPayload() {
         try {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e98c370..51f6ab0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -559,13 +559,17 @@
                 .asInterface(ServiceManager.getService("dnsresolver"));
     }
 
-    /** Handler thread used for both of the handlers below. */
+    /** Handler thread used for all of the handlers below. */
     @VisibleForTesting
     protected final HandlerThread mHandlerThread;
     /** Handler used for internal events. */
     final private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
     final private NetworkStateTrackerHandler mTrackerHandler;
+    /** Handler used for processing {@link android.net.ConnectivityDiagnosticsManager} events */
+    @VisibleForTesting
+    final ConnectivityDiagnosticsHandler mConnectivityDiagnosticsHandler;
+
     private final DnsManager mDnsManager;
 
     private boolean mSystemReady;
@@ -632,6 +636,10 @@
     @VisibleForTesting
     final MultipathPolicyTracker mMultipathPolicyTracker;
 
+    @VisibleForTesting
+    final Map<IConnectivityDiagnosticsCallback, ConnectivityDiagnosticsCallbackInfo>
+            mConnectivityDiagnosticsCallbacks = new HashMap<>();
+
     /**
      * Implements support for the legacy "one network per network type" model.
      *
@@ -964,6 +972,8 @@
         mHandlerThread.start();
         mHandler = new InternalHandler(mHandlerThread.getLooper());
         mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
+        mConnectivityDiagnosticsHandler =
+                new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper());
 
         mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
@@ -3384,18 +3394,7 @@
         nri.unlinkDeathRecipient();
         mNetworkRequests.remove(nri.request);
 
-        synchronized (mUidToNetworkRequestCount) {
-            int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
-            if (requests < 1) {
-                Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
-                        nri.mUid);
-            } else if (requests == 1) {
-                mUidToNetworkRequestCount.removeAt(
-                        mUidToNetworkRequestCount.indexOfKey(nri.mUid));
-            } else {
-                mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
-            }
-        }
+        decrementNetworkRequestPerUidCount(nri);
 
         mNetworkRequestInfoLogs.log("RELEASE " + nri);
         if (nri.request.isRequest()) {
@@ -3466,6 +3465,19 @@
         }
     }
 
+    private void decrementNetworkRequestPerUidCount(final NetworkRequestInfo nri) {
+        synchronized (mUidToNetworkRequestCount) {
+            final int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
+            if (requests < 1) {
+                Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " + nri.mUid);
+            } else if (requests == 1) {
+                mUidToNetworkRequestCount.removeAt(mUidToNetworkRequestCount.indexOfKey(nri.mUid));
+            } else {
+                mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
+            }
+        }
+    }
+
     @Override
     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
         enforceNetworkStackSettingsOrSetup();
@@ -5084,6 +5096,10 @@
             }
         }
 
+        NetworkRequestInfo(NetworkRequest r) {
+            this(r, null);
+        }
+
         private void enforceRequestCountLimit() {
             synchronized (mUidToNetworkRequestCount) {
                 int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
@@ -6174,7 +6190,10 @@
     private void callCallbackForRequest(NetworkRequestInfo nri,
             NetworkAgentInfo networkAgent, int notificationType, int arg1) {
         if (nri.messenger == null) {
-            return;  // Default request has no msgr
+            // Default request has no msgr. Also prevents callbacks from being invoked for
+            // NetworkRequestInfos registered with ConnectivityDiagnostics requests. Those callbacks
+            // are Type.LISTEN, but should not have NetworkCallbacks invoked.
+            return;
         }
         Bundle bundle = new Bundle();
         // TODO: check if defensive copies of data is needed.
@@ -6328,12 +6347,34 @@
             }
         }
 
+        static class RequestReassignment {
+            @NonNull public final NetworkRequestInfo mRequest;
+            @Nullable public final NetworkAgentInfo mOldNetwork;
+            @Nullable public final NetworkAgentInfo mNewNetwork;
+            RequestReassignment(@NonNull final NetworkRequestInfo request,
+                    @Nullable final NetworkAgentInfo oldNetwork,
+                    @Nullable final NetworkAgentInfo newNetwork) {
+                mRequest = request;
+                mOldNetwork = oldNetwork;
+                mNewNetwork = newNetwork;
+            }
+        }
+
         @NonNull private final Set<NetworkBgStatePair> mRematchedNetworks = new ArraySet<>();
+        @NonNull private final List<RequestReassignment> mReassignments = new ArrayList<>();
 
         @NonNull Iterable<NetworkBgStatePair> getRematchedNetworks() {
             return mRematchedNetworks;
         }
 
+        @NonNull Iterable<RequestReassignment> getRequestReassignments() {
+            return mReassignments;
+        }
+
+        void addRequestReassignment(@NonNull final RequestReassignment reassignment) {
+            mReassignments.add(reassignment);
+        }
+
         void addRematchedNetwork(@NonNull final NetworkBgStatePair network) {
             mRematchedNetworks.add(network);
         }
@@ -6409,20 +6450,13 @@
         changes.addRematchedNetwork(new NetworkReassignment.NetworkBgStatePair(newNetwork,
                 newNetwork.isBackgroundNetwork()));
 
-        final int score = newNetwork.getCurrentScore();
-
         if (VDBG || DDBG) log("rematching " + newNetwork.name());
 
         final ArrayMap<NetworkRequestInfo, NetworkAgentInfo> reassignedRequests =
                 computeRequestReassignmentForNetwork(newNetwork);
 
-        NetworkCapabilities nc = newNetwork.networkCapabilities;
-        if (VDBG) log(" network has: " + nc);
-
         // Find and migrate to this Network any NetworkRequests for
         // which this network is now the best.
-        final ArrayList<NetworkAgentInfo> removedRequests = new ArrayList<>();
-        final ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<>();
         for (final Map.Entry<NetworkRequestInfo, NetworkAgentInfo> entry :
                 reassignedRequests.entrySet()) {
             final NetworkRequestInfo nri = entry.getKey();
@@ -6436,7 +6470,6 @@
                     }
                     previousSatisfier.removeRequest(nri.request.requestId);
                     previousSatisfier.lingerRequest(nri.request, now, mLingerDelayMs);
-                    removedRequests.add(previousSatisfier);
                 } else {
                     if (VDBG || DDBG) log("   accepting network in place of null");
                 }
@@ -6445,7 +6478,8 @@
                 if (!newSatisfier.addRequest(nri.request)) {
                     Slog.wtf(TAG, "BUG: " + newSatisfier.name() + " already has " + nri.request);
                 }
-                addedRequests.add(nri);
+                changes.addRequestReassignment(new NetworkReassignment.RequestReassignment(
+                        nri, previousSatisfier, newSatisfier));
                 // Tell NetworkProviders about the new score, so they can stop
                 // trying to connect if they know they cannot match it.
                 // TODO - this could get expensive if we have a lot of requests for this
@@ -6502,21 +6536,6 @@
             // Have a new default network, release the transition wakelock in
             scheduleReleaseNetworkTransitionWakelock();
         }
-
-        if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
-            Slog.wtf(TAG, String.format(
-                    "BUG: %s changed requestable capabilities during rematch: %s -> %s",
-                    newNetwork.name(), nc, newNetwork.networkCapabilities));
-        }
-        if (newNetwork.getCurrentScore() != score) {
-            Slog.wtf(TAG, String.format(
-                    "BUG: %s changed score during rematch: %d -> %d",
-                    newNetwork.name(), score, newNetwork.getCurrentScore()));
-        }
-
-        // Notify requested networks are available after the default net is switched, but
-        // before LegacyTypeTracker sends legacy broadcasts
-        for (NetworkRequestInfo nri : addedRequests) notifyNetworkAvailable(newNetwork, nri);
     }
 
     /**
@@ -6545,6 +6564,15 @@
 
         final NetworkAgentInfo newDefaultNetwork = getDefaultNetwork();
 
+        // Notify requested networks are available after the default net is switched, but
+        // before LegacyTypeTracker sends legacy broadcasts
+        for (final NetworkReassignment.RequestReassignment event :
+                changes.getRequestReassignments()) {
+            if (null != event.mNewNetwork) {
+                notifyNetworkAvailable(event.mNewNetwork, event.mRequest);
+            }
+        }
+
         for (final NetworkReassignment.NetworkBgStatePair event : changes.getRematchedNetworks()) {
             // Process listen requests and update capabilities if the background state has
             // changed for this network. For consistency with previous behavior, send onLost
@@ -7330,19 +7358,161 @@
         }
     }
 
+    /**
+     * Handler used for managing all Connectivity Diagnostics related functions.
+     *
+     * @see android.net.ConnectivityDiagnosticsManager
+     *
+     * TODO(b/147816404): Explore moving ConnectivityDiagnosticsHandler to a separate file
+     */
+    @VisibleForTesting
+    class ConnectivityDiagnosticsHandler extends Handler {
+        /**
+         * Used to handle ConnectivityDiagnosticsCallback registration events from {@link
+         * android.net.ConnectivityDiagnosticsManager}.
+         * obj = ConnectivityDiagnosticsCallbackInfo with IConnectivityDiagnosticsCallback and
+         * NetworkRequestInfo to be registered
+         */
+        private static final int EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 1;
+
+        /**
+         * Used to handle ConnectivityDiagnosticsCallback unregister events from {@link
+         * android.net.ConnectivityDiagnosticsManager}.
+         * obj = the IConnectivityDiagnosticsCallback to be unregistered
+         * arg1 = the uid of the caller
+         */
+        private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2;
+
+        private ConnectivityDiagnosticsHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: {
+                    handleRegisterConnectivityDiagnosticsCallback(
+                            (ConnectivityDiagnosticsCallbackInfo) msg.obj);
+                    break;
+                }
+                case EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK: {
+                    handleUnregisterConnectivityDiagnosticsCallback(
+                            (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1);
+                    break;
+                }
+            }
+        }
+    }
+
+    /** Class used for cleaning up IConnectivityDiagnosticsCallback instances after their death. */
+    @VisibleForTesting
+    class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient {
+        @NonNull private final IConnectivityDiagnosticsCallback mCb;
+        @NonNull private final NetworkRequestInfo mRequestInfo;
+
+        @VisibleForTesting
+        ConnectivityDiagnosticsCallbackInfo(
+                @NonNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri) {
+            mCb = cb;
+            mRequestInfo = nri;
+        }
+
+        @Override
+        public void binderDied() {
+            log("ConnectivityDiagnosticsCallback IBinder died.");
+            unregisterConnectivityDiagnosticsCallback(mCb);
+        }
+    }
+
+    private void handleRegisterConnectivityDiagnosticsCallback(
+            @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) {
+        ensureRunningOnConnectivityServiceThread();
+
+        final IConnectivityDiagnosticsCallback cb = cbInfo.mCb;
+        final NetworkRequestInfo nri = cbInfo.mRequestInfo;
+
+        // This means that the client registered the same callback multiple times. Do
+        // not override the previous entry, and exit silently.
+        if (mConnectivityDiagnosticsCallbacks.containsKey(cb)) {
+            if (VDBG) log("Diagnostics callback is already registered");
+
+            // Decrement the reference count for this NetworkRequestInfo. The reference count is
+            // incremented when the NetworkRequestInfo is created as part of
+            // enforceRequestCountLimit().
+            decrementNetworkRequestPerUidCount(nri);
+            return;
+        }
+
+        mConnectivityDiagnosticsCallbacks.put(cb, cbInfo);
+
+        try {
+            cb.asBinder().linkToDeath(cbInfo, 0);
+        } catch (RemoteException e) {
+            cbInfo.binderDied();
+        }
+    }
+
+    private void handleUnregisterConnectivityDiagnosticsCallback(
+            @NonNull IConnectivityDiagnosticsCallback cb, int uid) {
+        ensureRunningOnConnectivityServiceThread();
+
+        if (!mConnectivityDiagnosticsCallbacks.containsKey(cb)) {
+            if (VDBG) log("Removing diagnostics callback that is not currently registered");
+            return;
+        }
+
+        final NetworkRequestInfo nri = mConnectivityDiagnosticsCallbacks.get(cb).mRequestInfo;
+
+        if (uid != nri.mUid) {
+            if (VDBG) loge("Different uid than registrant attempting to unregister cb");
+            return;
+        }
+
+        cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0);
+    }
+
     @Override
     public void registerConnectivityDiagnosticsCallback(
             @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) {
-        // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
-        throw new UnsupportedOperationException(
-                "registerConnectivityDiagnosticsCallback not yet implemented");
+        if (request.legacyType != TYPE_NONE) {
+            throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
+                    + " Please use NetworkCapabilities instead.");
+        }
+
+        // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
+        // and administrator uids to be safe.
+        final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities);
+        restrictRequestUidsForCaller(nc);
+
+        final NetworkRequest requestWithId =
+                new NetworkRequest(
+                        nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN);
+
+        // NetworkRequestInfos created here count towards MAX_NETWORK_REQUESTS_PER_UID limit.
+        //
+        // nri is not bound to the death of callback. Instead, callback.bindToDeath() is set in
+        // handleRegisterConnectivityDiagnosticsCallback(). nri will be cleaned up as part of the
+        // callback's binder death.
+        final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId);
+        final ConnectivityDiagnosticsCallbackInfo cbInfo =
+                new ConnectivityDiagnosticsCallbackInfo(callback, nri);
+
+        mConnectivityDiagnosticsHandler.sendMessage(
+                mConnectivityDiagnosticsHandler.obtainMessage(
+                        ConnectivityDiagnosticsHandler
+                                .EVENT_REGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
+                        cbInfo));
     }
 
     @Override
     public void unregisterConnectivityDiagnosticsCallback(
             @NonNull IConnectivityDiagnosticsCallback callback) {
-        // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
-        throw new UnsupportedOperationException(
-                "unregisterConnectivityDiagnosticsCallback not yet implemented");
+        mConnectivityDiagnosticsHandler.sendMessage(
+                mConnectivityDiagnosticsHandler.obtainMessage(
+                        ConnectivityDiagnosticsHandler
+                                .EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
+                        Binder.getCallingUid(),
+                        0,
+                        callback));
     }
 }
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index 5d31dbe..5c50962 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -86,6 +86,12 @@
             return mIsActive && mConfig != null;
         }
 
+        void release() {
+            if (mDeathHandler != null) {
+                mDeathHandler.release();
+            }
+        }
+
         // returns true if status of an active recording has changed
         boolean setActive(boolean active) {
             if (mIsActive == active) return false;
@@ -417,6 +423,7 @@
                     break;
                 case AudioManager.RECORD_CONFIG_EVENT_RELEASE:
                     configChanged = state.isActiveConfiguration();
+                    state.release();
                     mRecordStates.remove(stateIndex);
                     break;
                 default:
@@ -519,6 +526,10 @@
                 return false;
             }
         }
+
+        void release() {
+            mRecorderToken.unlinkToDeath(this, 0);
+        }
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 519856c..df72671 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -56,7 +56,6 @@
 import android.provider.Telephony.SimInfo;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsMmTelManager;
-import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Pair;
 
@@ -2374,23 +2373,24 @@
         final SubscriptionInfo subInfo =
                 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId);
 
-        Configuration config = context.getResources().getConfiguration();
-        Configuration newConfig = new Configuration();
-        newConfig.setTo(config);
+        Configuration overrideConfig = new Configuration();
         if (subInfo != null) {
-            newConfig.mcc = subInfo.getMcc();
-            newConfig.mnc = subInfo.getMnc();
-            if (newConfig.mnc == 0) newConfig.mnc = Configuration.MNC_ZERO;
+            overrideConfig.mcc = subInfo.getMcc();
+            overrideConfig.mnc = subInfo.getMnc();
+            if (overrideConfig.mnc == 0) overrideConfig.mnc = Configuration.MNC_ZERO;
         }
 
         if (useRootLocale) {
-            newConfig.setLocale(Locale.ROOT);
+            overrideConfig.setLocale(Locale.ROOT);
         }
 
-        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
-        DisplayMetrics newMetrics = new DisplayMetrics();
-        newMetrics.setTo(metrics);
-        Resources res = new Resources(context.getResources().getAssets(), newMetrics, newConfig);
+        // Create new context with new configuration so that we can avoid modifying the passed in
+        // context.
+        // Note that if the original context configuration changes, the resources here will also
+        // change for all values except those overridden by newConfig (e.g. if the device has an
+        // orientation change).
+        Context newContext = context.createConfigurationContext(overrideConfig);
+        Resources res = newContext.getResources();
 
         if (cacheKey != null) {
             // Save the newly created Resources in the resource cache.
diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 7ab4b56..2d5df4f 100644
--- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -27,12 +27,18 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.content.Context;
 import android.os.PersistableBundle;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,15 +58,27 @@
 
     private static final Executor INLINE_EXECUTOR = x -> x.run();
 
+    @Mock private Context mContext;
+    @Mock private IConnectivityManager mService;
     @Mock private ConnectivityDiagnosticsCallback mCb;
 
     private ConnectivityDiagnosticsBinder mBinder;
+    private ConnectivityDiagnosticsManager mManager;
 
     @Before
     public void setUp() {
+        mContext = mock(Context.class);
+        mService = mock(IConnectivityManager.class);
         mCb = mock(ConnectivityDiagnosticsCallback.class);
 
         mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR);
+        mManager = new ConnectivityDiagnosticsManager(mContext, mService);
+    }
+
+    @After
+    public void tearDown() {
+        // clear ConnectivityDiagnosticsManager callbacks map
+        ConnectivityDiagnosticsManager.sCallbacks.clear();
     }
 
     private ConnectivityReport createSampleConnectivityReport() {
@@ -245,4 +263,53 @@
         // latch without waiting.
         verify(mCb).onNetworkConnectivityReported(eq(n), eq(connectivity));
     }
+
+    @Test
+    public void testRegisterConnectivityDiagnosticsCallback() throws Exception {
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+
+        mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb);
+
+        verify(mService).registerConnectivityDiagnosticsCallback(
+                any(ConnectivityDiagnosticsBinder.class), eq(request));
+        assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb));
+    }
+
+    @Test
+    public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+
+        mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb);
+
+        try {
+            mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb);
+            fail("Duplicate callback registration should fail");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testUnregisterConnectivityDiagnosticsCallback() throws Exception {
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+        mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb);
+
+        mManager.unregisterConnectivityDiagnosticsCallback(mCb);
+
+        verify(mService).unregisterConnectivityDiagnosticsCallback(
+                any(ConnectivityDiagnosticsBinder.class));
+        assertFalse(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb));
+
+        // verify that re-registering is successful
+        mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb);
+        verify(mService, times(2)).registerConnectivityDiagnosticsCallback(
+                any(ConnectivityDiagnosticsBinder.class), eq(request));
+        assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb));
+    }
+
+    @Test
+    public void testUnregisterUnknownConnectivityDiagnosticsCallback() throws Exception {
+        mManager.unregisterConnectivityDiagnosticsCallback(mCb);
+
+        verifyNoMoreInteractions(mService);
+    }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e80b7c9..50f1bbe 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -139,6 +139,7 @@
 import android.net.ConnectivityManager.PacketKeepaliveCallback;
 import android.net.ConnectivityManager.TooManyRequestsException;
 import android.net.ConnectivityThread;
+import android.net.IConnectivityDiagnosticsCallback;
 import android.net.IDnsResolver;
 import android.net.IIpConnectivityMetrics;
 import android.net.INetd;
@@ -180,6 +181,7 @@
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Parcel;
@@ -210,6 +212,7 @@
 import com.android.internal.util.WakeupMessage;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
 import com.android.server.connectivity.ConnectivityConstants;
 import com.android.server.connectivity.DefaultNetworkMetrics;
 import com.android.server.connectivity.IpConnectivityMetrics;
@@ -322,6 +325,8 @@
     @Mock UserManager mUserManager;
     @Mock NotificationManager mNotificationManager;
     @Mock AlarmManager mAlarmManager;
+    @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
+    @Mock IBinder mIBinder;
 
     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
             ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -6355,4 +6360,70 @@
                 UserHandle.getAppId(uid));
         return packageInfo;
     }
+
+    @Test
+    public void testRegisterConnectivityDiagnosticsCallbackInvalidRequest() throws Exception {
+        final NetworkRequest request =
+                new NetworkRequest(
+                        new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE);
+        try {
+            mService.registerConnectivityDiagnosticsCallback(
+                    mConnectivityDiagnosticsCallback, request);
+            fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception {
+        final NetworkRequest wifiRequest =
+                new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
+
+        when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
+
+        mService.registerConnectivityDiagnosticsCallback(
+                mConnectivityDiagnosticsCallback, wifiRequest);
+
+        verify(mIBinder, timeout(TIMEOUT_MS))
+                .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
+        assertTrue(
+                mService.mConnectivityDiagnosticsCallbacks.containsKey(
+                        mConnectivityDiagnosticsCallback));
+
+        mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback);
+        verify(mIBinder, timeout(TIMEOUT_MS))
+                .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
+        assertFalse(
+                mService.mConnectivityDiagnosticsCallbacks.containsKey(
+                        mConnectivityDiagnosticsCallback));
+        verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder();
+    }
+
+    @Test
+    public void testRegisterDuplicateConnectivityDiagnosticsCallback() throws Exception {
+        final NetworkRequest wifiRequest =
+                new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI).build();
+        when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
+
+        mService.registerConnectivityDiagnosticsCallback(
+                mConnectivityDiagnosticsCallback, wifiRequest);
+
+        verify(mIBinder, timeout(TIMEOUT_MS))
+                .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt());
+        verify(mConnectivityDiagnosticsCallback).asBinder();
+        assertTrue(
+                mService.mConnectivityDiagnosticsCallbacks.containsKey(
+                        mConnectivityDiagnosticsCallback));
+
+        // Register the same callback again
+        mService.registerConnectivityDiagnosticsCallback(
+                mConnectivityDiagnosticsCallback, wifiRequest);
+
+        // Block until all other events are done processing.
+        HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
+
+        assertTrue(
+                mService.mConnectivityDiagnosticsCallbacks.containsKey(
+                        mConnectivityDiagnosticsCallback));
+    }
 }