Merge changes from topic "nsd_serviceinfo_network"

* changes:
  Support discover/resolve on specific networks
  NSD: Specify on what interface to getAddrInfo
diff --git a/core/api/current.txt b/core/api/current.txt
index d400f98..6a72017 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -30358,6 +30358,7 @@
     method public void setDataCapacity(int);
     method public void setDataPosition(int);
     method public void setDataSize(int);
+    method public void setPropagateAllowBlocking();
     method public void unmarshall(@NonNull byte[], int, int);
     method public void writeArray(@Nullable Object[]);
     method public void writeBinderArray(@Nullable android.os.IBinder[]);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 9e26908..1e4e787 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -140,7 +140,7 @@
     method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
     method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp();
     method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio();
-    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BtProfileConnectionInfo);
+    method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BluetoothProfileConnectionInfo);
     method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
     method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
     method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
@@ -150,18 +150,18 @@
     field public static final int FLAG_FROM_KEY = 4096; // 0x1000
   }
 
-  public final class BtProfileConnectionInfo implements android.os.Parcelable {
-    method @NonNull public static android.media.BtProfileConnectionInfo a2dpInfo(boolean, int);
-    method @NonNull public static android.media.BtProfileConnectionInfo a2dpSinkInfo(int);
+  public final class BluetoothProfileConnectionInfo implements android.os.Parcelable {
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpInfo(boolean, int);
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpSinkInfo(int);
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createHearingAidInfo(boolean);
+    method @NonNull public static android.media.BluetoothProfileConnectionInfo createLeAudioInfo(boolean, boolean);
     method public int describeContents();
-    method public boolean getIsLeOutput();
     method public int getProfile();
-    method public boolean getSuppressNoisyIntent();
     method public int getVolume();
-    method @NonNull public static android.media.BtProfileConnectionInfo hearingAidInfo(boolean);
-    method @NonNull public static android.media.BtProfileConnectionInfo leAudio(boolean, boolean);
+    method public boolean isLeOutput();
+    method public boolean isSuppressNoisyIntent();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.BtProfileConnectionInfo> CREATOR;
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.BluetoothProfileConnectionInfo> CREATOR;
   }
 
   public class MediaMetadataRetriever implements java.lang.AutoCloseable {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 845020d..3c483f4 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -7830,6 +7830,7 @@
   }
 
   public static class Build.VERSION {
+    field @NonNull public static final java.util.Set<java.lang.String> KNOWN_CODENAMES;
     field @NonNull public static final String PREVIEW_SDK_FINGERPRINT;
   }
 
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 18ceb25..88ab380 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1707,8 +1707,11 @@
 
   public final class Parcel {
     method public boolean allowSquashing();
+    method public int getFlags();
     method public int readExceptionCode();
     method public void restoreAllowSquashing(boolean);
+    field public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1; // 0x1
+    field public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 2; // 0x2
   }
 
   public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 2a2cbb9..71c63ff 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -516,12 +516,15 @@
     public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
         Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
 
-        if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
+        boolean warnOnBlocking = mWarnOnBlocking; // Cache it to reduce volatile access.
+
+        if (warnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
                 && Binder.sWarnOnBlockingOnCurrentThread.get()) {
 
             // For now, avoid spamming the log by disabling after we've logged
             // about this interface at least once
             mWarnOnBlocking = false;
+            warnOnBlocking = false;
 
             if (Build.IS_USERDEBUG) {
                 // Log this as a WTF on userdebug builds.
@@ -568,7 +571,13 @@
         }
 
         try {
-            return transactNative(code, data, reply, flags);
+            final boolean result = transactNative(code, data, reply, flags);
+
+            if (reply != null && !warnOnBlocking) {
+                reply.addFlags(Parcel.FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT);
+            }
+
+            return result;
         } finally {
             AppOpsManager.resumeNotedAppOpsCollection(prevCollection);
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index e519ff3..6863a0b 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -31,6 +31,7 @@
 import android.sysprop.SocProperties;
 import android.sysprop.TelephonyProperties;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.view.View;
 
@@ -39,6 +40,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -396,6 +398,17 @@
          */
         public static final String CODENAME = getString("ro.build.version.codename");
 
+        /**
+         * All known codenames starting from {@link VERSION_CODES.Q}.
+         *
+         * <p>This includes in development codenames as well.
+         *
+         * @hide
+         */
+        @SystemApi
+        @NonNull public static final Set<String> KNOWN_CODENAMES =
+                new ArraySet<>(new String[]{"Q", "R", "S", "Sv2", "Tiramisu"});
+
         private static final String[] ALL_CODENAMES
                 = getStringList("ro.build.version.all_codenames", ",");
 
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 004c020..13d1d96 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -18,6 +18,7 @@
 
 import static java.util.Objects.requireNonNull;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -53,6 +54,8 @@
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamClass;
 import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
@@ -229,6 +232,25 @@
 
     private RuntimeException mStack;
 
+    /** @hide */
+    @TestApi
+    public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1 << 0;
+
+    /** @hide */
+    @TestApi
+    public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 1 << 1;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+            FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT,
+            FLAG_PROPAGATE_ALLOW_BLOCKING,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ParcelFlags {}
+
+    @ParcelFlags
+    private int mFlags;
+
     /**
      * Whether or not to parcel the stack trace of an exception. This has a performance
      * impact, so should only be included in specific processes and only on debug builds.
@@ -585,6 +607,40 @@
         nativeMarkForBinder(mNativePtr, binder);
     }
 
+    /** @hide */
+    @ParcelFlags
+    @TestApi
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /** @hide */
+    public void setFlags(@ParcelFlags int flags) {
+        mFlags = flags;
+    }
+
+    /** @hide */
+    public void addFlags(@ParcelFlags int flags) {
+        mFlags |= flags;
+    }
+
+    /** @hide */
+    private boolean hasFlags(@ParcelFlags int flags) {
+        return (mFlags & flags) == flags;
+    }
+
+    /**
+     * This method is used by the AIDL compiler for system components. Not intended to be
+     * used by non-system apps.
+     */
+    // Note: Ideally this method should be @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES),
+    // but we need to make this method public due to the way the aidl compiler is compiled.
+    // We don't really need to protect it; even if 3p / non-system apps, nothing would happen.
+    // This would only work when used on a reply parcel by a binder object that's allowed-blocking.
+    public void setPropagateAllowBlocking() {
+        addFlags(FLAG_PROPAGATE_ALLOW_BLOCKING);
+    }
+
     /**
      * Returns the total amount of data contained in the parcel.
      */
@@ -3036,7 +3092,15 @@
      * Read an object from the parcel at the current dataPosition().
      */
     public final IBinder readStrongBinder() {
-        return nativeReadStrongBinder(mNativePtr);
+        final IBinder result = nativeReadStrongBinder(mNativePtr);
+
+        // If it's a reply from a method with @PropagateAllowBlocking, then inherit allow-blocking
+        // from the object that returned it.
+        if (result != null && hasFlags(
+                FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT | FLAG_PROPAGATE_ALLOW_BLOCKING)) {
+            Binder.allowBlocking(result);
+        }
+        return result;
     }
 
     /**
@@ -4988,6 +5052,7 @@
     }
 
     private void freeBuffer() {
+        mFlags = 0;
         resetSqaushingState();
         if (mOwnsNativeParcelObject) {
             nativeFreeBuffer(mNativePtr);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fa6b086..af47b17 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -461,6 +461,7 @@
         <!-- Permission needed for CTS test - WifiManagerTest -->
         <permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
         <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+        <permission name="android.permission.NEARBY_WIFI_DEVICES" />
         <permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
         <!-- Permission required for CTS test CarrierMessagingServiceWrapperTest -->
         <permission name="android.permission.BIND_CARRIER_SERVICES"/>
diff --git a/media/Android.bp b/media/Android.bp
index 1b7bef5..b7c3a9c 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -100,6 +100,11 @@
             vndk: {
                 enabled: true,
             },
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
         },
     },
 }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b7e8c8c..d8893cb 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5806,13 +5806,14 @@
      * @param newDevice Bluetooth device connected or null if there is no new devices
      * @param previousDevice Bluetooth device disconnected or null if there is no disconnected
      * devices
-     * @param info contain all info related to the device. {@link BtProfileConnectionInfo}
+     * @param info contain all info related to the device. {@link BluetoothProfileConnectionInfo}
      * {@hide}
      */
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
     public void handleBluetoothActiveDeviceChanged(@Nullable BluetoothDevice newDevice,
-            @Nullable BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
+            @Nullable BluetoothDevice previousDevice,
+            @NonNull BluetoothProfileConnectionInfo info) {
         final IAudioService service = getService();
         try {
             service.handleBluetoothActiveDeviceChanged(newDevice, previousDevice, info);
diff --git a/media/java/android/media/BtProfileConnectionInfo.aidl b/media/java/android/media/BluetoothProfileConnectionInfo.aidl
similarity index 93%
rename from media/java/android/media/BtProfileConnectionInfo.aidl
rename to media/java/android/media/BluetoothProfileConnectionInfo.aidl
index 047f06b..0617084 100644
--- a/media/java/android/media/BtProfileConnectionInfo.aidl
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.aidl
@@ -16,5 +16,5 @@
 
 package android.media;
 
-parcelable BtProfileConnectionInfo;
+parcelable BluetoothProfileConnectionInfo;
 
diff --git a/media/java/android/media/BtProfileConnectionInfo.java b/media/java/android/media/BluetoothProfileConnectionInfo.java
similarity index 65%
rename from media/java/android/media/BtProfileConnectionInfo.java
rename to media/java/android/media/BluetoothProfileConnectionInfo.java
index 88b9777..c148846 100644
--- a/media/java/android/media/BtProfileConnectionInfo.java
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.java
@@ -26,15 +26,14 @@
  * {@hide}
  */
 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public final class BtProfileConnectionInfo implements Parcelable {
-
+public final class BluetoothProfileConnectionInfo implements Parcelable {
     private final int mProfile;
     private final boolean mSupprNoisy;
     private final int mVolume;
     private final boolean mIsLeOutput;
 
-    private BtProfileConnectionInfo(int profile, boolean suppressNoisyIntent, int volume,
-            boolean isLeOutput) {
+    private BluetoothProfileConnectionInfo(int profile, boolean suppressNoisyIntent,
+            int volume, boolean isLeOutput) {
         mProfile = profile;
         mSupprNoisy = suppressNoisyIntent;
         mVolume = volume;
@@ -45,21 +44,21 @@
      * Constructor used by BtHelper when a profile is connected
      * {@hide}
      */
-    public BtProfileConnectionInfo(int profile) {
+    public BluetoothProfileConnectionInfo(int profile) {
         this(profile, false, -1, false);
     }
 
-    public static final @NonNull Parcelable.Creator<BtProfileConnectionInfo> CREATOR =
-            new Parcelable.Creator<BtProfileConnectionInfo>() {
+    public static final @NonNull Parcelable.Creator<BluetoothProfileConnectionInfo> CREATOR =
+            new Parcelable.Creator<BluetoothProfileConnectionInfo>() {
                 @Override
-                public BtProfileConnectionInfo createFromParcel(Parcel source) {
-                    return new BtProfileConnectionInfo(source.readInt(), source.readBoolean(),
-                            source.readInt(), source.readBoolean());
+                public BluetoothProfileConnectionInfo createFromParcel(Parcel source) {
+                    return new BluetoothProfileConnectionInfo(source.readInt(),
+                            source.readBoolean(), source.readInt(), source.readBoolean());
                 }
 
                 @Override
-                public BtProfileConnectionInfo[] newArray(int size) {
-                    return new BtProfileConnectionInfo[size];
+                public BluetoothProfileConnectionInfo[] newArray(int size) {
+                    return new BluetoothProfileConnectionInfo[size];
                 }
             };
 
@@ -84,10 +83,10 @@
      *
      * @param volume of device -1 to ignore value
      */
-    public static @NonNull BtProfileConnectionInfo a2dpInfo(boolean suppressNoisyIntent,
-            int volume) {
-        return new BtProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent, volume,
-            false);
+    public static @NonNull BluetoothProfileConnectionInfo createA2dpInfo(
+            boolean suppressNoisyIntent, int volume) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent,
+            volume, false);
     }
 
     /**
@@ -96,8 +95,8 @@
      *
      * @param volume of device -1 to ignore value
      */
-    public static @NonNull BtProfileConnectionInfo a2dpSinkInfo(int volume) {
-        return new BtProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false);
+    public static @NonNull BluetoothProfileConnectionInfo createA2dpSinkInfo(int volume) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false);
     }
 
     /**
@@ -106,9 +105,10 @@
      * @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY}
      * intent will not be sent.
      */
-    public static @NonNull BtProfileConnectionInfo hearingAidInfo(boolean suppressNoisyIntent) {
-        return new BtProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent, -1,
-            false);
+    public static @NonNull BluetoothProfileConnectionInfo createHearingAidInfo(
+            boolean suppressNoisyIntent) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent,
+            -1, false);
     }
 
     /**
@@ -119,10 +119,10 @@
      *
      * @param isLeOutput if true mean the device is an output device, if false it's an input device
      */
-    public static @NonNull BtProfileConnectionInfo leAudio(boolean suppressNoisyIntent,
-            boolean isLeOutput) {
-        return new BtProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent, -1,
-            isLeOutput);
+    public static @NonNull BluetoothProfileConnectionInfo createLeAudioInfo(
+            boolean suppressNoisyIntent, boolean isLeOutput) {
+        return new BluetoothProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent,
+            -1, isLeOutput);
     }
 
     /**
@@ -136,7 +136,7 @@
      * @return {@code true} if {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be
      * sent
      */
-    public boolean getSuppressNoisyIntent() {
+    public boolean isSuppressNoisyIntent() {
         return mSupprNoisy;
     }
 
@@ -153,7 +153,7 @@
      * @return {@code true} is the LE device is an output device, {@code false} if it's an input
      * device
      */
-    public boolean getIsLeOutput() {
+    public boolean isLeOutput() {
         return mIsLeOutput;
     }
 }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5ff56f9..d5a2d07 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -24,7 +24,7 @@
 import android.media.AudioPlaybackConfiguration;
 import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioModeDispatcher;
 import android.media.IAudioRoutesObserver;
@@ -268,7 +268,7 @@
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
     void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice,
-            in BluetoothDevice previousDevice, in BtProfileConnectionInfo info);
+            in BluetoothDevice previousDevice, in BluetoothProfileConnectionInfo info);
 
     oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
             in IAudioPolicyCallback pcb);
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index d8f48c2..20d711c 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -103,6 +103,7 @@
     private int mDeviceType;
     private String mHostType;
     private boolean mSkipThumbForHost = false;
+    private volatile boolean mHostIsWindows = false;
 
     private MtpServer mServer;
     private MtpStorageManager mManager;
@@ -358,7 +359,7 @@
     }
 
     public void addStorage(StorageVolume storage) {
-        MtpStorage mtpStorage = mManager.addMtpStorage(storage);
+        MtpStorage mtpStorage = mManager.addMtpStorage(storage, () -> mHostIsWindows);
         mStorageMap.put(storage.getPath(), mtpStorage);
         if (mServer != null) {
             mServer.addStorage(mtpStorage);
@@ -413,6 +414,7 @@
         }
         mHostType = "";
         mSkipThumbForHost = false;
+        mHostIsWindows = false;
     }
 
     @VisibleForNative
@@ -736,10 +738,12 @@
                         : MtpConstants.RESPONSE_GENERAL_ERROR);
             case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
                 mHostType = stringValue;
+                Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
+                        + "=" + stringValue);
                 if (stringValue.startsWith("Android/")) {
-                    Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
-                            + "=" + stringValue);
                     mSkipThumbForHost = true;
+                } else if (stringValue.startsWith("Windows/")) {
+                    mHostIsWindows = true;
                 }
                 return MtpConstants.RESPONSE_OK;
         }
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 88c32a3..a3754e90 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -19,6 +19,8 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.storage.StorageVolume;
 
+import java.util.function.Supplier;
+
 /**
  * This class represents a storage unit on an MTP device.
  * Used only for MTP support in USB responder mode.
@@ -33,14 +35,16 @@
     private final boolean mRemovable;
     private final long mMaxFileSize;
     private final String mVolumeName;
+    private final Supplier<Boolean> mIsHostWindows;
 
-    public MtpStorage(StorageVolume volume, int storageId) {
+    public MtpStorage(StorageVolume volume, int storageId, Supplier<Boolean> isHostWindows) {
         mStorageId = storageId;
         mPath = volume.getPath();
         mDescription = volume.getDescription(null);
         mRemovable = volume.isRemovable();
         mMaxFileSize = volume.getMaxFileSize();
         mVolumeName = volume.getMediaStoreVolumeName();
+        mIsHostWindows = isHostWindows;
     }
 
     /**
@@ -93,4 +97,13 @@
     public String getVolumeName() {
         return mVolumeName;
     }
+
+    /**
+     * Returns true if the mtp host of this storage is Windows.
+     *
+     * @return is host Windows
+     */
+    public boolean isHostWindows() {
+        return mIsHostWindows.get();
+    }
 }
diff --git a/media/java/android/mtp/MtpStorageManager.java b/media/java/android/mtp/MtpStorageManager.java
index 0bede0d..e9426cf 100644
--- a/media/java/android/mtp/MtpStorageManager.java
+++ b/media/java/android/mtp/MtpStorageManager.java
@@ -18,7 +18,11 @@
 
 import android.media.MediaFile;
 import android.os.FileObserver;
+import android.os.SystemProperties;
 import android.os.storage.StorageVolume;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -35,6 +39,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Supplier;
 
 /**
  * MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of
@@ -199,7 +204,38 @@
         }
 
         public long getSize() {
-            return mIsDir ? 0 : getPath().toFile().length();
+            return mIsDir ? 0 : maybeApplyTranscodeLengthWorkaround(getPath().toFile().length());
+        }
+
+        private long maybeApplyTranscodeLengthWorkaround(long length) {
+            // Windows truncates transferred files to the size advertised in the object property.
+            if (mStorage.isHostWindows() && isTranscodeMtpEnabled() && isFileTranscodeSupported()) {
+                // If the file supports transcoding, we double the returned size to accommodate
+                // the increase in size from transcoding to AVC. This is the same heuristic
+                // applied in the FUSE daemon (MediaProvider).
+                return length * 2;
+            }
+            return length;
+        }
+
+        private boolean isTranscodeMtpEnabled() {
+            return SystemProperties.getBoolean("sys.fuse.transcode_mtp", false);
+        }
+
+        private boolean isFileTranscodeSupported() {
+            // Check if the file supports transcoding by reading the |st_nlinks| struct stat
+            // field. This will be > 1 if the file supports transcoding. The FUSE daemon
+            // sets the field accordingly to enable the MTP stack workaround some Windows OS
+            // MTP client bug where they ignore the size returned as part of getting the MTP
+            // object, see MtpServer#doGetObject.
+            final Path path = getPath();
+            try {
+                StructStat stat = Os.stat(path.toString());
+                return stat.st_nlink > 1;
+            } catch (ErrnoException e) {
+                Log.w(TAG, "Failed to stat path: " + getPath() + ". Ignoring transcoding.");
+                return false;
+            }
         }
 
         public Path getPath() {
@@ -420,10 +456,12 @@
      * @param volume Storage to add.
      * @return the associated MtpStorage
      */
-    public synchronized MtpStorage addMtpStorage(StorageVolume volume) {
+    public synchronized MtpStorage addMtpStorage(StorageVolume volume,
+                                                 Supplier<Boolean> isHostWindows) {
         int storageId = ((getNextStorageId() & 0x0000FFFF) << 16) + 1;
-        MtpStorage storage = new MtpStorage(volume, storageId);
-        MtpObject root = new MtpObject(storage.getPath(), storageId, storage, null, true);
+        MtpStorage storage = new MtpStorage(volume, storageId, isHostWindows);
+        MtpObject root = new MtpObject(storage.getPath(), storageId, storage, /* parent= */ null,
+                                       /* isDir= */ true);
         mRoots.put(storageId, root);
         return storage;
     }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
similarity index 66%
rename from media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java
rename to media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
index fd66d3b..f23794b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
@@ -19,7 +19,7 @@
 import static org.junit.Assert.assertEquals;
 
 import android.bluetooth.BluetoothProfile;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -27,22 +27,24 @@
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidJUnit4.class)
-public class BtProfileConnectionInfoTest {
+public class BluetoothProfileConnectionInfoTest {
 
     @Test
     public void testCoverageA2dp() {
         final boolean supprNoisy = false;
         final int volume = 42;
-        final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpInfo(supprNoisy, volume);
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createA2dpInfo(supprNoisy, volume);
         assertEquals(info.getProfile(), BluetoothProfile.A2DP);
-        assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
+        assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
         assertEquals(info.getVolume(), volume);
     }
 
     @Test
     public void testCoverageA2dpSink() {
         final int volume = 42;
-        final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpSinkInfo(volume);
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createA2dpSinkInfo(volume);
         assertEquals(info.getProfile(), BluetoothProfile.A2DP_SINK);
         assertEquals(info.getVolume(), volume);
     }
@@ -50,20 +52,21 @@
     @Test
     public void testCoveragehearingAid() {
         final boolean supprNoisy = true;
-        final BtProfileConnectionInfo info = BtProfileConnectionInfo.hearingAidInfo(supprNoisy);
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createHearingAidInfo(supprNoisy);
         assertEquals(info.getProfile(), BluetoothProfile.HEARING_AID);
-        assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
+        assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
     }
 
     @Test
     public void testCoverageLeAudio() {
         final boolean supprNoisy = false;
         final boolean isLeOutput = true;
-        final BtProfileConnectionInfo info = BtProfileConnectionInfo.leAudio(supprNoisy,
-                isLeOutput);
+        final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+                .createLeAudioInfo(supprNoisy, isLeOutput);
         assertEquals(info.getProfile(), BluetoothProfile.LE_AUDIO);
-        assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
-        assertEquals(info.getIsLeOutput(), isLeOutput);
+        assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
+        assertEquals(info.isLeOutput(), isLeOutput);
     }
 }
 
diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
index fdf6582..eb357f6 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
@@ -159,10 +159,11 @@
                 Log.d(TAG, "sendObjectInfoChanged: " + id);
                 objectsInfoChanged.add(id);
             }
-        }, null);
+        }, /* subdirectories= */ null);
 
-        mainMtpStorage = manager.addMtpStorage(mainStorage);
-        secondaryMtpStorage = manager.addMtpStorage(secondaryStorage);
+        mainMtpStorage = manager.addMtpStorage(mainStorage, /* isHostWindows= */ () -> false);
+        secondaryMtpStorage = manager.addMtpStorage(secondaryStorage,
+                                                    /* isHostWindows= */ () -> false);
     }
 
     @After
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f33e118..2201753 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -300,6 +300,9 @@
     android_res_nquery; # introduced=29
     android_res_nresult; # introduced=29
     android_res_nsend; # introduced=29
+    android_tag_socket_with_uid; # introduced=Tiramisu
+    android_tag_socket; # introduced=Tiramisu
+    android_untag_socket; # introduced=Tiramisu
     AThermal_acquireManager; # introduced=30
     AThermal_releaseManager; # introduced=30
     AThermal_getCurrentThermalStatus; # introduced=30
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 327b1fb..54538d9 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -125,14 +125,14 @@
     name: "framework-connectivity-ethernet-sources",
     srcs: [
         "src/android/net/EthernetManager.java",
+        "src/android/net/EthernetNetworkManagementException.java",
+        "src/android/net/EthernetNetworkManagementException.aidl",
         "src/android/net/EthernetNetworkSpecifier.java",
+        "src/android/net/EthernetNetworkUpdateRequest.java",
+        "src/android/net/EthernetNetworkUpdateRequest.aidl",
         "src/android/net/IEthernetManager.aidl",
+        "src/android/net/IEthernetNetworkManagementListener.aidl",
         "src/android/net/IEthernetServiceListener.aidl",
-        "src/android/net/IInternalNetworkManagementListener.aidl",
-        "src/android/net/InternalNetworkUpdateRequest.java",
-        "src/android/net/InternalNetworkUpdateRequest.aidl",
-        "src/android/net/InternalNetworkManagementException.java",
-        "src/android/net/InternalNetworkManagementException.aidl",
         "src/android/net/ITetheredInterfaceCallback.aidl",
     ],
     path: "src",
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index ece54df..f472d56 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -320,15 +320,15 @@
     }
 
     private static final class InternalNetworkManagementListener
-            extends IInternalNetworkManagementListener.Stub {
+            extends IEthernetNetworkManagementListener.Stub {
         @NonNull
         private final Executor mExecutor;
         @NonNull
-        private final BiConsumer<Network, InternalNetworkManagementException> mListener;
+        private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
 
         InternalNetworkManagementListener(
                 @NonNull final Executor executor,
-                @NonNull final BiConsumer<Network, InternalNetworkManagementException> listener) {
+                @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) {
             Objects.requireNonNull(executor, "Pass a non-null executor");
             Objects.requireNonNull(listener, "Pass a non-null listener");
             mExecutor = executor;
@@ -338,14 +338,14 @@
         @Override
         public void onComplete(
                 @Nullable final Network network,
-                @Nullable final InternalNetworkManagementException e) {
+                @Nullable final EthernetNetworkManagementException e) {
             mExecutor.execute(() -> mListener.accept(network, e));
         }
     }
 
     private InternalNetworkManagementListener getInternalNetworkManagementListener(
             @Nullable final Executor executor,
-            @Nullable final BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) {
         if (null != listener) {
             Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
         }
@@ -360,9 +360,9 @@
 
     private void updateConfiguration(
             @NonNull String iface,
-            @NonNull InternalNetworkUpdateRequest request,
+            @NonNull EthernetNetworkUpdateRequest request,
             @Nullable @CallbackExecutor Executor executor,
-            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
         final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
                 executor, listener);
         try {
@@ -375,7 +375,7 @@
     private void connectNetwork(
             @NonNull String iface,
             @Nullable @CallbackExecutor Executor executor,
-            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
         final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
                 executor, listener);
         try {
@@ -388,7 +388,7 @@
     private void disconnectNetwork(
             @NonNull String iface,
             @Nullable @CallbackExecutor Executor executor,
-            @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+            @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
         final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
                 executor, listener);
         try {
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
similarity index 93%
rename from packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
index dcce706..adf9e5a 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
@@ -16,4 +16,4 @@
 
  package android.net;
 
- parcelable InternalNetworkManagementException;
\ No newline at end of file
+ parcelable EthernetNetworkManagementException;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
similarity index 73%
rename from packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
index 798e9c3..a35f28e 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
@@ -23,11 +23,11 @@
 import java.util.Objects;
 
 /** @hide */
-public final class InternalNetworkManagementException
+public final class EthernetNetworkManagementException
         extends RuntimeException implements Parcelable {
 
     /* @hide */
-    public InternalNetworkManagementException(@NonNull final String errorMessage) {
+    public EthernetNetworkManagementException(@NonNull final String errorMessage) {
         super(errorMessage);
     }
 
@@ -40,7 +40,7 @@
     public boolean equals(Object obj) {
         if (this == obj) return true;
         if (obj == null || getClass() != obj.getClass()) return false;
-        final InternalNetworkManagementException that = (InternalNetworkManagementException) obj;
+        final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj;
 
         return Objects.equals(getMessage(), that.getMessage());
     }
@@ -56,16 +56,16 @@
     }
 
     @NonNull
-    public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR =
-            new Parcelable.Creator<InternalNetworkManagementException>() {
+    public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR =
+            new Parcelable.Creator<EthernetNetworkManagementException>() {
                 @Override
-                public InternalNetworkManagementException[] newArray(int size) {
-                    return new InternalNetworkManagementException[size];
+                public EthernetNetworkManagementException[] newArray(int size) {
+                    return new EthernetNetworkManagementException[size];
                 }
 
                 @Override
-                public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) {
-                    return new InternalNetworkManagementException(source.readString());
+                public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) {
+                    return new EthernetNetworkManagementException(source.readString());
                 }
             };
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
similarity index 93%
rename from packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
index da00cb9..debc348 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
@@ -16,4 +16,4 @@
 
  package android.net;
 
- parcelable InternalNetworkUpdateRequest;
\ No newline at end of file
+ parcelable EthernetNetworkUpdateRequest;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
similarity index 80%
rename from packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
index f42c4b7..4d229d2 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
@@ -23,7 +23,7 @@
 import java.util.Objects;
 
 /** @hide */
-public final class InternalNetworkUpdateRequest implements Parcelable {
+public final class EthernetNetworkUpdateRequest implements Parcelable {
     @NonNull
     private final StaticIpConfiguration mIpConfig;
     @NonNull
@@ -40,7 +40,7 @@
     }
 
     /** @hide */
-    public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
+    public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
             @NonNull final NetworkCapabilities networkCapabilities) {
         Objects.requireNonNull(ipConfig);
         Objects.requireNonNull(networkCapabilities);
@@ -48,7 +48,7 @@
         mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
     }
 
-    private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
+    private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
         Objects.requireNonNull(source);
         mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
         mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
@@ -56,7 +56,7 @@
 
     @Override
     public String toString() {
-        return "InternalNetworkUpdateRequest{"
+        return "EthernetNetworkUpdateRequest{"
                 + "mIpConfig=" + mIpConfig
                 + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
     }
@@ -65,7 +65,7 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-        InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o;
+        EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
 
         return Objects.equals(that.getIpConfig(), mIpConfig)
                 && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
@@ -88,16 +88,16 @@
     }
 
     @NonNull
-    public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR =
-            new Parcelable.Creator<InternalNetworkUpdateRequest>() {
+    public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR =
+            new Parcelable.Creator<EthernetNetworkUpdateRequest>() {
                 @Override
-                public InternalNetworkUpdateRequest[] newArray(int size) {
-                    return new InternalNetworkUpdateRequest[size];
+                public EthernetNetworkUpdateRequest[] newArray(int size) {
+                    return new EthernetNetworkUpdateRequest[size];
                 }
 
                 @Override
-                public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
-                    return new InternalNetworkUpdateRequest(source);
+                public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
+                    return new EthernetNetworkUpdateRequest(source);
                 }
             };
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
index e688bea..544d02b 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
@@ -18,8 +18,8 @@
 
 import android.net.IpConfiguration;
 import android.net.IEthernetServiceListener;
-import android.net.IInternalNetworkManagementListener;
-import android.net.InternalNetworkUpdateRequest;
+import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkUpdateRequest;
 import android.net.ITetheredInterfaceCallback;
 
 /**
@@ -38,8 +38,8 @@
     void setIncludeTestInterfaces(boolean include);
     void requestTetheredInterface(in ITetheredInterfaceCallback callback);
     void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
-    void updateConfiguration(String iface, in InternalNetworkUpdateRequest request,
-        in IInternalNetworkManagementListener listener);
-    void connectNetwork(String iface, in IInternalNetworkManagementListener listener);
-    void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener);
+    void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
+        in IEthernetNetworkManagementListener listener);
+    void connectNetwork(String iface, in IEthernetNetworkManagementListener listener);
+    void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener);
 }
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
similarity index 80%
rename from packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
index 69cde3b..93edccf 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
@@ -16,10 +16,10 @@
 
 package android.net;
 
-import android.net.InternalNetworkManagementException;
+import android.net.EthernetNetworkManagementException;
 import android.net.Network;
 
 /** @hide */
-oneway interface IInternalNetworkManagementListener {
-    void onComplete(in Network network, in InternalNetworkManagementException exception);
+oneway interface IEthernetNetworkManagementListener {
+    void onComplete(in Network network, in EthernetNetworkManagementException exception);
 }
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 99e3160..df19c67 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -173,8 +173,10 @@
     }
 
     public BluetoothDevice getActiveDevice() {
-        if (mService == null) return null;
-        return mService.getActiveDevice();
+        if (mBluetoothAdapter == null) return null;
+        final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+                .getActiveDevices(BluetoothProfile.A2DP);
+        return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
     }
 
     @Override
@@ -221,7 +223,7 @@
     }
 
     public boolean supportsHighQualityAudio(BluetoothDevice device) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         if (bluetoothDevice == null) {
             return false;
         }
@@ -234,7 +236,7 @@
      */
     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         if (bluetoothDevice == null) {
             return false;
         }
@@ -260,7 +262,7 @@
     }
 
     public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         if (bluetoothDevice == null) {
             return;
         }
@@ -286,7 +288,7 @@
      */
     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
-        BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+        BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
         int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
         if (bluetoothDevice == null || !supportsHighQualityAudio(device)
                 || getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ddee433..233e798 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -500,6 +500,17 @@
     }
 
     /**
+     * Get identity address from remote device
+     * @return {@link BluetoothDevice#getIdentityAddress()} if
+     * {@link BluetoothDevice#getIdentityAddress()} is not null otherwise return
+     * {@link BluetoothDevice#getAddress()}
+     */
+    public String getIdentityAddress() {
+        final String identityAddress = mDevice.getIdentityAddress();
+        return TextUtils.isEmpty(identityAddress) ? getAddress() : identityAddress;
+    }
+
+    /**
      * Get name from remote device
      * @return {@link BluetoothDevice#getAlias()} if
      * {@link BluetoothDevice#getAlias()} is not null otherwise return
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 9dd329e..b44d914 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -132,10 +132,12 @@
     }
 
     public BluetoothDevice getActiveDevice() {
-        if (mService == null) {
+        if (mBluetoothAdapter == null) {
             return null;
         }
-        return mService.getActiveDevice();
+        final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+                .getActiveDevices(BluetoothProfile.HEADSET);
+        return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
     }
 
     public boolean isAudioOn() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index a1fba4a..ff1368a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -168,8 +168,10 @@
     }
 
     public List<BluetoothDevice> getActiveDevices() {
-        if (mService == null) return new ArrayList<>();
-        return mService.getActiveDevices();
+        if (mBluetoothAdapter == null) {
+            return new ArrayList<>();
+        }
+        return mBluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID);
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index 209507a..db6d41e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -21,12 +21,12 @@
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
 import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
 
-import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
@@ -177,10 +177,10 @@
     }
 
     public List<BluetoothDevice> getActiveDevices() {
-        if (mService == null) {
+        if (mBluetoothAdapter == null) {
             return new ArrayList<>();
         }
-        return mService.getActiveDevices();
+        return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
     }
 
     @Override
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index f167721..d7b366e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -60,6 +60,8 @@
     private BluetoothDevice mDevice;
     @Mock
     private BluetoothA2dp mBluetoothA2dp;
+    @Mock
+    private BluetoothAdapter mBluetoothAdapter;
     private BluetoothProfile.ServiceListener mServiceListener;
 
     private A2dpProfile mProfile;
@@ -72,7 +74,8 @@
         mProfile = new A2dpProfile(mContext, mDeviceManager, mProfileManager);
         mServiceListener = mShadowBluetoothAdapter.getServiceListener();
         mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
-        when(mBluetoothA2dp.getActiveDevice()).thenReturn(mDevice);
+        when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+                .thenReturn(Arrays.asList(mDevice));
     }
 
     @Test
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index bb5d783..7724c1a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -507,6 +507,7 @@
     <!-- Permission needed for CTS test - WifiManagerTest -->
     <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
     <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+    <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
 
     <!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 6a7afd9..2d328d8 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -539,7 +539,13 @@
     @GuardedBy("mLock")
     private void notifyAllPolicyListenersLocked() {
         for (final PolicyListenerBinderDeath policyListener : mRegisteredPolicyListeners.values()) {
-            Binder.withCleanCallingIdentity(() -> policyListener.mListener.onPolicyChanged());
+            Binder.withCleanCallingIdentity(() -> {
+                try {
+                    policyListener.mListener.onPolicyChanged();
+                } catch (RemoteException e) {
+                    logDbg("VcnStatusCallback threw on VCN status change", e);
+                }
+            });
         }
     }
 
@@ -548,8 +554,13 @@
             @NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) {
         for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
             if (isCallbackPermissioned(cbInfo, subGroup)) {
-                Binder.withCleanCallingIdentity(
-                        () -> cbInfo.mCallback.onVcnStatusChanged(statusCode));
+                Binder.withCleanCallingIdentity(() -> {
+                    try {
+                        cbInfo.mCallback.onVcnStatusChanged(statusCode);
+                    } catch (RemoteException e) {
+                        logDbg("VcnStatusCallback threw on VCN status change", e);
+                    }
+                });
             }
         }
     }
@@ -1222,13 +1233,17 @@
                 // Notify all registered StatusCallbacks for this subGroup
                 for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
                     if (isCallbackPermissioned(cbInfo, mSubGroup)) {
-                        Binder.withCleanCallingIdentity(
-                                () ->
-                                        cbInfo.mCallback.onGatewayConnectionError(
-                                                gatewayConnectionName,
-                                                errorCode,
-                                                exceptionClass,
-                                                exceptionMessage));
+                        Binder.withCleanCallingIdentity(() -> {
+                            try {
+                                cbInfo.mCallback.onGatewayConnectionError(
+                                        gatewayConnectionName,
+                                        errorCode,
+                                        exceptionClass,
+                                        exceptionMessage);
+                            } catch (RemoteException e) {
+                                logDbg("VcnStatusCallback threw on VCN status change", e);
+                            }
+                        });
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 2eb59b2..54987cf 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -29,7 +29,7 @@
 import android.media.AudioManager;
 import android.media.AudioRoutesInfo;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.media.IAudioRoutesObserver;
 import android.media.ICapturePresetDevicesRoleDispatcher;
 import android.media.ICommunicationDeviceDispatcher;
@@ -517,12 +517,12 @@
     /*package*/ static final class BtDeviceChangedData {
         final @Nullable BluetoothDevice mNewDevice;
         final @Nullable BluetoothDevice mPreviousDevice;
-        final @NonNull BtProfileConnectionInfo mInfo;
+        final @NonNull BluetoothProfileConnectionInfo mInfo;
         final @NonNull String mEventSource;
 
         BtDeviceChangedData(@Nullable BluetoothDevice newDevice,
                 @Nullable BluetoothDevice previousDevice,
-                @NonNull BtProfileConnectionInfo info, @NonNull String eventSource) {
+                @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) {
             mNewDevice = newDevice;
             mPreviousDevice = previousDevice;
             mInfo = info;
@@ -554,9 +554,9 @@
             mDevice = device;
             mState = state;
             mProfile = d.mInfo.getProfile();
-            mSupprNoisy = d.mInfo.getSuppressNoisyIntent();
+            mSupprNoisy = d.mInfo.isSuppressNoisyIntent();
             mVolume = d.mInfo.getVolume();
-            mIsLeOutput = d.mInfo.getIsLeOutput();
+            mIsLeOutput = d.mInfo.isLeOutput();
             mEventSource = d.mEventSource;
             mAudioSystemDevice = audioDevice;
             mMusicDevice = AudioSystem.DEVICE_NONE;
@@ -627,7 +627,7 @@
                 audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID;
                 break;
             case BluetoothProfile.LE_AUDIO:
-                if (d.mInfo.getIsLeOutput()) {
+                if (d.mInfo.isLeOutput()) {
                     audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET;
                 } else {
                     audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e00c8a3..070725e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -83,7 +83,7 @@
 import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioModeDispatcher;
 import android.media.IAudioRoutesObserver;
@@ -6301,14 +6301,14 @@
      * See AudioManager.handleBluetoothActiveDeviceChanged(...)
      */
     public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice,
-            BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
+            BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Bluetooth is the only caller allowed");
         }
         if (info == null) {
-            throw new IllegalArgumentException("Illegal null BtProfileConnectionInfo for device "
-                    + previousDevice + " -> " + newDevice);
+            throw new IllegalArgumentException("Illegal null BluetoothProfileConnectionInfo for"
+                    + " device " + previousDevice + " -> " + newDevice);
         }
         final int profile = info.getProfile();
         if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 9273a5d..1c29935 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -31,7 +31,7 @@
 import android.media.AudioDeviceAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.os.Binder;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -495,11 +495,13 @@
         if (state == BluetoothProfile.STATE_CONNECTED) {
             mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                     new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
-                        new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
+                        new BluetoothProfileConnectionInfo(profile),
+                        "mBluetoothProfileServiceListener"));
         } else {
             mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                     new AudioDeviceBroker.BtDeviceChangedData(null, btDevice,
-                        new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
+                        new BluetoothProfileConnectionInfo(profile),
+                        "mBluetoothProfileServiceListener"));
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index 9e1445c..bdea679 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -30,7 +30,7 @@
 import android.content.Intent;
 import android.media.AudioManager;
 import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -100,7 +100,7 @@
 
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
-                    BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource"));
         Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS);
         verify(mSpyDevInventory, times(1)).setBluetoothActiveDevice(
                 any(AudioDeviceBroker.BtDeviceInfo.class)
@@ -208,13 +208,13 @@
         // first connection: ensure the device is connected as a starting condition for the test
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
-                    BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource"));
         Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
 
         // disconnection
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(null, mFakeBtDevice,
-                    BtProfileConnectionInfo.a2dpInfo(false, -1), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(false, -1), "testSource"));
         if (delayAfterDisconnection > 0) {
             Thread.sleep(delayAfterDisconnection);
         }
@@ -222,7 +222,7 @@
         // reconnection
         mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
                 new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
-                    BtProfileConnectionInfo.a2dpInfo(true, 2), "testSource"));
+                    BluetoothProfileConnectionInfo.createA2dpInfo(true, 2), "testSource"));
         Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS);
 
         // Verify disconnection has been cancelled and we're seeing two connections attempts,
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 1252965..9a991a1 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -107,6 +107,25 @@
         }
     }
 
+    /**
+     * Convenience method for running the provided action in the provided
+     * executor enclosed in
+     * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity}
+     *
+     * Any exception thrown by the given action will need to be handled by caller.
+     *
+     */
+    public static void runWithCleanCallingIdentity(
+            @NonNull Runnable action, @NonNull Executor executor) {
+        if (action != null) {
+            if (executor != null) {
+                executor.execute(() -> runWithCleanCallingIdentity(action));
+            } else {
+                runWithCleanCallingIdentity(action);
+            }
+        }
+    }
+
 
     /**
      * Convenience method for running the provided action enclosed in
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 051d6c5..13d8c7b 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -259,9 +259,10 @@
     }
 
     /**
-     * Unthrottles the APN on the current transport.  There is no matching "APN throttle" method.
-     * Instead, the APN is throttled when {@link IDataService#setupDataCall} fails within
-     * the time specified by {@link DataCallResponse#getRetryDurationMillis}.
+     * Unthrottles the APN on the current transport.
+     * The APN is throttled when {@link IDataService#setupDataCall} fails within
+     * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain
+     * throttled until this method is called.
      * <p/>
      * see: {@link DataCallResponse#getRetryDurationMillis}
      *
@@ -282,9 +283,9 @@
 
     /**
      * Unthrottles the DataProfile on the current transport.
-     * There is no matching "DataProfile throttle" method.
-     * Instead, the DataProfile is throttled when {@link IDataService#setupDataCall} fails within
-     * the time specified by {@link DataCallResponse#getRetryDurationMillis}.
+     * The DataProfile is throttled when {@link IDataService#setupDataCall} fails within
+     * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain
+     * throttled until this method is called.
      * <p/>
      * see: {@link DataCallResponse#getRetryDurationMillis}
      *
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index dfe5e6c9..d65286f 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -27,10 +27,12 @@
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsVideoCallProvider;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Provides the call initiation/termination, and media exchange between two IMS endpoints.
@@ -522,6 +524,7 @@
     private final IImsCallSession miSession;
     private boolean mClosed = false;
     private Listener mListener;
+    private Executor mListenerExecutor = Runnable::run;
 
     /** @hide */
     public ImsCallSession(IImsCallSession iSession) {
@@ -538,9 +541,9 @@
     }
 
     /** @hide */
-    public ImsCallSession(IImsCallSession iSession, Listener listener) {
+    public ImsCallSession(IImsCallSession iSession, Listener listener, Executor executor) {
         this(iSession);
-        setListener(listener);
+        setListener(listener, executor);
     }
 
     /**
@@ -738,10 +741,14 @@
      * override the previous listener.
      *
      * @param listener to listen to the session events of this object
+     * @param executor an Executor that will execute callbacks
      * @hide
      */
-    public void setListener(Listener listener) {
+    public void setListener(Listener listener, Executor executor) {
         mListener = listener;
+        if (executor != null) {
+            mListenerExecutor = executor;
+        }
     }
 
     /**
@@ -1205,44 +1212,56 @@
          */
         @Override
         public void callSessionInitiating(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionInitiating(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionInitiating(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionProgressing(ImsStreamMediaProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionProgressing(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionProgressing(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInitiated(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionStarted(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionStarted(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInitiatingFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionTerminated(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1250,44 +1269,56 @@
          */
         @Override
         public void callSessionHeld(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionHeld(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHeld(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionHoldReceived(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionHoldReceived(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHoldReceived(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionResumed(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionResumed(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionResumed(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionResumeReceived(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionResumeReceived(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionResumeReceived(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1310,15 +1341,17 @@
          */
         @Override
         public void callSessionMergeComplete(IImsCallSession newSession) {
-            if (mListener != null) {
-                if (newSession != null) {
-                    // New session created after conference
-                    mListener.callSessionMergeComplete(new ImsCallSession(newSession));
-               } else {
-                   // Session already exists. Hence no need to pass
-                   mListener.callSessionMergeComplete(null);
-               }
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    if (newSession != null) {
+                        // New session created after conference
+                        mListener.callSessionMergeComplete(new ImsCallSession(newSession));
+                    } else {
+                        // Session already exists. Hence no need to pass
+                        mListener.callSessionMergeComplete(null);
+                    }
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1328,9 +1361,11 @@
          */
         @Override
         public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1338,23 +1373,29 @@
          */
         @Override
         public void callSessionUpdated(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionUpdated(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUpdated(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionUpdateReceived(ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1363,26 +1404,33 @@
         @Override
         public void callSessionConferenceExtended(IImsCallSession newSession,
                 ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionConferenceExtended(ImsCallSession.this,
-                        new ImsCallSession(newSession), profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceExtended(ImsCallSession.this,
+                            new ImsCallSession(newSession), profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceExtendFailed(
+                            ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionConferenceExtendReceived(IImsCallSession newSession,
                 ImsCallProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
-                        new ImsCallSession(newSession), profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
+                            new ImsCallSession(newSession), profile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1391,32 +1439,41 @@
          */
         @Override
         public void callSessionInviteParticipantsRequestDelivered() {
-            if (mListener != null) {
-                mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionInviteParticipantsRequestDelivered(
+                            ImsCallSession.this);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
-                        reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
+                            reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionRemoveParticipantsRequestDelivered() {
-            if (mListener != null) {
-                mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
-                        reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
+                            reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1424,9 +1481,11 @@
          */
         @Override
         public void callSessionConferenceStateUpdated(ImsConferenceState state) {
-            if (mListener != null) {
-                mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1434,9 +1493,12 @@
          */
         @Override
         public void callSessionUssdMessageReceived(int mode, String ussdMessage) {
-            if (mListener != null) {
-                mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode,
+                            ussdMessage);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1452,10 +1514,12 @@
          */
         @Override
         public void callSessionMayHandover(int srcNetworkType, int targetNetworkType) {
-            if (mListener != null) {
-                mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
-                        targetNetworkType);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
+                            targetNetworkType);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1464,10 +1528,12 @@
         @Override
         public void callSessionHandover(int srcNetworkType, int targetNetworkType,
                 ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
-                        targetNetworkType, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
+                            targetNetworkType, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1476,10 +1542,12 @@
         @Override
         public void callSessionHandoverFailed(int srcNetworkType, int targetNetworkType,
                 ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
-                        targetNetworkType, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
+                            targetNetworkType, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1487,9 +1555,11 @@
          */
         @Override
         public void callSessionTtyModeReceived(int mode) {
-            if (mListener != null) {
-                mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1499,16 +1569,22 @@
          *      otherwise.
          */
         public void callSessionMultipartyStateChanged(boolean isMultiParty) {
-            if (mListener != null) {
-                mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionMultipartyStateChanged(ImsCallSession.this,
+                            isMultiParty);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) {
-            if (mListener != null) {
-                mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionSuppServiceReceived(ImsCallSession.this,
+                            suppServiceInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1516,9 +1592,12 @@
          */
         @Override
         public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) {
-            if (mListener != null) {
-                mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttModifyRequestReceived(ImsCallSession.this,
+                            callProfile);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1526,9 +1605,11 @@
          */
         @Override
         public void callSessionRttModifyResponseReceived(int status) {
-            if (mListener != null) {
-                mListener.callSessionRttModifyResponseReceived(status);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttModifyResponseReceived(status);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1536,9 +1617,11 @@
          */
         @Override
         public void callSessionRttMessageReceived(String rttMessage) {
-            if (mListener != null) {
-                mListener.callSessionRttMessageReceived(rttMessage);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttMessageReceived(rttMessage);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1546,23 +1629,29 @@
          */
         @Override
         public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
-            if (mListener != null) {
-                mListener.callSessionRttAudioIndicatorChanged(profile);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRttAudioIndicatorChanged(profile);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionTransferred() {
-            if (mListener != null) {
-                mListener.callSessionTransferred(ImsCallSession.this);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTransferred(ImsCallSession.this);
+                }
+            }, mListenerExecutor);
         }
 
         @Override
         public void callSessionTransferFailed(@Nullable ImsReasonInfo reasonInfo) {
-            if (mListener != null) {
-                mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1571,9 +1660,11 @@
          */
         @Override
         public void callSessionDtmfReceived(char dtmf) {
-            if (mListener != null) {
-                mListener.callSessionDtmfReceived(dtmf);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionDtmfReceived(dtmf);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1581,9 +1672,11 @@
          */
         @Override
         public void callQualityChanged(CallQuality callQuality) {
-            if (mListener != null) {
-                mListener.callQualityChanged(callQuality);
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callQualityChanged(callQuality);
+                }
+            }, mListenerExecutor);
         }
 
         /**
@@ -1593,10 +1686,12 @@
         @Override
         public void callSessionRtpHeaderExtensionsReceived(
                 @NonNull List<RtpHeaderExtension> extensions) {
-            if (mListener != null) {
-                mListener.callSessionRtpHeaderExtensionsReceived(
-                        new ArraySet<RtpHeaderExtension>(extensions));
-            }
+            TelephonyUtils.runWithCleanCallingIdentity(()-> {
+                if (mListener != null) {
+                    mListener.callSessionRtpHeaderExtensionsReceived(
+                            new ArraySet<RtpHeaderExtension>(extensions));
+                }
+            }, mListenerExecutor);
         }
     }