Merge "Updating locked_region_code_injection to use ASM7"
diff --git a/core/api/current.txt b/core/api/current.txt
index 9922615..d9753ab 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -120,6 +120,7 @@
     field @Deprecated public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
     field @Deprecated public static final String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
     field public static final String QUERY_ALL_PACKAGES = "android.permission.QUERY_ALL_PACKAGES";
+    field public static final String READ_BASIC_PHONE_STATE = "android.permission.READ_BASIC_PHONE_STATE";
     field public static final String READ_CALENDAR = "android.permission.READ_CALENDAR";
     field public static final String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
     field public static final String READ_CONTACTS = "android.permission.READ_CONTACTS";
@@ -8648,10 +8649,10 @@
     method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
     method public int getState();
-    method public int isCisCentralSupported();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
     method public boolean isEnabled();
     method public boolean isLe2MPhySupported();
+    method public int isLeAudioSupported();
     method public boolean isLeCodedPhySupported();
     method public boolean isLeExtendedAdvertisingSupported();
     method public boolean isLePeriodicAdvertisingSupported();
@@ -9023,6 +9024,72 @@
     field public static final int TELEPHONY = 4194304; // 0x400000
   }
 
+  public final class BluetoothCodecConfig implements android.os.Parcelable {
+    ctor public BluetoothCodecConfig(int);
+    method public int describeContents();
+    method public int getBitsPerSample();
+    method public int getChannelMode();
+    method public int getCodecPriority();
+    method public long getCodecSpecific1();
+    method public long getCodecSpecific2();
+    method public long getCodecSpecific3();
+    method public long getCodecSpecific4();
+    method public int getCodecType();
+    method public static int getMaxCodecType();
+    method public int getSampleRate();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
+    field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
+    field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
+    field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
+    field public static final int CHANNEL_MODE_MONO = 1; // 0x1
+    field public static final int CHANNEL_MODE_NONE = 0; // 0x0
+    field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
+    field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
+    field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
+    field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
+    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
+    field public static final int SAMPLE_RATE_176400 = 16; // 0x10
+    field public static final int SAMPLE_RATE_192000 = 32; // 0x20
+    field public static final int SAMPLE_RATE_44100 = 1; // 0x1
+    field public static final int SAMPLE_RATE_48000 = 2; // 0x2
+    field public static final int SAMPLE_RATE_88200 = 4; // 0x4
+    field public static final int SAMPLE_RATE_96000 = 8; // 0x8
+    field public static final int SAMPLE_RATE_NONE = 0; // 0x0
+    field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
+    field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
+    field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
+    field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
+    field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
+    field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
+  }
+
+  public static final class BluetoothCodecConfig.Builder {
+    ctor public BluetoothCodecConfig.Builder();
+    method @NonNull public android.bluetooth.BluetoothCodecConfig build();
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setBitsPerSample(int);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setChannelMode(int);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecPriority(int);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific1(long);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific2(long);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific3(long);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific4(long);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecType(int);
+    method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setSampleRate(int);
+  }
+
+  public final class BluetoothCodecStatus implements android.os.Parcelable {
+    ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>);
+    method public int describeContents();
+    method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
+    method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsLocalCapabilities();
+    method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsSelectableCapabilities();
+    method public boolean isCodecConfigSelectable(@Nullable android.bluetooth.BluetoothCodecConfig);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
+    field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
+  }
+
   public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
     method public void close();
     method protected void finalize();
@@ -9453,6 +9520,20 @@
     field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
   }
 
+  public final class BluetoothLeAudioCodecConfig {
+    method @NonNull public String getCodecName();
+    method public int getCodecType();
+    method public static int getMaxCodecType();
+    field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
+    field public static final int SOURCE_CODEC_TYPE_LC3 = 0; // 0x0
+  }
+
+  public static final class BluetoothLeAudioCodecConfig.Builder {
+    ctor public BluetoothLeAudioCodecConfig.Builder();
+    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build();
+    method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int);
+  }
+
   public final class BluetoothManager {
     method public android.bluetooth.BluetoothAdapter getAdapter();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
@@ -31470,6 +31551,7 @@
     method public int dataPosition();
     method public int dataSize();
     method public void enforceInterface(@NonNull String);
+    method public void enforceNoDataAvail();
     method public boolean hasFileDescriptors();
     method public boolean hasFileDescriptors(int, int);
     method public byte[] marshall();
@@ -31508,17 +31590,17 @@
     method @Deprecated public void readMap(@NonNull java.util.Map, @Nullable ClassLoader);
     method public <K, V> void readMap(@NonNull java.util.Map<? super K,? super V>, @Nullable ClassLoader, @NonNull Class<K>, @NonNull Class<V>);
     method @Deprecated @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
-    method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>);
-    method @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader);
+    method @Nullable public <T> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>);
+    method @Deprecated @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader);
     method @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader, @NonNull Class<T>);
     method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
     method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
-    method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
+    method @Deprecated @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
     method @NonNull public <T> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader, @NonNull Class<T>);
     method @Nullable public android.os.PersistableBundle readPersistableBundle();
     method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
     method @Deprecated @Nullable public java.io.Serializable readSerializable();
-    method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
+    method @Nullable public <T> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
     method @NonNull public android.util.Size readSize();
     method @NonNull public android.util.SizeF readSizeF();
     method @Deprecated @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
@@ -39987,6 +40069,7 @@
     field public static final String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
     field public static final String EXTRA_IS_RTT_AUDIO_PRESENT = "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
     field public static final String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
+    field public static final String EXTRA_LAST_KNOWN_CELL_IDENTITY = "android.telecom.extra.LAST_KNOWN_CELL_IDENTITY";
     field public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
     field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200
     field public static final int PROPERTY_CROSS_SIM = 8192; // 0x2000
@@ -42722,11 +42805,11 @@
     method public int getCarrierIdFromSimMccMnc();
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.telephony.CellLocation getCellLocation();
     method public int getDataActivity();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getDataNetworkType();
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public int getDataNetworkType();
     method public int getDataState();
     method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId();
     method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(int);
-    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public String getDeviceSoftwareVersion();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<java.lang.String> getEquivalentHomePlmns();
@@ -42779,22 +42862,22 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber();
-    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getVoiceNetworkType();
+    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public int getVoiceNetworkType();
     method @Nullable public android.net.Uri getVoicemailRingtoneUri(android.telecom.PhoneAccountHandle);
     method public boolean hasCarrierPrivileges();
     method public boolean hasIccCard();
-    method @Deprecated public boolean iccCloseLogicalChannel(int);
-    method @Deprecated public byte[] iccExchangeSimIO(int, int, int, int, int, String);
+    method public boolean iccCloseLogicalChannel(int);
+    method public byte[] iccExchangeSimIO(int, int, int, int, int, String);
     method @Deprecated public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(String);
-    method @Deprecated public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(String, int);
-    method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
-    method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
+    method public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannel(String, int);
+    method public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
+    method public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
     method public boolean isConcurrentVoiceAndDataSupported();
     method public boolean isDataCapable();
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isDataConnectionAllowed();
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabled();
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataEnabledForReason(int);
-    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataConnectionAllowed();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataEnabled();
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataEnabledForReason(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_BASIC_PHONE_STATE}) public boolean isDataRoamingEnabled();
     method public boolean isEmergencyNumber(@NonNull String);
     method public boolean isHearingAidCompatibilitySupported();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isManualNetworkSelectionAllowed();
@@ -42813,7 +42896,7 @@
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
     method public void sendDialerSpecialCode(String);
-    method @Deprecated public String sendEnvelopeWithStatus(String);
+    method public String sendEnvelopeWithStatus(String);
     method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
     method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 84a4a44..cd1fef9 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12055,10 +12055,10 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
-    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
-    method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
@@ -12884,6 +12884,7 @@
     method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteredFeatureTags();
     method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteringFeatureTags();
     method @NonNull public java.util.Set<java.lang.String> getRegisteredFeatureTags();
+    method @NonNull public java.util.Set<java.lang.String> getRegisteringFeatureTags();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.DelegateRegistrationState> CREATOR;
     field public static final int DEREGISTERED_REASON_NOT_PROVISIONED = 1; // 0x1
@@ -12891,8 +12892,10 @@
     field public static final int DEREGISTERED_REASON_UNKNOWN = 0; // 0x0
     field public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6; // 0x6
     field public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5; // 0x5
+    field public static final int DEREGISTERING_REASON_LOSING_PDN = 7; // 0x7
     field public static final int DEREGISTERING_REASON_PDN_CHANGE = 3; // 0x3
     field public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4; // 0x4
+    field public static final int DEREGISTERING_REASON_UNSPECIFIED = 8; // 0x8
   }
 
   public static final class DelegateRegistrationState.Builder {
@@ -12901,6 +12904,7 @@
     method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addDeregisteringFeatureTag(@NonNull String, int);
     method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTag(@NonNull String);
     method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTags(@NonNull java.util.Set<java.lang.String>);
+    method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteringFeatureTags(@NonNull java.util.Set<java.lang.String>);
     method @NonNull public android.telephony.ims.DelegateRegistrationState build();
   }
 
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 2c875fe..14be921 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2283,21 +2283,21 @@
     public @interface LeFeatureReturnValues {}
 
     /**
-     * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Connected Isochronous Stream Central
-     * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
+     * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is
+     * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
      * the feature is not supported or an error code.
      *
-     * @return whether the chipset supports the LE Connected Isochronous Stream Central feature
+     * @return whether the LE audio is supported
      */
     @RequiresNoPermission
-    public @LeFeatureReturnValues int isCisCentralSupported() {
+    public @LeFeatureReturnValues int isLeAudioSupported() {
         if (!getLeAccess()) {
             return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
         }
         try {
             mServiceLock.readLock().lock();
             if (mService != null) {
-                return mService.isCisCentralSupported();
+                return mService.isLeAudioSupported();
             }
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 1d0bf97..9a4151a 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -29,16 +29,14 @@
 
 /**
  * Represents the codec configuration for a Bluetooth A2DP source device.
+ * <p>Contains the source codec type, the codec priority, the codec sample
+ * rate, the codec bits per sample, and the codec channel mode.
+ * <p>The source codec type values are the same as those supported by the
+ * device hardware.
  *
  * {@see BluetoothA2dp}
- *
- * {@hide}
  */
 public final class BluetoothCodecConfig implements Parcelable {
-    // Add an entry for each source codec here.
-    // NOTE: The values should be same as those listed in the following file:
-    //   hardware/libhardware/include/hardware/bt_av.h
-
     /** @hide */
     @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
             SOURCE_CODEC_TYPE_SBC,
@@ -46,33 +44,49 @@
             SOURCE_CODEC_TYPE_APTX,
             SOURCE_CODEC_TYPE_APTX_HD,
             SOURCE_CODEC_TYPE_LDAC,
-            SOURCE_CODEC_TYPE_MAX,
             SOURCE_CODEC_TYPE_INVALID
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SourceCodecType {}
 
-    @UnsupportedAppUsage
+    /**
+     * Source codec type SBC. This is the mandatory source codec
+     * type.
+     */
     public static final int SOURCE_CODEC_TYPE_SBC = 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Source codec type AAC.
+     */
     public static final int SOURCE_CODEC_TYPE_AAC = 1;
 
-    @UnsupportedAppUsage
+    /**
+     * Source codec type APTX.
+     */
     public static final int SOURCE_CODEC_TYPE_APTX = 2;
 
-    @UnsupportedAppUsage
+    /**
+     * Source codec type APTX HD.
+     */
     public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
 
-    @UnsupportedAppUsage
+    /**
+     * Source codec type LDAC.
+     */
     public static final int SOURCE_CODEC_TYPE_LDAC = 4;
 
-    @UnsupportedAppUsage
-    public static final int SOURCE_CODEC_TYPE_MAX = 5;
-
-    @UnsupportedAppUsage
+    /**
+     * Source codec type invalid. This is the default value used for codec
+     * type.
+     */
     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
 
+    /**
+     * Represents the count of valid source codec types. Can be accessed via
+     * {@link #getMaxCodecType}.
+     */
+    private static final int SOURCE_CODEC_TYPE_MAX = 5;
+
     /** @hide */
     @IntDef(prefix = "CODEC_PRIORITY_", value = {
             CODEC_PRIORITY_DISABLED,
@@ -82,16 +96,24 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface CodecPriority {}
 
-    @UnsupportedAppUsage
+    /**
+     * Codec priority disabled.
+     * Used to indicate that this codec is disabled and should not be used.
+     */
     public static final int CODEC_PRIORITY_DISABLED = -1;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec priority default.
+     * Default value used for codec priority.
+     */
     public static final int CODEC_PRIORITY_DEFAULT = 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec priority highest.
+     * Used to indicate the highest priority a codec can have.
+     */
     public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
 
-
     /** @hide */
     @IntDef(prefix = "SAMPLE_RATE_", value = {
             SAMPLE_RATE_NONE,
@@ -105,28 +127,42 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface SampleRate {}
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 0 Hz. Default value used for
+     * codec sample rate.
+     */
     public static final int SAMPLE_RATE_NONE = 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 44100 Hz.
+     */
     public static final int SAMPLE_RATE_44100 = 0x1 << 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 48000 Hz.
+     */
     public static final int SAMPLE_RATE_48000 = 0x1 << 1;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 88200 Hz.
+     */
     public static final int SAMPLE_RATE_88200 = 0x1 << 2;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 96000 Hz.
+     */
     public static final int SAMPLE_RATE_96000 = 0x1 << 3;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 176400 Hz.
+     */
     public static final int SAMPLE_RATE_176400 = 0x1 << 4;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec sample rate 192000 Hz.
+     */
     public static final int SAMPLE_RATE_192000 = 0x1 << 5;
 
-
     /** @hide */
     @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
             BITS_PER_SAMPLE_NONE,
@@ -137,19 +173,27 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface BitsPerSample {}
 
-    @UnsupportedAppUsage
+    /**
+     * Codec bits per sample 0. Default value of the codec
+     * bits per sample.
+     */
     public static final int BITS_PER_SAMPLE_NONE = 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec bits per sample 16.
+     */
     public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec bits per sample 24.
+     */
     public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec bits per sample 32.
+     */
     public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
 
-
     /** @hide */
     @IntDef(prefix = "CHANNEL_MODE_", value = {
             CHANNEL_MODE_NONE,
@@ -159,13 +203,20 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface ChannelMode {}
 
-    @UnsupportedAppUsage
+    /**
+     * Codec channel mode NONE. Default value of the
+     * codec channel mode.
+     */
     public static final int CHANNEL_MODE_NONE = 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec channel mode MONO.
+     */
     public static final int CHANNEL_MODE_MONO = 0x1 << 0;
 
-    @UnsupportedAppUsage
+    /**
+     * Codec channel mode STEREO.
+     */
     public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
 
     private final @SourceCodecType int mCodecType;
@@ -178,6 +229,21 @@
     private final long mCodecSpecific3;
     private final long mCodecSpecific4;
 
+    /**
+     * Creates a new BluetoothCodecConfig.
+     *
+     * @param codecType the source codec type
+     * @param codecPriority the priority of this codec
+     * @param sampleRate the codec sample rate
+     * @param bitsPerSample the bits per sample of this codec
+     * @param channelMode the channel mode of this codec
+     * @param codecSpecific1 the specific value 1
+     * @param codecSpecific2 the specific value 2
+     * @param codecSpecific3 the specific value 3
+     * @param codecSpecific4 the specific value 4
+     * values to 0.
+     * @hide
+     */
     @UnsupportedAppUsage
     public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
             @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
@@ -195,17 +261,34 @@
         mCodecSpecific4 = codecSpecific4;
     }
 
-    @UnsupportedAppUsage
+    /**
+     * Creates a new BluetoothCodecConfig.
+     * <p> By default, the codec priority will be set
+     * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
+     * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
+     * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
+     * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
+     * values to 0.
+     *
+     * @param codecType the source codec type
+     */
     public BluetoothCodecConfig(@SourceCodecType int codecType) {
-        mCodecType = codecType;
-        mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
-        mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
-        mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
-        mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
-        mCodecSpecific1 = 0;
-        mCodecSpecific2 = 0;
-        mCodecSpecific3 = 0;
-        mCodecSpecific4 = 0;
+        this(codecType, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                BluetoothCodecConfig.SAMPLE_RATE_NONE,
+                BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
+                BluetoothCodecConfig.CHANNEL_MODE_NONE, 0, 0, 0, 0);
+    }
+
+    private BluetoothCodecConfig(Parcel in) {
+        mCodecType = in.readInt();
+        mCodecPriority = in.readInt();
+        mSampleRate = in.readInt();
+        mBitsPerSample = in.readInt();
+        mChannelMode = in.readInt();
+        mCodecSpecific1 = in.readLong();
+        mCodecSpecific2 = in.readLong();
+        mCodecSpecific3 = in.readLong();
+        mCodecSpecific4 = in.readLong();
     }
 
     @Override
@@ -226,10 +309,8 @@
     }
 
     /**
-     * Returns a hash based on the config values
-     *
-     * @return a hash based on the config values
-     * @hide
+     * Returns a hash representation of this BluetoothCodecConfig
+     * based on all the config values.
      */
     @Override
     public int hashCode() {
@@ -239,32 +320,24 @@
     }
 
     /**
-     * Checks whether the object contains valid codec configuration.
-     *
-     * @return true if the object contains valid codec configuration, otherwise false.
-     * @hide
-     */
-    public boolean isValid() {
-        return (mSampleRate != SAMPLE_RATE_NONE)
-                && (mBitsPerSample != BITS_PER_SAMPLE_NONE)
-                && (mChannelMode != CHANNEL_MODE_NONE);
-    }
-
-    /**
      * Adds capability string to an existing string.
      *
-     * @param prevStr the previous string with the capabilities. Can be a null pointer.
-     * @param capStr the capability string to append to prevStr argument.
-     * @return the result string in the form "prevStr|capStr".
+     * @param prevStr the previous string with the capabilities. Can be a {@code null} pointer
+     * @param capStr the capability string to append to prevStr argument
+     * @return the result string in the form "prevStr|capStr"
      */
-    private static String appendCapabilityToString(String prevStr,
-            String capStr) {
+    private static String appendCapabilityToString(@Nullable String prevStr,
+            @NonNull String capStr) {
         if (prevStr == null) {
             return capStr;
         }
         return prevStr + "|" + capStr;
     }
 
+    /**
+     * Returns a {@link String} that describes each BluetoothCodecConfig parameter
+     * current value.
+     */
     @Override
     public String toString() {
         String sampleRateStr = null;
@@ -331,8 +404,6 @@
     }
 
     /**
-     * Always returns 0
-     *
      * @return 0
      * @hide
      */
@@ -344,20 +415,7 @@
     public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecConfig> CREATOR =
             new Parcelable.Creator<BluetoothCodecConfig>() {
                 public BluetoothCodecConfig createFromParcel(Parcel in) {
-                    final int codecType = in.readInt();
-                    final int codecPriority = in.readInt();
-                    final int sampleRate = in.readInt();
-                    final int bitsPerSample = in.readInt();
-                    final int channelMode = in.readInt();
-                    final long codecSpecific1 = in.readLong();
-                    final long codecSpecific2 = in.readLong();
-                    final long codecSpecific3 = in.readLong();
-                    final long codecSpecific4 = in.readLong();
-                    return new BluetoothCodecConfig(codecType, codecPriority,
-                            sampleRate, bitsPerSample,
-                            channelMode, codecSpecific1,
-                            codecSpecific2, codecSpecific3,
-                            codecSpecific4);
+                    return new BluetoothCodecConfig(in);
                 }
 
                 public BluetoothCodecConfig[] newArray(int size) {
@@ -368,8 +426,8 @@
     /**
      * Flattens the object to a parcel
      *
-     * @param out The Parcel in which the object should be written.
-     * @param flags Additional flags about how the object should be written.
+     * @param out The Parcel in which the object should be written
+     * @param flags Additional flags about how the object should be written
      *
      * @hide
      */
@@ -387,9 +445,8 @@
     }
 
     /**
-     * Gets the codec name.
-     *
-     * @return the codec name
+     * Returns the codec name converted to {@link String}.
+     * @hide
      */
     public @NonNull String getCodecName() {
         switch (mCodecType) {
@@ -412,137 +469,100 @@
     }
 
     /**
-     * Gets the codec type.
-     * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
-     *
-     * @return the codec type
+     * Returns the source codec type of this config.
      */
-    @UnsupportedAppUsage
     public @SourceCodecType int getCodecType() {
         return mCodecType;
     }
 
     /**
+     * Returns the valid codec types count.
+     */
+    public static int getMaxCodecType() {
+        return SOURCE_CODEC_TYPE_MAX;
+    }
+
+    /**
      * Checks whether the codec is mandatory.
+     * <p> The actual mandatory codec type for Android Bluetooth audio is SBC.
+     * See {@link #SOURCE_CODEC_TYPE_SBC}.
      *
-     * @return true if the codec is mandatory, otherwise false.
+     * @return {@code true} if the codec is mandatory, {@code false} otherwise
+     * @hide
      */
     public boolean isMandatoryCodec() {
         return mCodecType == SOURCE_CODEC_TYPE_SBC;
     }
 
     /**
-     * Gets the codec selection priority.
-     * The codec selection priority is relative to other codecs: larger value
-     * means higher priority. If 0, reset to default.
-     *
-     * @return the codec priority
+     * Returns the codec selection priority.
+     * <p>The codec selection priority is relative to other codecs: larger value
+     * means higher priority.
      */
-    @UnsupportedAppUsage
     public @CodecPriority int getCodecPriority() {
         return mCodecPriority;
     }
 
     /**
      * Sets the codec selection priority.
-     * The codec selection priority is relative to other codecs: larger value
-     * means higher priority. If 0, reset to default.
+     * <p>The codec selection priority is relative to other codecs: larger value
+     * means higher priority.
      *
-     * @param codecPriority the codec priority
+     * @param codecPriority the priority this codec should have
      * @hide
      */
-    @UnsupportedAppUsage
     public void setCodecPriority(@CodecPriority int codecPriority) {
         mCodecPriority = codecPriority;
     }
 
     /**
-     * Gets the codec sample rate. The value can be a bitmask with all
-     * supported sample rates:
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
-     * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
-     *
-     * @return the codec sample rate
+     * Returns the codec sample rate. The value can be a bitmask with all
+     * supported sample rates.
      */
-    @UnsupportedAppUsage
     public @SampleRate int getSampleRate() {
         return mSampleRate;
     }
 
     /**
-     * Gets the codec bits per sample. The value can be a bitmask with all
-     * bits per sample supported:
-     * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
-     * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
-     * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
-     * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
-     *
-     * @return the codec bits per sample
+     * Returns the codec bits per sample. The value can be a bitmask with all
+     * bits per sample supported.
      */
-    @UnsupportedAppUsage
     public @BitsPerSample int getBitsPerSample() {
         return mBitsPerSample;
     }
 
     /**
-     * Gets the codec channel mode. The value can be a bitmask with all
-     * supported channel modes:
-     * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
-     * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
-     * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
-     *
-     * @return the codec channel mode
-     * @hide
+     * Returns the codec channel mode. The value can be a bitmask with all
+     * supported channel modes.
      */
-    @UnsupportedAppUsage
     public @ChannelMode int getChannelMode() {
         return mChannelMode;
     }
 
     /**
-     * Gets a codec specific value1.
-     *
-     * @return a codec specific value1.
+     * Returns the codec specific value1.
      */
-    @UnsupportedAppUsage
     public long getCodecSpecific1() {
         return mCodecSpecific1;
     }
 
     /**
-     * Gets a codec specific value2.
-     *
-     * @return a codec specific value2
-     * @hide
+     * Returns the codec specific value2.
      */
-    @UnsupportedAppUsage
     public long getCodecSpecific2() {
         return mCodecSpecific2;
     }
 
     /**
-     * Gets a codec specific value3.
-     *
-     * @return a codec specific value3
-     * @hide
+     * Returns the codec specific value3.
      */
-    @UnsupportedAppUsage
     public long getCodecSpecific3() {
         return mCodecSpecific3;
     }
 
     /**
-     * Gets a codec specific value4.
-     *
-     * @return a codec specific value4
-     * @hide
+     * Returns the codec specific value4.
      */
-    @UnsupportedAppUsage
     public long getCodecSpecific4() {
         return mCodecSpecific4;
     }
@@ -551,7 +571,7 @@
      * Checks whether a value set presented by a bitmask has zero or single bit
      *
      * @param valueSet the value set presented by a bitmask
-     * @return true if the valueSet contains zero or single bit, otherwise false.
+     * @return {@code true} if the valueSet contains zero or single bit, {@code false} otherwise
      * @hide
      */
     private static boolean hasSingleBit(int valueSet) {
@@ -559,9 +579,7 @@
     }
 
     /**
-     * Checks whether the object contains none or single sample rate.
-     *
-     * @return true if the object contains none or single sample rate, otherwise false.
+     * Returns whether the object contains none or single sample rate.
      * @hide
      */
     public boolean hasSingleSampleRate() {
@@ -569,9 +587,7 @@
     }
 
     /**
-     * Checks whether the object contains none or single bits per sample.
-     *
-     * @return true if the object contains none or single bits per sample, otherwise false.
+     * Returns whether the object contains none or single bits per sample.
      * @hide
      */
     public boolean hasSingleBitsPerSample() {
@@ -579,9 +595,7 @@
     }
 
     /**
-     * Checks whether the object contains none or single channel mode.
-     *
-     * @return true if the object contains none or single channel mode, otherwise false.
+     * Returns whether the object contains none or single channel mode.
      * @hide
      */
     public boolean hasSingleChannelMode() {
@@ -589,10 +603,10 @@
     }
 
     /**
-     * Checks whether the audio feeding parameters are same.
+     * Checks whether the audio feeding parameters are the same.
      *
      * @param other the codec config to compare against
-     * @return true if the audio feeding parameters are same, otherwise false
+     * @return {@code true} if the audio feeding parameters are same, {@code false} otherwise
      * @hide
      */
     public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
@@ -606,7 +620,7 @@
      * Any parameters with NONE value will be considered to be a wildcard matching.
      *
      * @param other the codec config to compare against
-     * @return true if the audio feeding parameters are similar, otherwise false.
+     * @return {@code true} if the audio feeding parameters are similar, {@code false} otherwise
      * @hide
      */
     public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
@@ -614,18 +628,18 @@
             return false;
         }
         int sampleRate = other.mSampleRate;
-        if (mSampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE
-                || sampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE) {
+        if (mSampleRate == SAMPLE_RATE_NONE
+                || sampleRate == SAMPLE_RATE_NONE) {
             sampleRate = mSampleRate;
         }
         int bitsPerSample = other.mBitsPerSample;
-        if (mBitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE
-                || bitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
+        if (mBitsPerSample == BITS_PER_SAMPLE_NONE
+                || bitsPerSample == BITS_PER_SAMPLE_NONE) {
             bitsPerSample = mBitsPerSample;
         }
         int channelMode = other.mChannelMode;
-        if (mChannelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE
-                || channelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE) {
+        if (mChannelMode == CHANNEL_MODE_NONE
+                || channelMode == CHANNEL_MODE_NONE) {
             channelMode = mChannelMode;
         }
         return sameAudioFeedingParameters(new BluetoothCodecConfig(
@@ -636,25 +650,158 @@
 
     /**
      * Checks whether the codec specific parameters are the same.
+     * <p> Currently, only AAC VBR and LDAC Playback Quality on CodecSpecific1
+     * are compared.
      *
      * @param other the codec config to compare against
-     * @return true if the codec specific parameters are the same, otherwise false.
+     * @return {@code true} if the codec specific parameters are the same, {@code false} otherwise
      * @hide
      */
     public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
         if (other == null && mCodecType != other.mCodecType) {
             return false;
         }
-        // Currently we only care about the AAC VBR and LDAC Playback Quality at CodecSpecific1
         switch (mCodecType) {
             case SOURCE_CODEC_TYPE_AAC:
             case SOURCE_CODEC_TYPE_LDAC:
                 if (mCodecSpecific1 != other.mCodecSpecific1) {
                     return false;
                 }
-                // fall through
             default:
                 return true;
         }
     }
+
+    /**
+     * Builder for {@link BluetoothCodecConfig}.
+     * <p> By default, the codec type will be set to
+     * {@link BluetoothCodecConfig#SOURCE_CODEC_TYPE_INVALID}, the codec priority
+     * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
+     * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
+     * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
+     * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
+     * values to 0.
+     */
+    public static final class Builder {
+        private int mCodecType = BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+        private int mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
+        private int mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
+        private int mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
+        private int mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
+        private long mCodecSpecific1 = 0;
+        private long mCodecSpecific2 = 0;
+        private long mCodecSpecific3 = 0;
+        private long mCodecSpecific4 = 0;
+
+        /**
+         * Set codec type for Bluetooth codec config.
+         *
+         * @param codecType of this codec
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
+            mCodecType = codecType;
+            return this;
+        }
+
+        /**
+         * Set codec priority for Bluetooth codec config.
+         *
+         * @param codecPriority of this codec
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecPriority(@CodecPriority int codecPriority) {
+            mCodecPriority = codecPriority;
+            return this;
+        }
+
+        /**
+         * Set sample rate for Bluetooth codec config.
+         *
+         * @param sampleRate of this codec
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setSampleRate(@SampleRate int sampleRate) {
+            mSampleRate = sampleRate;
+            return this;
+        }
+
+        /**
+         * Set the bits per sample for Bluetooth codec config.
+         *
+         * @param bitsPerSample of this codec
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setBitsPerSample(@BitsPerSample int bitsPerSample) {
+            mBitsPerSample = bitsPerSample;
+            return this;
+        }
+
+        /**
+         * Set the channel mode for Bluetooth codec config.
+         *
+         * @param channelMode of this codec
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setChannelMode(@ChannelMode int channelMode) {
+            mChannelMode = channelMode;
+            return this;
+        }
+
+        /**
+         * Set the first codec specific values for Bluetooth codec config.
+         *
+         * @param codecSpecific1 codec specific value or 0 if default
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecSpecific1(long codecSpecific1) {
+            mCodecSpecific1 = codecSpecific1;
+            return this;
+        }
+
+        /**
+         * Set the second codec specific values for Bluetooth codec config.
+         *
+         * @param codecSpecific2 codec specific value or 0 if default
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecSpecific2(long codecSpecific2) {
+            mCodecSpecific2 = codecSpecific2;
+            return this;
+        }
+
+        /**
+         * Set the third codec specific values for Bluetooth codec config.
+         *
+         * @param codecSpecific3 codec specific value or 0 if default
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecSpecific3(long codecSpecific3) {
+            mCodecSpecific3 = codecSpecific3;
+            return this;
+        }
+
+        /**
+         * Set the fourth codec specific values for Bluetooth codec config.
+         *
+         * @param codecSpecific4 codec specific value or 0 if default
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecSpecific4(long codecSpecific4) {
+            mCodecSpecific4 = codecSpecific4;
+            return this;
+        }
+
+        /**
+         * Build {@link BluetoothCodecConfig}.
+         * @return new BluetoothCodecConfig built
+         */
+        public @NonNull BluetoothCodecConfig build() {
+            return new BluetoothCodecConfig(mCodecType, mCodecPriority,
+                    mSampleRate, mBitsPerSample,
+                    mChannelMode, mCodecSpecific1,
+                    mCodecSpecific2, mCodecSpecific3,
+                    mCodecSpecific4);
+        }
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 7764ebe..02606fe 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -16,12 +16,13 @@
 
 package android.bluetooth;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -29,8 +30,6 @@
  * A2DP source device.
  *
  * {@see BluetoothA2dp}
- *
- * {@hide}
  */
 public final class BluetoothCodecStatus implements Parcelable {
     /**
@@ -39,22 +38,27 @@
      * This extra represents the current codec status of the A2DP
      * profile.
      */
-    @UnsupportedAppUsage
     public static final String EXTRA_CODEC_STATUS =
             "android.bluetooth.extra.CODEC_STATUS";
 
     private final @Nullable BluetoothCodecConfig mCodecConfig;
-    private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
-    private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
+    private final @Nullable List<BluetoothCodecConfig> mCodecsLocalCapabilities;
+    private final @Nullable List<BluetoothCodecConfig> mCodecsSelectableCapabilities;
 
     public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
-            @Nullable BluetoothCodecConfig[] codecsLocalCapabilities,
-            @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) {
+            @Nullable List<BluetoothCodecConfig> codecsLocalCapabilities,
+            @Nullable List<BluetoothCodecConfig> codecsSelectableCapabilities) {
         mCodecConfig = codecConfig;
         mCodecsLocalCapabilities = codecsLocalCapabilities;
         mCodecsSelectableCapabilities = codecsSelectableCapabilities;
     }
 
+    private BluetoothCodecStatus(Parcel in) {
+        mCodecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
+        mCodecsLocalCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
+        mCodecsSelectableCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
+    }
+
     @Override
     public boolean equals(@Nullable Object o) {
         if (o instanceof BluetoothCodecStatus) {
@@ -68,26 +72,25 @@
     }
 
     /**
-     * Checks whether two arrays of capabilities contain same capabilities.
-     * The order of the capabilities in each array is ignored.
+     * Checks whether two lists of capabilities contain same capabilities.
+     * The order of the capabilities in each list is ignored.
      *
-     * @param c1 the first array of capabilities to compare
-     * @param c2 the second array of capabilities to compare
-     * @return true if both arrays contain same capabilities
-     * @hide
+     * @param c1 the first list of capabilities to compare
+     * @param c2 the second list of capabilities to compare
+     * @return {@code true} if both lists contain same capabilities
      */
-    public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
-                                           BluetoothCodecConfig[] c2) {
+    private static boolean sameCapabilities(@Nullable List<BluetoothCodecConfig> c1,
+                                           @Nullable List<BluetoothCodecConfig> c2) {
         if (c1 == null) {
             return (c2 == null);
         }
         if (c2 == null) {
             return false;
         }
-        if (c1.length != c2.length) {
+        if (c1.size() != c2.size()) {
             return false;
         }
-        return Arrays.asList(c1).containsAll(Arrays.asList(c2));
+        return c1.containsAll(c2);
     }
 
     /**
@@ -95,10 +98,9 @@
      * Any parameters of the codec config with NONE value will be considered a wildcard matching.
      *
      * @param codecConfig the codec config to compare against
-     * @return true if the codec config matches, otherwise false
-     * @hide
+     * @return {@code true} if the codec config matches, {@code false} otherwise
      */
-    public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
+    public boolean isCodecConfigSelectable(@Nullable BluetoothCodecConfig codecConfig) {
         if (codecConfig == null || !codecConfig.hasSingleSampleRate()
                 || !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) {
             return false;
@@ -128,10 +130,7 @@
     }
 
     /**
-     * Returns a hash based on the codec config and local capabilities
-     *
-     * @return a hash based on the config values
-     * @hide
+     * Returns a hash based on the codec config and local capabilities.
      */
     @Override
     public int hashCode() {
@@ -139,17 +138,19 @@
                 mCodecsLocalCapabilities);
     }
 
+    /**
+     * Returns a {@link String} that describes each BluetoothCodecStatus parameter
+     * current value.
+     */
     @Override
     public String toString() {
         return "{mCodecConfig:" + mCodecConfig
-                + ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities)
-                + ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities)
+                + ",mCodecsLocalCapabilities:" + mCodecsLocalCapabilities
+                + ",mCodecsSelectableCapabilities:" + mCodecsSelectableCapabilities
                 + "}";
     }
 
     /**
-     * Always returns 0
-     *
      * @return 0
      * @hide
      */
@@ -161,16 +162,7 @@
     public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecStatus> CREATOR =
             new Parcelable.Creator<BluetoothCodecStatus>() {
                 public BluetoothCodecStatus createFromParcel(Parcel in) {
-                    final BluetoothCodecConfig codecConfig = in.readTypedObject(
-                            BluetoothCodecConfig.CREATOR);
-                    final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray(
-                            BluetoothCodecConfig.CREATOR);
-                    final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray(
-                            BluetoothCodecConfig.CREATOR);
-
-                    return new BluetoothCodecStatus(codecConfig,
-                            codecsLocalCapabilities,
-                            codecsSelectableCapabilities);
+                    return new BluetoothCodecStatus(in);
                 }
 
                 public BluetoothCodecStatus[] newArray(int size) {
@@ -179,47 +171,38 @@
             };
 
     /**
-     * Flattens the object to a parcel
+     * Flattens the object to a parcel.
      *
-     * @param out The Parcel in which the object should be written.
-     * @param flags Additional flags about how the object should be written.
-     *
-     * @hide
+     * @param out The Parcel in which the object should be written
+     * @param flags Additional flags about how the object should be written
      */
     @Override
-    public void writeToParcel(Parcel out, int flags) {
+    public void writeToParcel(@NonNull Parcel out, int flags) {
         out.writeTypedObject(mCodecConfig, 0);
-        out.writeTypedArray(mCodecsLocalCapabilities, 0);
-        out.writeTypedArray(mCodecsSelectableCapabilities, 0);
+        out.writeTypedList(mCodecsLocalCapabilities);
+        out.writeTypedList(mCodecsSelectableCapabilities);
     }
 
     /**
-     * Gets the current codec configuration.
-     *
-     * @return the current codec configuration
+     * Returns the current codec configuration.
      */
-    @UnsupportedAppUsage
     public @Nullable BluetoothCodecConfig getCodecConfig() {
         return mCodecConfig;
     }
 
     /**
-     * Gets the codecs local capabilities.
-     *
-     * @return an array with the codecs local capabilities
+     * Returns the codecs local capabilities.
      */
-    @UnsupportedAppUsage
-    public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
-        return mCodecsLocalCapabilities;
+    public @NonNull List<BluetoothCodecConfig> getCodecsLocalCapabilities() {
+        return (mCodecsLocalCapabilities == null)
+                ? Collections.emptyList() : mCodecsLocalCapabilities;
     }
 
     /**
-     * Gets the codecs selectable capabilities.
-     *
-     * @return an array with the codecs selectable capabilities
+     * Returns the codecs selectable capabilities.
      */
-    @UnsupportedAppUsage
-    public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
-        return mCodecsSelectableCapabilities;
+    public @NonNull List<BluetoothCodecConfig> getCodecsSelectableCapabilities() {
+        return (mCodecsSelectableCapabilities == null)
+                ? Collections.emptyList() : mCodecsSelectableCapabilities;
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
new file mode 100644
index 0000000..dcaf4b6
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Represents the codec configuration for a Bluetooth LE Audio source device.
+ * <p>Contains the source codec type.
+ * <p>The source codec type values are the same as those supported by the
+ * device hardware.
+ *
+ * {@see BluetoothLeAudioCodecConfig}
+ */
+public final class BluetoothLeAudioCodecConfig {
+    // Add an entry for each source codec here.
+
+    /** @hide */
+    @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
+            SOURCE_CODEC_TYPE_LC3,
+            SOURCE_CODEC_TYPE_INVALID
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SourceCodecType {};
+
+    public static final int SOURCE_CODEC_TYPE_LC3 = 0;
+    public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+
+    /**
+     * Represents the count of valid source codec types. Can be accessed via
+     * {@link #getMaxCodecType}.
+     */
+    private static final int SOURCE_CODEC_TYPE_MAX = 1;
+
+    private final @SourceCodecType int mCodecType;
+
+    /**
+     * Creates a new BluetoothLeAudioCodecConfig.
+     *
+     * @param codecType the source codec type
+     */
+    private BluetoothLeAudioCodecConfig(@SourceCodecType int codecType) {
+        mCodecType = codecType;
+    }
+
+    @Override
+    public String toString() {
+        return "{codecName:" + getCodecName() + "}";
+    }
+
+    /**
+     * Gets the codec type.
+     *
+     * @return the codec type
+     */
+    public @SourceCodecType int getCodecType() {
+        return mCodecType;
+    }
+
+    /**
+     * Returns the valid codec types count.
+     */
+    public static int getMaxCodecType() {
+        return SOURCE_CODEC_TYPE_MAX;
+    }
+
+    /**
+     * Gets the codec name.
+     *
+     * @return the codec name
+     */
+    public @NonNull String getCodecName() {
+        switch (mCodecType) {
+            case SOURCE_CODEC_TYPE_LC3:
+                return "LC3";
+            case SOURCE_CODEC_TYPE_INVALID:
+                return "INVALID CODEC";
+            default:
+                break;
+        }
+        return "UNKNOWN CODEC(" + mCodecType + ")";
+    }
+
+    /**
+     * Builder for {@link BluetoothLeAudioCodecConfig}.
+     * <p> By default, the codec type will be set to
+     * {@link BluetoothLeAudioCodecConfig#SOURCE_CODEC_TYPE_INVALID}
+     */
+    public static final class Builder {
+        private int mCodecType = BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+
+        /**
+         * Set codec type for Bluetooth codec config.
+         *
+         * @param codecType of this codec
+         * @return the same Builder instance
+         */
+        public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
+            mCodecType = codecType;
+            return this;
+        }
+
+        /**
+         * Build {@link BluetoothLeAudioCodecConfig}.
+         * @return new BluetoothLeAudioCodecConfig built
+         */
+        public @NonNull BluetoothLeAudioCodecConfig build() {
+            return new BluetoothLeAudioCodecConfig(mCodecType);
+        }
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothLeBroadcast.java b/core/java/android/bluetooth/BluetoothLeBroadcast.java
new file mode 100644
index 0000000..fed9f91
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeBroadcast.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * This class provides the public APIs to control the Bluetooth LE Broadcast Source profile.
+ *
+ * <p>BluetoothLeBroadcast is a proxy object for controlling the Bluetooth LE Broadcast
+ * Source Service via IPC. Use {@link BluetoothAdapter#getProfileProxy}
+ * to get the BluetoothLeBroadcast proxy object.
+ *
+ * @hide
+ */
+public final class BluetoothLeBroadcast implements BluetoothProfile {
+    private static final String TAG = "BluetoothLeBroadcast";
+    private static final boolean DBG = true;
+    private static final boolean VDBG = false;
+
+    /**
+     * Constants used by the LE Audio Broadcast profile for the Broadcast state
+     *
+     * @hide
+     */
+    @IntDef(prefix = {"LE_AUDIO_BROADCAST_STATE_"}, value = {
+      LE_AUDIO_BROADCAST_STATE_DISABLED,
+      LE_AUDIO_BROADCAST_STATE_ENABLING,
+      LE_AUDIO_BROADCAST_STATE_ENABLED,
+      LE_AUDIO_BROADCAST_STATE_DISABLING,
+      LE_AUDIO_BROADCAST_STATE_PLAYING,
+      LE_AUDIO_BROADCAST_STATE_NOT_PLAYING
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface LeAudioBroadcastState {}
+
+    /**
+     * Indicates that LE Audio Broadcast mode is currently disabled
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_STATE_DISABLED = 10;
+
+    /**
+     * Indicates that LE Audio Broadcast mode is being enabled
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_STATE_ENABLING = 11;
+
+    /**
+     * Indicates that LE Audio Broadcast mode is currently enabled
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_STATE_ENABLED = 12;
+    /**
+     * Indicates that LE Audio Broadcast mode is being disabled
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_STATE_DISABLING = 13;
+
+    /**
+     * Indicates that an LE Audio Broadcast mode is currently playing
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_STATE_PLAYING = 14;
+
+    /**
+     * Indicates that LE Audio Broadcast is currently not playing
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_STATE_NOT_PLAYING = 15;
+
+    /**
+     * Constants used by the LE Audio Broadcast profile for encryption key length
+     *
+     * @hide
+     */
+    @IntDef(prefix = {"LE_AUDIO_BROADCAST_ENCRYPTION_KEY_"}, value = {
+      LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT,
+      LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface LeAudioEncryptionKeyLength {}
+
+    /**
+     * Indicates that the LE Audio Broadcast encryption key size is 32 bits.
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT = 16;
+
+    /**
+     * Indicates that the LE Audio Broadcast encryption key size is 128 bits.
+     *
+     * @hide
+     */
+    public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT = 17;
+
+    /**
+     * Interface for receiving events related to broadcasts
+     */
+    public interface Callback {
+        /**
+         * Called when broadcast state has changed
+         *
+         * @param prevState broadcast state before the change
+         * @param newState broadcast state after the change
+         */
+        @LeAudioBroadcastState
+        void onBroadcastStateChange(int prevState, int newState);
+        /**
+         * Called when encryption key has been updated
+         *
+         * @param success true if the key was updated successfully, false otherwise
+         */
+        void onEncryptionKeySet(boolean success);
+    }
+
+    /**
+     * Create a BluetoothLeBroadcast proxy object for interacting with the local
+     * LE Audio Broadcast Source service.
+     *
+     * @hide
+     */
+    /*package*/ BluetoothLeBroadcast(Context context,
+                                     BluetoothProfile.ServiceListener listener) {
+    }
+
+    /**
+     * Not supported since LE Audio Broadcasts do not establish a connection
+     *
+     * @throws UnsupportedOperationException
+     *
+     * @hide
+     */
+    @Override
+    public int getConnectionState(BluetoothDevice device) {
+        throw new UnsupportedOperationException(
+                   "LE Audio Broadcasts are not connection-oriented.");
+    }
+
+    /**
+     * Not supported since LE Audio Broadcasts do not establish a connection
+     *
+     * @throws UnsupportedOperationException
+     *
+     * @hide
+     */
+    @Override
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+        throw new UnsupportedOperationException(
+                   "LE Audio Broadcasts are not connection-oriented.");
+    }
+
+    /**
+     * Not supported since LE Audio Broadcasts do not establish a connection
+     *
+     * @throws UnsupportedOperationException
+     *
+     * @hide
+     */
+    @Override
+    public List<BluetoothDevice> getConnectedDevices() {
+        throw new UnsupportedOperationException(
+                   "LE Audio Broadcasts are not connection-oriented.");
+    }
+
+    /**
+     * Enable LE Audio Broadcast mode.
+     *
+     * Generates a new broadcast ID and enables sending of encrypted or unencrypted
+     * isochronous PDUs
+     *
+     * @hide
+     */
+    public int enableBroadcastMode() {
+        if (DBG) log("enableBroadcastMode");
+        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
+    }
+
+    /**
+     * Disable LE Audio Broadcast mode.
+     *
+     * @hide
+     */
+    public int disableBroadcastMode() {
+        if (DBG) log("disableBroadcastMode");
+        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
+    }
+
+    /**
+     * Get the current LE Audio broadcast state
+     *
+     * @hide
+     */
+    @LeAudioBroadcastState
+    public int getBroadcastState() {
+        if (DBG) log("getBroadcastState");
+        return LE_AUDIO_BROADCAST_STATE_DISABLED;
+    }
+
+    /**
+     * Enable LE Audio broadcast encryption
+     *
+     * @param keyLength if useExisting is true, this specifies the length of the key that should
+     *                  be generated
+     * @param useExisting true, if an existing key should be used
+     *                    false, if a new key should be generated
+     *
+     * @hide
+     */
+    @LeAudioEncryptionKeyLength
+    public int enableEncryption(boolean useExisting, int keyLength) {
+        if (DBG) log("enableEncryption useExisting=" + useExisting + " keyLength=" + keyLength);
+        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED;
+    }
+
+    /**
+     * Disable LE Audio broadcast encryption
+     *
+     * @param removeExisting true, if the existing key should be removed
+     *                       false, otherwise
+     *
+     * @hide
+     */
+    public int disableEncryption(boolean removeExisting) {
+        if (DBG) log("disableEncryption removeExisting=" + removeExisting);
+        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED;
+    }
+
+    /**
+     * Enable or disable LE Audio broadcast encryption
+     *
+     * @param key use the provided key if non-null, generate a new key if null
+     * @param keyLength 0 if encryption is disabled, 4 bytes (low security),
+     *                  16 bytes (high security)
+     *
+     * @hide
+     */
+    @LeAudioEncryptionKeyLength
+    public int setEncryptionKey(byte[] key, int keyLength) {
+        if (DBG) log("setEncryptionKey key=" + key + " keyLength=" + keyLength);
+        return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED;
+    }
+
+
+    /**
+     * Get the encryption key that was set before
+     *
+     * @return encryption key as a byte array or null if no encryption key was set
+     *
+     * @hide
+     */
+    public byte[] getEncryptionKey() {
+        if (DBG) log("getEncryptionKey");
+        return null;
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index c000e56..8ee38d3 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -23,7 +23,6 @@
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Attributable;
 import android.content.AttributionSource;
@@ -170,7 +169,7 @@
                             mContext.getPackageManager(), 0);
                     intent.setComponent(comp);
                     if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
-                            UserHandle.CURRENT_OR_SELF)) {
+                            UserHandle.CURRENT)) {
                         Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
                         return false;
                     }
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 0cf9f9f..e047e5d 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -233,12 +233,19 @@
     int CSIP_SET_COORDINATOR = 25;
 
     /**
+     * LE Audio Broadcast Source
+     *
+     * @hide
+     */
+    int LE_AUDIO_BROADCAST = 26;
+
+    /**
      * Max profile ID. This value should be updated whenever a new profile is added to match
      * the largest value assigned to a profile.
      *
      * @hide
      */
-    int MAX_PROFILE_ID = 25;
+    int MAX_PROFILE_ID = 26;
 
     /**
      * Default priority for devices that we try to auto-connect to and
@@ -436,6 +443,8 @@
                 return "OPP";
             case HEARING_AID:
                 return "HEARING_AID";
+            case LE_AUDIO:
+                return "LE_AUDIO";
             default:
                 return "UNKNOWN_PROFILE";
         }
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
index a254291..ecd5e40 100644
--- a/core/java/android/bluetooth/BluetoothProfileConnector.java
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -103,7 +103,7 @@
                             mContext.getPackageManager(), 0);
                     intent.setComponent(comp);
                     if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
-                            UserHandle.CURRENT_OR_SELF)) {
+                            UserHandle.CURRENT)) {
                         logError("Could not bind to Bluetooth Service with " + intent);
                         return false;
                     }
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index ca01784..9dafa07 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -226,6 +226,66 @@
     public static final int ERROR_DISCONNECT_REASON_BAD_PARAMETERS = 1109;
 
     /**
+     * Indicates that setting the LE Audio Broadcast mode failed.
+     * <p>
+     * Example solution: Change parameters and try again. If error persists, the app can report
+     * telemetry and/or log the error in a bugreport.
+     *
+     * @hide
+     */
+    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED = 1110;
+
+    /**
+     * Indicates that setting a new encryption key for Bluetooth LE Audio Broadcast Source failed.
+     * <p>
+     * Example solution: Change parameters and try again. If error persists, the app can report
+     * telemetry and/or log the error in a bugreport.
+     *
+     * @hide
+     */
+    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED = 1111;
+
+    /**
+     * Indicates that connecting to a remote Broadcast Audio Scan Service failed.
+     * <p>
+     * Example solution: Change parameters and try again. If error persists, the app can report
+     * telemetry and/or log the error in a bugreport.
+     *
+     * @hide
+     */
+    public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_CONNECT_FAILED = 1112;
+
+    /**
+     * Indicates that disconnecting from a remote Broadcast Audio Scan Service failed.
+     * <p>
+     * Example solution: Change parameters and try again. If error persists, the app can report
+     * telemetry and/or log the error in a bugreport.
+     *
+     * @hide
+     */
+    public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_DISCONNECT_FAILED = 1113;
+
+    /**
+     * Indicates that enabling LE Audio Broadcast encryption failed
+     * <p>
+     * Example solution: Change parameters and try again. If error persists, the app can report
+     * telemetry and/or log the error in a bugreport.
+     *
+     * @hide
+     */
+    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED = 1114;
+
+    /**
+     * Indicates that disabling LE Audio Broadcast encryption failed
+     * <p>
+     * Example solution: Change parameters and try again. If error persists, the app can report
+     * telemetry and/or log the error in a bugreport.
+     *
+     * @hide
+     */
+    public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115;
+
+    /**
      * Indicates that an unknown error has occurred has occurred.
      */
     public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;
diff --git a/core/java/android/bluetooth/le/TransportBlock.java b/core/java/android/bluetooth/le/TransportBlock.java
index b388bed..18bad9c 100644
--- a/core/java/android/bluetooth/le/TransportBlock.java
+++ b/core/java/android/bluetooth/le/TransportBlock.java
@@ -24,6 +24,7 @@
 
 import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 
 /**
  * Wrapper for Transport Discovery Data Transport Blocks.
@@ -59,8 +60,12 @@
         mOrgId = in.readInt();
         mTdsFlags = in.readInt();
         mTransportDataLength = in.readInt();
-        mTransportData = new byte[mTransportDataLength];
-        in.readByteArray(mTransportData);
+        if (mTransportDataLength > 0) {
+            mTransportData = new byte[mTransportDataLength];
+            in.readByteArray(mTransportData);
+        } else {
+            mTransportData = null;
+        }
     }
 
     @Override
@@ -68,7 +73,9 @@
         dest.writeInt(mOrgId);
         dest.writeInt(mTdsFlags);
         dest.writeInt(mTransportDataLength);
-        dest.writeByteArray(mTransportData);
+        if (mTransportData != null) {
+            dest.writeByteArray(mTransportData);
+        }
     }
 
     /**
@@ -79,6 +86,21 @@
         return 0;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        TransportBlock other = (TransportBlock) obj;
+        return Arrays.equals(toByteArray(), other.toByteArray());
+    }
+
     public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() {
         @Override
         public TransportBlock createFromParcel(Parcel in) {
diff --git a/core/java/android/bluetooth/le/TransportDiscoveryData.java b/core/java/android/bluetooth/le/TransportDiscoveryData.java
index c8e97f9..2b52f19 100644
--- a/core/java/android/bluetooth/le/TransportDiscoveryData.java
+++ b/core/java/android/bluetooth/le/TransportDiscoveryData.java
@@ -26,6 +26,7 @@
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -96,6 +97,21 @@
         return 0;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        TransportDiscoveryData other = (TransportDiscoveryData) obj;
+        return Arrays.equals(toByteArray(), other.toByteArray());
+    }
+
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mTransportDataType);
diff --git a/core/java/android/content/AttributionSource.aidl b/core/java/android/content/AttributionSource.aidl
index 10d5c27..7554cb2 100644
--- a/core/java/android/content/AttributionSource.aidl
+++ b/core/java/android/content/AttributionSource.aidl
@@ -16,4 +16,5 @@
 
 package android.content;
 
+@JavaOnlyStableParcelable
 parcelable AttributionSource;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2c4ff58..84c9fa9 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -409,7 +409,7 @@
 
     /**
      * Value for {@link #flags}: {@code true} if the application may use cleartext network traffic
-     * (e.g., HTTP rather than HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP
+     * (e.g., HTTP rather than HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, SMTP
      * without STARTTLS or TLS). If {@code false}, the app declares that it does not intend to use
      * cleartext network traffic, in which case platform components (e.g., HTTP stacks,
      * {@code DownloadManager}, {@code MediaPlayer}) will refuse app's requests to use cleartext
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index f55bcd3..b989488 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -2,5 +2,6 @@
 
 include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
 
+per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
 per-file SSL*,Uri*,Url* = prb@google.com,oth@google.com,narayan@google.com,ngeoffray@google.com
 per-file SntpClient* = file:/services/core/java/com/android/server/timedetector/OWNERS
diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkPriority.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkPriority.java
new file mode 100644
index 0000000..b3f7345
--- /dev/null
+++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkPriority.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.vcn;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
+import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
+import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
+import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.PersistableBundle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+
+// TODO: Add documents
+/** @hide */
+public final class VcnCellUnderlyingNetworkPriority extends VcnUnderlyingNetworkPriority {
+    private static final String ALLOWED_NETWORK_PLMN_IDS_KEY = "mAllowedNetworkPlmnIds";
+    @NonNull private final Set<String> mAllowedNetworkPlmnIds;
+    private static final String ALLOWED_SPECIFIC_CARRIER_IDS_KEY = "mAllowedSpecificCarrierIds";
+    @NonNull private final Set<Integer> mAllowedSpecificCarrierIds;
+
+    private static final String ALLOW_ROAMING_KEY = "mAllowRoaming";
+    private final boolean mAllowRoaming;
+
+    private static final String REQUIRE_OPPORTUNISTIC_KEY = "mRequireOpportunistic";
+    private final boolean mRequireOpportunistic;
+
+    private VcnCellUnderlyingNetworkPriority(
+            int networkQuality,
+            boolean allowMetered,
+            Set<String> allowedNetworkPlmnIds,
+            Set<Integer> allowedSpecificCarrierIds,
+            boolean allowRoaming,
+            boolean requireOpportunistic) {
+        super(NETWORK_PRIORITY_TYPE_CELL, networkQuality, allowMetered);
+        mAllowedNetworkPlmnIds = new ArraySet<>(allowedNetworkPlmnIds);
+        mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
+        mAllowRoaming = allowRoaming;
+        mRequireOpportunistic = requireOpportunistic;
+
+        validate();
+    }
+
+    /** @hide */
+    @Override
+    protected void validate() {
+        super.validate();
+        validatePlmnIds(mAllowedNetworkPlmnIds);
+        Objects.requireNonNull(mAllowedSpecificCarrierIds, "allowedCarrierIds is null");
+    }
+
+    private static void validatePlmnIds(Set<String> allowedNetworkPlmnIds) {
+        Objects.requireNonNull(allowedNetworkPlmnIds, "allowedNetworkPlmnIds is null");
+
+        // A valid PLMN is a concatenation of MNC and MCC, and thus consists of 5 or 6 decimal
+        // digits.
+        for (String id : allowedNetworkPlmnIds) {
+            if ((id.length() == 5 || id.length() == 6) && id.matches("[0-9]+")) {
+                continue;
+            } else {
+                throw new IllegalArgumentException("Found invalid PLMN ID: " + id);
+            }
+        }
+    }
+
+    /** @hide */
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PROTECTED)
+    public static VcnCellUnderlyingNetworkPriority fromPersistableBundle(
+            @NonNull PersistableBundle in) {
+        Objects.requireNonNull(in, "PersistableBundle is null");
+
+        final int networkQuality = in.getInt(NETWORK_QUALITY_KEY);
+        final boolean allowMetered = in.getBoolean(ALLOW_METERED_KEY);
+
+        final PersistableBundle plmnIdsBundle =
+                in.getPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY);
+        Objects.requireNonNull(plmnIdsBundle, "plmnIdsBundle is null");
+        final Set<String> allowedNetworkPlmnIds =
+                new ArraySet<String>(
+                        PersistableBundleUtils.toList(plmnIdsBundle, STRING_DESERIALIZER));
+
+        final PersistableBundle specificCarrierIdsBundle =
+                in.getPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY);
+        Objects.requireNonNull(specificCarrierIdsBundle, "specificCarrierIdsBundle is null");
+        final Set<Integer> allowedSpecificCarrierIds =
+                new ArraySet<Integer>(
+                        PersistableBundleUtils.toList(
+                                specificCarrierIdsBundle, INTEGER_DESERIALIZER));
+
+        final boolean allowRoaming = in.getBoolean(ALLOW_ROAMING_KEY);
+        final boolean requireOpportunistic = in.getBoolean(REQUIRE_OPPORTUNISTIC_KEY);
+
+        return new VcnCellUnderlyingNetworkPriority(
+                networkQuality,
+                allowMetered,
+                allowedNetworkPlmnIds,
+                allowedSpecificCarrierIds,
+                allowRoaming,
+                requireOpportunistic);
+    }
+
+    /** @hide */
+    @Override
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PROTECTED)
+    public PersistableBundle toPersistableBundle() {
+        final PersistableBundle result = super.toPersistableBundle();
+
+        final PersistableBundle plmnIdsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mAllowedNetworkPlmnIds), STRING_SERIALIZER);
+        result.putPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY, plmnIdsBundle);
+
+        final PersistableBundle specificCarrierIdsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mAllowedSpecificCarrierIds), INTEGER_SERIALIZER);
+        result.putPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY, specificCarrierIdsBundle);
+
+        result.putBoolean(ALLOW_ROAMING_KEY, mAllowRoaming);
+        result.putBoolean(REQUIRE_OPPORTUNISTIC_KEY, mRequireOpportunistic);
+
+        return result;
+    }
+
+    /** Retrieve the allowed PLMN IDs, or an empty set if any PLMN ID is acceptable. */
+    @NonNull
+    public Set<String> getAllowedOperatorPlmnIds() {
+        return Collections.unmodifiableSet(mAllowedNetworkPlmnIds);
+    }
+
+    /**
+     * Retrieve the allowed specific carrier IDs, or an empty set if any specific carrier ID is
+     * acceptable.
+     */
+    @NonNull
+    public Set<Integer> getAllowedSpecificCarrierIds() {
+        return Collections.unmodifiableSet(mAllowedSpecificCarrierIds);
+    }
+
+    /** Return if roaming is allowed. */
+    public boolean allowRoaming() {
+        return mAllowRoaming;
+    }
+
+    /** Return if requiring an opportunistic network. */
+    public boolean requireOpportunistic() {
+        return mRequireOpportunistic;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                super.hashCode(),
+                mAllowedNetworkPlmnIds,
+                mAllowedSpecificCarrierIds,
+                mAllowRoaming,
+                mRequireOpportunistic);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+
+        if (!(other instanceof VcnCellUnderlyingNetworkPriority)) {
+            return false;
+        }
+
+        final VcnCellUnderlyingNetworkPriority rhs = (VcnCellUnderlyingNetworkPriority) other;
+        return Objects.equals(mAllowedNetworkPlmnIds, rhs.mAllowedNetworkPlmnIds)
+                && Objects.equals(mAllowedSpecificCarrierIds, rhs.mAllowedSpecificCarrierIds)
+                && mAllowRoaming == rhs.mAllowRoaming
+                && mRequireOpportunistic == rhs.mRequireOpportunistic;
+    }
+
+    /** @hide */
+    @Override
+    void dumpTransportSpecificFields(IndentingPrintWriter pw) {
+        pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds.toString());
+        pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds.toString());
+        pw.println("mAllowRoaming: " + mAllowRoaming);
+        pw.println("mRequireOpportunistic: " + mRequireOpportunistic);
+    }
+
+    /** This class is used to incrementally build WifiNetworkPriority objects. */
+    public static final class Builder extends VcnUnderlyingNetworkPriority.Builder<Builder> {
+        @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
+        @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();
+
+        private boolean mAllowRoaming = false;
+        private boolean mRequireOpportunistic = false;
+
+        /** Construct a Builder object. */
+        public Builder() {}
+
+        /**
+         * Set allowed operator PLMN IDs.
+         *
+         * <p>This is used to distinguish cases where roaming agreements may dictate a different
+         * priority from a partner's networks.
+         *
+         * @param allowedNetworkPlmnIds the allowed operator PLMN IDs in String. Defaults to an
+         *     empty set, allowing ANY PLMN ID. A valid PLMN is a concatenation of MNC and MCC, and
+         *     thus consists of 5 or 6 decimal digits. See {@link SubscriptionInfo#getMccString()}
+         *     and {@link SubscriptionInfo#getMncString()}.
+         */
+        @NonNull
+        public Builder setAllowedOperatorPlmnIds(@NonNull Set<String> allowedNetworkPlmnIds) {
+            validatePlmnIds(allowedNetworkPlmnIds);
+
+            mAllowedNetworkPlmnIds.clear();
+            mAllowedNetworkPlmnIds.addAll(allowedNetworkPlmnIds);
+            return this;
+        }
+
+        /**
+         * Set allowed specific carrier IDs.
+         *
+         * @param allowedSpecificCarrierIds the allowed specific carrier IDs. Defaults to an empty
+         *     set, allowing ANY carrier ID. See {@link TelephonyManager#getSimSpecificCarrierId()}.
+         */
+        @NonNull
+        public Builder setAllowedSpecificCarrierIds(
+                @NonNull Set<Integer> allowedSpecificCarrierIds) {
+            Objects.requireNonNull(allowedSpecificCarrierIds, "allowedCarrierIds is null");
+            mAllowedSpecificCarrierIds.clear();
+            mAllowedSpecificCarrierIds.addAll(allowedSpecificCarrierIds);
+            return this;
+        }
+
+        /**
+         * Set if roaming is allowed.
+         *
+         * @param allowRoaming the flag to indicate if roaming is allowed. Defaults to {@code
+         *     false}.
+         */
+        @NonNull
+        public Builder setAllowRoaming(boolean allowRoaming) {
+            mAllowRoaming = allowRoaming;
+            return this;
+        }
+
+        /**
+         * Set if requiring an opportunistic network.
+         *
+         * @param requireOpportunistic the flag to indicate if caller requires an opportunistic
+         *     network. Defaults to {@code false}.
+         */
+        @NonNull
+        public Builder setRequireOpportunistic(boolean requireOpportunistic) {
+            mRequireOpportunistic = requireOpportunistic;
+            return this;
+        }
+
+        /** Build the VcnCellUnderlyingNetworkPriority. */
+        @NonNull
+        public VcnCellUnderlyingNetworkPriority build() {
+            return new VcnCellUnderlyingNetworkPriority(
+                    mNetworkQuality,
+                    mAllowMetered,
+                    mAllowedNetworkPlmnIds,
+                    mAllowedSpecificCarrierIds,
+                    mAllowRoaming,
+                    mRequireOpportunistic);
+        }
+
+        /** @hide */
+        @Override
+        Builder self() {
+            return this;
+        }
+    }
+}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 752ef3e..55d3ecd 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -16,6 +16,7 @@
 package android.net.vcn;
 
 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
+import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_OK;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility;
 
@@ -41,6 +42,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.Objects;
 import java.util.Set;
 import java.util.SortedSet;
@@ -157,6 +159,36 @@
                 TimeUnit.MINUTES.toMillis(5),
                 TimeUnit.MINUTES.toMillis(15)
             };
+
+    /** @hide */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static final LinkedHashSet<VcnUnderlyingNetworkPriority>
+            DEFAULT_UNDERLYING_NETWORK_PRIORITIES = new LinkedHashSet<>();
+
+    static {
+        DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
+                new VcnCellUnderlyingNetworkPriority.Builder()
+                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setAllowMetered(true /* allowMetered */)
+                        .setAllowRoaming(true /* allowRoaming */)
+                        .setRequireOpportunistic(true /* requireOpportunistic */)
+                        .build());
+
+        DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
+                new VcnWifiUnderlyingNetworkPriority.Builder()
+                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setAllowMetered(true /* allowMetered */)
+                        .build());
+
+        DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
+                new VcnCellUnderlyingNetworkPriority.Builder()
+                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setAllowMetered(true /* allowMetered */)
+                        .setAllowRoaming(true /* allowRoaming */)
+                        .setRequireOpportunistic(false /* requireOpportunistic */)
+                        .build());
+    }
+
     private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName";
     @NonNull private final String mGatewayConnectionName;
 
@@ -166,6 +198,12 @@
     private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
     @NonNull private final SortedSet<Integer> mExposedCapabilities;
 
+    /** @hide */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static final String UNDERLYING_NETWORK_PRIORITIES_KEY = "mUnderlyingNetworkPriorities";
+
+    @NonNull private final LinkedHashSet<VcnUnderlyingNetworkPriority> mUnderlyingNetworkPriorities;
+
     private static final String MAX_MTU_KEY = "mMaxMtu";
     private final int mMaxMtu;
 
@@ -177,6 +215,7 @@
             @NonNull String gatewayConnectionName,
             @NonNull IkeTunnelConnectionParams tunnelConnectionParams,
             @NonNull Set<Integer> exposedCapabilities,
+            @NonNull LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities,
             @NonNull long[] retryIntervalsMs,
             @IntRange(from = MIN_MTU_V6) int maxMtu) {
         mGatewayConnectionName = gatewayConnectionName;
@@ -185,9 +224,16 @@
         mRetryIntervalsMs = retryIntervalsMs;
         mMaxMtu = maxMtu;
 
+        mUnderlyingNetworkPriorities = new LinkedHashSet<>(underlyingNetworkPriorities);
+        if (mUnderlyingNetworkPriorities.isEmpty()) {
+            mUnderlyingNetworkPriorities.addAll(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+        }
+
         validate();
     }
 
+    // Null check MUST be done for all new fields added to VcnGatewayConnectionConfig, to avoid
+    // crashes when parsing PersistableBundle built on old platforms.
     /** @hide */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) {
@@ -198,12 +244,30 @@
 
         final PersistableBundle exposedCapsBundle =
                 in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
-
         mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
         mTunnelConnectionParams =
                 TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle);
         mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
                 exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+
+        final PersistableBundle networkPrioritiesBundle =
+                in.getPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY);
+
+        if (networkPrioritiesBundle == null) {
+            // UNDERLYING_NETWORK_PRIORITIES_KEY was added in Android T. Thus
+            // VcnGatewayConnectionConfig created on old platforms will not have this data and will
+            // be assigned with the default value
+            mUnderlyingNetworkPriorities =
+                    new LinkedHashSet<>(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+
+        } else {
+            mUnderlyingNetworkPriorities =
+                    new LinkedHashSet<>(
+                            PersistableBundleUtils.toList(
+                                    networkPrioritiesBundle,
+                                    VcnUnderlyingNetworkPriority::fromPersistableBundle));
+        }
+
         mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
         mMaxMtu = in.getInt(MAX_MTU_KEY);
 
@@ -221,6 +285,7 @@
             checkValidCapability(cap);
         }
 
+        Objects.requireNonNull(mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null");
         Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
         validateRetryInterval(mRetryIntervalsMs);
 
@@ -303,6 +368,18 @@
     }
 
     /**
+     * Retrieve the configured VcnUnderlyingNetworkPriority list, or a default list if it is not
+     * configured.
+     *
+     * @see Builder#setVcnUnderlyingNetworkPriorities(LinkedHashSet<VcnUnderlyingNetworkPriority>)
+     * @hide
+     */
+    @NonNull
+    public LinkedHashSet<VcnUnderlyingNetworkPriority> getVcnUnderlyingNetworkPriorities() {
+        return new LinkedHashSet<>(mUnderlyingNetworkPriorities);
+    }
+
+    /**
      * Retrieves the configured retry intervals.
      *
      * @see Builder#setRetryIntervalsMillis(long[])
@@ -338,10 +415,15 @@
                 PersistableBundleUtils.fromList(
                         new ArrayList<>(mExposedCapabilities),
                         PersistableBundleUtils.INTEGER_SERIALIZER);
+        final PersistableBundle networkPrioritiesBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mUnderlyingNetworkPriorities),
+                        VcnUnderlyingNetworkPriority::toPersistableBundle);
 
         result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
         result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
         result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
+        result.putPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY, networkPrioritiesBundle);
         result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
         result.putInt(MAX_MTU_KEY, mMaxMtu);
 
@@ -354,6 +436,7 @@
                 mGatewayConnectionName,
                 mTunnelConnectionParams,
                 mExposedCapabilities,
+                mUnderlyingNetworkPriorities,
                 Arrays.hashCode(mRetryIntervalsMs),
                 mMaxMtu);
     }
@@ -368,6 +451,7 @@
         return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
                 && mTunnelConnectionParams.equals(rhs.mTunnelConnectionParams)
                 && mExposedCapabilities.equals(rhs.mExposedCapabilities)
+                && mUnderlyingNetworkPriorities.equals(rhs.mUnderlyingNetworkPriorities)
                 && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
                 && mMaxMtu == rhs.mMaxMtu;
     }
@@ -379,6 +463,11 @@
         @NonNull private final String mGatewayConnectionName;
         @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams;
         @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
+
+        @NonNull
+        private final LinkedHashSet<VcnUnderlyingNetworkPriority> mUnderlyingNetworkPriorities =
+                new LinkedHashSet<>(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+
         @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
         private int mMaxMtu = DEFAULT_MAX_MTU;
 
@@ -450,6 +539,33 @@
         }
 
         /**
+         * Set the VcnUnderlyingNetworkPriority list.
+         *
+         * @param underlyingNetworkPriorities a list of unique VcnUnderlyingNetworkPriorities that
+         *     are ordered from most to least preferred, or an empty list to use the default
+         *     prioritization. The default network prioritization is Opportunistic cellular, Carrier
+         *     WiFi and Macro cellular
+         * @return
+         */
+        /** @hide */
+        @NonNull
+        public Builder setVcnUnderlyingNetworkPriorities(
+                @NonNull LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities) {
+            Objects.requireNonNull(
+                    mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null");
+
+            mUnderlyingNetworkPriorities.clear();
+
+            if (underlyingNetworkPriorities.isEmpty()) {
+                mUnderlyingNetworkPriorities.addAll(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+            } else {
+                mUnderlyingNetworkPriorities.addAll(underlyingNetworkPriorities);
+            }
+
+            return this;
+        }
+
+        /**
          * Set the retry interval between VCN establishment attempts upon successive failures.
          *
          * <p>The last retry interval will be repeated until safe mode is entered, or a connection
@@ -513,6 +629,7 @@
                     mGatewayConnectionName,
                     mTunnelConnectionParams,
                     mExposedCapabilities,
+                    mUnderlyingNetworkPriorities,
                     mRetryIntervalsMs,
                     mMaxMtu);
         }
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkPriority.java b/core/java/android/net/vcn/VcnUnderlyingNetworkPriority.java
index 27750c6..551f757 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkPriority.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkPriority.java
@@ -21,8 +21,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.PersistableBundle;
+import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
@@ -37,10 +39,17 @@
     /** @hide */
     protected static final int NETWORK_PRIORITY_TYPE_CELL = 2;
 
-    /** Denotes that network quality needs to be OK */
-    public static final int NETWORK_QUALITY_OK = 10000;
     /** Denotes that any network quality is acceptable */
-    public static final int NETWORK_QUALITY_ANY = Integer.MAX_VALUE;
+    public static final int NETWORK_QUALITY_ANY = 0;
+    /** Denotes that network quality needs to be OK */
+    public static final int NETWORK_QUALITY_OK = 100000;
+
+    private static final SparseArray<String> NETWORK_QUALITY_TO_STRING_MAP = new SparseArray<>();
+
+    static {
+        NETWORK_QUALITY_TO_STRING_MAP.put(NETWORK_QUALITY_ANY, "NETWORK_QUALITY_ANY");
+        NETWORK_QUALITY_TO_STRING_MAP.put(NETWORK_QUALITY_OK, "NETWORK_QUALITY_OK");
+    }
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -89,7 +98,7 @@
             case NETWORK_PRIORITY_TYPE_WIFI:
                 return VcnWifiUnderlyingNetworkPriority.fromPersistableBundle(in);
             case NETWORK_PRIORITY_TYPE_CELL:
-                throw new UnsupportedOperationException("Not implemented");
+                return VcnCellUnderlyingNetworkPriority.fromPersistableBundle(in);
             default:
                 throw new IllegalArgumentException(
                         "Invalid networkPriorityType:" + networkPriorityType);
@@ -125,6 +134,28 @@
                 && mAllowMetered == rhs.mAllowMetered;
     }
 
+    /** @hide */
+    abstract void dumpTransportSpecificFields(IndentingPrintWriter pw);
+
+    /**
+     * Dumps the state of this record for logging and debugging purposes.
+     *
+     * @hide
+     */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println(this.getClass().getSimpleName() + ":");
+        pw.increaseIndent();
+
+        pw.println(
+                "mNetworkQuality: "
+                        + NETWORK_QUALITY_TO_STRING_MAP.get(
+                                mNetworkQuality, "Invalid value " + mNetworkQuality));
+        pw.println("mAllowMetered: " + mAllowMetered);
+        dumpTransportSpecificFields(pw);
+
+        pw.decreaseIndent();
+    }
+
     /** Retrieve the required network quality. */
     @NetworkQuality
     public int getNetworkQuality() {
diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkPriority.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkPriority.java
index fc7e7e2..85eb100 100644
--- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkPriority.java
+++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkPriority.java
@@ -22,6 +22,7 @@
 import android.os.PersistableBundle;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.IndentingPrintWriter;
 
 import java.util.Objects;
 
@@ -78,7 +79,13 @@
         }
 
         final VcnWifiUnderlyingNetworkPriority rhs = (VcnWifiUnderlyingNetworkPriority) other;
-        return mSsid == rhs.mSsid;
+        return mSsid.equals(rhs.mSsid);
+    }
+
+    /** @hide */
+    @Override
+    void dumpTransportSpecificFields(IndentingPrintWriter pw) {
+        pw.println("mSsid: " + mSsid);
     }
 
     /** Retrieve the required SSID, or {@code null} if there is no requirement on SSID. */
diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java
index 74b814e..c8b4226e 100644
--- a/core/java/android/os/AppZygote.java
+++ b/core/java/android/os/AppZygote.java
@@ -45,6 +45,8 @@
     // Last UID/GID of the range the AppZygote can setuid()/setgid() to
     private final int mZygoteUidGidMax;
 
+    private final int mZygoteRuntimeFlags;
+
     private final Object mLock = new Object();
 
     /**
@@ -56,11 +58,13 @@
 
     private final ApplicationInfo mAppInfo;
 
-    public AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax) {
+    public AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax,
+            int runtimeFlags) {
         mAppInfo = appInfo;
         mZygoteUid = zygoteUid;
         mZygoteUidGidMin = uidGidMin;
         mZygoteUidGidMax = uidGidMax;
+        mZygoteRuntimeFlags = runtimeFlags;
     }
 
     /**
@@ -110,7 +114,7 @@
                     mZygoteUid,
                     mZygoteUid,
                     null,  // gids
-                    0,  // runtimeFlags
+                    mZygoteRuntimeFlags,  // runtimeFlags
                     "app_zygote",  // seInfo
                     abi,  // abi
                     abi, // acceptedAbiList
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index be21fea..2ea6329 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -71,6 +71,9 @@
     private static final String SYSTEM_DRIVER_NAME = "system";
     private static final String SYSTEM_DRIVER_VERSION_NAME = "";
     private static final long SYSTEM_DRIVER_VERSION_CODE = 0;
+    private static final String ANGLE_DRIVER_NAME = "angle";
+    private static final String ANGLE_DRIVER_VERSION_NAME = "";
+    private static final long ANGLE_DRIVER_VERSION_CODE = 0;
 
     // System properties related to updatable graphics drivers.
     private static final String PROPERTY_GFX_DRIVER_PRODUCTION = "ro.gfx.driver.0";
@@ -138,14 +141,24 @@
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
 
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupAngle");
-        setupAngle(context, coreSettings, pm, packageName);
+        boolean useAngle = false;
+        if (setupAngle(context, coreSettings, pm, packageName)) {
+            if (shouldUseAngle(context, coreSettings, packageName)) {
+                useAngle = true;
+                setGpuStats(ANGLE_DRIVER_NAME, ANGLE_DRIVER_VERSION_NAME, ANGLE_DRIVER_VERSION_CODE,
+                        0, packageName, getVulkanVersion(pm));
+            }
+        }
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
 
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "chooseDriver");
         if (!chooseDriver(context, coreSettings, pm, packageName, appInfoWithMetaData)) {
-            setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
-                    SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), packageName,
-                    getVulkanVersion(pm));
+            if (!useAngle) {
+                setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME,
+                        SYSTEM_DRIVER_VERSION_CODE,
+                        SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0),
+                        packageName, getVulkanVersion(pm));
+            }
         }
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
     }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index afd0ff7..09eac79 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -846,6 +846,19 @@
     }
 
     /**
+     * Verify there are no bytes left to be read on the Parcel.
+     *
+     * @throws BadParcelableException If the current position hasn't reached the end of the Parcel.
+     * When used over binder, this exception should propagate to the caller.
+     */
+    public void enforceNoDataAvail() {
+        final int n = dataAvail();
+        if (n > 0) {
+            throw new BadParcelableException("Parcel data not fully consumed, unread size: " + n);
+        }
+    }
+
+    /**
      * Writes the work source uid to the request headers.
      *
      * <p>It requires the headers to have been written/read already to replace the work source.
@@ -3646,7 +3659,14 @@
      * list was {@code null}, {@code list} is cleared.
      *
      * @see #writeParcelableList(List, int)
+     *
+     * @deprecated Use the type-safer version {@link #readParcelableList(List, ClassLoader, Class)}
+     *      starting from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the
+     *      format to use {@link #readTypedList(List, Parcelable.Creator)} if possible (eg. if the
+     *      items' class is final) since this is also more performant. Note that changing to the
+     *      latter also requires changing the writes.
      */
+    @Deprecated
     @NonNull
     public final <T extends Parcelable> List<T> readParcelableList(@NonNull List<T> list,
             @Nullable ClassLoader cl) {
@@ -4190,8 +4210,7 @@
      * trying to instantiate an element.
      */
     @Nullable
-    public <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader,
-            @NonNull Class<T> clazz) {
+    public <T> T readParcelable(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
         Objects.requireNonNull(clazz);
         return readParcelableInternal(loader, clazz);
     }
@@ -4202,10 +4221,6 @@
     @SuppressWarnings("unchecked")
     @Nullable
     private <T> T readParcelableInternal(@Nullable ClassLoader loader, @Nullable Class<T> clazz) {
-        if (clazz != null && !Parcelable.class.isAssignableFrom(clazz)) {
-            throw new BadParcelableException("About to unparcel a parcelable object "
-                    + " but class required " + clazz.getName() + " is not Parcelable");
-        }
         Parcelable.Creator<?> creator = readParcelableCreatorInternal(loader, clazz);
         if (creator == null) {
             return null;
@@ -4368,9 +4383,16 @@
      * The given class loader will be used to load any enclosed
      * Parcelables.
      * @return the Parcelable array, or null if the array is null
+     *
+     * @deprecated Use the type-safer version {@link #readParcelableArray(ClassLoader, Class)}
+     *      starting from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the
+     *      format to use {@link #createTypedArray(Parcelable.Creator)} if possible (eg. if the
+     *      items' class is final) since this is also more performant. Note that changing to the
+     *      latter also requires changing the writes.
      */
+    @Deprecated
     @Nullable
-    public final Parcelable[] readParcelableArray(@Nullable ClassLoader loader) {
+    public Parcelable[] readParcelableArray(@Nullable ClassLoader loader) {
         int N = readInt();
         if (N < 0) {
             return null;
@@ -4410,6 +4432,9 @@
      * @return the Serializable object, or null if the Serializable name
      * wasn't found in the parcel.
      *
+     * Unlike {@link #readSerializable(ClassLoader, Class)}, it uses the nearest valid class loader
+     * up the execution stack to instantiate the Serializable object.
+     *
      * @deprecated Use the type-safer version {@link #readSerializable(ClassLoader, Class)} starting
      *       from Android {@link Build.VERSION_CODES#TIRAMISU}.
      */
@@ -4420,19 +4445,21 @@
     }
 
     /**
-     * Same as {@link #readSerializable()} but accepts {@code loader} parameter
-     * as the primary classLoader for resolving the Serializable class; and {@code clazz} parameter
-     * as the required type.
+     * Same as {@link #readSerializable()} but accepts {@code loader} and {@code clazz} parameters.
+     *
+     * @param loader A ClassLoader from which to instantiate the Serializable object,
+     * or null for the default class loader.
+     * @param clazz The type of the object expected.
      *
      * @throws BadParcelableException Throws BadParcelableException if the item to be deserialized
      * is not an instance of that class or any of its children class or there there was an error
      * deserializing the object.
      */
     @Nullable
-    public <T extends Serializable> T readSerializable(@Nullable ClassLoader loader,
-            @NonNull Class<T> clazz) {
+    public <T> T readSerializable(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
         Objects.requireNonNull(clazz);
-        return readSerializableInternal(loader, clazz);
+        return readSerializableInternal(
+                loader == null ? getClass().getClassLoader() : loader, clazz);
     }
 
     /**
@@ -4441,11 +4468,6 @@
     @Nullable
     private <T> T readSerializableInternal(@Nullable final ClassLoader loader,
             @Nullable Class<T> clazz) {
-        if (clazz != null && !Serializable.class.isAssignableFrom(clazz)) {
-            throw new BadParcelableException("About to unparcel a serializable object "
-                    + " but class required " + clazz.getName() + " is not Serializable");
-        }
-
         String name = readString();
         if (name == null) {
             // For some reason we were unable to read the name of the Serializable (either there
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 3e01c53..b7e3068 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -238,7 +238,7 @@
         public static final int DISABLED = 9;
     }
 
-    private IUpdateEngine mUpdateEngine;
+    private final IUpdateEngine mUpdateEngine;
     private IUpdateEngineCallback mUpdateEngineCallback = null;
     private final Object mUpdateEngineCallbackLock = new Object();
 
@@ -248,6 +248,9 @@
     public UpdateEngine() {
         mUpdateEngine = IUpdateEngine.Stub.asInterface(
                 ServiceManager.getService(UPDATE_ENGINE_SERVICE));
+        if (mUpdateEngine == null) {
+            throw new IllegalStateException("Failed to find update_engine");
+        }
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ac520e8..84be746 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11218,22 +11218,38 @@
                 "night_display_forced_auto_mode_available";
 
         /**
-        * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
-        * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
-        * exceeded.
-        * @hide
-        */
+         * If UTC time between two NITZ signals is greater than this value then the second signal
+         * cannot be ignored.
+         *
+         * <p>This value is in milliseconds. It is used for telephony-based time and time zone
+         * detection.
+         * @hide
+         */
         @Readable
         public static final String NITZ_UPDATE_DIFF = "nitz_update_diff";
 
         /**
-        * The length of time in milli-seconds that automatic small adjustments to
-        * SystemClock are ignored if NITZ_UPDATE_DIFF is not exceeded.
-        * @hide
-        */
+         * If the elapsed realtime between two NITZ signals is greater than this value then the
+         * second signal cannot be ignored.
+         *
+         * <p>This value is in milliseconds. It is used for telephony-based time and time zone
+         * detection.
+         * @hide
+         */
         @Readable
         public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing";
 
+        /**
+         * If the device connects to a telephony network and was disconnected from a telephony
+         * network for less than this time, a previously received NITZ signal can be restored.
+         *
+         * <p>This value is in milliseconds. It is used for telephony-based time and time zone
+         * detection.
+         * @hide
+         */
+        public static final String NITZ_NETWORK_DISCONNECT_RETENTION =
+                "nitz_network_disconnect_retention";
+
         /** Preferred NTP server. {@hide} */
         @Readable
         public static final String NTP_SERVER = "ntp_server";
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index 8c4dcb3..cd077e1 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -22,6 +22,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.time.Duration;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.util.ArrayDeque;
@@ -63,7 +64,8 @@
         if (mUseLocalTimestamps) {
             logLine = LocalDateTime.now() + " - " + msg;
         } else {
-            logLine = SystemClock.elapsedRealtime() + " / " + Instant.now() + " - " + msg;
+            logLine = Duration.ofMillis(SystemClock.elapsedRealtime())
+                    + " / " + Instant.now() + " - " + msg;
         }
         append(logLine);
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3550a31..2257f6c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -8448,13 +8448,13 @@
             MotionEvent me = (MotionEvent) event;
             if (me.getAction() == MotionEvent.ACTION_CANCEL) {
                 EventLog.writeEvent(EventLogTags.VIEW_ENQUEUE_INPUT_EVENT, "Motion - Cancel",
-                        getTitle());
+                        getTitle().toString());
             }
         } else if (event instanceof KeyEvent) {
             KeyEvent ke = (KeyEvent) event;
             if (ke.isCanceled()) {
                 EventLog.writeEvent(EventLogTags.VIEW_ENQUEUE_INPUT_EVENT, "Key - Cancel",
-                        getTitle());
+                        getTitle().toString());
             }
         }
         // Always enqueue the input event in order, regardless of its time stamp.
diff --git a/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java b/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java
new file mode 100644
index 0000000..615e4b79
--- /dev/null
+++ b/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.Build;
+import android.util.ArrayMap;
+
+import dalvik.system.PathClassLoader;
+
+/** @hide */
+public final class SystemServerClassLoaderFactory {
+    /**
+     * Map of paths to PathClassLoader for standalone system server jars.
+     */
+    private static final ArrayMap<String, PathClassLoader> sLoadedPaths = new ArrayMap<>();
+
+    /**
+     * Creates and caches a ClassLoader for the jar at the given path, or returns a cached
+     * ClassLoader if it exists.
+     *
+     * The parent class loader should always be the system server class loader. Changing it has
+     * implications that require discussion with the mainline team.
+     *
+     * @hide for internal use only
+     */
+    public static PathClassLoader getOrCreateClassLoader(String path, ClassLoader parent) {
+        PathClassLoader pathClassLoader = sLoadedPaths.get(path);
+        if (pathClassLoader == null) {
+            pathClassLoader = (PathClassLoader) ClassLoaderFactory.createClassLoader(
+                    path, /*librarySearchPath=*/null, /*libraryPermittedPath=*/null, parent,
+                    Build.VERSION.SDK_INT, /*isNamespaceShared=*/true , /*classLoaderName=*/null);
+            sLoadedPaths.put(path, pathClassLoader);
+        }
+        return pathClassLoader;
+    }
+}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 29e5a5a..6b9d95f 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -46,6 +46,7 @@
 import android.system.StructCapUserData;
 import android.system.StructCapUserHeader;
 import android.text.Hyphenator;
+import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -560,9 +561,8 @@
 
     /**
      * Create the classloader for the system server and store it in
-     * {@link sCachedSystemServerClassLoader}. This function may be called through JNI in
-     * system server startup, when the runtime is in a critically low state. Do not do
-     * extended computation etc here.
+     * {@link sCachedSystemServerClassLoader}. This function is called through JNI in the forked
+     * system server process in the zygote SELinux domain.
      */
     private static ClassLoader getOrCreateSystemServerClassLoader() {
         if (sCachedSystemServerClassLoader == null) {
@@ -576,6 +576,29 @@
     }
 
     /**
+     * Creates class loaders for standalone system server jars. This function is called through JNI
+     * in the forked system server process in the zygote SELinux domain.
+     */
+    private static void prefetchStandaloneSystemServerJars() {
+        String envStr = Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
+        if (TextUtils.isEmpty(envStr)) {
+            return;
+        }
+        for (String jar : envStr.split(":")) {
+            try {
+                SystemServerClassLoaderFactory.getOrCreateClassLoader(
+                        jar, getOrCreateSystemServerClassLoader());
+            } catch (Error e) {
+                // We don't want the process to crash for this error because prefetching is just an
+                // optimization.
+                Log.e(TAG,
+                        String.format("Failed to prefetch standalone system server jar \"%s\": %s",
+                                jar, e.toString()));
+            }
+        }
+    }
+
+    /**
      * Note that preparing the profiles for system server does not require special selinux
      * permissions. From the installer perspective the system server is a regular package which can
      * capture profile information.
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index b0cf5dc..ae9d716 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -56,6 +56,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -95,6 +96,9 @@
     // property for runtime configuration differentiation in vendor
     private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
 
+    private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS =
+            new ArrayMap<>();
+
     // Group-ids that are given to all packages as read from etc/permissions/*.xml.
     int[] mGlobalGids = EmptyArray.INT;
 
@@ -224,6 +228,11 @@
     final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
     final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
 
+    final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppPermissions =
+            new ArrayMap<>();
+    final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppDenyPermissions =
+            new ArrayMap<>();
+
     final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
 
     // Allowed associations between applications.  If there are any entries
@@ -360,6 +369,18 @@
         return mPrivAppDenyPermissions.get(packageName);
     }
 
+    /** Get privapp permission allowlist for an apk-in-apex. */
+    public ArraySet<String> getApexPrivAppPermissions(String module, String packageName) {
+        return mApexPrivAppPermissions.getOrDefault(module, EMPTY_PERMISSIONS)
+                .get(packageName);
+    }
+
+    /** Get privapp permissions denylist for an apk-in-apex. */
+    public ArraySet<String> getApexPrivAppDenyPermissions(String module, String packageName) {
+        return mApexPrivAppDenyPermissions.getOrDefault(module, EMPTY_PERMISSIONS)
+                .get(packageName);
+    }
+
     public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
         return mVendorPrivAppPermissions.get(packageName);
     }
@@ -573,8 +594,8 @@
         if (!isSystemProcess()) {
             return;
         }
-        // Read configuration of features and libs from apex module.
-        int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES;
+        // Read configuration of features, libs and priv-app permissions from apex module.
+        int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
         // TODO: Use a solid way to filter apex module folders?
         for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
             if (f.isFile() || f.getPath().contains("@")) {
@@ -1040,10 +1061,10 @@
                     } break;
                     case "privapp-permissions": {
                         if (allowPrivappPermissions) {
-                            // privapp permissions from system, vendor, product and system_ext
-                            // partitions are stored separately. This is to prevent xml files in
-                            // the vendor partition from granting permissions to priv apps in the
-                            // system partition and vice versa.
+                            // privapp permissions from system, apex, vendor, product and
+                            // system_ext partitions are stored separately. This is to
+                            // prevent xml files in the vendor partition from granting
+                            // permissions to priv apps in the system partition and vice versa.
                             boolean vendor = permFile.toPath().startsWith(
                                     Environment.getVendorDirectory().toPath() + "/")
                                     || permFile.toPath().startsWith(
@@ -1052,6 +1073,8 @@
                                     Environment.getProductDirectory().toPath() + "/");
                             boolean systemExt = permFile.toPath().startsWith(
                                     Environment.getSystemExtDirectory().toPath() + "/");
+                            boolean apex = permFile.toPath().startsWith(
+                                    Environment.getApexDirectory().toPath() + "/");
                             if (vendor) {
                                 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
                                         mVendorPrivAppDenyPermissions);
@@ -1061,6 +1084,8 @@
                             } else if (systemExt) {
                                 readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
                                         mSystemExtPrivAppDenyPermissions);
+                            } else if (apex) {
+                                readApexPrivAppPermissions(parser, permFile);
                             } else {
                                 readPrivAppPermissions(parser, mPrivAppPermissions,
                                         mPrivAppDenyPermissions);
@@ -1616,6 +1641,43 @@
         }
     }
 
+
+    /**
+     * Returns the module name for a file in the apex module's partition.
+     */
+    private String getApexModuleNameFromFilePath(Path path) {
+        final Path apexDirectoryPath = Environment.getApexDirectory().toPath();
+        if (!path.startsWith(apexDirectoryPath)) {
+            throw new IllegalArgumentException("File " + path + " is not part of an APEX.");
+        }
+        // File must be in <apex_directory>/<module_name>/[extra_paths/]<xml_file>
+        if (path.getNameCount() <= (apexDirectoryPath.getNameCount() + 1)) {
+            throw new IllegalArgumentException("File " + path + " is in the APEX partition,"
+                                                + " but not inside a module.");
+        }
+        return path.getName(apexDirectoryPath.getNameCount()).toString();
+    }
+
+    private void readApexPrivAppPermissions(XmlPullParser parser, File permFile)
+            throws IOException, XmlPullParserException {
+        final String moduleName = getApexModuleNameFromFilePath(permFile.toPath());
+        final ArrayMap<String, ArraySet<String>> privAppPermissions;
+        if (mApexPrivAppPermissions.containsKey(moduleName)) {
+            privAppPermissions = mApexPrivAppPermissions.get(moduleName);
+        } else {
+            privAppPermissions = new ArrayMap<>();
+            mApexPrivAppPermissions.put(moduleName, privAppPermissions);
+        }
+        final ArrayMap<String, ArraySet<String>> privAppDenyPermissions;
+        if (mApexPrivAppDenyPermissions.containsKey(moduleName)) {
+            privAppDenyPermissions = mApexPrivAppDenyPermissions.get(moduleName);
+        } else {
+            privAppDenyPermissions = new ArrayMap<>();
+            mApexPrivAppDenyPermissions.put(moduleName, privAppDenyPermissions);
+        }
+        readPrivAppPermissions(parser, privAppPermissions, privAppDenyPermissions);
+    }
+
     private static boolean isSystemProcess() {
         return Process.myUid() == Process.SYSTEM_UID;
     }
diff --git a/core/jni/android_media_AudioAttributes.cpp b/core/jni/android_media_AudioAttributes.cpp
index f1ae268..423ef7c 100644
--- a/core/jni/android_media_AudioAttributes.cpp
+++ b/core/jni/android_media_AudioAttributes.cpp
@@ -58,7 +58,7 @@
     jmethodID setSystemUsage;
     jmethodID setInternalCapturePreset;
     jmethodID setContentType;
-    jmethodID setFlags;
+    jmethodID replaceFlags;
     jmethodID addTag;
 } gAudioAttributesBuilderMethods;
 
@@ -130,7 +130,7 @@
                           gAudioAttributesBuilderMethods.setContentType,
                           attributes.content_type);
     env->CallObjectMethod(jAttributeBuilder.get(),
-                          gAudioAttributesBuilderMethods.setFlags,
+                          gAudioAttributesBuilderMethods.replaceFlags,
                           attributes.flags);
     env->CallObjectMethod(jAttributeBuilder.get(),
                           gAudioAttributesBuilderMethods.addTag,
@@ -205,8 +205,8 @@
     gAudioAttributesBuilderMethods.setContentType = GetMethodIDOrDie(
                 env, audioAttributesBuilderClass, "setContentType",
                 "(I)Landroid/media/AudioAttributes$Builder;");
-    gAudioAttributesBuilderMethods.setFlags = GetMethodIDOrDie(
-                env, audioAttributesBuilderClass, "setFlags",
+    gAudioAttributesBuilderMethods.replaceFlags = GetMethodIDOrDie(
+                env, audioAttributesBuilderClass, "replaceFlags",
                 "(I)Landroid/media/AudioAttributes$Builder;");
     gAudioAttributesBuilderMethods.addTag = GetMethodIDOrDie(
                 env, audioAttributesBuilderClass, "addTag",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 4b93363..c847e4d 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2273,10 +2273,8 @@
     return jStatus;
 }
 
-static jint
-android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP(
-                        JNIEnv *env, jobject thiz, jobject jEncodingFormatList)
-{
+static jint android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia(
+        JNIEnv *env, jobject thiz, jint deviceType, jobject jEncodingFormatList) {
     ALOGV("%s", __FUNCTION__);
     jint jStatus = AUDIO_JAVA_SUCCESS;
     if (!env->IsInstanceOf(jEncodingFormatList, gArrayListClass)) {
@@ -2284,8 +2282,10 @@
         return (jint)AUDIO_JAVA_BAD_VALUE;
     }
     std::vector<audio_format_t> encodingFormats;
-    status_t status = AudioSystem::getHwOffloadEncodingFormatsSupportedForA2DP(
-                          &encodingFormats);
+    status_t status =
+            AudioSystem::getHwOffloadFormatsSupportedForBluetoothMedia(static_cast<audio_devices_t>(
+                                                                               deviceType),
+                                                                       &encodingFormats);
     if (status != NO_ERROR) {
         ALOGE("%s: error %d", __FUNCTION__, status);
         jStatus = nativeToJavaStatus(status);
@@ -2810,8 +2810,8 @@
          {"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
          {"isHapticPlaybackSupported", "()Z",
           (void *)android_media_AudioSystem_isHapticPlaybackSupported},
-         {"getHwOffloadEncodingFormatsSupportedForA2DP", "(Ljava/util/ArrayList;)I",
-          (void *)android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP},
+         {"getHwOffloadFormatsSupportedForBluetoothMedia", "(ILjava/util/ArrayList;)I",
+          (void *)android_media_AudioSystem_getHwOffloadFormatsSupportedForBluetoothMedia},
          {"setSupportedSystemUsages", "([I)I",
           (void *)android_media_AudioSystem_setSupportedSystemUsages},
          {"setAllowedCapturePolicy", "(II)I",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1b3f78c..aacf700 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -124,6 +124,7 @@
 static constexpr const char* kZygoteInitClassName = "com/android/internal/os/ZygoteInit";
 static jclass gZygoteInitClass;
 static jmethodID gGetOrCreateSystemServerClassLoader;
+static jmethodID gPrefetchStandaloneSystemServerJars;
 
 static bool gIsSecurityEnforced = true;
 
@@ -1617,6 +1618,12 @@
             // at a later point (but may not have rights to use AoT artifacts).
             env->ExceptionClear();
         }
+        // Also prefetch standalone system server jars. The reason for doing this here is the same
+        // as above.
+        env->CallStaticObjectMethod(gZygoteInitClass, gPrefetchStandaloneSystemServerJars);
+        if (env->ExceptionCheck()) {
+            env->ExceptionClear();
+        }
     }
 
     if (setresgid(gid, gid, gid) == -1) {
@@ -2678,6 +2685,9 @@
   gGetOrCreateSystemServerClassLoader =
           GetStaticMethodIDOrDie(env, gZygoteInitClass, "getOrCreateSystemServerClassLoader",
                                  "()Ljava/lang/ClassLoader;");
+  gPrefetchStandaloneSystemServerJars =
+          GetStaticMethodIDOrDie(env, gZygoteInitClass, "prefetchStandaloneSystemServerJars",
+                                 "()V");
 
   RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
 
diff --git a/core/proto/android/app/OWNERS b/core/proto/android/app/OWNERS
index cc479e6..4d76aee 100644
--- a/core/proto/android/app/OWNERS
+++ b/core/proto/android/app/OWNERS
@@ -1 +1,2 @@
-per-file location_time_zone_manager.proto, time_zone_detector.proto = nfuller@google.com, mingaleev@google.com
+per-file location_time_zone_manager.proto = file:platform/frameworks/base:/services/core/java/com/android/server/timezonedetector/OWNERS
+per-file time_zone_detector.proto = file:platform/frameworks/base:/services/core/java/com/android/server/timezonedetector/OWNERS
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c3d1596..ed3968a 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -672,18 +672,31 @@
     optional SettingProto new_contact_aggregator = 79 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto night_display_forced_auto_mode_available = 80 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
-    message NitzUpdate {
+    message Nitz {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
 
-        // If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment to
-        // SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
-        // exceeded.
-        optional SettingProto diff = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
-        // The length of time in milli-seconds that automatic small adjustments to
-        // SystemClock are ignored if NITZ_UPDATE_DIFF is not exceeded.
-        optional SettingProto spacing = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // If UTC time between two NITZ signals is greater than this value then the second signal
+        // cannot be ignored.
+        //
+        // This value is in milliseconds. It is used for telephony-based time and time zone
+        // detection.
+        optional SettingProto update_diff = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+        // If the elapsed realtime between two NITZ signals is greater than this value then the
+        // second signal cannot be ignored.
+        //
+        // This value is in milliseconds. It is used for telephony-based time and time zone
+        // detection.
+        optional SettingProto update_spacing = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+        // If the device connects to a telephony network and was disconnected from a telephony
+        // network for less than this time, a previously received NITZ signal can be restored.
+        //
+        // This value is in milliseconds. It is used for telephony-based time and time zone
+        // detection.
+        optional SettingProto network_disconnect_retention = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
-    optional NitzUpdate nitz_update = 81;
+    optional Nitz nitz = 81;
 
     message Notification {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 261334b..1a38ea1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1199,6 +1199,14 @@
         android:description="@string/permdesc_readPhoneState"
         android:protectionLevel="dangerous" />
 
+    <!-- Allows read only access to phone state with a non dangerous permission,
+         including the information like cellular network type, software version. -->
+    <permission android:name="android.permission.READ_BASIC_PHONE_STATE"
+            android:permissionGroup="android.permission-group.UNDEFINED"
+            android:label="@string/permlab_readBasicPhoneState"
+            android:description="@string/permdesc_readBasicPhoneState"
+            android:protectionLevel="normal" />
+
     <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
          granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
          <p>Protection level: dangerous-->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index d052d70..f4acfaa 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -547,7 +547,7 @@
     <attr name="allowTaskReparenting" format="boolean" />
 
     <!-- Declare that this application may use cleartext traffic, such as HTTP rather than HTTPS;
-         WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or TLS.
+         WebSockets rather than WebSockets Secure; XMPP, IMAP, SMTP without STARTTLS or TLS.
          Defaults to true. If set to false {@code false}, the application declares that it does not
          intend to use cleartext network traffic, in which case platform components (e.g. HTTP
          stacks, {@code DownloadManager}, {@code MediaPlayer}) will refuse applications's requests
@@ -1762,7 +1762,7 @@
         <!-- @deprecated replaced by setting appCategory attribute to "game" -->
         <attr name="isGame" />
         <!-- Declare that this application may use cleartext traffic, such as HTTP rather than
-             HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP without STARTTLS or
+             HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, SMTP without STARTTLS or
              TLS). Defaults to true. If set to false {@code false}, the application declares that it
              does not intend to use cleartext network traffic, in which case platform components
              (e.g. HTTP stacks, {@code DownloadManager}, {@code MediaPlayer}) will refuse
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index be5063f..8eede56 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1350,6 +1350,12 @@
       phone number and device IDs, whether a call is active, and the remote number
       connected by a call.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=80]-->
+    <string name="permlab_readBasicPhoneState">read basic telephony status and identity </string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
+    <string name="permdesc_readBasicPhoneState">Allows the app to access the basic telephony
+        features of the device.</string>
+
     <!-- Title of an application permission.  When granted the user is giving access to a third
          party app to route its calls through the system. -->
     <string name="permlab_manageOwnCalls">route calls through the system</string>
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
index 59b4665..bd55426 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
@@ -17,7 +17,6 @@
 package android.bluetooth;
 
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
 import junit.framework.TestCase;
 
@@ -34,7 +33,6 @@
         BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
         BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
         BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
-        BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX,
         BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID,
     };
     private static final int[] kCodecPriorityArray = new int[] {
@@ -168,20 +166,11 @@
             long codec_specific3 = selectCodecSpecific3(config_id);
             long codec_specific4 = selectCodecSpecific4(config_id);
 
-            BluetoothCodecConfig bcc = new BluetoothCodecConfig(codec_type, codec_priority,
+            BluetoothCodecConfig bcc = buildBluetoothCodecConfig(codec_type, codec_priority,
                                                                 sample_rate, bits_per_sample,
                                                                 channel_mode, codec_specific1,
                                                                 codec_specific2, codec_specific3,
                                                                 codec_specific4);
-            if (sample_rate == BluetoothCodecConfig.SAMPLE_RATE_NONE) {
-                assertFalse(bcc.isValid());
-            } else if (bits_per_sample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
-                assertFalse(bcc.isValid());
-            } else if (channel_mode == BluetoothCodecConfig.CHANNEL_MODE_NONE) {
-                assertFalse(bcc.isValid());
-            } else {
-                assertTrue(bcc.isValid());
-            }
 
             if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
                 assertTrue(bcc.isMandatoryCodec());
@@ -204,10 +193,6 @@
             if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC) {
                 assertEquals("LDAC", bcc.getCodecName());
             }
-            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX) {
-                assertEquals("UNKNOWN CODEC(" + BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX + ")",
-                             bcc.getCodecName());
-            }
             if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
                 assertEquals("INVALID CODEC", bcc.getCodecName());
             }
@@ -227,7 +212,7 @@
     @SmallTest
     public void testBluetoothCodecConfig_equals() {
         BluetoothCodecConfig bcc1 =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -235,7 +220,7 @@
                                      1000, 2000, 3000, 4000);
 
         BluetoothCodecConfig bcc2_same =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -244,7 +229,7 @@
         assertTrue(bcc1.equals(bcc2_same));
 
         BluetoothCodecConfig bcc3_codec_type =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -253,7 +238,7 @@
         assertFalse(bcc1.equals(bcc3_codec_type));
 
         BluetoothCodecConfig bcc4_codec_priority =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -262,7 +247,7 @@
         assertFalse(bcc1.equals(bcc4_codec_priority));
 
         BluetoothCodecConfig bcc5_sample_rate =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_48000,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -271,7 +256,7 @@
         assertFalse(bcc1.equals(bcc5_sample_rate));
 
         BluetoothCodecConfig bcc6_bits_per_sample =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_24,
@@ -280,7 +265,7 @@
         assertFalse(bcc1.equals(bcc6_bits_per_sample));
 
         BluetoothCodecConfig bcc7_channel_mode =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -289,7 +274,7 @@
         assertFalse(bcc1.equals(bcc7_channel_mode));
 
         BluetoothCodecConfig bcc8_codec_specific1 =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -298,7 +283,7 @@
         assertFalse(bcc1.equals(bcc8_codec_specific1));
 
         BluetoothCodecConfig bcc9_codec_specific2 =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -307,7 +292,7 @@
         assertFalse(bcc1.equals(bcc9_codec_specific2));
 
         BluetoothCodecConfig bcc10_codec_specific3 =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -316,7 +301,7 @@
         assertFalse(bcc1.equals(bcc10_codec_specific3));
 
         BluetoothCodecConfig bcc11_codec_specific4 =
-            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                      BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                      BluetoothCodecConfig.SAMPLE_RATE_44100,
                                      BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -324,4 +309,21 @@
                                      1000, 2000, 3000, 4004);
         assertFalse(bcc1.equals(bcc11_codec_specific4));
     }
+
+    private BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
+            int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
+            long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
+        return new BluetoothCodecConfig.Builder()
+                    .setCodecType(sourceCodecType)
+                    .setCodecPriority(codecPriority)
+                    .setSampleRate(sampleRate)
+                    .setBitsPerSample(bitsPerSample)
+                    .setChannelMode(channelMode)
+                    .setCodecSpecific1(codecSpecific1)
+                    .setCodecSpecific2(codecSpecific2)
+                    .setCodecSpecific3(codecSpecific3)
+                    .setCodecSpecific4(codecSpecific4)
+                    .build();
+
+    }
 }
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
index 83bf2ed..1cb2dca 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
@@ -17,13 +17,13 @@
 package android.bluetooth;
 
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.Objects;
 
 import junit.framework.TestCase;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
 /**
  * Unit test cases for {@link BluetoothCodecStatus}.
  * <p>
@@ -34,7 +34,7 @@
 
     // Codec configs: A and B are same; C is different
     private static final BluetoothCodecConfig config_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -42,7 +42,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig config_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -50,7 +50,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig config_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -59,7 +59,7 @@
 
     // Local capabilities: A and B are same; C is different
     private static final BluetoothCodecConfig local_capability1_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -69,7 +69,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability1_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -79,7 +79,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability1_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -89,7 +89,7 @@
 
 
     private static final BluetoothCodecConfig local_capability2_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -99,7 +99,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability2_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -109,7 +109,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability2_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -118,7 +118,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability3_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -128,7 +128,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability3_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -138,7 +138,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability3_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -147,7 +147,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability4_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -157,7 +157,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability4_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -167,7 +167,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability4_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000,
@@ -176,7 +176,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability5_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000 |
@@ -190,7 +190,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability5_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000 |
@@ -204,7 +204,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig local_capability5_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000 |
@@ -219,7 +219,7 @@
 
     // Selectable capabilities: A and B are same; C is different
     private static final BluetoothCodecConfig selectable_capability1_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -228,7 +228,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability1_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -237,7 +237,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability1_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -245,7 +245,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability2_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -254,7 +254,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability2_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -263,7 +263,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability2_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -271,7 +271,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability3_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -280,7 +280,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability3_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -289,7 +289,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability3_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_16,
@@ -297,7 +297,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability4_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_24,
@@ -306,7 +306,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability4_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_24,
@@ -315,7 +315,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability4_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100,
                                  BluetoothCodecConfig.BITS_PER_SAMPLE_24,
@@ -323,7 +323,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability5_A =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000 |
@@ -337,7 +337,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability5_B =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000 |
@@ -351,7 +351,7 @@
                                  1000, 2000, 3000, 4000);
 
     private static final BluetoothCodecConfig selectable_capability5_C =
-        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+            buildBluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
                                  BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
                                  BluetoothCodecConfig.SAMPLE_RATE_44100 |
                                  BluetoothCodecConfig.SAMPLE_RATE_48000 |
@@ -363,79 +363,87 @@
                                  BluetoothCodecConfig.CHANNEL_MODE_STEREO,
                                  1000, 2000, 3000, 4000);
 
-    private static final BluetoothCodecConfig[] local_capability_A = {
-        local_capability1_A,
-        local_capability2_A,
-        local_capability3_A,
-        local_capability4_A,
-        local_capability5_A,
-    };
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_A =
+            new ArrayList() {{
+                    add(local_capability1_A);
+                    add(local_capability2_A);
+                    add(local_capability3_A);
+                    add(local_capability4_A);
+                    add(local_capability5_A);
+            }};
 
-    private static final BluetoothCodecConfig[] local_capability_B = {
-        local_capability1_B,
-        local_capability2_B,
-        local_capability3_B,
-        local_capability4_B,
-        local_capability5_B,
-    };
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B =
+            new ArrayList() {{
+                    add(local_capability1_B);
+                    add(local_capability2_B);
+                    add(local_capability3_B);
+                    add(local_capability4_B);
+                    add(local_capability5_B);
+            }};
 
-    private static final BluetoothCodecConfig[] local_capability_B_reordered = {
-        local_capability5_B,
-        local_capability4_B,
-        local_capability2_B,
-        local_capability3_B,
-        local_capability1_B,
-    };
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_B_REORDERED =
+            new ArrayList() {{
+                    add(local_capability5_B);
+                    add(local_capability4_B);
+                    add(local_capability2_B);
+                    add(local_capability3_B);
+                    add(local_capability1_B);
+            }};
 
-    private static final BluetoothCodecConfig[] local_capability_C = {
-        local_capability1_C,
-        local_capability2_C,
-        local_capability3_C,
-        local_capability4_C,
-        local_capability5_C,
-    };
+    private static final List<BluetoothCodecConfig> LOCAL_CAPABILITY_C =
+            new ArrayList() {{
+                    add(local_capability1_C);
+                    add(local_capability2_C);
+                    add(local_capability3_C);
+                    add(local_capability4_C);
+                    add(local_capability5_C);
+            }};
 
-    private static final BluetoothCodecConfig[] selectable_capability_A = {
-        selectable_capability1_A,
-        selectable_capability2_A,
-        selectable_capability3_A,
-        selectable_capability4_A,
-        selectable_capability5_A,
-    };
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_A =
+            new ArrayList() {{
+                    add(selectable_capability1_A);
+                    add(selectable_capability2_A);
+                    add(selectable_capability3_A);
+                    add(selectable_capability4_A);
+                    add(selectable_capability5_A);
+            }};
 
-    private static final BluetoothCodecConfig[] selectable_capability_B = {
-        selectable_capability1_B,
-        selectable_capability2_B,
-        selectable_capability3_B,
-        selectable_capability4_B,
-        selectable_capability5_B,
-    };
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B =
+            new ArrayList() {{
+                    add(selectable_capability1_B);
+                    add(selectable_capability2_B);
+                    add(selectable_capability3_B);
+                    add(selectable_capability4_B);
+                    add(selectable_capability5_B);
+            }};
 
-    private static final BluetoothCodecConfig[] selectable_capability_B_reordered = {
-        selectable_capability5_B,
-        selectable_capability4_B,
-        selectable_capability2_B,
-        selectable_capability3_B,
-        selectable_capability1_B,
-    };
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_B_REORDERED =
+            new ArrayList() {{
+                    add(selectable_capability5_B);
+                    add(selectable_capability4_B);
+                    add(selectable_capability2_B);
+                    add(selectable_capability3_B);
+                    add(selectable_capability1_B);
+            }};
 
-    private static final BluetoothCodecConfig[] selectable_capability_C = {
-        selectable_capability1_C,
-        selectable_capability2_C,
-        selectable_capability3_C,
-        selectable_capability4_C,
-        selectable_capability5_C,
-    };
+    private static final List<BluetoothCodecConfig> SELECTABLE_CAPABILITY_C =
+            new ArrayList() {{
+                    add(selectable_capability1_C);
+                    add(selectable_capability2_C);
+                    add(selectable_capability3_C);
+                    add(selectable_capability4_C);
+                    add(selectable_capability5_C);
+            }};
 
     private static final BluetoothCodecStatus bcs_A =
-        new BluetoothCodecStatus(config_A, local_capability_A, selectable_capability_A);
+            new BluetoothCodecStatus(config_A, LOCAL_CAPABILITY_A, SELECTABLE_CAPABILITY_A);
     private static final BluetoothCodecStatus bcs_B =
-        new BluetoothCodecStatus(config_B, local_capability_B, selectable_capability_B);
+            new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B, SELECTABLE_CAPABILITY_B);
     private static final BluetoothCodecStatus bcs_B_reordered =
-        new BluetoothCodecStatus(config_B, local_capability_B_reordered,
-                                 selectable_capability_B_reordered);
+            new BluetoothCodecStatus(config_B, LOCAL_CAPABILITY_B_REORDERED,
+                                 SELECTABLE_CAPABILITY_B_REORDERED);
     private static final BluetoothCodecStatus bcs_C =
-        new BluetoothCodecStatus(config_C, local_capability_C, selectable_capability_C);
+            new BluetoothCodecStatus(config_C, LOCAL_CAPABILITY_C, SELECTABLE_CAPABILITY_C);
 
     @SmallTest
     public void testBluetoothCodecStatus_get_methods() {
@@ -444,16 +452,16 @@
         assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_B));
         assertFalse(Objects.equals(bcs_A.getCodecConfig(), config_C));
 
-        assertTrue(Arrays.equals(bcs_A.getCodecsLocalCapabilities(), local_capability_A));
-        assertTrue(Arrays.equals(bcs_A.getCodecsLocalCapabilities(), local_capability_B));
-        assertFalse(Arrays.equals(bcs_A.getCodecsLocalCapabilities(), local_capability_C));
+        assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_A));
+        assertTrue(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_B));
+        assertFalse(bcs_A.getCodecsLocalCapabilities().equals(LOCAL_CAPABILITY_C));
 
-        assertTrue(Arrays.equals(bcs_A.getCodecsSelectableCapabilities(),
-                                 selectable_capability_A));
-        assertTrue(Arrays.equals(bcs_A.getCodecsSelectableCapabilities(),
-                                  selectable_capability_B));
-        assertFalse(Arrays.equals(bcs_A.getCodecsSelectableCapabilities(),
-                                  selectable_capability_C));
+        assertTrue(bcs_A.getCodecsSelectableCapabilities()
+                                 .equals(SELECTABLE_CAPABILITY_A));
+        assertTrue(bcs_A.getCodecsSelectableCapabilities()
+                                  .equals(SELECTABLE_CAPABILITY_B));
+        assertFalse(bcs_A.getCodecsSelectableCapabilities()
+                                  .equals(SELECTABLE_CAPABILITY_C));
     }
 
     @SmallTest
@@ -465,4 +473,21 @@
         assertFalse(bcs_A.equals(bcs_C));
         assertFalse(bcs_C.equals(bcs_A));
     }
+
+    private static BluetoothCodecConfig buildBluetoothCodecConfig(int sourceCodecType,
+            int codecPriority, int sampleRate, int bitsPerSample, int channelMode,
+            long codecSpecific1, long codecSpecific2, long codecSpecific3, long codecSpecific4) {
+        return new BluetoothCodecConfig.Builder()
+                    .setCodecType(sourceCodecType)
+                    .setCodecPriority(codecPriority)
+                    .setSampleRate(sampleRate)
+                    .setBitsPerSample(bitsPerSample)
+                    .setChannelMode(channelMode)
+                    .setCodecSpecific1(codecSpecific1)
+                    .setCodecSpecific2(codecSpecific2)
+                    .setCodecSpecific3(codecSpecific3)
+                    .setCodecSpecific4(codecSpecific4)
+                    .build();
+
+    }
 }
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
new file mode 100644
index 0000000..c3d707c
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothLeAudioCodecConfigTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test cases for {@link BluetoothLeAudioCodecConfig}.
+ */
+public class BluetoothLeAudioCodecConfigTest extends TestCase {
+    private int[] mCodecTypeArray = new int[] {
+        BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3,
+        BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID,
+    };
+
+    @SmallTest
+    public void testBluetoothLeAudioCodecConfig_valid_get_methods() {
+
+        for (int codecIdx = 0; codecIdx < mCodecTypeArray.length; codecIdx++) {
+            int codecType = mCodecTypeArray[codecIdx];
+
+            BluetoothLeAudioCodecConfig leAudioCodecConfig =
+                    buildBluetoothLeAudioCodecConfig(codecType);
+
+            if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3) {
+                assertEquals("LC3", leAudioCodecConfig.getCodecName());
+            }
+            if (codecType == BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+                assertEquals("INVALID CODEC", leAudioCodecConfig.getCodecName());
+            }
+
+            assertEquals(codecType, leAudioCodecConfig.getCodecType());
+        }
+    }
+
+    private BluetoothLeAudioCodecConfig buildBluetoothLeAudioCodecConfig(int sourceCodecType) {
+        return new BluetoothLeAudioCodecConfig.Builder()
+                    .setCodecType(sourceCodecType)
+                    .build();
+
+    }
+}
diff --git a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java
index 6be9306..bd4d80d 100644
--- a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java
+++ b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java
@@ -169,13 +169,13 @@
 
         assertEquals("19/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + HOUR,
                 FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
-        assertEquals("19/1/2009–22/1/2009",
+        assertEquals("19/1/2009 – 22/1/2009",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY,
                         FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
-        assertEquals("19/1/2009–22/4/2009",
+        assertEquals("19/1/2009 – 22/4/2009",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH,
                         FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
-        assertEquals("19/1/2009–9/2/2012",
+        assertEquals("19/1/2009 – 9/2/2012",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR,
                         FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
 
@@ -251,35 +251,35 @@
 
         assertEquals("19–22 de enero de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, 0));
-        assertEquals("19–22 de ene. de 2009",
+        assertEquals("19–22 de ene de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY,
                         FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
-        assertEquals("lun, 19 de ene. – jue, 22 de ene. de 2009",
+        assertEquals("lun, 19 de ene – jue, 22 de ene de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY,
                         FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
-        assertEquals("lunes, 19 de enero–jueves, 22 de enero de 2009",
+        assertEquals("lunes, 19 de enero – jueves, 22 de enero de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
 
-        assertEquals("19 de enero–22 de abril de 2009",
+        assertEquals("19 de enero – 22 de abril de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, 0));
-        assertEquals("19 de ene. – 22 de abr. 2009",
+        assertEquals("19 de ene – 22 de abr 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH,
                         FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
-        assertEquals("lun, 19 de ene. – mié, 22 de abr. de 2009",
+        assertEquals("lun, 19 de ene – mié, 22 de abr de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH,
                         FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
         assertEquals("enero–abril de 2009",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH, FORMAT_NO_MONTH_DAY));
 
-        assertEquals("19 de ene. de 2009 – 9 de feb. de 2012",
+        assertEquals("19 de ene de 2009 – 9 de feb de 2012",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR,
                         FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
-        assertEquals("ene. de 2009 – feb. de 2012",
+        assertEquals("ene de 2009 – feb de 2012",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR,
                         FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
-        assertEquals("19 de enero de 2009–9 de febrero de 2012",
+        assertEquals("19 de enero de 2009 – 9 de febrero de 2012",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, 0));
-        assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012",
+        assertEquals("lunes, 19 de enero de 2009 – jueves, 9 de febrero de 2012",
                 formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
 
         // The same tests but for es_ES.
@@ -291,10 +291,10 @@
         assertEquals("lun, 19 ene – jue, 22 ene 2009",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY,
                         FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
-        assertEquals("lunes, 19 de enero–jueves, 22 de enero de 2009",
+        assertEquals("lunes, 19 de enero – jueves, 22 de enero de 2009",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY, FORMAT_SHOW_WEEKDAY));
 
-        assertEquals("19 de enero–22 de abril de 2009",
+        assertEquals("19 de enero – 22 de abril de 2009",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH, 0));
         assertEquals("19 ene – 22 abr 2009",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH,
@@ -311,9 +311,9 @@
         assertEquals("ene 2009 – feb 2012",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR,
                         FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
-        assertEquals("19 de enero de 2009–9 de febrero de 2012",
+        assertEquals("19 de enero de 2009 – 9 de febrero de 2012",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, 0));
-        assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012",
+        assertEquals("lunes, 19 de enero de 2009 – jueves, 9 de febrero de 2012",
                 formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY));
     }
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index e81adec..1c7659e 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -503,6 +503,8 @@
         <permission name="android.permission.UPDATE_DEVICE_STATS" />
         <!-- Permission required for GTS test - PendingSystemUpdateTest -->
         <permission name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE" />
+        <!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
+        <permission name="android.permission.LOCK_DEVICE" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index d1e4309..2f61a28 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -187,7 +187,10 @@
         if (!actualPerm.containsAll(expectedPerm)) {
             return buildDescription(tree)
                     .setMessage("Method " + method.name.toString() + "() annotated " + expectedPerm
-                            + " but too wide; only invokes methods requiring " + actualPerm)
+                            + " but too wide; only invokes methods requiring " + actualPerm
+                            + "\n  If calling an AIDL interface, it can be annotated by adding:"
+                            + "\n  @JavaPassthrough(annotation=\""
+                            + "@android.annotation.RequiresPermission(...)\")")
                     .build();
         }
 
diff --git a/libs/androidfw/LocaleDataTables.cpp b/libs/androidfw/LocaleDataTables.cpp
index 2c3567a..2c005fd 100644
--- a/libs/androidfw/LocaleDataTables.cpp
+++ b/libs/androidfw/LocaleDataTables.cpp
@@ -34,206 +34,209 @@
     /* 30 */ {'H', 'a', 'n', 't'},
     /* 31 */ {'H', 'e', 'b', 'r'},
     /* 32 */ {'H', 'l', 'u', 'w'},
-    /* 33 */ {'H', 'm', 'n', 'g'},
-    /* 34 */ {'H', 'm', 'n', 'p'},
-    /* 35 */ {'I', 't', 'a', 'l'},
-    /* 36 */ {'J', 'p', 'a', 'n'},
-    /* 37 */ {'K', 'a', 'l', 'i'},
-    /* 38 */ {'K', 'a', 'n', 'a'},
-    /* 39 */ {'K', 'h', 'a', 'r'},
-    /* 40 */ {'K', 'h', 'm', 'r'},
-    /* 41 */ {'K', 'i', 't', 's'},
-    /* 42 */ {'K', 'n', 'd', 'a'},
-    /* 43 */ {'K', 'o', 'r', 'e'},
-    /* 44 */ {'L', 'a', 'n', 'a'},
-    /* 45 */ {'L', 'a', 'o', 'o'},
-    /* 46 */ {'L', 'a', 't', 'n'},
-    /* 47 */ {'L', 'e', 'p', 'c'},
-    /* 48 */ {'L', 'i', 'n', 'a'},
-    /* 49 */ {'L', 'i', 's', 'u'},
-    /* 50 */ {'L', 'y', 'c', 'i'},
-    /* 51 */ {'L', 'y', 'd', 'i'},
-    /* 52 */ {'M', 'a', 'n', 'd'},
-    /* 53 */ {'M', 'a', 'n', 'i'},
-    /* 54 */ {'M', 'e', 'd', 'f'},
-    /* 55 */ {'M', 'e', 'r', 'c'},
-    /* 56 */ {'M', 'l', 'y', 'm'},
-    /* 57 */ {'M', 'o', 'n', 'g'},
-    /* 58 */ {'M', 'r', 'o', 'o'},
-    /* 59 */ {'M', 'y', 'm', 'r'},
-    /* 60 */ {'N', 'a', 'r', 'b'},
-    /* 61 */ {'N', 'k', 'o', 'o'},
-    /* 62 */ {'N', 's', 'h', 'u'},
-    /* 63 */ {'O', 'g', 'a', 'm'},
-    /* 64 */ {'O', 'l', 'c', 'k'},
-    /* 65 */ {'O', 'r', 'k', 'h'},
-    /* 66 */ {'O', 'r', 'y', 'a'},
-    /* 67 */ {'O', 's', 'g', 'e'},
+    /* 33 */ {'H', 'm', 'n', 'p'},
+    /* 34 */ {'I', 't', 'a', 'l'},
+    /* 35 */ {'J', 'p', 'a', 'n'},
+    /* 36 */ {'K', 'a', 'l', 'i'},
+    /* 37 */ {'K', 'a', 'n', 'a'},
+    /* 38 */ {'K', 'h', 'a', 'r'},
+    /* 39 */ {'K', 'h', 'm', 'r'},
+    /* 40 */ {'K', 'i', 't', 's'},
+    /* 41 */ {'K', 'n', 'd', 'a'},
+    /* 42 */ {'K', 'o', 'r', 'e'},
+    /* 43 */ {'L', 'a', 'n', 'a'},
+    /* 44 */ {'L', 'a', 'o', 'o'},
+    /* 45 */ {'L', 'a', 't', 'n'},
+    /* 46 */ {'L', 'e', 'p', 'c'},
+    /* 47 */ {'L', 'i', 'n', 'a'},
+    /* 48 */ {'L', 'i', 's', 'u'},
+    /* 49 */ {'L', 'y', 'c', 'i'},
+    /* 50 */ {'L', 'y', 'd', 'i'},
+    /* 51 */ {'M', 'a', 'n', 'd'},
+    /* 52 */ {'M', 'a', 'n', 'i'},
+    /* 53 */ {'M', 'e', 'd', 'f'},
+    /* 54 */ {'M', 'e', 'r', 'c'},
+    /* 55 */ {'M', 'l', 'y', 'm'},
+    /* 56 */ {'M', 'o', 'n', 'g'},
+    /* 57 */ {'M', 'r', 'o', 'o'},
+    /* 58 */ {'M', 'y', 'm', 'r'},
+    /* 59 */ {'N', 'a', 'r', 'b'},
+    /* 60 */ {'N', 'k', 'o', 'o'},
+    /* 61 */ {'N', 's', 'h', 'u'},
+    /* 62 */ {'O', 'g', 'a', 'm'},
+    /* 63 */ {'O', 'l', 'c', 'k'},
+    /* 64 */ {'O', 'r', 'k', 'h'},
+    /* 65 */ {'O', 'r', 'y', 'a'},
+    /* 66 */ {'O', 's', 'g', 'e'},
+    /* 67 */ {'O', 'u', 'g', 'r'},
     /* 68 */ {'P', 'a', 'u', 'c'},
     /* 69 */ {'P', 'h', 'l', 'i'},
     /* 70 */ {'P', 'h', 'n', 'x'},
     /* 71 */ {'P', 'l', 'r', 'd'},
     /* 72 */ {'P', 'r', 't', 'i'},
-    /* 73 */ {'R', 'u', 'n', 'r'},
-    /* 74 */ {'S', 'a', 'm', 'r'},
-    /* 75 */ {'S', 'a', 'r', 'b'},
-    /* 76 */ {'S', 'a', 'u', 'r'},
-    /* 77 */ {'S', 'g', 'n', 'w'},
-    /* 78 */ {'S', 'i', 'n', 'h'},
-    /* 79 */ {'S', 'o', 'g', 'd'},
-    /* 80 */ {'S', 'o', 'r', 'a'},
-    /* 81 */ {'S', 'o', 'y', 'o'},
-    /* 82 */ {'S', 'y', 'r', 'c'},
-    /* 83 */ {'T', 'a', 'l', 'e'},
-    /* 84 */ {'T', 'a', 'l', 'u'},
-    /* 85 */ {'T', 'a', 'm', 'l'},
-    /* 86 */ {'T', 'a', 'n', 'g'},
-    /* 87 */ {'T', 'a', 'v', 't'},
-    /* 88 */ {'T', 'e', 'l', 'u'},
-    /* 89 */ {'T', 'f', 'n', 'g'},
-    /* 90 */ {'T', 'h', 'a', 'a'},
-    /* 91 */ {'T', 'h', 'a', 'i'},
-    /* 92 */ {'T', 'i', 'b', 't'},
-    /* 93 */ {'U', 'g', 'a', 'r'},
-    /* 94 */ {'V', 'a', 'i', 'i'},
-    /* 95 */ {'W', 'c', 'h', 'o'},
-    /* 96 */ {'X', 'p', 'e', 'o'},
-    /* 97 */ {'X', 's', 'u', 'x'},
-    /* 98 */ {'Y', 'i', 'i', 'i'},
-    /* 99 */ {'~', '~', '~', 'A'},
-    /* 100 */ {'~', '~', '~', 'B'},
+    /* 73 */ {'R', 'o', 'h', 'g'},
+    /* 74 */ {'R', 'u', 'n', 'r'},
+    /* 75 */ {'S', 'a', 'm', 'r'},
+    /* 76 */ {'S', 'a', 'r', 'b'},
+    /* 77 */ {'S', 'a', 'u', 'r'},
+    /* 78 */ {'S', 'g', 'n', 'w'},
+    /* 79 */ {'S', 'i', 'n', 'h'},
+    /* 80 */ {'S', 'o', 'g', 'd'},
+    /* 81 */ {'S', 'o', 'r', 'a'},
+    /* 82 */ {'S', 'o', 'y', 'o'},
+    /* 83 */ {'S', 'y', 'r', 'c'},
+    /* 84 */ {'T', 'a', 'l', 'e'},
+    /* 85 */ {'T', 'a', 'l', 'u'},
+    /* 86 */ {'T', 'a', 'm', 'l'},
+    /* 87 */ {'T', 'a', 'n', 'g'},
+    /* 88 */ {'T', 'a', 'v', 't'},
+    /* 89 */ {'T', 'e', 'l', 'u'},
+    /* 90 */ {'T', 'f', 'n', 'g'},
+    /* 91 */ {'T', 'h', 'a', 'a'},
+    /* 92 */ {'T', 'h', 'a', 'i'},
+    /* 93 */ {'T', 'i', 'b', 't'},
+    /* 94 */ {'T', 'n', 's', 'a'},
+    /* 95 */ {'T', 'o', 't', 'o'},
+    /* 96 */ {'U', 'g', 'a', 'r'},
+    /* 97 */ {'V', 'a', 'i', 'i'},
+    /* 98 */ {'W', 'c', 'h', 'o'},
+    /* 99 */ {'X', 'p', 'e', 'o'},
+    /* 100 */ {'X', 's', 'u', 'x'},
+    /* 101 */ {'Y', 'i', 'i', 'i'},
+    /* 102 */ {'~', '~', '~', 'A'},
+    /* 103 */ {'~', '~', '~', 'B'},
 };
 
 
 const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({
-    {0x61610000u, 46u}, // aa -> Latn
-    {0xA0000000u, 46u}, // aai -> Latn
-    {0xA8000000u, 46u}, // aak -> Latn
-    {0xD0000000u, 46u}, // aau -> Latn
+    {0x61610000u, 45u}, // aa -> Latn
+    {0xA0000000u, 45u}, // aai -> Latn
+    {0xA8000000u, 45u}, // aak -> Latn
+    {0xD0000000u, 45u}, // aau -> Latn
     {0x61620000u, 18u}, // ab -> Cyrl
-    {0xA0200000u, 46u}, // abi -> Latn
+    {0xA0200000u, 45u}, // abi -> Latn
     {0xC0200000u, 18u}, // abq -> Cyrl
-    {0xC4200000u, 46u}, // abr -> Latn
-    {0xCC200000u, 46u}, // abt -> Latn
-    {0xE0200000u, 46u}, // aby -> Latn
-    {0x8C400000u, 46u}, // acd -> Latn
-    {0x90400000u, 46u}, // ace -> Latn
-    {0x9C400000u, 46u}, // ach -> Latn
-    {0x80600000u, 46u}, // ada -> Latn
-    {0x90600000u, 46u}, // ade -> Latn
-    {0xA4600000u, 46u}, // adj -> Latn
-    {0xBC600000u, 92u}, // adp -> Tibt
+    {0xC4200000u, 45u}, // abr -> Latn
+    {0xCC200000u, 45u}, // abt -> Latn
+    {0xE0200000u, 45u}, // aby -> Latn
+    {0x8C400000u, 45u}, // acd -> Latn
+    {0x90400000u, 45u}, // ace -> Latn
+    {0x9C400000u, 45u}, // ach -> Latn
+    {0x80600000u, 45u}, // ada -> Latn
+    {0x90600000u, 45u}, // ade -> Latn
+    {0xA4600000u, 45u}, // adj -> Latn
+    {0xBC600000u, 93u}, // adp -> Tibt
     {0xE0600000u, 18u}, // ady -> Cyrl
-    {0xE4600000u, 46u}, // adz -> Latn
+    {0xE4600000u, 45u}, // adz -> Latn
     {0x61650000u,  5u}, // ae -> Avst
     {0x84800000u,  2u}, // aeb -> Arab
-    {0xE0800000u, 46u}, // aey -> Latn
-    {0x61660000u, 46u}, // af -> Latn
-    {0x88C00000u, 46u}, // agc -> Latn
-    {0x8CC00000u, 46u}, // agd -> Latn
-    {0x98C00000u, 46u}, // agg -> Latn
-    {0xB0C00000u, 46u}, // agm -> Latn
-    {0xB8C00000u, 46u}, // ago -> Latn
-    {0xC0C00000u, 46u}, // agq -> Latn
-    {0x80E00000u, 46u}, // aha -> Latn
-    {0xACE00000u, 46u}, // ahl -> Latn
+    {0xE0800000u, 45u}, // aey -> Latn
+    {0x61660000u, 45u}, // af -> Latn
+    {0x88C00000u, 45u}, // agc -> Latn
+    {0x8CC00000u, 45u}, // agd -> Latn
+    {0x98C00000u, 45u}, // agg -> Latn
+    {0xB0C00000u, 45u}, // agm -> Latn
+    {0xB8C00000u, 45u}, // ago -> Latn
+    {0xC0C00000u, 45u}, // agq -> Latn
+    {0x80E00000u, 45u}, // aha -> Latn
+    {0xACE00000u, 45u}, // ahl -> Latn
     {0xB8E00000u,  1u}, // aho -> Ahom
-    {0x99200000u, 46u}, // ajg -> Latn
-    {0x616B0000u, 46u}, // ak -> Latn
-    {0xA9400000u, 97u}, // akk -> Xsux
-    {0x81600000u, 46u}, // ala -> Latn
-    {0xA1600000u, 46u}, // ali -> Latn
-    {0xB5600000u, 46u}, // aln -> Latn
+    {0x99200000u, 45u}, // ajg -> Latn
+    {0x616B0000u, 45u}, // ak -> Latn
+    {0xA9400000u, 100u}, // akk -> Xsux
+    {0x81600000u, 45u}, // ala -> Latn
+    {0xA1600000u, 45u}, // ali -> Latn
+    {0xB5600000u, 45u}, // aln -> Latn
     {0xCD600000u, 18u}, // alt -> Cyrl
     {0x616D0000u, 21u}, // am -> Ethi
-    {0xB1800000u, 46u}, // amm -> Latn
-    {0xB5800000u, 46u}, // amn -> Latn
-    {0xB9800000u, 46u}, // amo -> Latn
-    {0xBD800000u, 46u}, // amp -> Latn
-    {0x616E0000u, 46u}, // an -> Latn
-    {0x89A00000u, 46u}, // anc -> Latn
-    {0xA9A00000u, 46u}, // ank -> Latn
-    {0xB5A00000u, 46u}, // ann -> Latn
-    {0xE1A00000u, 46u}, // any -> Latn
-    {0xA5C00000u, 46u}, // aoj -> Latn
-    {0xB1C00000u, 46u}, // aom -> Latn
-    {0xE5C00000u, 46u}, // aoz -> Latn
+    {0xB1800000u, 45u}, // amm -> Latn
+    {0xB5800000u, 45u}, // amn -> Latn
+    {0xB9800000u, 45u}, // amo -> Latn
+    {0xBD800000u, 45u}, // amp -> Latn
+    {0x616E0000u, 45u}, // an -> Latn
+    {0x89A00000u, 45u}, // anc -> Latn
+    {0xA9A00000u, 45u}, // ank -> Latn
+    {0xB5A00000u, 45u}, // ann -> Latn
+    {0xE1A00000u, 45u}, // any -> Latn
+    {0xA5C00000u, 45u}, // aoj -> Latn
+    {0xB1C00000u, 45u}, // aom -> Latn
+    {0xE5C00000u, 45u}, // aoz -> Latn
     {0x89E00000u,  2u}, // apc -> Arab
     {0x8DE00000u,  2u}, // apd -> Arab
-    {0x91E00000u, 46u}, // ape -> Latn
-    {0xC5E00000u, 46u}, // apr -> Latn
-    {0xC9E00000u, 46u}, // aps -> Latn
-    {0xE5E00000u, 46u}, // apz -> Latn
+    {0x91E00000u, 45u}, // ape -> Latn
+    {0xC5E00000u, 45u}, // apr -> Latn
+    {0xC9E00000u, 45u}, // aps -> Latn
+    {0xE5E00000u, 45u}, // apz -> Latn
     {0x61720000u,  2u}, // ar -> Arab
-    {0x61725842u, 100u}, // ar-XB -> ~~~B
+    {0x61725842u, 103u}, // ar-XB -> ~~~B
     {0x8A200000u,  3u}, // arc -> Armi
-    {0x9E200000u, 46u}, // arh -> Latn
-    {0xB6200000u, 46u}, // arn -> Latn
-    {0xBA200000u, 46u}, // aro -> Latn
+    {0x9E200000u, 45u}, // arh -> Latn
+    {0xB6200000u, 45u}, // arn -> Latn
+    {0xBA200000u, 45u}, // aro -> Latn
     {0xC2200000u,  2u}, // arq -> Arab
     {0xCA200000u,  2u}, // ars -> Arab
     {0xE2200000u,  2u}, // ary -> Arab
     {0xE6200000u,  2u}, // arz -> Arab
     {0x61730000u,  8u}, // as -> Beng
-    {0x82400000u, 46u}, // asa -> Latn
-    {0x92400000u, 77u}, // ase -> Sgnw
-    {0x9A400000u, 46u}, // asg -> Latn
-    {0xBA400000u, 46u}, // aso -> Latn
-    {0xCE400000u, 46u}, // ast -> Latn
-    {0x82600000u, 46u}, // ata -> Latn
-    {0x9A600000u, 46u}, // atg -> Latn
-    {0xA6600000u, 46u}, // atj -> Latn
-    {0xE2800000u, 46u}, // auy -> Latn
+    {0x82400000u, 45u}, // asa -> Latn
+    {0x92400000u, 78u}, // ase -> Sgnw
+    {0x9A400000u, 45u}, // asg -> Latn
+    {0xBA400000u, 45u}, // aso -> Latn
+    {0xCE400000u, 45u}, // ast -> Latn
+    {0x82600000u, 45u}, // ata -> Latn
+    {0x9A600000u, 45u}, // atg -> Latn
+    {0xA6600000u, 45u}, // atj -> Latn
+    {0xE2800000u, 45u}, // auy -> Latn
     {0x61760000u, 18u}, // av -> Cyrl
     {0xAEA00000u,  2u}, // avl -> Arab
-    {0xB6A00000u, 46u}, // avn -> Latn
-    {0xCEA00000u, 46u}, // avt -> Latn
-    {0xD2A00000u, 46u}, // avu -> Latn
+    {0xB6A00000u, 45u}, // avn -> Latn
+    {0xCEA00000u, 45u}, // avt -> Latn
+    {0xD2A00000u, 45u}, // avu -> Latn
     {0x82C00000u, 19u}, // awa -> Deva
-    {0x86C00000u, 46u}, // awb -> Latn
-    {0xBAC00000u, 46u}, // awo -> Latn
-    {0xDEC00000u, 46u}, // awx -> Latn
-    {0x61790000u, 46u}, // ay -> Latn
-    {0x87000000u, 46u}, // ayb -> Latn
-    {0x617A0000u, 46u}, // az -> Latn
+    {0x86C00000u, 45u}, // awb -> Latn
+    {0xBAC00000u, 45u}, // awo -> Latn
+    {0xDEC00000u, 45u}, // awx -> Latn
+    {0x61790000u, 45u}, // ay -> Latn
+    {0x87000000u, 45u}, // ayb -> Latn
+    {0x617A0000u, 45u}, // az -> Latn
     {0x617A4951u,  2u}, // az-IQ -> Arab
     {0x617A4952u,  2u}, // az-IR -> Arab
     {0x617A5255u, 18u}, // az-RU -> Cyrl
     {0x62610000u, 18u}, // ba -> Cyrl
     {0xAC010000u,  2u}, // bal -> Arab
-    {0xB4010000u, 46u}, // ban -> Latn
+    {0xB4010000u, 45u}, // ban -> Latn
     {0xBC010000u, 19u}, // bap -> Deva
-    {0xC4010000u, 46u}, // bar -> Latn
-    {0xC8010000u, 46u}, // bas -> Latn
-    {0xD4010000u, 46u}, // bav -> Latn
+    {0xC4010000u, 45u}, // bar -> Latn
+    {0xC8010000u, 45u}, // bas -> Latn
+    {0xD4010000u, 45u}, // bav -> Latn
     {0xDC010000u,  6u}, // bax -> Bamu
-    {0x80210000u, 46u}, // bba -> Latn
-    {0x84210000u, 46u}, // bbb -> Latn
-    {0x88210000u, 46u}, // bbc -> Latn
-    {0x8C210000u, 46u}, // bbd -> Latn
-    {0xA4210000u, 46u}, // bbj -> Latn
-    {0xBC210000u, 46u}, // bbp -> Latn
-    {0xC4210000u, 46u}, // bbr -> Latn
-    {0x94410000u, 46u}, // bcf -> Latn
-    {0x9C410000u, 46u}, // bch -> Latn
-    {0xA0410000u, 46u}, // bci -> Latn
-    {0xB0410000u, 46u}, // bcm -> Latn
-    {0xB4410000u, 46u}, // bcn -> Latn
-    {0xB8410000u, 46u}, // bco -> Latn
+    {0x80210000u, 45u}, // bba -> Latn
+    {0x84210000u, 45u}, // bbb -> Latn
+    {0x88210000u, 45u}, // bbc -> Latn
+    {0x8C210000u, 45u}, // bbd -> Latn
+    {0xA4210000u, 45u}, // bbj -> Latn
+    {0xBC210000u, 45u}, // bbp -> Latn
+    {0xC4210000u, 45u}, // bbr -> Latn
+    {0x94410000u, 45u}, // bcf -> Latn
+    {0x9C410000u, 45u}, // bch -> Latn
+    {0xA0410000u, 45u}, // bci -> Latn
+    {0xB0410000u, 45u}, // bcm -> Latn
+    {0xB4410000u, 45u}, // bcn -> Latn
+    {0xB8410000u, 45u}, // bco -> Latn
     {0xC0410000u, 21u}, // bcq -> Ethi
-    {0xD0410000u, 46u}, // bcu -> Latn
-    {0x8C610000u, 46u}, // bdd -> Latn
+    {0xD0410000u, 45u}, // bcu -> Latn
+    {0x8C610000u, 45u}, // bdd -> Latn
     {0x62650000u, 18u}, // be -> Cyrl
-    {0x94810000u, 46u}, // bef -> Latn
-    {0x9C810000u, 46u}, // beh -> Latn
+    {0x94810000u, 45u}, // bef -> Latn
+    {0x9C810000u, 45u}, // beh -> Latn
     {0xA4810000u,  2u}, // bej -> Arab
-    {0xB0810000u, 46u}, // bem -> Latn
-    {0xCC810000u, 46u}, // bet -> Latn
-    {0xD8810000u, 46u}, // bew -> Latn
-    {0xDC810000u, 46u}, // bex -> Latn
-    {0xE4810000u, 46u}, // bez -> Latn
-    {0x8CA10000u, 46u}, // bfd -> Latn
-    {0xC0A10000u, 85u}, // bfq -> Taml
+    {0xB0810000u, 45u}, // bem -> Latn
+    {0xCC810000u, 45u}, // bet -> Latn
+    {0xD8810000u, 45u}, // bew -> Latn
+    {0xDC810000u, 45u}, // bex -> Latn
+    {0xE4810000u, 45u}, // bez -> Latn
+    {0x8CA10000u, 45u}, // bfd -> Latn
+    {0xC0A10000u, 86u}, // bfq -> Taml
     {0xCCA10000u,  2u}, // bft -> Arab
     {0xE0A10000u, 19u}, // bfy -> Deva
     {0x62670000u, 18u}, // bg -> Cyrl
@@ -241,1235 +244,1239 @@
     {0xB4C10000u,  2u}, // bgn -> Arab
     {0xDCC10000u, 26u}, // bgx -> Grek
     {0x84E10000u, 19u}, // bhb -> Deva
-    {0x98E10000u, 46u}, // bhg -> Latn
+    {0x98E10000u, 45u}, // bhg -> Latn
     {0xA0E10000u, 19u}, // bhi -> Deva
-    {0xACE10000u, 46u}, // bhl -> Latn
+    {0xACE10000u, 45u}, // bhl -> Latn
     {0xB8E10000u, 19u}, // bho -> Deva
-    {0xE0E10000u, 46u}, // bhy -> Latn
-    {0x62690000u, 46u}, // bi -> Latn
-    {0x85010000u, 46u}, // bib -> Latn
-    {0x99010000u, 46u}, // big -> Latn
-    {0xA9010000u, 46u}, // bik -> Latn
-    {0xB1010000u, 46u}, // bim -> Latn
-    {0xB5010000u, 46u}, // bin -> Latn
-    {0xB9010000u, 46u}, // bio -> Latn
-    {0xC1010000u, 46u}, // biq -> Latn
-    {0x9D210000u, 46u}, // bjh -> Latn
+    {0xE0E10000u, 45u}, // bhy -> Latn
+    {0x62690000u, 45u}, // bi -> Latn
+    {0x85010000u, 45u}, // bib -> Latn
+    {0x99010000u, 45u}, // big -> Latn
+    {0xA9010000u, 45u}, // bik -> Latn
+    {0xB1010000u, 45u}, // bim -> Latn
+    {0xB5010000u, 45u}, // bin -> Latn
+    {0xB9010000u, 45u}, // bio -> Latn
+    {0xC1010000u, 45u}, // biq -> Latn
+    {0x9D210000u, 45u}, // bjh -> Latn
     {0xA1210000u, 21u}, // bji -> Ethi
     {0xA5210000u, 19u}, // bjj -> Deva
-    {0xB5210000u, 46u}, // bjn -> Latn
-    {0xB9210000u, 46u}, // bjo -> Latn
-    {0xC5210000u, 46u}, // bjr -> Latn
-    {0xCD210000u, 46u}, // bjt -> Latn
-    {0xE5210000u, 46u}, // bjz -> Latn
-    {0x89410000u, 46u}, // bkc -> Latn
-    {0xB1410000u, 46u}, // bkm -> Latn
-    {0xC1410000u, 46u}, // bkq -> Latn
-    {0xD1410000u, 46u}, // bku -> Latn
-    {0xD5410000u, 46u}, // bkv -> Latn
-    {0xCD610000u, 87u}, // blt -> Tavt
-    {0x626D0000u, 46u}, // bm -> Latn
-    {0x9D810000u, 46u}, // bmh -> Latn
-    {0xA9810000u, 46u}, // bmk -> Latn
-    {0xC1810000u, 46u}, // bmq -> Latn
-    {0xD1810000u, 46u}, // bmu -> Latn
+    {0xB5210000u, 45u}, // bjn -> Latn
+    {0xB9210000u, 45u}, // bjo -> Latn
+    {0xC5210000u, 45u}, // bjr -> Latn
+    {0xCD210000u, 45u}, // bjt -> Latn
+    {0xE5210000u, 45u}, // bjz -> Latn
+    {0x89410000u, 45u}, // bkc -> Latn
+    {0xB1410000u, 45u}, // bkm -> Latn
+    {0xC1410000u, 45u}, // bkq -> Latn
+    {0xD1410000u, 45u}, // bku -> Latn
+    {0xD5410000u, 45u}, // bkv -> Latn
+    {0x99610000u, 45u}, // blg -> Latn
+    {0xCD610000u, 88u}, // blt -> Tavt
+    {0x626D0000u, 45u}, // bm -> Latn
+    {0x9D810000u, 45u}, // bmh -> Latn
+    {0xA9810000u, 45u}, // bmk -> Latn
+    {0xC1810000u, 45u}, // bmq -> Latn
+    {0xD1810000u, 45u}, // bmu -> Latn
     {0x626E0000u,  8u}, // bn -> Beng
-    {0x99A10000u, 46u}, // bng -> Latn
-    {0xB1A10000u, 46u}, // bnm -> Latn
-    {0xBDA10000u, 46u}, // bnp -> Latn
-    {0x626F0000u, 92u}, // bo -> Tibt
-    {0xA5C10000u, 46u}, // boj -> Latn
-    {0xB1C10000u, 46u}, // bom -> Latn
-    {0xB5C10000u, 46u}, // bon -> Latn
+    {0x99A10000u, 45u}, // bng -> Latn
+    {0xB1A10000u, 45u}, // bnm -> Latn
+    {0xBDA10000u, 45u}, // bnp -> Latn
+    {0x626F0000u, 93u}, // bo -> Tibt
+    {0xA5C10000u, 45u}, // boj -> Latn
+    {0xB1C10000u, 45u}, // bom -> Latn
+    {0xB5C10000u, 45u}, // bon -> Latn
     {0xE1E10000u,  8u}, // bpy -> Beng
-    {0x8A010000u, 46u}, // bqc -> Latn
+    {0x8A010000u, 45u}, // bqc -> Latn
     {0xA2010000u,  2u}, // bqi -> Arab
-    {0xBE010000u, 46u}, // bqp -> Latn
-    {0xD6010000u, 46u}, // bqv -> Latn
-    {0x62720000u, 46u}, // br -> Latn
+    {0xBE010000u, 45u}, // bqp -> Latn
+    {0xD6010000u, 45u}, // bqv -> Latn
+    {0x62720000u, 45u}, // br -> Latn
     {0x82210000u, 19u}, // bra -> Deva
     {0x9E210000u,  2u}, // brh -> Arab
     {0xDE210000u, 19u}, // brx -> Deva
-    {0xE6210000u, 46u}, // brz -> Latn
-    {0x62730000u, 46u}, // bs -> Latn
-    {0xA6410000u, 46u}, // bsj -> Latn
+    {0xE6210000u, 45u}, // brz -> Latn
+    {0x62730000u, 45u}, // bs -> Latn
+    {0xA6410000u, 45u}, // bsj -> Latn
     {0xC2410000u,  7u}, // bsq -> Bass
-    {0xCA410000u, 46u}, // bss -> Latn
+    {0xCA410000u, 45u}, // bss -> Latn
     {0xCE410000u, 21u}, // bst -> Ethi
-    {0xBA610000u, 46u}, // bto -> Latn
-    {0xCE610000u, 46u}, // btt -> Latn
+    {0xBA610000u, 45u}, // bto -> Latn
+    {0xCE610000u, 45u}, // btt -> Latn
     {0xD6610000u, 19u}, // btv -> Deva
     {0x82810000u, 18u}, // bua -> Cyrl
-    {0x8A810000u, 46u}, // buc -> Latn
-    {0x8E810000u, 46u}, // bud -> Latn
-    {0x9A810000u, 46u}, // bug -> Latn
-    {0xAA810000u, 46u}, // buk -> Latn
-    {0xB2810000u, 46u}, // bum -> Latn
-    {0xBA810000u, 46u}, // buo -> Latn
-    {0xCA810000u, 46u}, // bus -> Latn
-    {0xD2810000u, 46u}, // buu -> Latn
-    {0x86A10000u, 46u}, // bvb -> Latn
-    {0x8EC10000u, 46u}, // bwd -> Latn
-    {0xC6C10000u, 46u}, // bwr -> Latn
-    {0x9EE10000u, 46u}, // bxh -> Latn
-    {0x93010000u, 46u}, // bye -> Latn
+    {0x8A810000u, 45u}, // buc -> Latn
+    {0x8E810000u, 45u}, // bud -> Latn
+    {0x9A810000u, 45u}, // bug -> Latn
+    {0xAA810000u, 45u}, // buk -> Latn
+    {0xB2810000u, 45u}, // bum -> Latn
+    {0xBA810000u, 45u}, // buo -> Latn
+    {0xCA810000u, 45u}, // bus -> Latn
+    {0xD2810000u, 45u}, // buu -> Latn
+    {0x86A10000u, 45u}, // bvb -> Latn
+    {0x8EC10000u, 45u}, // bwd -> Latn
+    {0xC6C10000u, 45u}, // bwr -> Latn
+    {0x9EE10000u, 45u}, // bxh -> Latn
+    {0x93010000u, 45u}, // bye -> Latn
     {0xB7010000u, 21u}, // byn -> Ethi
-    {0xC7010000u, 46u}, // byr -> Latn
-    {0xCB010000u, 46u}, // bys -> Latn
-    {0xD7010000u, 46u}, // byv -> Latn
-    {0xDF010000u, 46u}, // byx -> Latn
-    {0x83210000u, 46u}, // bza -> Latn
-    {0x93210000u, 46u}, // bze -> Latn
-    {0x97210000u, 46u}, // bzf -> Latn
-    {0x9F210000u, 46u}, // bzh -> Latn
-    {0xDB210000u, 46u}, // bzw -> Latn
-    {0x63610000u, 46u}, // ca -> Latn
-    {0x8C020000u, 46u}, // cad -> Latn
-    {0xB4020000u, 46u}, // can -> Latn
-    {0xA4220000u, 46u}, // cbj -> Latn
-    {0x9C420000u, 46u}, // cch -> Latn
+    {0xC7010000u, 45u}, // byr -> Latn
+    {0xCB010000u, 45u}, // bys -> Latn
+    {0xD7010000u, 45u}, // byv -> Latn
+    {0xDF010000u, 45u}, // byx -> Latn
+    {0x83210000u, 45u}, // bza -> Latn
+    {0x93210000u, 45u}, // bze -> Latn
+    {0x97210000u, 45u}, // bzf -> Latn
+    {0x9F210000u, 45u}, // bzh -> Latn
+    {0xDB210000u, 45u}, // bzw -> Latn
+    {0x63610000u, 45u}, // ca -> Latn
+    {0x8C020000u, 45u}, // cad -> Latn
+    {0xB4020000u, 45u}, // can -> Latn
+    {0xA4220000u, 45u}, // cbj -> Latn
+    {0x9C420000u, 45u}, // cch -> Latn
     {0xBC420000u, 10u}, // ccp -> Cakm
     {0x63650000u, 18u}, // ce -> Cyrl
-    {0x84820000u, 46u}, // ceb -> Latn
-    {0x80A20000u, 46u}, // cfa -> Latn
-    {0x98C20000u, 46u}, // cgg -> Latn
-    {0x63680000u, 46u}, // ch -> Latn
-    {0xA8E20000u, 46u}, // chk -> Latn
+    {0x84820000u, 45u}, // ceb -> Latn
+    {0x80A20000u, 45u}, // cfa -> Latn
+    {0x98C20000u, 45u}, // cgg -> Latn
+    {0x63680000u, 45u}, // ch -> Latn
+    {0xA8E20000u, 45u}, // chk -> Latn
     {0xB0E20000u, 18u}, // chm -> Cyrl
-    {0xB8E20000u, 46u}, // cho -> Latn
-    {0xBCE20000u, 46u}, // chp -> Latn
+    {0xB8E20000u, 45u}, // cho -> Latn
+    {0xBCE20000u, 45u}, // chp -> Latn
     {0xC4E20000u, 14u}, // chr -> Cher
-    {0x89020000u, 46u}, // cic -> Latn
+    {0x89020000u, 45u}, // cic -> Latn
     {0x81220000u,  2u}, // cja -> Arab
     {0xB1220000u, 13u}, // cjm -> Cham
-    {0xD5220000u, 46u}, // cjv -> Latn
+    {0xD5220000u, 45u}, // cjv -> Latn
     {0x85420000u,  2u}, // ckb -> Arab
-    {0xAD420000u, 46u}, // ckl -> Latn
-    {0xB9420000u, 46u}, // cko -> Latn
-    {0xE1420000u, 46u}, // cky -> Latn
-    {0x81620000u, 46u}, // cla -> Latn
-    {0x91820000u, 46u}, // cme -> Latn
-    {0x99820000u, 81u}, // cmg -> Soyo
-    {0x636F0000u, 46u}, // co -> Latn
+    {0xAD420000u, 45u}, // ckl -> Latn
+    {0xB9420000u, 45u}, // cko -> Latn
+    {0xE1420000u, 45u}, // cky -> Latn
+    {0x81620000u, 45u}, // cla -> Latn
+    {0x91820000u, 45u}, // cme -> Latn
+    {0x99820000u, 82u}, // cmg -> Soyo
+    {0x636F0000u, 45u}, // co -> Latn
     {0xBDC20000u, 16u}, // cop -> Copt
-    {0xC9E20000u, 46u}, // cps -> Latn
+    {0xC9E20000u, 45u}, // cps -> Latn
     {0x63720000u, 11u}, // cr -> Cans
     {0x9E220000u, 18u}, // crh -> Cyrl
     {0xA6220000u, 11u}, // crj -> Cans
     {0xAA220000u, 11u}, // crk -> Cans
     {0xAE220000u, 11u}, // crl -> Cans
     {0xB2220000u, 11u}, // crm -> Cans
-    {0xCA220000u, 46u}, // crs -> Latn
-    {0x63730000u, 46u}, // cs -> Latn
-    {0x86420000u, 46u}, // csb -> Latn
+    {0xCA220000u, 45u}, // crs -> Latn
+    {0x63730000u, 45u}, // cs -> Latn
+    {0x86420000u, 45u}, // csb -> Latn
     {0xDA420000u, 11u}, // csw -> Cans
     {0x8E620000u, 68u}, // ctd -> Pauc
     {0x63750000u, 18u}, // cu -> Cyrl
     {0x63760000u, 18u}, // cv -> Cyrl
-    {0x63790000u, 46u}, // cy -> Latn
-    {0x64610000u, 46u}, // da -> Latn
-    {0x8C030000u, 46u}, // dad -> Latn
-    {0x94030000u, 46u}, // daf -> Latn
-    {0x98030000u, 46u}, // dag -> Latn
-    {0x9C030000u, 46u}, // dah -> Latn
-    {0xA8030000u, 46u}, // dak -> Latn
+    {0x63790000u, 45u}, // cy -> Latn
+    {0x64610000u, 45u}, // da -> Latn
+    {0x8C030000u, 45u}, // dad -> Latn
+    {0x94030000u, 45u}, // daf -> Latn
+    {0x98030000u, 45u}, // dag -> Latn
+    {0x9C030000u, 45u}, // dah -> Latn
+    {0xA8030000u, 45u}, // dak -> Latn
     {0xC4030000u, 18u}, // dar -> Cyrl
-    {0xD4030000u, 46u}, // dav -> Latn
-    {0x8C230000u, 46u}, // dbd -> Latn
-    {0xC0230000u, 46u}, // dbq -> Latn
+    {0xD4030000u, 45u}, // dav -> Latn
+    {0x8C230000u, 45u}, // dbd -> Latn
+    {0xC0230000u, 45u}, // dbq -> Latn
     {0x88430000u,  2u}, // dcc -> Arab
-    {0xB4630000u, 46u}, // ddn -> Latn
-    {0x64650000u, 46u}, // de -> Latn
-    {0x8C830000u, 46u}, // ded -> Latn
-    {0xB4830000u, 46u}, // den -> Latn
-    {0x80C30000u, 46u}, // dga -> Latn
-    {0x9CC30000u, 46u}, // dgh -> Latn
-    {0xA0C30000u, 46u}, // dgi -> Latn
+    {0xB4630000u, 45u}, // ddn -> Latn
+    {0x64650000u, 45u}, // de -> Latn
+    {0x8C830000u, 45u}, // ded -> Latn
+    {0xB4830000u, 45u}, // den -> Latn
+    {0x80C30000u, 45u}, // dga -> Latn
+    {0x9CC30000u, 45u}, // dgh -> Latn
+    {0xA0C30000u, 45u}, // dgi -> Latn
     {0xACC30000u,  2u}, // dgl -> Arab
-    {0xC4C30000u, 46u}, // dgr -> Latn
-    {0xE4C30000u, 46u}, // dgz -> Latn
-    {0x81030000u, 46u}, // dia -> Latn
-    {0x91230000u, 46u}, // dje -> Latn
-    {0x95830000u, 54u}, // dmf -> Medf
-    {0xA5A30000u, 46u}, // dnj -> Latn
-    {0x85C30000u, 46u}, // dob -> Latn
+    {0xC4C30000u, 45u}, // dgr -> Latn
+    {0xE4C30000u, 45u}, // dgz -> Latn
+    {0x81030000u, 45u}, // dia -> Latn
+    {0x91230000u, 45u}, // dje -> Latn
+    {0x95830000u, 53u}, // dmf -> Medf
+    {0xA5A30000u, 45u}, // dnj -> Latn
+    {0x85C30000u, 45u}, // dob -> Latn
     {0xA1C30000u, 19u}, // doi -> Deva
-    {0xBDC30000u, 46u}, // dop -> Latn
-    {0xD9C30000u, 46u}, // dow -> Latn
-    {0x9E230000u, 57u}, // drh -> Mong
-    {0xA2230000u, 46u}, // dri -> Latn
+    {0xBDC30000u, 45u}, // dop -> Latn
+    {0xD9C30000u, 45u}, // dow -> Latn
+    {0x9E230000u, 56u}, // drh -> Mong
+    {0xA2230000u, 45u}, // dri -> Latn
     {0xCA230000u, 21u}, // drs -> Ethi
-    {0x86430000u, 46u}, // dsb -> Latn
-    {0xB2630000u, 46u}, // dtm -> Latn
-    {0xBE630000u, 46u}, // dtp -> Latn
-    {0xCA630000u, 46u}, // dts -> Latn
+    {0x86430000u, 45u}, // dsb -> Latn
+    {0xB2630000u, 45u}, // dtm -> Latn
+    {0xBE630000u, 45u}, // dtp -> Latn
+    {0xCA630000u, 45u}, // dts -> Latn
     {0xE2630000u, 19u}, // dty -> Deva
-    {0x82830000u, 46u}, // dua -> Latn
-    {0x8A830000u, 46u}, // duc -> Latn
-    {0x8E830000u, 46u}, // dud -> Latn
-    {0x9A830000u, 46u}, // dug -> Latn
-    {0x64760000u, 90u}, // dv -> Thaa
-    {0x82A30000u, 46u}, // dva -> Latn
-    {0xDAC30000u, 46u}, // dww -> Latn
-    {0xBB030000u, 46u}, // dyo -> Latn
-    {0xD3030000u, 46u}, // dyu -> Latn
-    {0x647A0000u, 92u}, // dz -> Tibt
-    {0x9B230000u, 46u}, // dzg -> Latn
-    {0xD0240000u, 46u}, // ebu -> Latn
-    {0x65650000u, 46u}, // ee -> Latn
-    {0xA0A40000u, 46u}, // efi -> Latn
-    {0xACC40000u, 46u}, // egl -> Latn
+    {0x82830000u, 45u}, // dua -> Latn
+    {0x8A830000u, 45u}, // duc -> Latn
+    {0x8E830000u, 45u}, // dud -> Latn
+    {0x9A830000u, 45u}, // dug -> Latn
+    {0x64760000u, 91u}, // dv -> Thaa
+    {0x82A30000u, 45u}, // dva -> Latn
+    {0xDAC30000u, 45u}, // dww -> Latn
+    {0xBB030000u, 45u}, // dyo -> Latn
+    {0xD3030000u, 45u}, // dyu -> Latn
+    {0x647A0000u, 93u}, // dz -> Tibt
+    {0x9B230000u, 45u}, // dzg -> Latn
+    {0xD0240000u, 45u}, // ebu -> Latn
+    {0x65650000u, 45u}, // ee -> Latn
+    {0xA0A40000u, 45u}, // efi -> Latn
+    {0xACC40000u, 45u}, // egl -> Latn
     {0xE0C40000u, 20u}, // egy -> Egyp
-    {0x81440000u, 46u}, // eka -> Latn
-    {0xE1440000u, 37u}, // eky -> Kali
+    {0x81440000u, 45u}, // eka -> Latn
+    {0xE1440000u, 36u}, // eky -> Kali
     {0x656C0000u, 26u}, // el -> Grek
-    {0x81840000u, 46u}, // ema -> Latn
-    {0xA1840000u, 46u}, // emi -> Latn
-    {0x656E0000u, 46u}, // en -> Latn
-    {0x656E5841u, 99u}, // en-XA -> ~~~A
-    {0xB5A40000u, 46u}, // enn -> Latn
-    {0xC1A40000u, 46u}, // enq -> Latn
-    {0x656F0000u, 46u}, // eo -> Latn
-    {0xA2240000u, 46u}, // eri -> Latn
-    {0x65730000u, 46u}, // es -> Latn
+    {0x81840000u, 45u}, // ema -> Latn
+    {0xA1840000u, 45u}, // emi -> Latn
+    {0x656E0000u, 45u}, // en -> Latn
+    {0x656E5841u, 102u}, // en-XA -> ~~~A
+    {0xB5A40000u, 45u}, // enn -> Latn
+    {0xC1A40000u, 45u}, // enq -> Latn
+    {0x656F0000u, 45u}, // eo -> Latn
+    {0xA2240000u, 45u}, // eri -> Latn
+    {0x65730000u, 45u}, // es -> Latn
     {0x9A440000u, 24u}, // esg -> Gonm
-    {0xD2440000u, 46u}, // esu -> Latn
-    {0x65740000u, 46u}, // et -> Latn
-    {0xC6640000u, 46u}, // etr -> Latn
-    {0xCE640000u, 35u}, // ett -> Ital
-    {0xD2640000u, 46u}, // etu -> Latn
-    {0xDE640000u, 46u}, // etx -> Latn
-    {0x65750000u, 46u}, // eu -> Latn
-    {0xBAC40000u, 46u}, // ewo -> Latn
-    {0xCEE40000u, 46u}, // ext -> Latn
-    {0x83240000u, 46u}, // eza -> Latn
+    {0xD2440000u, 45u}, // esu -> Latn
+    {0x65740000u, 45u}, // et -> Latn
+    {0xC6640000u, 45u}, // etr -> Latn
+    {0xCE640000u, 34u}, // ett -> Ital
+    {0xD2640000u, 45u}, // etu -> Latn
+    {0xDE640000u, 45u}, // etx -> Latn
+    {0x65750000u, 45u}, // eu -> Latn
+    {0xBAC40000u, 45u}, // ewo -> Latn
+    {0xCEE40000u, 45u}, // ext -> Latn
+    {0x83240000u, 45u}, // eza -> Latn
     {0x66610000u,  2u}, // fa -> Arab
-    {0x80050000u, 46u}, // faa -> Latn
-    {0x84050000u, 46u}, // fab -> Latn
-    {0x98050000u, 46u}, // fag -> Latn
-    {0xA0050000u, 46u}, // fai -> Latn
-    {0xB4050000u, 46u}, // fan -> Latn
-    {0x66660000u, 46u}, // ff -> Latn
-    {0xA0A50000u, 46u}, // ffi -> Latn
-    {0xB0A50000u, 46u}, // ffm -> Latn
-    {0x66690000u, 46u}, // fi -> Latn
+    {0x80050000u, 45u}, // faa -> Latn
+    {0x84050000u, 45u}, // fab -> Latn
+    {0x98050000u, 45u}, // fag -> Latn
+    {0xA0050000u, 45u}, // fai -> Latn
+    {0xB4050000u, 45u}, // fan -> Latn
+    {0x66660000u, 45u}, // ff -> Latn
+    {0xA0A50000u, 45u}, // ffi -> Latn
+    {0xB0A50000u, 45u}, // ffm -> Latn
+    {0x66690000u, 45u}, // fi -> Latn
     {0x81050000u,  2u}, // fia -> Arab
-    {0xAD050000u, 46u}, // fil -> Latn
-    {0xCD050000u, 46u}, // fit -> Latn
-    {0x666A0000u, 46u}, // fj -> Latn
-    {0xC5650000u, 46u}, // flr -> Latn
-    {0xBD850000u, 46u}, // fmp -> Latn
-    {0x666F0000u, 46u}, // fo -> Latn
-    {0x8DC50000u, 46u}, // fod -> Latn
-    {0xB5C50000u, 46u}, // fon -> Latn
-    {0xC5C50000u, 46u}, // for -> Latn
-    {0x91E50000u, 46u}, // fpe -> Latn
-    {0xCA050000u, 46u}, // fqs -> Latn
-    {0x66720000u, 46u}, // fr -> Latn
-    {0x8A250000u, 46u}, // frc -> Latn
-    {0xBE250000u, 46u}, // frp -> Latn
-    {0xC6250000u, 46u}, // frr -> Latn
-    {0xCA250000u, 46u}, // frs -> Latn
+    {0xAD050000u, 45u}, // fil -> Latn
+    {0xCD050000u, 45u}, // fit -> Latn
+    {0x666A0000u, 45u}, // fj -> Latn
+    {0xC5650000u, 45u}, // flr -> Latn
+    {0xBD850000u, 45u}, // fmp -> Latn
+    {0x666F0000u, 45u}, // fo -> Latn
+    {0x8DC50000u, 45u}, // fod -> Latn
+    {0xB5C50000u, 45u}, // fon -> Latn
+    {0xC5C50000u, 45u}, // for -> Latn
+    {0x91E50000u, 45u}, // fpe -> Latn
+    {0xCA050000u, 45u}, // fqs -> Latn
+    {0x66720000u, 45u}, // fr -> Latn
+    {0x8A250000u, 45u}, // frc -> Latn
+    {0xBE250000u, 45u}, // frp -> Latn
+    {0xC6250000u, 45u}, // frr -> Latn
+    {0xCA250000u, 45u}, // frs -> Latn
     {0x86850000u,  2u}, // fub -> Arab
-    {0x8E850000u, 46u}, // fud -> Latn
-    {0x92850000u, 46u}, // fue -> Latn
-    {0x96850000u, 46u}, // fuf -> Latn
-    {0x9E850000u, 46u}, // fuh -> Latn
-    {0xC2850000u, 46u}, // fuq -> Latn
-    {0xC6850000u, 46u}, // fur -> Latn
-    {0xD6850000u, 46u}, // fuv -> Latn
-    {0xE2850000u, 46u}, // fuy -> Latn
-    {0xC6A50000u, 46u}, // fvr -> Latn
-    {0x66790000u, 46u}, // fy -> Latn
-    {0x67610000u, 46u}, // ga -> Latn
-    {0x80060000u, 46u}, // gaa -> Latn
-    {0x94060000u, 46u}, // gaf -> Latn
-    {0x98060000u, 46u}, // gag -> Latn
-    {0x9C060000u, 46u}, // gah -> Latn
-    {0xA4060000u, 46u}, // gaj -> Latn
-    {0xB0060000u, 46u}, // gam -> Latn
+    {0x8E850000u, 45u}, // fud -> Latn
+    {0x92850000u, 45u}, // fue -> Latn
+    {0x96850000u, 45u}, // fuf -> Latn
+    {0x9E850000u, 45u}, // fuh -> Latn
+    {0xC2850000u, 45u}, // fuq -> Latn
+    {0xC6850000u, 45u}, // fur -> Latn
+    {0xD6850000u, 45u}, // fuv -> Latn
+    {0xE2850000u, 45u}, // fuy -> Latn
+    {0xC6A50000u, 45u}, // fvr -> Latn
+    {0x66790000u, 45u}, // fy -> Latn
+    {0x67610000u, 45u}, // ga -> Latn
+    {0x80060000u, 45u}, // gaa -> Latn
+    {0x94060000u, 45u}, // gaf -> Latn
+    {0x98060000u, 45u}, // gag -> Latn
+    {0x9C060000u, 45u}, // gah -> Latn
+    {0xA4060000u, 45u}, // gaj -> Latn
+    {0xB0060000u, 45u}, // gam -> Latn
     {0xB4060000u, 29u}, // gan -> Hans
-    {0xD8060000u, 46u}, // gaw -> Latn
-    {0xE0060000u, 46u}, // gay -> Latn
-    {0x80260000u, 46u}, // gba -> Latn
-    {0x94260000u, 46u}, // gbf -> Latn
+    {0xD8060000u, 45u}, // gaw -> Latn
+    {0xE0060000u, 45u}, // gay -> Latn
+    {0x80260000u, 45u}, // gba -> Latn
+    {0x94260000u, 45u}, // gbf -> Latn
     {0xB0260000u, 19u}, // gbm -> Deva
-    {0xE0260000u, 46u}, // gby -> Latn
+    {0xE0260000u, 45u}, // gby -> Latn
     {0xE4260000u,  2u}, // gbz -> Arab
-    {0xC4460000u, 46u}, // gcr -> Latn
-    {0x67640000u, 46u}, // gd -> Latn
-    {0x90660000u, 46u}, // gde -> Latn
-    {0xB4660000u, 46u}, // gdn -> Latn
-    {0xC4660000u, 46u}, // gdr -> Latn
-    {0x84860000u, 46u}, // geb -> Latn
-    {0xA4860000u, 46u}, // gej -> Latn
-    {0xAC860000u, 46u}, // gel -> Latn
+    {0xC4460000u, 45u}, // gcr -> Latn
+    {0x67640000u, 45u}, // gd -> Latn
+    {0x90660000u, 45u}, // gde -> Latn
+    {0xB4660000u, 45u}, // gdn -> Latn
+    {0xC4660000u, 45u}, // gdr -> Latn
+    {0x84860000u, 45u}, // geb -> Latn
+    {0xA4860000u, 45u}, // gej -> Latn
+    {0xAC860000u, 45u}, // gel -> Latn
     {0xE4860000u, 21u}, // gez -> Ethi
-    {0xA8A60000u, 46u}, // gfk -> Latn
+    {0xA8A60000u, 45u}, // gfk -> Latn
     {0xB4C60000u, 19u}, // ggn -> Deva
-    {0xC8E60000u, 46u}, // ghs -> Latn
-    {0xAD060000u, 46u}, // gil -> Latn
-    {0xB1060000u, 46u}, // gim -> Latn
+    {0xC8E60000u, 45u}, // ghs -> Latn
+    {0xAD060000u, 45u}, // gil -> Latn
+    {0xB1060000u, 45u}, // gim -> Latn
     {0xA9260000u,  2u}, // gjk -> Arab
-    {0xB5260000u, 46u}, // gjn -> Latn
+    {0xB5260000u, 45u}, // gjn -> Latn
     {0xD1260000u,  2u}, // gju -> Arab
-    {0xB5460000u, 46u}, // gkn -> Latn
-    {0xBD460000u, 46u}, // gkp -> Latn
-    {0x676C0000u, 46u}, // gl -> Latn
+    {0xB5460000u, 45u}, // gkn -> Latn
+    {0xBD460000u, 45u}, // gkp -> Latn
+    {0x676C0000u, 45u}, // gl -> Latn
     {0xA9660000u,  2u}, // glk -> Arab
-    {0xB1860000u, 46u}, // gmm -> Latn
+    {0xB1860000u, 45u}, // gmm -> Latn
     {0xD5860000u, 21u}, // gmv -> Ethi
-    {0x676E0000u, 46u}, // gn -> Latn
-    {0x8DA60000u, 46u}, // gnd -> Latn
-    {0x99A60000u, 46u}, // gng -> Latn
-    {0x8DC60000u, 46u}, // god -> Latn
+    {0x676E0000u, 45u}, // gn -> Latn
+    {0x8DA60000u, 45u}, // gnd -> Latn
+    {0x99A60000u, 45u}, // gng -> Latn
+    {0x8DC60000u, 45u}, // god -> Latn
     {0x95C60000u, 21u}, // gof -> Ethi
-    {0xA1C60000u, 46u}, // goi -> Latn
+    {0xA1C60000u, 45u}, // goi -> Latn
     {0xB1C60000u, 19u}, // gom -> Deva
-    {0xB5C60000u, 88u}, // gon -> Telu
-    {0xC5C60000u, 46u}, // gor -> Latn
-    {0xC9C60000u, 46u}, // gos -> Latn
+    {0xB5C60000u, 89u}, // gon -> Telu
+    {0xC5C60000u, 45u}, // gor -> Latn
+    {0xC9C60000u, 45u}, // gos -> Latn
     {0xCDC60000u, 25u}, // got -> Goth
-    {0x86260000u, 46u}, // grb -> Latn
+    {0x86260000u, 45u}, // grb -> Latn
     {0x8A260000u, 17u}, // grc -> Cprt
     {0xCE260000u,  8u}, // grt -> Beng
-    {0xDA260000u, 46u}, // grw -> Latn
-    {0xDA460000u, 46u}, // gsw -> Latn
+    {0xDA260000u, 45u}, // grw -> Latn
+    {0xDA460000u, 45u}, // gsw -> Latn
     {0x67750000u, 27u}, // gu -> Gujr
-    {0x86860000u, 46u}, // gub -> Latn
-    {0x8A860000u, 46u}, // guc -> Latn
-    {0x8E860000u, 46u}, // gud -> Latn
-    {0xC6860000u, 46u}, // gur -> Latn
-    {0xDA860000u, 46u}, // guw -> Latn
-    {0xDE860000u, 46u}, // gux -> Latn
-    {0xE6860000u, 46u}, // guz -> Latn
-    {0x67760000u, 46u}, // gv -> Latn
-    {0x96A60000u, 46u}, // gvf -> Latn
+    {0x86860000u, 45u}, // gub -> Latn
+    {0x8A860000u, 45u}, // guc -> Latn
+    {0x8E860000u, 45u}, // gud -> Latn
+    {0xC6860000u, 45u}, // gur -> Latn
+    {0xDA860000u, 45u}, // guw -> Latn
+    {0xDE860000u, 45u}, // gux -> Latn
+    {0xE6860000u, 45u}, // guz -> Latn
+    {0x67760000u, 45u}, // gv -> Latn
+    {0x96A60000u, 45u}, // gvf -> Latn
     {0xC6A60000u, 19u}, // gvr -> Deva
-    {0xCAA60000u, 46u}, // gvs -> Latn
+    {0xCAA60000u, 45u}, // gvs -> Latn
     {0x8AC60000u,  2u}, // gwc -> Arab
-    {0xA2C60000u, 46u}, // gwi -> Latn
+    {0xA2C60000u, 45u}, // gwi -> Latn
     {0xCEC60000u,  2u}, // gwt -> Arab
-    {0xA3060000u, 46u}, // gyi -> Latn
-    {0x68610000u, 46u}, // ha -> Latn
+    {0xA3060000u, 45u}, // gyi -> Latn
+    {0x68610000u, 45u}, // ha -> Latn
     {0x6861434Du,  2u}, // ha-CM -> Arab
     {0x68615344u,  2u}, // ha-SD -> Arab
-    {0x98070000u, 46u}, // hag -> Latn
+    {0x98070000u, 45u}, // hag -> Latn
     {0xA8070000u, 29u}, // hak -> Hans
-    {0xB0070000u, 46u}, // ham -> Latn
-    {0xD8070000u, 46u}, // haw -> Latn
+    {0xB0070000u, 45u}, // ham -> Latn
+    {0xD8070000u, 45u}, // haw -> Latn
     {0xE4070000u,  2u}, // haz -> Arab
-    {0x84270000u, 46u}, // hbb -> Latn
+    {0x84270000u, 45u}, // hbb -> Latn
     {0xE0670000u, 21u}, // hdy -> Ethi
     {0x68650000u, 31u}, // he -> Hebr
-    {0xE0E70000u, 46u}, // hhy -> Latn
+    {0xE0E70000u, 45u}, // hhy -> Latn
     {0x68690000u, 19u}, // hi -> Deva
-    {0x81070000u, 46u}, // hia -> Latn
-    {0x95070000u, 46u}, // hif -> Latn
-    {0x99070000u, 46u}, // hig -> Latn
-    {0x9D070000u, 46u}, // hih -> Latn
-    {0xAD070000u, 46u}, // hil -> Latn
-    {0x81670000u, 46u}, // hla -> Latn
+    {0x81070000u, 45u}, // hia -> Latn
+    {0x95070000u, 45u}, // hif -> Latn
+    {0x99070000u, 45u}, // hig -> Latn
+    {0x9D070000u, 45u}, // hih -> Latn
+    {0xAD070000u, 45u}, // hil -> Latn
+    {0x81670000u, 45u}, // hla -> Latn
     {0xD1670000u, 32u}, // hlu -> Hluw
     {0x8D870000u, 71u}, // hmd -> Plrd
-    {0xCD870000u, 46u}, // hmt -> Latn
+    {0xCD870000u, 45u}, // hmt -> Latn
     {0x8DA70000u,  2u}, // hnd -> Arab
     {0x91A70000u, 19u}, // hne -> Deva
-    {0xA5A70000u, 33u}, // hnj -> Hmng
-    {0xB5A70000u, 46u}, // hnn -> Latn
+    {0xA5A70000u, 33u}, // hnj -> Hmnp
+    {0xB5A70000u, 45u}, // hnn -> Latn
     {0xB9A70000u,  2u}, // hno -> Arab
-    {0x686F0000u, 46u}, // ho -> Latn
+    {0x686F0000u, 45u}, // ho -> Latn
     {0x89C70000u, 19u}, // hoc -> Deva
     {0xA5C70000u, 19u}, // hoj -> Deva
-    {0xCDC70000u, 46u}, // hot -> Latn
-    {0x68720000u, 46u}, // hr -> Latn
-    {0x86470000u, 46u}, // hsb -> Latn
+    {0xCDC70000u, 45u}, // hot -> Latn
+    {0x68720000u, 45u}, // hr -> Latn
+    {0x86470000u, 45u}, // hsb -> Latn
     {0xB6470000u, 29u}, // hsn -> Hans
-    {0x68740000u, 46u}, // ht -> Latn
-    {0x68750000u, 46u}, // hu -> Latn
-    {0xA2870000u, 46u}, // hui -> Latn
+    {0x68740000u, 45u}, // ht -> Latn
+    {0x68750000u, 45u}, // hu -> Latn
+    {0xA2870000u, 45u}, // hui -> Latn
     {0x68790000u,  4u}, // hy -> Armn
-    {0x687A0000u, 46u}, // hz -> Latn
-    {0x69610000u, 46u}, // ia -> Latn
-    {0xB4080000u, 46u}, // ian -> Latn
-    {0xC4080000u, 46u}, // iar -> Latn
-    {0x80280000u, 46u}, // iba -> Latn
-    {0x84280000u, 46u}, // ibb -> Latn
-    {0xE0280000u, 46u}, // iby -> Latn
-    {0x80480000u, 46u}, // ica -> Latn
-    {0x9C480000u, 46u}, // ich -> Latn
-    {0x69640000u, 46u}, // id -> Latn
-    {0x8C680000u, 46u}, // idd -> Latn
-    {0xA0680000u, 46u}, // idi -> Latn
-    {0xD0680000u, 46u}, // idu -> Latn
-    {0x90A80000u, 46u}, // ife -> Latn
-    {0x69670000u, 46u}, // ig -> Latn
-    {0x84C80000u, 46u}, // igb -> Latn
-    {0x90C80000u, 46u}, // ige -> Latn
-    {0x69690000u, 98u}, // ii -> Yiii
-    {0xA5280000u, 46u}, // ijj -> Latn
-    {0x696B0000u, 46u}, // ik -> Latn
-    {0xA9480000u, 46u}, // ikk -> Latn
-    {0xCD480000u, 46u}, // ikt -> Latn
-    {0xD9480000u, 46u}, // ikw -> Latn
-    {0xDD480000u, 46u}, // ikx -> Latn
-    {0xB9680000u, 46u}, // ilo -> Latn
-    {0xB9880000u, 46u}, // imo -> Latn
-    {0x696E0000u, 46u}, // in -> Latn
+    {0x687A0000u, 45u}, // hz -> Latn
+    {0x69610000u, 45u}, // ia -> Latn
+    {0xB4080000u, 45u}, // ian -> Latn
+    {0xC4080000u, 45u}, // iar -> Latn
+    {0x80280000u, 45u}, // iba -> Latn
+    {0x84280000u, 45u}, // ibb -> Latn
+    {0xE0280000u, 45u}, // iby -> Latn
+    {0x80480000u, 45u}, // ica -> Latn
+    {0x9C480000u, 45u}, // ich -> Latn
+    {0x69640000u, 45u}, // id -> Latn
+    {0x8C680000u, 45u}, // idd -> Latn
+    {0xA0680000u, 45u}, // idi -> Latn
+    {0xD0680000u, 45u}, // idu -> Latn
+    {0x90A80000u, 45u}, // ife -> Latn
+    {0x69670000u, 45u}, // ig -> Latn
+    {0x84C80000u, 45u}, // igb -> Latn
+    {0x90C80000u, 45u}, // ige -> Latn
+    {0x69690000u, 101u}, // ii -> Yiii
+    {0xA5280000u, 45u}, // ijj -> Latn
+    {0x696B0000u, 45u}, // ik -> Latn
+    {0xA9480000u, 45u}, // ikk -> Latn
+    {0xCD480000u, 45u}, // ikt -> Latn
+    {0xD9480000u, 45u}, // ikw -> Latn
+    {0xDD480000u, 45u}, // ikx -> Latn
+    {0xB9680000u, 45u}, // ilo -> Latn
+    {0xB9880000u, 45u}, // imo -> Latn
+    {0x696E0000u, 45u}, // in -> Latn
     {0x9DA80000u, 18u}, // inh -> Cyrl
-    {0x696F0000u, 46u}, // io -> Latn
-    {0xD1C80000u, 46u}, // iou -> Latn
-    {0xA2280000u, 46u}, // iri -> Latn
-    {0x69730000u, 46u}, // is -> Latn
-    {0x69740000u, 46u}, // it -> Latn
+    {0x696F0000u, 45u}, // io -> Latn
+    {0xD1C80000u, 45u}, // iou -> Latn
+    {0xA2280000u, 45u}, // iri -> Latn
+    {0x69730000u, 45u}, // is -> Latn
+    {0x69740000u, 45u}, // it -> Latn
     {0x69750000u, 11u}, // iu -> Cans
     {0x69770000u, 31u}, // iw -> Hebr
-    {0xB2C80000u, 46u}, // iwm -> Latn
-    {0xCAC80000u, 46u}, // iws -> Latn
-    {0x9F280000u, 46u}, // izh -> Latn
-    {0xA3280000u, 46u}, // izi -> Latn
-    {0x6A610000u, 36u}, // ja -> Jpan
-    {0x84090000u, 46u}, // jab -> Latn
-    {0xB0090000u, 46u}, // jam -> Latn
-    {0xC4090000u, 46u}, // jar -> Latn
-    {0xB8290000u, 46u}, // jbo -> Latn
-    {0xD0290000u, 46u}, // jbu -> Latn
-    {0xB4890000u, 46u}, // jen -> Latn
-    {0xA8C90000u, 46u}, // jgk -> Latn
-    {0xB8C90000u, 46u}, // jgo -> Latn
+    {0xB2C80000u, 45u}, // iwm -> Latn
+    {0xCAC80000u, 45u}, // iws -> Latn
+    {0x9F280000u, 45u}, // izh -> Latn
+    {0xA3280000u, 45u}, // izi -> Latn
+    {0x6A610000u, 35u}, // ja -> Jpan
+    {0x84090000u, 45u}, // jab -> Latn
+    {0xB0090000u, 45u}, // jam -> Latn
+    {0xC4090000u, 45u}, // jar -> Latn
+    {0xB8290000u, 45u}, // jbo -> Latn
+    {0xD0290000u, 45u}, // jbu -> Latn
+    {0xB4890000u, 45u}, // jen -> Latn
+    {0xA8C90000u, 45u}, // jgk -> Latn
+    {0xB8C90000u, 45u}, // jgo -> Latn
     {0x6A690000u, 31u}, // ji -> Hebr
-    {0x85090000u, 46u}, // jib -> Latn
-    {0x89890000u, 46u}, // jmc -> Latn
+    {0x85090000u, 45u}, // jib -> Latn
+    {0x89890000u, 45u}, // jmc -> Latn
     {0xAD890000u, 19u}, // jml -> Deva
-    {0x82290000u, 46u}, // jra -> Latn
-    {0xCE890000u, 46u}, // jut -> Latn
-    {0x6A760000u, 46u}, // jv -> Latn
-    {0x6A770000u, 46u}, // jw -> Latn
+    {0x82290000u, 45u}, // jra -> Latn
+    {0xCE890000u, 45u}, // jut -> Latn
+    {0x6A760000u, 45u}, // jv -> Latn
+    {0x6A770000u, 45u}, // jw -> Latn
     {0x6B610000u, 22u}, // ka -> Geor
     {0x800A0000u, 18u}, // kaa -> Cyrl
-    {0x840A0000u, 46u}, // kab -> Latn
-    {0x880A0000u, 46u}, // kac -> Latn
-    {0x8C0A0000u, 46u}, // kad -> Latn
-    {0xA00A0000u, 46u}, // kai -> Latn
-    {0xA40A0000u, 46u}, // kaj -> Latn
-    {0xB00A0000u, 46u}, // kam -> Latn
-    {0xB80A0000u, 46u}, // kao -> Latn
+    {0x840A0000u, 45u}, // kab -> Latn
+    {0x880A0000u, 45u}, // kac -> Latn
+    {0x8C0A0000u, 45u}, // kad -> Latn
+    {0xA00A0000u, 45u}, // kai -> Latn
+    {0xA40A0000u, 45u}, // kaj -> Latn
+    {0xB00A0000u, 45u}, // kam -> Latn
+    {0xB80A0000u, 45u}, // kao -> Latn
     {0x8C2A0000u, 18u}, // kbd -> Cyrl
-    {0xB02A0000u, 46u}, // kbm -> Latn
-    {0xBC2A0000u, 46u}, // kbp -> Latn
-    {0xC02A0000u, 46u}, // kbq -> Latn
-    {0xDC2A0000u, 46u}, // kbx -> Latn
+    {0xB02A0000u, 45u}, // kbm -> Latn
+    {0xBC2A0000u, 45u}, // kbp -> Latn
+    {0xC02A0000u, 45u}, // kbq -> Latn
+    {0xDC2A0000u, 45u}, // kbx -> Latn
     {0xE02A0000u,  2u}, // kby -> Arab
-    {0x984A0000u, 46u}, // kcg -> Latn
-    {0xA84A0000u, 46u}, // kck -> Latn
-    {0xAC4A0000u, 46u}, // kcl -> Latn
-    {0xCC4A0000u, 46u}, // kct -> Latn
-    {0x906A0000u, 46u}, // kde -> Latn
-    {0x9C6A0000u,  2u}, // kdh -> Arab
-    {0xAC6A0000u, 46u}, // kdl -> Latn
-    {0xCC6A0000u, 91u}, // kdt -> Thai
-    {0x808A0000u, 46u}, // kea -> Latn
-    {0xB48A0000u, 46u}, // ken -> Latn
-    {0xE48A0000u, 46u}, // kez -> Latn
-    {0xB8AA0000u, 46u}, // kfo -> Latn
+    {0x984A0000u, 45u}, // kcg -> Latn
+    {0xA84A0000u, 45u}, // kck -> Latn
+    {0xAC4A0000u, 45u}, // kcl -> Latn
+    {0xCC4A0000u, 45u}, // kct -> Latn
+    {0x906A0000u, 45u}, // kde -> Latn
+    {0x9C6A0000u, 45u}, // kdh -> Latn
+    {0xAC6A0000u, 45u}, // kdl -> Latn
+    {0xCC6A0000u, 92u}, // kdt -> Thai
+    {0x808A0000u, 45u}, // kea -> Latn
+    {0xB48A0000u, 45u}, // ken -> Latn
+    {0xE48A0000u, 45u}, // kez -> Latn
+    {0xB8AA0000u, 45u}, // kfo -> Latn
     {0xC4AA0000u, 19u}, // kfr -> Deva
     {0xE0AA0000u, 19u}, // kfy -> Deva
-    {0x6B670000u, 46u}, // kg -> Latn
-    {0x90CA0000u, 46u}, // kge -> Latn
-    {0x94CA0000u, 46u}, // kgf -> Latn
-    {0xBCCA0000u, 46u}, // kgp -> Latn
-    {0x80EA0000u, 46u}, // kha -> Latn
-    {0x84EA0000u, 84u}, // khb -> Talu
+    {0x6B670000u, 45u}, // kg -> Latn
+    {0x90CA0000u, 45u}, // kge -> Latn
+    {0x94CA0000u, 45u}, // kgf -> Latn
+    {0xBCCA0000u, 45u}, // kgp -> Latn
+    {0x80EA0000u, 45u}, // kha -> Latn
+    {0x84EA0000u, 85u}, // khb -> Talu
     {0xB4EA0000u, 19u}, // khn -> Deva
-    {0xC0EA0000u, 46u}, // khq -> Latn
-    {0xC8EA0000u, 46u}, // khs -> Latn
-    {0xCCEA0000u, 59u}, // kht -> Mymr
+    {0xC0EA0000u, 45u}, // khq -> Latn
+    {0xC8EA0000u, 45u}, // khs -> Latn
+    {0xCCEA0000u, 58u}, // kht -> Mymr
     {0xD8EA0000u,  2u}, // khw -> Arab
-    {0xE4EA0000u, 46u}, // khz -> Latn
-    {0x6B690000u, 46u}, // ki -> Latn
-    {0xA50A0000u, 46u}, // kij -> Latn
-    {0xD10A0000u, 46u}, // kiu -> Latn
-    {0xD90A0000u, 46u}, // kiw -> Latn
-    {0x6B6A0000u, 46u}, // kj -> Latn
-    {0x8D2A0000u, 46u}, // kjd -> Latn
-    {0x992A0000u, 45u}, // kjg -> Laoo
-    {0xC92A0000u, 46u}, // kjs -> Latn
-    {0xE12A0000u, 46u}, // kjy -> Latn
+    {0xE4EA0000u, 45u}, // khz -> Latn
+    {0x6B690000u, 45u}, // ki -> Latn
+    {0xA50A0000u, 45u}, // kij -> Latn
+    {0xD10A0000u, 45u}, // kiu -> Latn
+    {0xD90A0000u, 45u}, // kiw -> Latn
+    {0x6B6A0000u, 45u}, // kj -> Latn
+    {0x8D2A0000u, 45u}, // kjd -> Latn
+    {0x992A0000u, 44u}, // kjg -> Laoo
+    {0xC92A0000u, 45u}, // kjs -> Latn
+    {0xE12A0000u, 45u}, // kjy -> Latn
     {0x6B6B0000u, 18u}, // kk -> Cyrl
     {0x6B6B4146u,  2u}, // kk-AF -> Arab
     {0x6B6B434Eu,  2u}, // kk-CN -> Arab
     {0x6B6B4952u,  2u}, // kk-IR -> Arab
     {0x6B6B4D4Eu,  2u}, // kk-MN -> Arab
-    {0x894A0000u, 46u}, // kkc -> Latn
-    {0xA54A0000u, 46u}, // kkj -> Latn
-    {0x6B6C0000u, 46u}, // kl -> Latn
-    {0xB56A0000u, 46u}, // kln -> Latn
-    {0xC16A0000u, 46u}, // klq -> Latn
-    {0xCD6A0000u, 46u}, // klt -> Latn
-    {0xDD6A0000u, 46u}, // klx -> Latn
-    {0x6B6D0000u, 40u}, // km -> Khmr
-    {0x858A0000u, 46u}, // kmb -> Latn
-    {0x9D8A0000u, 46u}, // kmh -> Latn
-    {0xB98A0000u, 46u}, // kmo -> Latn
-    {0xC98A0000u, 46u}, // kms -> Latn
-    {0xD18A0000u, 46u}, // kmu -> Latn
-    {0xD98A0000u, 46u}, // kmw -> Latn
-    {0x6B6E0000u, 42u}, // kn -> Knda
-    {0x95AA0000u, 46u}, // knf -> Latn
-    {0xBDAA0000u, 46u}, // knp -> Latn
-    {0x6B6F0000u, 43u}, // ko -> Kore
+    {0x894A0000u, 45u}, // kkc -> Latn
+    {0xA54A0000u, 45u}, // kkj -> Latn
+    {0x6B6C0000u, 45u}, // kl -> Latn
+    {0xB56A0000u, 45u}, // kln -> Latn
+    {0xC16A0000u, 45u}, // klq -> Latn
+    {0xCD6A0000u, 45u}, // klt -> Latn
+    {0xDD6A0000u, 45u}, // klx -> Latn
+    {0x6B6D0000u, 39u}, // km -> Khmr
+    {0x858A0000u, 45u}, // kmb -> Latn
+    {0x9D8A0000u, 45u}, // kmh -> Latn
+    {0xB98A0000u, 45u}, // kmo -> Latn
+    {0xC98A0000u, 45u}, // kms -> Latn
+    {0xD18A0000u, 45u}, // kmu -> Latn
+    {0xD98A0000u, 45u}, // kmw -> Latn
+    {0x6B6E0000u, 41u}, // kn -> Knda
+    {0x95AA0000u, 45u}, // knf -> Latn
+    {0xBDAA0000u, 45u}, // knp -> Latn
+    {0x6B6F0000u, 42u}, // ko -> Kore
     {0xA1CA0000u, 18u}, // koi -> Cyrl
     {0xA9CA0000u, 19u}, // kok -> Deva
-    {0xADCA0000u, 46u}, // kol -> Latn
-    {0xC9CA0000u, 46u}, // kos -> Latn
-    {0xE5CA0000u, 46u}, // koz -> Latn
-    {0x91EA0000u, 46u}, // kpe -> Latn
-    {0x95EA0000u, 46u}, // kpf -> Latn
-    {0xB9EA0000u, 46u}, // kpo -> Latn
-    {0xC5EA0000u, 46u}, // kpr -> Latn
-    {0xDDEA0000u, 46u}, // kpx -> Latn
-    {0x860A0000u, 46u}, // kqb -> Latn
-    {0x960A0000u, 46u}, // kqf -> Latn
-    {0xCA0A0000u, 46u}, // kqs -> Latn
+    {0xADCA0000u, 45u}, // kol -> Latn
+    {0xC9CA0000u, 45u}, // kos -> Latn
+    {0xE5CA0000u, 45u}, // koz -> Latn
+    {0x91EA0000u, 45u}, // kpe -> Latn
+    {0x95EA0000u, 45u}, // kpf -> Latn
+    {0xB9EA0000u, 45u}, // kpo -> Latn
+    {0xC5EA0000u, 45u}, // kpr -> Latn
+    {0xDDEA0000u, 45u}, // kpx -> Latn
+    {0x860A0000u, 45u}, // kqb -> Latn
+    {0x960A0000u, 45u}, // kqf -> Latn
+    {0xCA0A0000u, 45u}, // kqs -> Latn
     {0xE20A0000u, 21u}, // kqy -> Ethi
-    {0x6B720000u, 46u}, // kr -> Latn
+    {0x6B720000u, 45u}, // kr -> Latn
     {0x8A2A0000u, 18u}, // krc -> Cyrl
-    {0xA22A0000u, 46u}, // kri -> Latn
-    {0xA62A0000u, 46u}, // krj -> Latn
-    {0xAE2A0000u, 46u}, // krl -> Latn
-    {0xCA2A0000u, 46u}, // krs -> Latn
+    {0xA22A0000u, 45u}, // kri -> Latn
+    {0xA62A0000u, 45u}, // krj -> Latn
+    {0xAE2A0000u, 45u}, // krl -> Latn
+    {0xCA2A0000u, 45u}, // krs -> Latn
     {0xD22A0000u, 19u}, // kru -> Deva
     {0x6B730000u,  2u}, // ks -> Arab
-    {0x864A0000u, 46u}, // ksb -> Latn
-    {0x8E4A0000u, 46u}, // ksd -> Latn
-    {0x964A0000u, 46u}, // ksf -> Latn
-    {0x9E4A0000u, 46u}, // ksh -> Latn
-    {0xA64A0000u, 46u}, // ksj -> Latn
-    {0xC64A0000u, 46u}, // ksr -> Latn
+    {0x864A0000u, 45u}, // ksb -> Latn
+    {0x8E4A0000u, 45u}, // ksd -> Latn
+    {0x964A0000u, 45u}, // ksf -> Latn
+    {0x9E4A0000u, 45u}, // ksh -> Latn
+    {0xA64A0000u, 45u}, // ksj -> Latn
+    {0xC64A0000u, 45u}, // ksr -> Latn
     {0x866A0000u, 21u}, // ktb -> Ethi
-    {0xB26A0000u, 46u}, // ktm -> Latn
-    {0xBA6A0000u, 46u}, // kto -> Latn
-    {0xC66A0000u, 46u}, // ktr -> Latn
-    {0x6B750000u, 46u}, // ku -> Latn
+    {0xB26A0000u, 45u}, // ktm -> Latn
+    {0xBA6A0000u, 45u}, // kto -> Latn
+    {0xC66A0000u, 45u}, // ktr -> Latn
+    {0x6B750000u, 45u}, // ku -> Latn
     {0x6B754952u,  2u}, // ku-IR -> Arab
     {0x6B754C42u,  2u}, // ku-LB -> Arab
-    {0x868A0000u, 46u}, // kub -> Latn
-    {0x8E8A0000u, 46u}, // kud -> Latn
-    {0x928A0000u, 46u}, // kue -> Latn
-    {0xA68A0000u, 46u}, // kuj -> Latn
+    {0x868A0000u, 45u}, // kub -> Latn
+    {0x8E8A0000u, 45u}, // kud -> Latn
+    {0x928A0000u, 45u}, // kue -> Latn
+    {0xA68A0000u, 45u}, // kuj -> Latn
     {0xB28A0000u, 18u}, // kum -> Cyrl
-    {0xB68A0000u, 46u}, // kun -> Latn
-    {0xBE8A0000u, 46u}, // kup -> Latn
-    {0xCA8A0000u, 46u}, // kus -> Latn
+    {0xB68A0000u, 45u}, // kun -> Latn
+    {0xBE8A0000u, 45u}, // kup -> Latn
+    {0xCA8A0000u, 45u}, // kus -> Latn
     {0x6B760000u, 18u}, // kv -> Cyrl
-    {0x9AAA0000u, 46u}, // kvg -> Latn
-    {0xC6AA0000u, 46u}, // kvr -> Latn
+    {0x9AAA0000u, 45u}, // kvg -> Latn
+    {0xC6AA0000u, 45u}, // kvr -> Latn
     {0xDEAA0000u,  2u}, // kvx -> Arab
-    {0x6B770000u, 46u}, // kw -> Latn
-    {0xA6CA0000u, 46u}, // kwj -> Latn
-    {0xBACA0000u, 46u}, // kwo -> Latn
-    {0xC2CA0000u, 46u}, // kwq -> Latn
-    {0x82EA0000u, 46u}, // kxa -> Latn
+    {0x6B770000u, 45u}, // kw -> Latn
+    {0xA6CA0000u, 45u}, // kwj -> Latn
+    {0xBACA0000u, 45u}, // kwo -> Latn
+    {0xC2CA0000u, 45u}, // kwq -> Latn
+    {0x82EA0000u, 45u}, // kxa -> Latn
     {0x8AEA0000u, 21u}, // kxc -> Ethi
-    {0x92EA0000u, 46u}, // kxe -> Latn
+    {0x92EA0000u, 45u}, // kxe -> Latn
     {0xAEEA0000u, 19u}, // kxl -> Deva
-    {0xB2EA0000u, 91u}, // kxm -> Thai
+    {0xB2EA0000u, 92u}, // kxm -> Thai
     {0xBEEA0000u,  2u}, // kxp -> Arab
-    {0xDAEA0000u, 46u}, // kxw -> Latn
-    {0xE6EA0000u, 46u}, // kxz -> Latn
+    {0xDAEA0000u, 45u}, // kxw -> Latn
+    {0xE6EA0000u, 45u}, // kxz -> Latn
     {0x6B790000u, 18u}, // ky -> Cyrl
     {0x6B79434Eu,  2u}, // ky-CN -> Arab
-    {0x6B795452u, 46u}, // ky-TR -> Latn
-    {0x930A0000u, 46u}, // kye -> Latn
-    {0xDF0A0000u, 46u}, // kyx -> Latn
+    {0x6B795452u, 45u}, // ky-TR -> Latn
+    {0x930A0000u, 45u}, // kye -> Latn
+    {0xDF0A0000u, 45u}, // kyx -> Latn
     {0x9F2A0000u,  2u}, // kzh -> Arab
-    {0xA72A0000u, 46u}, // kzj -> Latn
-    {0xC72A0000u, 46u}, // kzr -> Latn
-    {0xCF2A0000u, 46u}, // kzt -> Latn
-    {0x6C610000u, 46u}, // la -> Latn
-    {0x840B0000u, 48u}, // lab -> Lina
+    {0xA72A0000u, 45u}, // kzj -> Latn
+    {0xC72A0000u, 45u}, // kzr -> Latn
+    {0xCF2A0000u, 45u}, // kzt -> Latn
+    {0x6C610000u, 45u}, // la -> Latn
+    {0x840B0000u, 47u}, // lab -> Lina
     {0x8C0B0000u, 31u}, // lad -> Hebr
-    {0x980B0000u, 46u}, // lag -> Latn
+    {0x980B0000u, 45u}, // lag -> Latn
     {0x9C0B0000u,  2u}, // lah -> Arab
-    {0xA40B0000u, 46u}, // laj -> Latn
-    {0xC80B0000u, 46u}, // las -> Latn
-    {0x6C620000u, 46u}, // lb -> Latn
+    {0xA40B0000u, 45u}, // laj -> Latn
+    {0xC80B0000u, 45u}, // las -> Latn
+    {0x6C620000u, 45u}, // lb -> Latn
     {0x902B0000u, 18u}, // lbe -> Cyrl
-    {0xD02B0000u, 46u}, // lbu -> Latn
-    {0xD82B0000u, 46u}, // lbw -> Latn
-    {0xB04B0000u, 46u}, // lcm -> Latn
-    {0xBC4B0000u, 91u}, // lcp -> Thai
-    {0x846B0000u, 46u}, // ldb -> Latn
-    {0x8C8B0000u, 46u}, // led -> Latn
-    {0x908B0000u, 46u}, // lee -> Latn
-    {0xB08B0000u, 46u}, // lem -> Latn
-    {0xBC8B0000u, 47u}, // lep -> Lepc
-    {0xC08B0000u, 46u}, // leq -> Latn
-    {0xD08B0000u, 46u}, // leu -> Latn
+    {0xD02B0000u, 45u}, // lbu -> Latn
+    {0xD82B0000u, 45u}, // lbw -> Latn
+    {0xB04B0000u, 45u}, // lcm -> Latn
+    {0xBC4B0000u, 92u}, // lcp -> Thai
+    {0x846B0000u, 45u}, // ldb -> Latn
+    {0x8C8B0000u, 45u}, // led -> Latn
+    {0x908B0000u, 45u}, // lee -> Latn
+    {0xB08B0000u, 45u}, // lem -> Latn
+    {0xBC8B0000u, 46u}, // lep -> Lepc
+    {0xC08B0000u, 45u}, // leq -> Latn
+    {0xD08B0000u, 45u}, // leu -> Latn
     {0xE48B0000u, 18u}, // lez -> Cyrl
-    {0x6C670000u, 46u}, // lg -> Latn
-    {0x98CB0000u, 46u}, // lgg -> Latn
-    {0x6C690000u, 46u}, // li -> Latn
-    {0x810B0000u, 46u}, // lia -> Latn
-    {0x8D0B0000u, 46u}, // lid -> Latn
+    {0x6C670000u, 45u}, // lg -> Latn
+    {0x98CB0000u, 45u}, // lgg -> Latn
+    {0x6C690000u, 45u}, // li -> Latn
+    {0x810B0000u, 45u}, // lia -> Latn
+    {0x8D0B0000u, 45u}, // lid -> Latn
     {0x950B0000u, 19u}, // lif -> Deva
-    {0x990B0000u, 46u}, // lig -> Latn
-    {0x9D0B0000u, 46u}, // lih -> Latn
-    {0xA50B0000u, 46u}, // lij -> Latn
-    {0xC90B0000u, 49u}, // lis -> Lisu
-    {0xBD2B0000u, 46u}, // ljp -> Latn
+    {0x990B0000u, 45u}, // lig -> Latn
+    {0x9D0B0000u, 45u}, // lih -> Latn
+    {0xA50B0000u, 45u}, // lij -> Latn
+    {0xC90B0000u, 48u}, // lis -> Lisu
+    {0xBD2B0000u, 45u}, // ljp -> Latn
     {0xA14B0000u,  2u}, // lki -> Arab
-    {0xCD4B0000u, 46u}, // lkt -> Latn
-    {0x916B0000u, 46u}, // lle -> Latn
-    {0xB56B0000u, 46u}, // lln -> Latn
-    {0xB58B0000u, 88u}, // lmn -> Telu
-    {0xB98B0000u, 46u}, // lmo -> Latn
-    {0xBD8B0000u, 46u}, // lmp -> Latn
-    {0x6C6E0000u, 46u}, // ln -> Latn
-    {0xC9AB0000u, 46u}, // lns -> Latn
-    {0xD1AB0000u, 46u}, // lnu -> Latn
-    {0x6C6F0000u, 45u}, // lo -> Laoo
-    {0xA5CB0000u, 46u}, // loj -> Latn
-    {0xA9CB0000u, 46u}, // lok -> Latn
-    {0xADCB0000u, 46u}, // lol -> Latn
-    {0xC5CB0000u, 46u}, // lor -> Latn
-    {0xC9CB0000u, 46u}, // los -> Latn
-    {0xE5CB0000u, 46u}, // loz -> Latn
+    {0xCD4B0000u, 45u}, // lkt -> Latn
+    {0x916B0000u, 45u}, // lle -> Latn
+    {0xB56B0000u, 45u}, // lln -> Latn
+    {0xB58B0000u, 89u}, // lmn -> Telu
+    {0xB98B0000u, 45u}, // lmo -> Latn
+    {0xBD8B0000u, 45u}, // lmp -> Latn
+    {0x6C6E0000u, 45u}, // ln -> Latn
+    {0xC9AB0000u, 45u}, // lns -> Latn
+    {0xD1AB0000u, 45u}, // lnu -> Latn
+    {0x6C6F0000u, 44u}, // lo -> Laoo
+    {0xA5CB0000u, 45u}, // loj -> Latn
+    {0xA9CB0000u, 45u}, // lok -> Latn
+    {0xADCB0000u, 45u}, // lol -> Latn
+    {0xC5CB0000u, 45u}, // lor -> Latn
+    {0xC9CB0000u, 45u}, // los -> Latn
+    {0xE5CB0000u, 45u}, // loz -> Latn
     {0x8A2B0000u,  2u}, // lrc -> Arab
-    {0x6C740000u, 46u}, // lt -> Latn
-    {0x9A6B0000u, 46u}, // ltg -> Latn
-    {0x6C750000u, 46u}, // lu -> Latn
-    {0x828B0000u, 46u}, // lua -> Latn
-    {0xBA8B0000u, 46u}, // luo -> Latn
-    {0xE28B0000u, 46u}, // luy -> Latn
+    {0x6C740000u, 45u}, // lt -> Latn
+    {0x9A6B0000u, 45u}, // ltg -> Latn
+    {0x6C750000u, 45u}, // lu -> Latn
+    {0x828B0000u, 45u}, // lua -> Latn
+    {0xBA8B0000u, 45u}, // luo -> Latn
+    {0xE28B0000u, 45u}, // luy -> Latn
     {0xE68B0000u,  2u}, // luz -> Arab
-    {0x6C760000u, 46u}, // lv -> Latn
-    {0xAECB0000u, 91u}, // lwl -> Thai
+    {0x6C760000u, 45u}, // lv -> Latn
+    {0xAECB0000u, 92u}, // lwl -> Thai
     {0x9F2B0000u, 29u}, // lzh -> Hans
-    {0xE72B0000u, 46u}, // lzz -> Latn
-    {0x8C0C0000u, 46u}, // mad -> Latn
-    {0x940C0000u, 46u}, // maf -> Latn
+    {0xE72B0000u, 45u}, // lzz -> Latn
+    {0x8C0C0000u, 45u}, // mad -> Latn
+    {0x940C0000u, 45u}, // maf -> Latn
     {0x980C0000u, 19u}, // mag -> Deva
     {0xA00C0000u, 19u}, // mai -> Deva
-    {0xA80C0000u, 46u}, // mak -> Latn
-    {0xB40C0000u, 46u}, // man -> Latn
-    {0xB40C474Eu, 61u}, // man-GN -> Nkoo
-    {0xC80C0000u, 46u}, // mas -> Latn
-    {0xD80C0000u, 46u}, // maw -> Latn
-    {0xE40C0000u, 46u}, // maz -> Latn
-    {0x9C2C0000u, 46u}, // mbh -> Latn
-    {0xB82C0000u, 46u}, // mbo -> Latn
-    {0xC02C0000u, 46u}, // mbq -> Latn
-    {0xD02C0000u, 46u}, // mbu -> Latn
-    {0xD82C0000u, 46u}, // mbw -> Latn
-    {0xA04C0000u, 46u}, // mci -> Latn
-    {0xBC4C0000u, 46u}, // mcp -> Latn
-    {0xC04C0000u, 46u}, // mcq -> Latn
-    {0xC44C0000u, 46u}, // mcr -> Latn
-    {0xD04C0000u, 46u}, // mcu -> Latn
-    {0x806C0000u, 46u}, // mda -> Latn
+    {0xA80C0000u, 45u}, // mak -> Latn
+    {0xB40C0000u, 45u}, // man -> Latn
+    {0xB40C474Eu, 60u}, // man-GN -> Nkoo
+    {0xC80C0000u, 45u}, // mas -> Latn
+    {0xD80C0000u, 45u}, // maw -> Latn
+    {0xE40C0000u, 45u}, // maz -> Latn
+    {0x9C2C0000u, 45u}, // mbh -> Latn
+    {0xB82C0000u, 45u}, // mbo -> Latn
+    {0xC02C0000u, 45u}, // mbq -> Latn
+    {0xD02C0000u, 45u}, // mbu -> Latn
+    {0xD82C0000u, 45u}, // mbw -> Latn
+    {0xA04C0000u, 45u}, // mci -> Latn
+    {0xBC4C0000u, 45u}, // mcp -> Latn
+    {0xC04C0000u, 45u}, // mcq -> Latn
+    {0xC44C0000u, 45u}, // mcr -> Latn
+    {0xD04C0000u, 45u}, // mcu -> Latn
+    {0x806C0000u, 45u}, // mda -> Latn
     {0x906C0000u,  2u}, // mde -> Arab
     {0x946C0000u, 18u}, // mdf -> Cyrl
-    {0x9C6C0000u, 46u}, // mdh -> Latn
-    {0xA46C0000u, 46u}, // mdj -> Latn
-    {0xC46C0000u, 46u}, // mdr -> Latn
+    {0x9C6C0000u, 45u}, // mdh -> Latn
+    {0xA46C0000u, 45u}, // mdj -> Latn
+    {0xC46C0000u, 45u}, // mdr -> Latn
     {0xDC6C0000u, 21u}, // mdx -> Ethi
-    {0x8C8C0000u, 46u}, // med -> Latn
-    {0x908C0000u, 46u}, // mee -> Latn
-    {0xA88C0000u, 46u}, // mek -> Latn
-    {0xB48C0000u, 46u}, // men -> Latn
-    {0xC48C0000u, 46u}, // mer -> Latn
-    {0xCC8C0000u, 46u}, // met -> Latn
-    {0xD08C0000u, 46u}, // meu -> Latn
+    {0x8C8C0000u, 45u}, // med -> Latn
+    {0x908C0000u, 45u}, // mee -> Latn
+    {0xA88C0000u, 45u}, // mek -> Latn
+    {0xB48C0000u, 45u}, // men -> Latn
+    {0xC48C0000u, 45u}, // mer -> Latn
+    {0xCC8C0000u, 45u}, // met -> Latn
+    {0xD08C0000u, 45u}, // meu -> Latn
     {0x80AC0000u,  2u}, // mfa -> Arab
-    {0x90AC0000u, 46u}, // mfe -> Latn
-    {0xB4AC0000u, 46u}, // mfn -> Latn
-    {0xB8AC0000u, 46u}, // mfo -> Latn
-    {0xC0AC0000u, 46u}, // mfq -> Latn
-    {0x6D670000u, 46u}, // mg -> Latn
-    {0x9CCC0000u, 46u}, // mgh -> Latn
-    {0xACCC0000u, 46u}, // mgl -> Latn
-    {0xB8CC0000u, 46u}, // mgo -> Latn
+    {0x90AC0000u, 45u}, // mfe -> Latn
+    {0xB4AC0000u, 45u}, // mfn -> Latn
+    {0xB8AC0000u, 45u}, // mfo -> Latn
+    {0xC0AC0000u, 45u}, // mfq -> Latn
+    {0x6D670000u, 45u}, // mg -> Latn
+    {0x9CCC0000u, 45u}, // mgh -> Latn
+    {0xACCC0000u, 45u}, // mgl -> Latn
+    {0xB8CC0000u, 45u}, // mgo -> Latn
     {0xBCCC0000u, 19u}, // mgp -> Deva
-    {0xE0CC0000u, 46u}, // mgy -> Latn
-    {0x6D680000u, 46u}, // mh -> Latn
-    {0xA0EC0000u, 46u}, // mhi -> Latn
-    {0xACEC0000u, 46u}, // mhl -> Latn
-    {0x6D690000u, 46u}, // mi -> Latn
-    {0x950C0000u, 46u}, // mif -> Latn
-    {0xB50C0000u, 46u}, // min -> Latn
-    {0xD90C0000u, 46u}, // miw -> Latn
+    {0xE0CC0000u, 45u}, // mgy -> Latn
+    {0x6D680000u, 45u}, // mh -> Latn
+    {0xA0EC0000u, 45u}, // mhi -> Latn
+    {0xACEC0000u, 45u}, // mhl -> Latn
+    {0x6D690000u, 45u}, // mi -> Latn
+    {0x950C0000u, 45u}, // mif -> Latn
+    {0xB50C0000u, 45u}, // min -> Latn
+    {0xD90C0000u, 45u}, // miw -> Latn
     {0x6D6B0000u, 18u}, // mk -> Cyrl
     {0xA14C0000u,  2u}, // mki -> Arab
-    {0xAD4C0000u, 46u}, // mkl -> Latn
-    {0xBD4C0000u, 46u}, // mkp -> Latn
-    {0xD94C0000u, 46u}, // mkw -> Latn
-    {0x6D6C0000u, 56u}, // ml -> Mlym
-    {0x916C0000u, 46u}, // mle -> Latn
-    {0xBD6C0000u, 46u}, // mlp -> Latn
-    {0xC96C0000u, 46u}, // mls -> Latn
-    {0xB98C0000u, 46u}, // mmo -> Latn
-    {0xD18C0000u, 46u}, // mmu -> Latn
-    {0xDD8C0000u, 46u}, // mmx -> Latn
+    {0xAD4C0000u, 45u}, // mkl -> Latn
+    {0xBD4C0000u, 45u}, // mkp -> Latn
+    {0xD94C0000u, 45u}, // mkw -> Latn
+    {0x6D6C0000u, 55u}, // ml -> Mlym
+    {0x916C0000u, 45u}, // mle -> Latn
+    {0xBD6C0000u, 45u}, // mlp -> Latn
+    {0xC96C0000u, 45u}, // mls -> Latn
+    {0xB98C0000u, 45u}, // mmo -> Latn
+    {0xD18C0000u, 45u}, // mmu -> Latn
+    {0xDD8C0000u, 45u}, // mmx -> Latn
     {0x6D6E0000u, 18u}, // mn -> Cyrl
-    {0x6D6E434Eu, 57u}, // mn-CN -> Mong
-    {0x81AC0000u, 46u}, // mna -> Latn
-    {0x95AC0000u, 46u}, // mnf -> Latn
+    {0x6D6E434Eu, 56u}, // mn-CN -> Mong
+    {0x81AC0000u, 45u}, // mna -> Latn
+    {0x95AC0000u, 45u}, // mnf -> Latn
     {0xA1AC0000u,  8u}, // mni -> Beng
-    {0xD9AC0000u, 59u}, // mnw -> Mymr
-    {0x6D6F0000u, 46u}, // mo -> Latn
-    {0x81CC0000u, 46u}, // moa -> Latn
-    {0x91CC0000u, 46u}, // moe -> Latn
-    {0x9DCC0000u, 46u}, // moh -> Latn
-    {0xC9CC0000u, 46u}, // mos -> Latn
-    {0xDDCC0000u, 46u}, // mox -> Latn
-    {0xBDEC0000u, 46u}, // mpp -> Latn
-    {0xC9EC0000u, 46u}, // mps -> Latn
-    {0xCDEC0000u, 46u}, // mpt -> Latn
-    {0xDDEC0000u, 46u}, // mpx -> Latn
-    {0xAE0C0000u, 46u}, // mql -> Latn
+    {0xD9AC0000u, 58u}, // mnw -> Mymr
+    {0x6D6F0000u, 45u}, // mo -> Latn
+    {0x81CC0000u, 45u}, // moa -> Latn
+    {0x91CC0000u, 45u}, // moe -> Latn
+    {0x9DCC0000u, 45u}, // moh -> Latn
+    {0xC9CC0000u, 45u}, // mos -> Latn
+    {0xDDCC0000u, 45u}, // mox -> Latn
+    {0xBDEC0000u, 45u}, // mpp -> Latn
+    {0xC9EC0000u, 45u}, // mps -> Latn
+    {0xCDEC0000u, 45u}, // mpt -> Latn
+    {0xDDEC0000u, 45u}, // mpx -> Latn
+    {0xAE0C0000u, 45u}, // mql -> Latn
     {0x6D720000u, 19u}, // mr -> Deva
     {0x8E2C0000u, 19u}, // mrd -> Deva
     {0xA62C0000u, 18u}, // mrj -> Cyrl
-    {0xBA2C0000u, 58u}, // mro -> Mroo
-    {0x6D730000u, 46u}, // ms -> Latn
+    {0xBA2C0000u, 57u}, // mro -> Mroo
+    {0x6D730000u, 45u}, // ms -> Latn
     {0x6D734343u,  2u}, // ms-CC -> Arab
-    {0x6D740000u, 46u}, // mt -> Latn
-    {0x8A6C0000u, 46u}, // mtc -> Latn
-    {0x966C0000u, 46u}, // mtf -> Latn
-    {0xA26C0000u, 46u}, // mti -> Latn
+    {0x6D740000u, 45u}, // mt -> Latn
+    {0x8A6C0000u, 45u}, // mtc -> Latn
+    {0x966C0000u, 45u}, // mtf -> Latn
+    {0xA26C0000u, 45u}, // mti -> Latn
     {0xC66C0000u, 19u}, // mtr -> Deva
-    {0x828C0000u, 46u}, // mua -> Latn
-    {0xC68C0000u, 46u}, // mur -> Latn
-    {0xCA8C0000u, 46u}, // mus -> Latn
-    {0x82AC0000u, 46u}, // mva -> Latn
-    {0xB6AC0000u, 46u}, // mvn -> Latn
+    {0x828C0000u, 45u}, // mua -> Latn
+    {0xC68C0000u, 45u}, // mur -> Latn
+    {0xCA8C0000u, 45u}, // mus -> Latn
+    {0x82AC0000u, 45u}, // mva -> Latn
+    {0xB6AC0000u, 45u}, // mvn -> Latn
     {0xE2AC0000u,  2u}, // mvy -> Arab
-    {0xAACC0000u, 46u}, // mwk -> Latn
+    {0xAACC0000u, 45u}, // mwk -> Latn
     {0xC6CC0000u, 19u}, // mwr -> Deva
-    {0xD6CC0000u, 46u}, // mwv -> Latn
-    {0xDACC0000u, 34u}, // mww -> Hmnp
-    {0x8AEC0000u, 46u}, // mxc -> Latn
-    {0xB2EC0000u, 46u}, // mxm -> Latn
-    {0x6D790000u, 59u}, // my -> Mymr
-    {0xAB0C0000u, 46u}, // myk -> Latn
+    {0xD6CC0000u, 45u}, // mwv -> Latn
+    {0xDACC0000u, 33u}, // mww -> Hmnp
+    {0x8AEC0000u, 45u}, // mxc -> Latn
+    {0xB2EC0000u, 45u}, // mxm -> Latn
+    {0x6D790000u, 58u}, // my -> Mymr
+    {0xAB0C0000u, 45u}, // myk -> Latn
     {0xB30C0000u, 21u}, // mym -> Ethi
     {0xD70C0000u, 18u}, // myv -> Cyrl
-    {0xDB0C0000u, 46u}, // myw -> Latn
-    {0xDF0C0000u, 46u}, // myx -> Latn
-    {0xE70C0000u, 52u}, // myz -> Mand
-    {0xAB2C0000u, 46u}, // mzk -> Latn
-    {0xB32C0000u, 46u}, // mzm -> Latn
+    {0xDB0C0000u, 45u}, // myw -> Latn
+    {0xDF0C0000u, 45u}, // myx -> Latn
+    {0xE70C0000u, 51u}, // myz -> Mand
+    {0xAB2C0000u, 45u}, // mzk -> Latn
+    {0xB32C0000u, 45u}, // mzm -> Latn
     {0xB72C0000u,  2u}, // mzn -> Arab
-    {0xBF2C0000u, 46u}, // mzp -> Latn
-    {0xDB2C0000u, 46u}, // mzw -> Latn
-    {0xE72C0000u, 46u}, // mzz -> Latn
-    {0x6E610000u, 46u}, // na -> Latn
-    {0x880D0000u, 46u}, // nac -> Latn
-    {0x940D0000u, 46u}, // naf -> Latn
-    {0xA80D0000u, 46u}, // nak -> Latn
+    {0xBF2C0000u, 45u}, // mzp -> Latn
+    {0xDB2C0000u, 45u}, // mzw -> Latn
+    {0xE72C0000u, 45u}, // mzz -> Latn
+    {0x6E610000u, 45u}, // na -> Latn
+    {0x880D0000u, 45u}, // nac -> Latn
+    {0x940D0000u, 45u}, // naf -> Latn
+    {0xA80D0000u, 45u}, // nak -> Latn
     {0xB40D0000u, 29u}, // nan -> Hans
-    {0xBC0D0000u, 46u}, // nap -> Latn
-    {0xC00D0000u, 46u}, // naq -> Latn
-    {0xC80D0000u, 46u}, // nas -> Latn
-    {0x6E620000u, 46u}, // nb -> Latn
-    {0x804D0000u, 46u}, // nca -> Latn
-    {0x904D0000u, 46u}, // nce -> Latn
-    {0x944D0000u, 46u}, // ncf -> Latn
-    {0x9C4D0000u, 46u}, // nch -> Latn
-    {0xB84D0000u, 46u}, // nco -> Latn
-    {0xD04D0000u, 46u}, // ncu -> Latn
-    {0x6E640000u, 46u}, // nd -> Latn
-    {0x886D0000u, 46u}, // ndc -> Latn
-    {0xC86D0000u, 46u}, // nds -> Latn
+    {0xBC0D0000u, 45u}, // nap -> Latn
+    {0xC00D0000u, 45u}, // naq -> Latn
+    {0xC80D0000u, 45u}, // nas -> Latn
+    {0x6E620000u, 45u}, // nb -> Latn
+    {0x804D0000u, 45u}, // nca -> Latn
+    {0x904D0000u, 45u}, // nce -> Latn
+    {0x944D0000u, 45u}, // ncf -> Latn
+    {0x9C4D0000u, 45u}, // nch -> Latn
+    {0xB84D0000u, 45u}, // nco -> Latn
+    {0xD04D0000u, 45u}, // ncu -> Latn
+    {0x6E640000u, 45u}, // nd -> Latn
+    {0x886D0000u, 45u}, // ndc -> Latn
+    {0xC86D0000u, 45u}, // nds -> Latn
     {0x6E650000u, 19u}, // ne -> Deva
-    {0x848D0000u, 46u}, // neb -> Latn
+    {0x848D0000u, 45u}, // neb -> Latn
     {0xD88D0000u, 19u}, // new -> Deva
-    {0xDC8D0000u, 46u}, // nex -> Latn
-    {0xC4AD0000u, 46u}, // nfr -> Latn
-    {0x6E670000u, 46u}, // ng -> Latn
-    {0x80CD0000u, 46u}, // nga -> Latn
-    {0x84CD0000u, 46u}, // ngb -> Latn
-    {0xACCD0000u, 46u}, // ngl -> Latn
-    {0x84ED0000u, 46u}, // nhb -> Latn
-    {0x90ED0000u, 46u}, // nhe -> Latn
-    {0xD8ED0000u, 46u}, // nhw -> Latn
-    {0x950D0000u, 46u}, // nif -> Latn
-    {0xA10D0000u, 46u}, // nii -> Latn
-    {0xA50D0000u, 46u}, // nij -> Latn
-    {0xB50D0000u, 46u}, // nin -> Latn
-    {0xD10D0000u, 46u}, // niu -> Latn
-    {0xE10D0000u, 46u}, // niy -> Latn
-    {0xE50D0000u, 46u}, // niz -> Latn
-    {0xB92D0000u, 46u}, // njo -> Latn
-    {0x994D0000u, 46u}, // nkg -> Latn
-    {0xB94D0000u, 46u}, // nko -> Latn
-    {0x6E6C0000u, 46u}, // nl -> Latn
-    {0x998D0000u, 46u}, // nmg -> Latn
-    {0xE58D0000u, 46u}, // nmz -> Latn
-    {0x6E6E0000u, 46u}, // nn -> Latn
-    {0x95AD0000u, 46u}, // nnf -> Latn
-    {0x9DAD0000u, 46u}, // nnh -> Latn
-    {0xA9AD0000u, 46u}, // nnk -> Latn
-    {0xB1AD0000u, 46u}, // nnm -> Latn
-    {0xBDAD0000u, 95u}, // nnp -> Wcho
-    {0x6E6F0000u, 46u}, // no -> Latn
-    {0x8DCD0000u, 44u}, // nod -> Lana
+    {0xDC8D0000u, 45u}, // nex -> Latn
+    {0xC4AD0000u, 45u}, // nfr -> Latn
+    {0x6E670000u, 45u}, // ng -> Latn
+    {0x80CD0000u, 45u}, // nga -> Latn
+    {0x84CD0000u, 45u}, // ngb -> Latn
+    {0xACCD0000u, 45u}, // ngl -> Latn
+    {0x84ED0000u, 45u}, // nhb -> Latn
+    {0x90ED0000u, 45u}, // nhe -> Latn
+    {0xD8ED0000u, 45u}, // nhw -> Latn
+    {0x950D0000u, 45u}, // nif -> Latn
+    {0xA10D0000u, 45u}, // nii -> Latn
+    {0xA50D0000u, 45u}, // nij -> Latn
+    {0xB50D0000u, 45u}, // nin -> Latn
+    {0xD10D0000u, 45u}, // niu -> Latn
+    {0xE10D0000u, 45u}, // niy -> Latn
+    {0xE50D0000u, 45u}, // niz -> Latn
+    {0xB92D0000u, 45u}, // njo -> Latn
+    {0x994D0000u, 45u}, // nkg -> Latn
+    {0xB94D0000u, 45u}, // nko -> Latn
+    {0x6E6C0000u, 45u}, // nl -> Latn
+    {0x998D0000u, 45u}, // nmg -> Latn
+    {0xE58D0000u, 45u}, // nmz -> Latn
+    {0x6E6E0000u, 45u}, // nn -> Latn
+    {0x95AD0000u, 45u}, // nnf -> Latn
+    {0x9DAD0000u, 45u}, // nnh -> Latn
+    {0xA9AD0000u, 45u}, // nnk -> Latn
+    {0xB1AD0000u, 45u}, // nnm -> Latn
+    {0xBDAD0000u, 98u}, // nnp -> Wcho
+    {0x6E6F0000u, 45u}, // no -> Latn
+    {0x8DCD0000u, 43u}, // nod -> Lana
     {0x91CD0000u, 19u}, // noe -> Deva
-    {0xB5CD0000u, 73u}, // non -> Runr
-    {0xBDCD0000u, 46u}, // nop -> Latn
-    {0xD1CD0000u, 46u}, // nou -> Latn
-    {0xBA0D0000u, 61u}, // nqo -> Nkoo
-    {0x6E720000u, 46u}, // nr -> Latn
-    {0x862D0000u, 46u}, // nrb -> Latn
+    {0xB5CD0000u, 74u}, // non -> Runr
+    {0xBDCD0000u, 45u}, // nop -> Latn
+    {0xD1CD0000u, 45u}, // nou -> Latn
+    {0xBA0D0000u, 60u}, // nqo -> Nkoo
+    {0x6E720000u, 45u}, // nr -> Latn
+    {0x862D0000u, 45u}, // nrb -> Latn
     {0xAA4D0000u, 11u}, // nsk -> Cans
-    {0xB64D0000u, 46u}, // nsn -> Latn
-    {0xBA4D0000u, 46u}, // nso -> Latn
-    {0xCA4D0000u, 46u}, // nss -> Latn
-    {0xB26D0000u, 46u}, // ntm -> Latn
-    {0xC66D0000u, 46u}, // ntr -> Latn
-    {0xA28D0000u, 46u}, // nui -> Latn
-    {0xBE8D0000u, 46u}, // nup -> Latn
-    {0xCA8D0000u, 46u}, // nus -> Latn
-    {0xD68D0000u, 46u}, // nuv -> Latn
-    {0xDE8D0000u, 46u}, // nux -> Latn
-    {0x6E760000u, 46u}, // nv -> Latn
-    {0x86CD0000u, 46u}, // nwb -> Latn
-    {0xC2ED0000u, 46u}, // nxq -> Latn
-    {0xC6ED0000u, 46u}, // nxr -> Latn
-    {0x6E790000u, 46u}, // ny -> Latn
-    {0xB30D0000u, 46u}, // nym -> Latn
-    {0xB70D0000u, 46u}, // nyn -> Latn
-    {0xA32D0000u, 46u}, // nzi -> Latn
-    {0x6F630000u, 46u}, // oc -> Latn
-    {0x88CE0000u, 46u}, // ogc -> Latn
-    {0xC54E0000u, 46u}, // okr -> Latn
-    {0xD54E0000u, 46u}, // okv -> Latn
-    {0x6F6D0000u, 46u}, // om -> Latn
-    {0x99AE0000u, 46u}, // ong -> Latn
-    {0xB5AE0000u, 46u}, // onn -> Latn
-    {0xC9AE0000u, 46u}, // ons -> Latn
-    {0xB1EE0000u, 46u}, // opm -> Latn
-    {0x6F720000u, 66u}, // or -> Orya
-    {0xBA2E0000u, 46u}, // oro -> Latn
+    {0xB64D0000u, 45u}, // nsn -> Latn
+    {0xBA4D0000u, 45u}, // nso -> Latn
+    {0xCA4D0000u, 45u}, // nss -> Latn
+    {0xCE4D0000u, 94u}, // nst -> Tnsa
+    {0xB26D0000u, 45u}, // ntm -> Latn
+    {0xC66D0000u, 45u}, // ntr -> Latn
+    {0xA28D0000u, 45u}, // nui -> Latn
+    {0xBE8D0000u, 45u}, // nup -> Latn
+    {0xCA8D0000u, 45u}, // nus -> Latn
+    {0xD68D0000u, 45u}, // nuv -> Latn
+    {0xDE8D0000u, 45u}, // nux -> Latn
+    {0x6E760000u, 45u}, // nv -> Latn
+    {0x86CD0000u, 45u}, // nwb -> Latn
+    {0xC2ED0000u, 45u}, // nxq -> Latn
+    {0xC6ED0000u, 45u}, // nxr -> Latn
+    {0x6E790000u, 45u}, // ny -> Latn
+    {0xB30D0000u, 45u}, // nym -> Latn
+    {0xB70D0000u, 45u}, // nyn -> Latn
+    {0xA32D0000u, 45u}, // nzi -> Latn
+    {0x6F630000u, 45u}, // oc -> Latn
+    {0x88CE0000u, 45u}, // ogc -> Latn
+    {0xC54E0000u, 45u}, // okr -> Latn
+    {0xD54E0000u, 45u}, // okv -> Latn
+    {0x6F6D0000u, 45u}, // om -> Latn
+    {0x99AE0000u, 45u}, // ong -> Latn
+    {0xB5AE0000u, 45u}, // onn -> Latn
+    {0xC9AE0000u, 45u}, // ons -> Latn
+    {0xB1EE0000u, 45u}, // opm -> Latn
+    {0x6F720000u, 65u}, // or -> Orya
+    {0xBA2E0000u, 45u}, // oro -> Latn
     {0xD22E0000u,  2u}, // oru -> Arab
     {0x6F730000u, 18u}, // os -> Cyrl
-    {0x824E0000u, 67u}, // osa -> Osge
+    {0x824E0000u, 66u}, // osa -> Osge
     {0x826E0000u,  2u}, // ota -> Arab
-    {0xAA6E0000u, 65u}, // otk -> Orkh
-    {0xB32E0000u, 46u}, // ozm -> Latn
+    {0xAA6E0000u, 64u}, // otk -> Orkh
+    {0xA28E0000u, 67u}, // oui -> Ougr
+    {0xB32E0000u, 45u}, // ozm -> Latn
     {0x70610000u, 28u}, // pa -> Guru
     {0x7061504Bu,  2u}, // pa-PK -> Arab
-    {0x980F0000u, 46u}, // pag -> Latn
+    {0x980F0000u, 45u}, // pag -> Latn
     {0xAC0F0000u, 69u}, // pal -> Phli
-    {0xB00F0000u, 46u}, // pam -> Latn
-    {0xBC0F0000u, 46u}, // pap -> Latn
-    {0xD00F0000u, 46u}, // pau -> Latn
-    {0xA02F0000u, 46u}, // pbi -> Latn
-    {0x8C4F0000u, 46u}, // pcd -> Latn
-    {0xB04F0000u, 46u}, // pcm -> Latn
-    {0x886F0000u, 46u}, // pdc -> Latn
-    {0xCC6F0000u, 46u}, // pdt -> Latn
-    {0x8C8F0000u, 46u}, // ped -> Latn
-    {0xB88F0000u, 96u}, // peo -> Xpeo
-    {0xDC8F0000u, 46u}, // pex -> Latn
-    {0xACAF0000u, 46u}, // pfl -> Latn
+    {0xB00F0000u, 45u}, // pam -> Latn
+    {0xBC0F0000u, 45u}, // pap -> Latn
+    {0xD00F0000u, 45u}, // pau -> Latn
+    {0xA02F0000u, 45u}, // pbi -> Latn
+    {0x8C4F0000u, 45u}, // pcd -> Latn
+    {0xB04F0000u, 45u}, // pcm -> Latn
+    {0x886F0000u, 45u}, // pdc -> Latn
+    {0xCC6F0000u, 45u}, // pdt -> Latn
+    {0x8C8F0000u, 45u}, // ped -> Latn
+    {0xB88F0000u, 99u}, // peo -> Xpeo
+    {0xDC8F0000u, 45u}, // pex -> Latn
+    {0xACAF0000u, 45u}, // pfl -> Latn
     {0xACEF0000u,  2u}, // phl -> Arab
     {0xB4EF0000u, 70u}, // phn -> Phnx
-    {0xAD0F0000u, 46u}, // pil -> Latn
-    {0xBD0F0000u, 46u}, // pip -> Latn
+    {0xAD0F0000u, 45u}, // pil -> Latn
+    {0xBD0F0000u, 45u}, // pip -> Latn
     {0x814F0000u,  9u}, // pka -> Brah
-    {0xB94F0000u, 46u}, // pko -> Latn
-    {0x706C0000u, 46u}, // pl -> Latn
-    {0x816F0000u, 46u}, // pla -> Latn
-    {0xC98F0000u, 46u}, // pms -> Latn
-    {0x99AF0000u, 46u}, // png -> Latn
-    {0xB5AF0000u, 46u}, // pnn -> Latn
+    {0xB94F0000u, 45u}, // pko -> Latn
+    {0x706C0000u, 45u}, // pl -> Latn
+    {0x816F0000u, 45u}, // pla -> Latn
+    {0xC98F0000u, 45u}, // pms -> Latn
+    {0x99AF0000u, 45u}, // png -> Latn
+    {0xB5AF0000u, 45u}, // pnn -> Latn
     {0xCDAF0000u, 26u}, // pnt -> Grek
-    {0xB5CF0000u, 46u}, // pon -> Latn
+    {0xB5CF0000u, 45u}, // pon -> Latn
     {0x81EF0000u, 19u}, // ppa -> Deva
-    {0xB9EF0000u, 46u}, // ppo -> Latn
-    {0x822F0000u, 39u}, // pra -> Khar
+    {0xB9EF0000u, 45u}, // ppo -> Latn
+    {0x822F0000u, 38u}, // pra -> Khar
     {0x8E2F0000u,  2u}, // prd -> Arab
-    {0x9A2F0000u, 46u}, // prg -> Latn
+    {0x9A2F0000u, 45u}, // prg -> Latn
     {0x70730000u,  2u}, // ps -> Arab
-    {0xCA4F0000u, 46u}, // pss -> Latn
-    {0x70740000u, 46u}, // pt -> Latn
-    {0xBE6F0000u, 46u}, // ptp -> Latn
-    {0xD28F0000u, 46u}, // puu -> Latn
-    {0x82CF0000u, 46u}, // pwa -> Latn
-    {0x71750000u, 46u}, // qu -> Latn
-    {0x8A900000u, 46u}, // quc -> Latn
-    {0x9A900000u, 46u}, // qug -> Latn
-    {0xA0110000u, 46u}, // rai -> Latn
+    {0xCA4F0000u, 45u}, // pss -> Latn
+    {0x70740000u, 45u}, // pt -> Latn
+    {0xBE6F0000u, 45u}, // ptp -> Latn
+    {0xD28F0000u, 45u}, // puu -> Latn
+    {0x82CF0000u, 45u}, // pwa -> Latn
+    {0x71750000u, 45u}, // qu -> Latn
+    {0x8A900000u, 45u}, // quc -> Latn
+    {0x9A900000u, 45u}, // qug -> Latn
+    {0xA0110000u, 45u}, // rai -> Latn
     {0xA4110000u, 19u}, // raj -> Deva
-    {0xB8110000u, 46u}, // rao -> Latn
-    {0x94510000u, 46u}, // rcf -> Latn
-    {0xA4910000u, 46u}, // rej -> Latn
-    {0xAC910000u, 46u}, // rel -> Latn
-    {0xC8910000u, 46u}, // res -> Latn
-    {0xB4D10000u, 46u}, // rgn -> Latn
-    {0x98F10000u,  2u}, // rhg -> Arab
-    {0x81110000u, 46u}, // ria -> Latn
-    {0x95110000u, 89u}, // rif -> Tfng
-    {0x95114E4Cu, 46u}, // rif-NL -> Latn
+    {0xB8110000u, 45u}, // rao -> Latn
+    {0x94510000u, 45u}, // rcf -> Latn
+    {0xA4910000u, 45u}, // rej -> Latn
+    {0xAC910000u, 45u}, // rel -> Latn
+    {0xC8910000u, 45u}, // res -> Latn
+    {0xB4D10000u, 45u}, // rgn -> Latn
+    {0x98F10000u, 73u}, // rhg -> Rohg
+    {0x81110000u, 45u}, // ria -> Latn
+    {0x95110000u, 90u}, // rif -> Tfng
+    {0x95114E4Cu, 45u}, // rif-NL -> Latn
     {0xC9310000u, 19u}, // rjs -> Deva
     {0xCD510000u,  8u}, // rkt -> Beng
-    {0x726D0000u, 46u}, // rm -> Latn
-    {0x95910000u, 46u}, // rmf -> Latn
-    {0xB9910000u, 46u}, // rmo -> Latn
+    {0x726D0000u, 45u}, // rm -> Latn
+    {0x95910000u, 45u}, // rmf -> Latn
+    {0xB9910000u, 45u}, // rmo -> Latn
     {0xCD910000u,  2u}, // rmt -> Arab
-    {0xD1910000u, 46u}, // rmu -> Latn
-    {0x726E0000u, 46u}, // rn -> Latn
-    {0x81B10000u, 46u}, // rna -> Latn
-    {0x99B10000u, 46u}, // rng -> Latn
-    {0x726F0000u, 46u}, // ro -> Latn
-    {0x85D10000u, 46u}, // rob -> Latn
-    {0x95D10000u, 46u}, // rof -> Latn
-    {0xB9D10000u, 46u}, // roo -> Latn
-    {0xBA310000u, 46u}, // rro -> Latn
-    {0xB2710000u, 46u}, // rtm -> Latn
+    {0xD1910000u, 45u}, // rmu -> Latn
+    {0x726E0000u, 45u}, // rn -> Latn
+    {0x81B10000u, 45u}, // rna -> Latn
+    {0x99B10000u, 45u}, // rng -> Latn
+    {0x726F0000u, 45u}, // ro -> Latn
+    {0x85D10000u, 45u}, // rob -> Latn
+    {0x95D10000u, 45u}, // rof -> Latn
+    {0xB9D10000u, 45u}, // roo -> Latn
+    {0xBA310000u, 45u}, // rro -> Latn
+    {0xB2710000u, 45u}, // rtm -> Latn
     {0x72750000u, 18u}, // ru -> Cyrl
     {0x92910000u, 18u}, // rue -> Cyrl
-    {0x9A910000u, 46u}, // rug -> Latn
-    {0x72770000u, 46u}, // rw -> Latn
-    {0xAAD10000u, 46u}, // rwk -> Latn
-    {0xBAD10000u, 46u}, // rwo -> Latn
-    {0xD3110000u, 38u}, // ryu -> Kana
+    {0x9A910000u, 45u}, // rug -> Latn
+    {0x72770000u, 45u}, // rw -> Latn
+    {0xAAD10000u, 45u}, // rwk -> Latn
+    {0xBAD10000u, 45u}, // rwo -> Latn
+    {0xD3110000u, 37u}, // ryu -> Kana
     {0x73610000u, 19u}, // sa -> Deva
-    {0x94120000u, 46u}, // saf -> Latn
+    {0x94120000u, 45u}, // saf -> Latn
     {0x9C120000u, 18u}, // sah -> Cyrl
-    {0xC0120000u, 46u}, // saq -> Latn
-    {0xC8120000u, 46u}, // sas -> Latn
-    {0xCC120000u, 64u}, // sat -> Olck
-    {0xD4120000u, 46u}, // sav -> Latn
-    {0xE4120000u, 76u}, // saz -> Saur
-    {0x80320000u, 46u}, // sba -> Latn
-    {0x90320000u, 46u}, // sbe -> Latn
-    {0xBC320000u, 46u}, // sbp -> Latn
-    {0x73630000u, 46u}, // sc -> Latn
+    {0xC0120000u, 45u}, // saq -> Latn
+    {0xC8120000u, 45u}, // sas -> Latn
+    {0xCC120000u, 63u}, // sat -> Olck
+    {0xD4120000u, 45u}, // sav -> Latn
+    {0xE4120000u, 77u}, // saz -> Saur
+    {0x80320000u, 45u}, // sba -> Latn
+    {0x90320000u, 45u}, // sbe -> Latn
+    {0xBC320000u, 45u}, // sbp -> Latn
+    {0x73630000u, 45u}, // sc -> Latn
     {0xA8520000u, 19u}, // sck -> Deva
     {0xAC520000u,  2u}, // scl -> Arab
-    {0xB4520000u, 46u}, // scn -> Latn
-    {0xB8520000u, 46u}, // sco -> Latn
-    {0xC8520000u, 46u}, // scs -> Latn
+    {0xB4520000u, 45u}, // scn -> Latn
+    {0xB8520000u, 45u}, // sco -> Latn
+    {0xC8520000u, 45u}, // scs -> Latn
     {0x73640000u,  2u}, // sd -> Arab
-    {0x88720000u, 46u}, // sdc -> Latn
+    {0x88720000u, 45u}, // sdc -> Latn
     {0x9C720000u,  2u}, // sdh -> Arab
-    {0x73650000u, 46u}, // se -> Latn
-    {0x94920000u, 46u}, // sef -> Latn
-    {0x9C920000u, 46u}, // seh -> Latn
-    {0xA0920000u, 46u}, // sei -> Latn
-    {0xC8920000u, 46u}, // ses -> Latn
-    {0x73670000u, 46u}, // sg -> Latn
-    {0x80D20000u, 63u}, // sga -> Ogam
-    {0xC8D20000u, 46u}, // sgs -> Latn
+    {0x73650000u, 45u}, // se -> Latn
+    {0x94920000u, 45u}, // sef -> Latn
+    {0x9C920000u, 45u}, // seh -> Latn
+    {0xA0920000u, 45u}, // sei -> Latn
+    {0xC8920000u, 45u}, // ses -> Latn
+    {0x73670000u, 45u}, // sg -> Latn
+    {0x80D20000u, 62u}, // sga -> Ogam
+    {0xC8D20000u, 45u}, // sgs -> Latn
     {0xD8D20000u, 21u}, // sgw -> Ethi
-    {0xE4D20000u, 46u}, // sgz -> Latn
-    {0x73680000u, 46u}, // sh -> Latn
-    {0xA0F20000u, 89u}, // shi -> Tfng
-    {0xA8F20000u, 46u}, // shk -> Latn
-    {0xB4F20000u, 59u}, // shn -> Mymr
+    {0xE4D20000u, 45u}, // sgz -> Latn
+    {0x73680000u, 45u}, // sh -> Latn
+    {0xA0F20000u, 90u}, // shi -> Tfng
+    {0xA8F20000u, 45u}, // shk -> Latn
+    {0xB4F20000u, 58u}, // shn -> Mymr
     {0xD0F20000u,  2u}, // shu -> Arab
-    {0x73690000u, 78u}, // si -> Sinh
-    {0x8D120000u, 46u}, // sid -> Latn
-    {0x99120000u, 46u}, // sig -> Latn
-    {0xAD120000u, 46u}, // sil -> Latn
-    {0xB1120000u, 46u}, // sim -> Latn
-    {0xC5320000u, 46u}, // sjr -> Latn
-    {0x736B0000u, 46u}, // sk -> Latn
-    {0x89520000u, 46u}, // skc -> Latn
+    {0x73690000u, 79u}, // si -> Sinh
+    {0x8D120000u, 45u}, // sid -> Latn
+    {0x99120000u, 45u}, // sig -> Latn
+    {0xAD120000u, 45u}, // sil -> Latn
+    {0xB1120000u, 45u}, // sim -> Latn
+    {0xC5320000u, 45u}, // sjr -> Latn
+    {0x736B0000u, 45u}, // sk -> Latn
+    {0x89520000u, 45u}, // skc -> Latn
     {0xC5520000u,  2u}, // skr -> Arab
-    {0xC9520000u, 46u}, // sks -> Latn
-    {0x736C0000u, 46u}, // sl -> Latn
-    {0x8D720000u, 46u}, // sld -> Latn
-    {0xA1720000u, 46u}, // sli -> Latn
-    {0xAD720000u, 46u}, // sll -> Latn
-    {0xE1720000u, 46u}, // sly -> Latn
-    {0x736D0000u, 46u}, // sm -> Latn
-    {0x81920000u, 46u}, // sma -> Latn
-    {0xA5920000u, 46u}, // smj -> Latn
-    {0xB5920000u, 46u}, // smn -> Latn
-    {0xBD920000u, 74u}, // smp -> Samr
-    {0xC1920000u, 46u}, // smq -> Latn
-    {0xC9920000u, 46u}, // sms -> Latn
-    {0x736E0000u, 46u}, // sn -> Latn
-    {0x89B20000u, 46u}, // snc -> Latn
-    {0xA9B20000u, 46u}, // snk -> Latn
-    {0xBDB20000u, 46u}, // snp -> Latn
-    {0xDDB20000u, 46u}, // snx -> Latn
-    {0xE1B20000u, 46u}, // sny -> Latn
-    {0x736F0000u, 46u}, // so -> Latn
-    {0x99D20000u, 79u}, // sog -> Sogd
-    {0xA9D20000u, 46u}, // sok -> Latn
-    {0xC1D20000u, 46u}, // soq -> Latn
-    {0xD1D20000u, 91u}, // sou -> Thai
-    {0xE1D20000u, 46u}, // soy -> Latn
-    {0x8DF20000u, 46u}, // spd -> Latn
-    {0xADF20000u, 46u}, // spl -> Latn
-    {0xC9F20000u, 46u}, // sps -> Latn
-    {0x73710000u, 46u}, // sq -> Latn
+    {0xC9520000u, 45u}, // sks -> Latn
+    {0x736C0000u, 45u}, // sl -> Latn
+    {0x8D720000u, 45u}, // sld -> Latn
+    {0xA1720000u, 45u}, // sli -> Latn
+    {0xAD720000u, 45u}, // sll -> Latn
+    {0xE1720000u, 45u}, // sly -> Latn
+    {0x736D0000u, 45u}, // sm -> Latn
+    {0x81920000u, 45u}, // sma -> Latn
+    {0xA5920000u, 45u}, // smj -> Latn
+    {0xB5920000u, 45u}, // smn -> Latn
+    {0xBD920000u, 75u}, // smp -> Samr
+    {0xC1920000u, 45u}, // smq -> Latn
+    {0xC9920000u, 45u}, // sms -> Latn
+    {0x736E0000u, 45u}, // sn -> Latn
+    {0x89B20000u, 45u}, // snc -> Latn
+    {0xA9B20000u, 45u}, // snk -> Latn
+    {0xBDB20000u, 45u}, // snp -> Latn
+    {0xDDB20000u, 45u}, // snx -> Latn
+    {0xE1B20000u, 45u}, // sny -> Latn
+    {0x736F0000u, 45u}, // so -> Latn
+    {0x99D20000u, 80u}, // sog -> Sogd
+    {0xA9D20000u, 45u}, // sok -> Latn
+    {0xC1D20000u, 45u}, // soq -> Latn
+    {0xD1D20000u, 92u}, // sou -> Thai
+    {0xE1D20000u, 45u}, // soy -> Latn
+    {0x8DF20000u, 45u}, // spd -> Latn
+    {0xADF20000u, 45u}, // spl -> Latn
+    {0xC9F20000u, 45u}, // sps -> Latn
+    {0x73710000u, 45u}, // sq -> Latn
     {0x73720000u, 18u}, // sr -> Cyrl
-    {0x73724D45u, 46u}, // sr-ME -> Latn
-    {0x7372524Fu, 46u}, // sr-RO -> Latn
-    {0x73725255u, 46u}, // sr-RU -> Latn
-    {0x73725452u, 46u}, // sr-TR -> Latn
-    {0x86320000u, 80u}, // srb -> Sora
-    {0xB6320000u, 46u}, // srn -> Latn
-    {0xC6320000u, 46u}, // srr -> Latn
+    {0x73724D45u, 45u}, // sr-ME -> Latn
+    {0x7372524Fu, 45u}, // sr-RO -> Latn
+    {0x73725255u, 45u}, // sr-RU -> Latn
+    {0x73725452u, 45u}, // sr-TR -> Latn
+    {0x86320000u, 81u}, // srb -> Sora
+    {0xB6320000u, 45u}, // srn -> Latn
+    {0xC6320000u, 45u}, // srr -> Latn
     {0xDE320000u, 19u}, // srx -> Deva
-    {0x73730000u, 46u}, // ss -> Latn
-    {0x8E520000u, 46u}, // ssd -> Latn
-    {0x9A520000u, 46u}, // ssg -> Latn
-    {0xE2520000u, 46u}, // ssy -> Latn
-    {0x73740000u, 46u}, // st -> Latn
-    {0xAA720000u, 46u}, // stk -> Latn
-    {0xC2720000u, 46u}, // stq -> Latn
-    {0x73750000u, 46u}, // su -> Latn
-    {0x82920000u, 46u}, // sua -> Latn
-    {0x92920000u, 46u}, // sue -> Latn
-    {0xAA920000u, 46u}, // suk -> Latn
-    {0xC6920000u, 46u}, // sur -> Latn
-    {0xCA920000u, 46u}, // sus -> Latn
-    {0x73760000u, 46u}, // sv -> Latn
-    {0x73770000u, 46u}, // sw -> Latn
+    {0x73730000u, 45u}, // ss -> Latn
+    {0x8E520000u, 45u}, // ssd -> Latn
+    {0x9A520000u, 45u}, // ssg -> Latn
+    {0xE2520000u, 45u}, // ssy -> Latn
+    {0x73740000u, 45u}, // st -> Latn
+    {0xAA720000u, 45u}, // stk -> Latn
+    {0xC2720000u, 45u}, // stq -> Latn
+    {0x73750000u, 45u}, // su -> Latn
+    {0x82920000u, 45u}, // sua -> Latn
+    {0x92920000u, 45u}, // sue -> Latn
+    {0xAA920000u, 45u}, // suk -> Latn
+    {0xC6920000u, 45u}, // sur -> Latn
+    {0xCA920000u, 45u}, // sus -> Latn
+    {0x73760000u, 45u}, // sv -> Latn
+    {0x73770000u, 45u}, // sw -> Latn
     {0x86D20000u,  2u}, // swb -> Arab
-    {0x8AD20000u, 46u}, // swc -> Latn
-    {0x9AD20000u, 46u}, // swg -> Latn
-    {0xBED20000u, 46u}, // swp -> Latn
+    {0x8AD20000u, 45u}, // swc -> Latn
+    {0x9AD20000u, 45u}, // swg -> Latn
+    {0xBED20000u, 45u}, // swp -> Latn
     {0xD6D20000u, 19u}, // swv -> Deva
-    {0xB6F20000u, 46u}, // sxn -> Latn
-    {0xDAF20000u, 46u}, // sxw -> Latn
+    {0xB6F20000u, 45u}, // sxn -> Latn
+    {0xDAF20000u, 45u}, // sxw -> Latn
     {0xAF120000u,  8u}, // syl -> Beng
-    {0xC7120000u, 82u}, // syr -> Syrc
-    {0xAF320000u, 46u}, // szl -> Latn
-    {0x74610000u, 85u}, // ta -> Taml
+    {0xC7120000u, 83u}, // syr -> Syrc
+    {0xAF320000u, 45u}, // szl -> Latn
+    {0x74610000u, 86u}, // ta -> Taml
     {0xA4130000u, 19u}, // taj -> Deva
-    {0xAC130000u, 46u}, // tal -> Latn
-    {0xB4130000u, 46u}, // tan -> Latn
-    {0xC0130000u, 46u}, // taq -> Latn
-    {0x88330000u, 46u}, // tbc -> Latn
-    {0x8C330000u, 46u}, // tbd -> Latn
-    {0x94330000u, 46u}, // tbf -> Latn
-    {0x98330000u, 46u}, // tbg -> Latn
-    {0xB8330000u, 46u}, // tbo -> Latn
-    {0xD8330000u, 46u}, // tbw -> Latn
-    {0xE4330000u, 46u}, // tbz -> Latn
-    {0xA0530000u, 46u}, // tci -> Latn
-    {0xE0530000u, 42u}, // tcy -> Knda
-    {0x8C730000u, 83u}, // tdd -> Tale
+    {0xAC130000u, 45u}, // tal -> Latn
+    {0xB4130000u, 45u}, // tan -> Latn
+    {0xC0130000u, 45u}, // taq -> Latn
+    {0x88330000u, 45u}, // tbc -> Latn
+    {0x8C330000u, 45u}, // tbd -> Latn
+    {0x94330000u, 45u}, // tbf -> Latn
+    {0x98330000u, 45u}, // tbg -> Latn
+    {0xB8330000u, 45u}, // tbo -> Latn
+    {0xD8330000u, 45u}, // tbw -> Latn
+    {0xE4330000u, 45u}, // tbz -> Latn
+    {0xA0530000u, 45u}, // tci -> Latn
+    {0xE0530000u, 41u}, // tcy -> Knda
+    {0x8C730000u, 84u}, // tdd -> Tale
     {0x98730000u, 19u}, // tdg -> Deva
     {0x9C730000u, 19u}, // tdh -> Deva
-    {0xD0730000u, 46u}, // tdu -> Latn
-    {0x74650000u, 88u}, // te -> Telu
-    {0x8C930000u, 46u}, // ted -> Latn
-    {0xB0930000u, 46u}, // tem -> Latn
-    {0xB8930000u, 46u}, // teo -> Latn
-    {0xCC930000u, 46u}, // tet -> Latn
-    {0xA0B30000u, 46u}, // tfi -> Latn
+    {0xD0730000u, 45u}, // tdu -> Latn
+    {0x74650000u, 89u}, // te -> Telu
+    {0x8C930000u, 45u}, // ted -> Latn
+    {0xB0930000u, 45u}, // tem -> Latn
+    {0xB8930000u, 45u}, // teo -> Latn
+    {0xCC930000u, 45u}, // tet -> Latn
+    {0xA0B30000u, 45u}, // tfi -> Latn
     {0x74670000u, 18u}, // tg -> Cyrl
     {0x7467504Bu,  2u}, // tg-PK -> Arab
-    {0x88D30000u, 46u}, // tgc -> Latn
-    {0xB8D30000u, 46u}, // tgo -> Latn
-    {0xD0D30000u, 46u}, // tgu -> Latn
-    {0x74680000u, 91u}, // th -> Thai
+    {0x88D30000u, 45u}, // tgc -> Latn
+    {0xB8D30000u, 45u}, // tgo -> Latn
+    {0xD0D30000u, 45u}, // tgu -> Latn
+    {0x74680000u, 92u}, // th -> Thai
     {0xACF30000u, 19u}, // thl -> Deva
     {0xC0F30000u, 19u}, // thq -> Deva
     {0xC4F30000u, 19u}, // thr -> Deva
     {0x74690000u, 21u}, // ti -> Ethi
-    {0x95130000u, 46u}, // tif -> Latn
+    {0x95130000u, 45u}, // tif -> Latn
     {0x99130000u, 21u}, // tig -> Ethi
-    {0xA9130000u, 46u}, // tik -> Latn
-    {0xB1130000u, 46u}, // tim -> Latn
-    {0xB9130000u, 46u}, // tio -> Latn
-    {0xD5130000u, 46u}, // tiv -> Latn
-    {0x746B0000u, 46u}, // tk -> Latn
-    {0xAD530000u, 46u}, // tkl -> Latn
-    {0xC5530000u, 46u}, // tkr -> Latn
+    {0xA9130000u, 45u}, // tik -> Latn
+    {0xB1130000u, 45u}, // tim -> Latn
+    {0xB9130000u, 45u}, // tio -> Latn
+    {0xD5130000u, 45u}, // tiv -> Latn
+    {0x746B0000u, 45u}, // tk -> Latn
+    {0xAD530000u, 45u}, // tkl -> Latn
+    {0xC5530000u, 45u}, // tkr -> Latn
     {0xCD530000u, 19u}, // tkt -> Deva
-    {0x746C0000u, 46u}, // tl -> Latn
-    {0x95730000u, 46u}, // tlf -> Latn
-    {0xDD730000u, 46u}, // tlx -> Latn
-    {0xE1730000u, 46u}, // tly -> Latn
-    {0x9D930000u, 46u}, // tmh -> Latn
-    {0xE1930000u, 46u}, // tmy -> Latn
-    {0x746E0000u, 46u}, // tn -> Latn
-    {0x9DB30000u, 46u}, // tnh -> Latn
-    {0x746F0000u, 46u}, // to -> Latn
-    {0x95D30000u, 46u}, // tof -> Latn
-    {0x99D30000u, 46u}, // tog -> Latn
-    {0xC1D30000u, 46u}, // toq -> Latn
-    {0xA1F30000u, 46u}, // tpi -> Latn
-    {0xB1F30000u, 46u}, // tpm -> Latn
-    {0xE5F30000u, 46u}, // tpz -> Latn
-    {0xBA130000u, 46u}, // tqo -> Latn
-    {0x74720000u, 46u}, // tr -> Latn
-    {0xD2330000u, 46u}, // tru -> Latn
-    {0xD6330000u, 46u}, // trv -> Latn
+    {0x746C0000u, 45u}, // tl -> Latn
+    {0x95730000u, 45u}, // tlf -> Latn
+    {0xDD730000u, 45u}, // tlx -> Latn
+    {0xE1730000u, 45u}, // tly -> Latn
+    {0x9D930000u, 45u}, // tmh -> Latn
+    {0xE1930000u, 45u}, // tmy -> Latn
+    {0x746E0000u, 45u}, // tn -> Latn
+    {0x9DB30000u, 45u}, // tnh -> Latn
+    {0x746F0000u, 45u}, // to -> Latn
+    {0x95D30000u, 45u}, // tof -> Latn
+    {0x99D30000u, 45u}, // tog -> Latn
+    {0xC1D30000u, 45u}, // toq -> Latn
+    {0xA1F30000u, 45u}, // tpi -> Latn
+    {0xB1F30000u, 45u}, // tpm -> Latn
+    {0xE5F30000u, 45u}, // tpz -> Latn
+    {0xBA130000u, 45u}, // tqo -> Latn
+    {0x74720000u, 45u}, // tr -> Latn
+    {0xD2330000u, 45u}, // tru -> Latn
+    {0xD6330000u, 45u}, // trv -> Latn
     {0xDA330000u,  2u}, // trw -> Arab
-    {0x74730000u, 46u}, // ts -> Latn
+    {0x74730000u, 45u}, // ts -> Latn
     {0x8E530000u, 26u}, // tsd -> Grek
     {0x96530000u, 19u}, // tsf -> Deva
-    {0x9A530000u, 46u}, // tsg -> Latn
-    {0xA6530000u, 92u}, // tsj -> Tibt
-    {0xDA530000u, 46u}, // tsw -> Latn
+    {0x9A530000u, 45u}, // tsg -> Latn
+    {0xA6530000u, 93u}, // tsj -> Tibt
+    {0xDA530000u, 45u}, // tsw -> Latn
     {0x74740000u, 18u}, // tt -> Cyrl
-    {0x8E730000u, 46u}, // ttd -> Latn
-    {0x92730000u, 46u}, // tte -> Latn
-    {0xA6730000u, 46u}, // ttj -> Latn
-    {0xC6730000u, 46u}, // ttr -> Latn
-    {0xCA730000u, 91u}, // tts -> Thai
-    {0xCE730000u, 46u}, // ttt -> Latn
-    {0x9E930000u, 46u}, // tuh -> Latn
-    {0xAE930000u, 46u}, // tul -> Latn
-    {0xB2930000u, 46u}, // tum -> Latn
-    {0xC2930000u, 46u}, // tuq -> Latn
-    {0x8EB30000u, 46u}, // tvd -> Latn
-    {0xAEB30000u, 46u}, // tvl -> Latn
-    {0xD2B30000u, 46u}, // tvu -> Latn
-    {0x9ED30000u, 46u}, // twh -> Latn
-    {0xC2D30000u, 46u}, // twq -> Latn
-    {0x9AF30000u, 86u}, // txg -> Tang
-    {0x74790000u, 46u}, // ty -> Latn
-    {0x83130000u, 46u}, // tya -> Latn
+    {0x8E730000u, 45u}, // ttd -> Latn
+    {0x92730000u, 45u}, // tte -> Latn
+    {0xA6730000u, 45u}, // ttj -> Latn
+    {0xC6730000u, 45u}, // ttr -> Latn
+    {0xCA730000u, 92u}, // tts -> Thai
+    {0xCE730000u, 45u}, // ttt -> Latn
+    {0x9E930000u, 45u}, // tuh -> Latn
+    {0xAE930000u, 45u}, // tul -> Latn
+    {0xB2930000u, 45u}, // tum -> Latn
+    {0xC2930000u, 45u}, // tuq -> Latn
+    {0x8EB30000u, 45u}, // tvd -> Latn
+    {0xAEB30000u, 45u}, // tvl -> Latn
+    {0xD2B30000u, 45u}, // tvu -> Latn
+    {0x9ED30000u, 45u}, // twh -> Latn
+    {0xC2D30000u, 45u}, // twq -> Latn
+    {0x9AF30000u, 87u}, // txg -> Tang
+    {0xBAF30000u, 95u}, // txo -> Toto
+    {0x74790000u, 45u}, // ty -> Latn
+    {0x83130000u, 45u}, // tya -> Latn
     {0xD7130000u, 18u}, // tyv -> Cyrl
-    {0xB3330000u, 46u}, // tzm -> Latn
-    {0xD0340000u, 46u}, // ubu -> Latn
+    {0xB3330000u, 45u}, // tzm -> Latn
+    {0xD0340000u, 45u}, // ubu -> Latn
     {0xA0740000u,  0u}, // udi -> Aghb
     {0xB0740000u, 18u}, // udm -> Cyrl
     {0x75670000u,  2u}, // ug -> Arab
     {0x75674B5Au, 18u}, // ug-KZ -> Cyrl
     {0x75674D4Eu, 18u}, // ug-MN -> Cyrl
-    {0x80D40000u, 93u}, // uga -> Ugar
+    {0x80D40000u, 96u}, // uga -> Ugar
     {0x756B0000u, 18u}, // uk -> Cyrl
-    {0xA1740000u, 46u}, // uli -> Latn
-    {0x85940000u, 46u}, // umb -> Latn
+    {0xA1740000u, 45u}, // uli -> Latn
+    {0x85940000u, 45u}, // umb -> Latn
     {0xC5B40000u,  8u}, // unr -> Beng
     {0xC5B44E50u, 19u}, // unr-NP -> Deva
     {0xDDB40000u,  8u}, // unx -> Beng
-    {0xA9D40000u, 46u}, // uok -> Latn
+    {0xA9D40000u, 45u}, // uok -> Latn
     {0x75720000u,  2u}, // ur -> Arab
-    {0xA2340000u, 46u}, // uri -> Latn
-    {0xCE340000u, 46u}, // urt -> Latn
-    {0xDA340000u, 46u}, // urw -> Latn
-    {0x82540000u, 46u}, // usa -> Latn
-    {0x9E740000u, 46u}, // uth -> Latn
-    {0xC6740000u, 46u}, // utr -> Latn
-    {0x9EB40000u, 46u}, // uvh -> Latn
-    {0xAEB40000u, 46u}, // uvl -> Latn
-    {0x757A0000u, 46u}, // uz -> Latn
+    {0xA2340000u, 45u}, // uri -> Latn
+    {0xCE340000u, 45u}, // urt -> Latn
+    {0xDA340000u, 45u}, // urw -> Latn
+    {0x82540000u, 45u}, // usa -> Latn
+    {0x9E740000u, 45u}, // uth -> Latn
+    {0xC6740000u, 45u}, // utr -> Latn
+    {0x9EB40000u, 45u}, // uvh -> Latn
+    {0xAEB40000u, 45u}, // uvl -> Latn
+    {0x757A0000u, 45u}, // uz -> Latn
     {0x757A4146u,  2u}, // uz-AF -> Arab
     {0x757A434Eu, 18u}, // uz-CN -> Cyrl
-    {0x98150000u, 46u}, // vag -> Latn
-    {0xA0150000u, 94u}, // vai -> Vaii
-    {0xB4150000u, 46u}, // van -> Latn
-    {0x76650000u, 46u}, // ve -> Latn
-    {0x88950000u, 46u}, // vec -> Latn
-    {0xBC950000u, 46u}, // vep -> Latn
-    {0x76690000u, 46u}, // vi -> Latn
-    {0x89150000u, 46u}, // vic -> Latn
-    {0xD5150000u, 46u}, // viv -> Latn
-    {0xC9750000u, 46u}, // vls -> Latn
-    {0x95950000u, 46u}, // vmf -> Latn
-    {0xD9950000u, 46u}, // vmw -> Latn
-    {0x766F0000u, 46u}, // vo -> Latn
-    {0xCDD50000u, 46u}, // vot -> Latn
-    {0xBA350000u, 46u}, // vro -> Latn
-    {0xB6950000u, 46u}, // vun -> Latn
-    {0xCE950000u, 46u}, // vut -> Latn
-    {0x77610000u, 46u}, // wa -> Latn
-    {0x90160000u, 46u}, // wae -> Latn
-    {0xA4160000u, 46u}, // waj -> Latn
+    {0x98150000u, 45u}, // vag -> Latn
+    {0xA0150000u, 97u}, // vai -> Vaii
+    {0xB4150000u, 45u}, // van -> Latn
+    {0x76650000u, 45u}, // ve -> Latn
+    {0x88950000u, 45u}, // vec -> Latn
+    {0xBC950000u, 45u}, // vep -> Latn
+    {0x76690000u, 45u}, // vi -> Latn
+    {0x89150000u, 45u}, // vic -> Latn
+    {0xD5150000u, 45u}, // viv -> Latn
+    {0xC9750000u, 45u}, // vls -> Latn
+    {0x95950000u, 45u}, // vmf -> Latn
+    {0xD9950000u, 45u}, // vmw -> Latn
+    {0x766F0000u, 45u}, // vo -> Latn
+    {0xCDD50000u, 45u}, // vot -> Latn
+    {0xBA350000u, 45u}, // vro -> Latn
+    {0xB6950000u, 45u}, // vun -> Latn
+    {0xCE950000u, 45u}, // vut -> Latn
+    {0x77610000u, 45u}, // wa -> Latn
+    {0x90160000u, 45u}, // wae -> Latn
+    {0xA4160000u, 45u}, // waj -> Latn
     {0xAC160000u, 21u}, // wal -> Ethi
-    {0xB4160000u, 46u}, // wan -> Latn
-    {0xC4160000u, 46u}, // war -> Latn
-    {0xBC360000u, 46u}, // wbp -> Latn
-    {0xC0360000u, 88u}, // wbq -> Telu
+    {0xB4160000u, 45u}, // wan -> Latn
+    {0xC4160000u, 45u}, // war -> Latn
+    {0xBC360000u, 45u}, // wbp -> Latn
+    {0xC0360000u, 89u}, // wbq -> Telu
     {0xC4360000u, 19u}, // wbr -> Deva
-    {0xA0560000u, 46u}, // wci -> Latn
-    {0xC4960000u, 46u}, // wer -> Latn
-    {0xA0D60000u, 46u}, // wgi -> Latn
-    {0x98F60000u, 46u}, // whg -> Latn
-    {0x85160000u, 46u}, // wib -> Latn
-    {0xD1160000u, 46u}, // wiu -> Latn
-    {0xD5160000u, 46u}, // wiv -> Latn
-    {0x81360000u, 46u}, // wja -> Latn
-    {0xA1360000u, 46u}, // wji -> Latn
-    {0xC9760000u, 46u}, // wls -> Latn
-    {0xB9960000u, 46u}, // wmo -> Latn
-    {0x89B60000u, 46u}, // wnc -> Latn
+    {0xA0560000u, 45u}, // wci -> Latn
+    {0xC4960000u, 45u}, // wer -> Latn
+    {0xA0D60000u, 45u}, // wgi -> Latn
+    {0x98F60000u, 45u}, // whg -> Latn
+    {0x85160000u, 45u}, // wib -> Latn
+    {0xD1160000u, 45u}, // wiu -> Latn
+    {0xD5160000u, 45u}, // wiv -> Latn
+    {0x81360000u, 45u}, // wja -> Latn
+    {0xA1360000u, 45u}, // wji -> Latn
+    {0xC9760000u, 45u}, // wls -> Latn
+    {0xB9960000u, 45u}, // wmo -> Latn
+    {0x89B60000u, 45u}, // wnc -> Latn
     {0xA1B60000u,  2u}, // wni -> Arab
-    {0xD1B60000u, 46u}, // wnu -> Latn
-    {0x776F0000u, 46u}, // wo -> Latn
-    {0x85D60000u, 46u}, // wob -> Latn
-    {0xC9D60000u, 46u}, // wos -> Latn
-    {0xCA360000u, 46u}, // wrs -> Latn
+    {0xD1B60000u, 45u}, // wnu -> Latn
+    {0x776F0000u, 45u}, // wo -> Latn
+    {0x85D60000u, 45u}, // wob -> Latn
+    {0xC9D60000u, 45u}, // wos -> Latn
+    {0xCA360000u, 45u}, // wrs -> Latn
     {0x9A560000u, 23u}, // wsg -> Gong
-    {0xAA560000u, 46u}, // wsk -> Latn
+    {0xAA560000u, 45u}, // wsk -> Latn
     {0xB2760000u, 19u}, // wtm -> Deva
     {0xD2960000u, 29u}, // wuu -> Hans
-    {0xD6960000u, 46u}, // wuv -> Latn
-    {0x82D60000u, 46u}, // wwa -> Latn
-    {0xD4170000u, 46u}, // xav -> Latn
-    {0xA0370000u, 46u}, // xbi -> Latn
+    {0xD6960000u, 45u}, // wuv -> Latn
+    {0x82D60000u, 45u}, // wwa -> Latn
+    {0xD4170000u, 45u}, // xav -> Latn
+    {0xA0370000u, 45u}, // xbi -> Latn
     {0xB8570000u, 15u}, // xco -> Chrs
     {0xC4570000u, 12u}, // xcr -> Cari
-    {0xC8970000u, 46u}, // xes -> Latn
-    {0x78680000u, 46u}, // xh -> Latn
-    {0x81770000u, 46u}, // xla -> Latn
-    {0x89770000u, 50u}, // xlc -> Lyci
-    {0x8D770000u, 51u}, // xld -> Lydi
+    {0xC8970000u, 45u}, // xes -> Latn
+    {0x78680000u, 45u}, // xh -> Latn
+    {0x81770000u, 45u}, // xla -> Latn
+    {0x89770000u, 49u}, // xlc -> Lyci
+    {0x8D770000u, 50u}, // xld -> Lydi
     {0x95970000u, 22u}, // xmf -> Geor
-    {0xB5970000u, 53u}, // xmn -> Mani
-    {0xC5970000u, 55u}, // xmr -> Merc
-    {0x81B70000u, 60u}, // xna -> Narb
+    {0xB5970000u, 52u}, // xmn -> Mani
+    {0xC5970000u, 54u}, // xmr -> Merc
+    {0x81B70000u, 59u}, // xna -> Narb
     {0xC5B70000u, 19u}, // xnr -> Deva
-    {0x99D70000u, 46u}, // xog -> Latn
-    {0xB5D70000u, 46u}, // xon -> Latn
+    {0x99D70000u, 45u}, // xog -> Latn
+    {0xB5D70000u, 45u}, // xon -> Latn
     {0xC5F70000u, 72u}, // xpr -> Prti
-    {0x86370000u, 46u}, // xrb -> Latn
-    {0x82570000u, 75u}, // xsa -> Sarb
-    {0xA2570000u, 46u}, // xsi -> Latn
-    {0xB2570000u, 46u}, // xsm -> Latn
+    {0x86370000u, 45u}, // xrb -> Latn
+    {0x82570000u, 76u}, // xsa -> Sarb
+    {0xA2570000u, 45u}, // xsi -> Latn
+    {0xB2570000u, 45u}, // xsm -> Latn
     {0xC6570000u, 19u}, // xsr -> Deva
-    {0x92D70000u, 46u}, // xwe -> Latn
-    {0xB0180000u, 46u}, // yam -> Latn
-    {0xB8180000u, 46u}, // yao -> Latn
-    {0xBC180000u, 46u}, // yap -> Latn
-    {0xC8180000u, 46u}, // yas -> Latn
-    {0xCC180000u, 46u}, // yat -> Latn
-    {0xD4180000u, 46u}, // yav -> Latn
-    {0xE0180000u, 46u}, // yay -> Latn
-    {0xE4180000u, 46u}, // yaz -> Latn
-    {0x80380000u, 46u}, // yba -> Latn
-    {0x84380000u, 46u}, // ybb -> Latn
-    {0xE0380000u, 46u}, // yby -> Latn
-    {0xC4980000u, 46u}, // yer -> Latn
-    {0xC4D80000u, 46u}, // ygr -> Latn
-    {0xD8D80000u, 46u}, // ygw -> Latn
+    {0x92D70000u, 45u}, // xwe -> Latn
+    {0xB0180000u, 45u}, // yam -> Latn
+    {0xB8180000u, 45u}, // yao -> Latn
+    {0xBC180000u, 45u}, // yap -> Latn
+    {0xC8180000u, 45u}, // yas -> Latn
+    {0xCC180000u, 45u}, // yat -> Latn
+    {0xD4180000u, 45u}, // yav -> Latn
+    {0xE0180000u, 45u}, // yay -> Latn
+    {0xE4180000u, 45u}, // yaz -> Latn
+    {0x80380000u, 45u}, // yba -> Latn
+    {0x84380000u, 45u}, // ybb -> Latn
+    {0xE0380000u, 45u}, // yby -> Latn
+    {0xC4980000u, 45u}, // yer -> Latn
+    {0xC4D80000u, 45u}, // ygr -> Latn
+    {0xD8D80000u, 45u}, // ygw -> Latn
     {0x79690000u, 31u}, // yi -> Hebr
-    {0xB9580000u, 46u}, // yko -> Latn
-    {0x91780000u, 46u}, // yle -> Latn
-    {0x99780000u, 46u}, // ylg -> Latn
-    {0xAD780000u, 46u}, // yll -> Latn
-    {0xAD980000u, 46u}, // yml -> Latn
-    {0x796F0000u, 46u}, // yo -> Latn
-    {0xB5D80000u, 46u}, // yon -> Latn
-    {0x86380000u, 46u}, // yrb -> Latn
-    {0x92380000u, 46u}, // yre -> Latn
-    {0xAE380000u, 46u}, // yrl -> Latn
-    {0xCA580000u, 46u}, // yss -> Latn
-    {0x82980000u, 46u}, // yua -> Latn
+    {0xB9580000u, 45u}, // yko -> Latn
+    {0x91780000u, 45u}, // yle -> Latn
+    {0x99780000u, 45u}, // ylg -> Latn
+    {0xAD780000u, 45u}, // yll -> Latn
+    {0xAD980000u, 45u}, // yml -> Latn
+    {0x796F0000u, 45u}, // yo -> Latn
+    {0xB5D80000u, 45u}, // yon -> Latn
+    {0x86380000u, 45u}, // yrb -> Latn
+    {0x92380000u, 45u}, // yre -> Latn
+    {0xAE380000u, 45u}, // yrl -> Latn
+    {0xCA580000u, 45u}, // yss -> Latn
+    {0x82980000u, 45u}, // yua -> Latn
     {0x92980000u, 30u}, // yue -> Hant
     {0x9298434Eu, 29u}, // yue-CN -> Hans
-    {0xA6980000u, 46u}, // yuj -> Latn
-    {0xCE980000u, 46u}, // yut -> Latn
-    {0xDA980000u, 46u}, // yuw -> Latn
-    {0x7A610000u, 46u}, // za -> Latn
-    {0x98190000u, 46u}, // zag -> Latn
+    {0xA6980000u, 45u}, // yuj -> Latn
+    {0xCE980000u, 45u}, // yut -> Latn
+    {0xDA980000u, 45u}, // yuw -> Latn
+    {0x7A610000u, 45u}, // za -> Latn
+    {0x98190000u, 45u}, // zag -> Latn
     {0xA4790000u,  2u}, // zdj -> Arab
-    {0x80990000u, 46u}, // zea -> Latn
-    {0x9CD90000u, 89u}, // zgh -> Tfng
+    {0x80990000u, 45u}, // zea -> Latn
+    {0x9CD90000u, 90u}, // zgh -> Tfng
     {0x7A680000u, 29u}, // zh -> Hans
     {0x7A684155u, 30u}, // zh-AU -> Hant
     {0x7A68424Eu, 30u}, // zh-BN -> Hant
@@ -1486,14 +1493,14 @@
     {0x7A685457u, 30u}, // zh-TW -> Hant
     {0x7A685553u, 30u}, // zh-US -> Hant
     {0x7A68564Eu, 30u}, // zh-VN -> Hant
-    {0xDCF90000u, 62u}, // zhx -> Nshu
-    {0x81190000u, 46u}, // zia -> Latn
-    {0xCD590000u, 41u}, // zkt -> Kits
-    {0xB1790000u, 46u}, // zlm -> Latn
-    {0xA1990000u, 46u}, // zmi -> Latn
-    {0x91B90000u, 46u}, // zne -> Latn
-    {0x7A750000u, 46u}, // zu -> Latn
-    {0x83390000u, 46u}, // zza -> Latn
+    {0xDCF90000u, 61u}, // zhx -> Nshu
+    {0x81190000u, 45u}, // zia -> Latn
+    {0xCD590000u, 40u}, // zkt -> Kits
+    {0xB1790000u, 45u}, // zlm -> Latn
+    {0xA1990000u, 45u}, // zmi -> Latn
+    {0x91B90000u, 45u}, // zne -> Latn
+    {0x7A750000u, 45u}, // zu -> Latn
+    {0x83390000u, 45u}, // zza -> Latn
 });
 
 std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({
@@ -1573,6 +1580,7 @@
     0xCD21534E4C61746ELLU, // bjt_Latn_SN
     0xB141434D4C61746ELLU, // bkm_Latn_CM
     0xD14150484C61746ELLU, // bku_Latn_PH
+    0x99614D594C61746ELLU, // blg_Latn_MY
     0xCD61564E54617674LLU, // blt_Tavt_VN
     0x626D4D4C4C61746ELLU, // bm_Latn_ML
     0xC1814D4C4C61746ELLU, // bmq_Latn_ML
@@ -1748,7 +1756,7 @@
     0x8D87434E506C7264LLU, // hmd_Plrd_CN
     0x8DA7504B41726162LLU, // hnd_Arab_PK
     0x91A7494E44657661LLU, // hne_Deva_IN
-    0xA5A74C41486D6E67LLU, // hnj_Hmng_LA
+    0xA5A75553486D6E70LLU, // hnj_Hmnp_US
     0xB5A750484C61746ELLU, // hnn_Latn_PH
     0xB9A7504B41726162LLU, // hno_Arab_PK
     0x686F50474C61746ELLU, // ho_Latn_PG
@@ -1797,7 +1805,7 @@
     0x984A4E474C61746ELLU, // kcg_Latn_NG
     0xA84A5A574C61746ELLU, // kck_Latn_ZW
     0x906A545A4C61746ELLU, // kde_Latn_TZ
-    0x9C6A544741726162LLU, // kdh_Arab_TG
+    0x9C6A54474C61746ELLU, // kdh_Latn_TG
     0xCC6A544854686169LLU, // kdt_Thai_TH
     0x808A43564C61746ELLU, // kea_Latn_CV
     0xB48A434D4C61746ELLU, // ken_Latn_CM
@@ -1982,6 +1990,7 @@
     0x6E725A414C61746ELLU, // nr_Latn_ZA
     0xAA4D434143616E73LLU, // nsk_Cans_CA
     0xBA4D5A414C61746ELLU, // nso_Latn_ZA
+    0xCE4D494E546E7361LLU, // nst_Tnsa_IN
     0xCA8D53534C61746ELLU, // nus_Latn_SS
     0x6E7655534C61746ELLU, // nv_Latn_US
     0xC2ED434E4C61746ELLU, // nxq_Latn_CN
@@ -1995,6 +2004,7 @@
     0x6F7347454379726CLLU, // os_Cyrl_GE
     0x824E55534F736765LLU, // osa_Osge_US
     0xAA6E4D4E4F726B68LLU, // otk_Orkh_MN
+    0xA28E8C814F756772LLU, // oui_Ougr_143
     0x7061504B41726162LLU, // pa_Arab_PK
     0x7061494E47757275LLU, // pa_Guru_IN
     0x980F50484C61746ELLU, // pag_Latn_PH
@@ -2029,7 +2039,7 @@
     0x945152454C61746ELLU, // rcf_Latn_RE
     0xA49149444C61746ELLU, // rej_Latn_ID
     0xB4D149544C61746ELLU, // rgn_Latn_IT
-    0x98F14D4D41726162LLU, // rhg_Arab_MM
+    0x98F14D4D526F6867LLU, // rhg_Rohg_MM
     0x8111494E4C61746ELLU, // ria_Latn_IN
     0x95114D4154666E67LLU, // rif_Tfng_MA
     0xC9314E5044657661LLU, // rjs_Deva_NP
@@ -2172,6 +2182,7 @@
     0xAEB354564C61746ELLU, // tvl_Latn_TV
     0xC2D34E454C61746ELLU, // twq_Latn_NE
     0x9AF3434E54616E67LLU, // txg_Tang_CN
+    0xBAF3494E546F746FLLU, // txo_Toto_IN
     0x747950464C61746ELLU, // ty_Latn_PF
     0xD71352554379726CLLU, // tyv_Cyrl_RU
     0xB3334D414C61746ELLU, // tzm_Latn_MA
@@ -2256,6 +2267,7 @@
 });
 
 const std::unordered_map<uint32_t, uint32_t> ARAB_PARENTS({
+    {0x61724145u, 0x61729420u}, // ar-AE -> ar-015
     {0x6172445Au, 0x61729420u}, // ar-DZ -> ar-015
     {0x61724548u, 0x61729420u}, // ar-EH -> ar-015
     {0x61724C59u, 0x61729420u}, // ar-LY -> ar-015
@@ -2279,7 +2291,6 @@
     {0x656E4253u, 0x656E8400u}, // en-BS -> en-001
     {0x656E4257u, 0x656E8400u}, // en-BW -> en-001
     {0x656E425Au, 0x656E8400u}, // en-BZ -> en-001
-    {0x656E4341u, 0x656E8400u}, // en-CA -> en-001
     {0x656E4343u, 0x656E8400u}, // en-CC -> en-001
     {0x656E4348u, 0x656E80A1u}, // en-CH -> en-150
     {0x656E434Bu, 0x656E8400u}, // en-CK -> en-001
@@ -2332,7 +2343,6 @@
     {0x656E4E55u, 0x656E8400u}, // en-NU -> en-001
     {0x656E4E5Au, 0x656E8400u}, // en-NZ -> en-001
     {0x656E5047u, 0x656E8400u}, // en-PG -> en-001
-    {0x656E5048u, 0x656E8400u}, // en-PH -> en-001
     {0x656E504Bu, 0x656E8400u}, // en-PK -> en-001
     {0x656E504Eu, 0x656E8400u}, // en-PN -> en-001
     {0x656E5057u, 0x656E8400u}, // en-PW -> en-001
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c7f5696..60f4a5a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -32,6 +32,7 @@
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -6790,30 +6791,56 @@
 
     /**
      * Returns a list of audio formats that corresponds to encoding formats
-     * supported on offload path for A2DP playback.
+     * supported on offload path for A2DP and LE audio playback.
      *
+     * @param deviceType Indicates the target device type {@link AudioSystem.DeviceType}
      * @return a list of {@link BluetoothCodecConfig} objects containing encoding formats
-     * supported for offload A2DP playback
+     * supported for offload A2DP playback or a list of {@link BluetoothLeAudioCodecConfig}
+     * objects containing encoding formats supported for offload LE Audio playback
      * @hide
      */
-    public List<BluetoothCodecConfig> getHwOffloadEncodingFormatsSupportedForA2DP() {
+    public List<?> getHwOffloadFormatsSupportedForBluetoothMedia(
+            @AudioSystem.DeviceType int deviceType) {
         ArrayList<Integer> formatsList = new ArrayList<Integer>();
-        ArrayList<BluetoothCodecConfig> codecConfigList = new ArrayList<BluetoothCodecConfig>();
+        ArrayList<BluetoothCodecConfig> a2dpCodecConfigList = new ArrayList<BluetoothCodecConfig>();
+        ArrayList<BluetoothLeAudioCodecConfig> leAudioCodecConfigList =
+                new ArrayList<BluetoothLeAudioCodecConfig>();
 
-        int status = AudioSystem.getHwOffloadEncodingFormatsSupportedForA2DP(formatsList);
+        if (deviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP
+                && deviceType != AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+            throw new IllegalArgumentException(
+                    "Illegal devicetype for the getHwOffloadFormatsSupportedForBluetoothMedia");
+        }
+
+        int status = AudioSystem.getHwOffloadFormatsSupportedForBluetoothMedia(deviceType,
+                                                                                formatsList);
         if (status != AudioManager.SUCCESS) {
-            Log.e(TAG, "getHwOffloadEncodingFormatsSupportedForA2DP failed:" + status);
-            return codecConfigList;
+            Log.e(TAG, "getHwOffloadFormatsSupportedForBluetoothMedia for deviceType "
+                    + deviceType + " failed:" + status);
+            return a2dpCodecConfigList;
         }
 
-        for (Integer format : formatsList) {
-            int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
-            if (btSourceCodec
-                    != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
-                codecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
+        if (deviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
+            for (Integer format : formatsList) {
+                int btSourceCodec = AudioSystem.audioFormatToBluetoothSourceCodec(format);
+                if (btSourceCodec != BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+                    a2dpCodecConfigList.add(new BluetoothCodecConfig(btSourceCodec));
+                }
             }
+            return a2dpCodecConfigList;
+        } else if (deviceType == AudioSystem.DEVICE_OUT_BLE_HEADSET) {
+            for (Integer format : formatsList) {
+                int btLeAudioCodec = AudioSystem.audioFormatToBluetoothLeAudioSourceCodec(format);
+                if (btLeAudioCodec != BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+                    leAudioCodecConfigList.add(new BluetoothLeAudioCodecConfig.Builder()
+                                                .setCodecType(btLeAudioCodec)
+                                                .build());
+                }
+            }
+            return leAudioCodecConfigList;
         }
-        return codecConfigList;
+        Log.e(TAG, "Input deviceType " + deviceType + " doesn't support.");
+        return a2dpCodecConfigList;
     }
 
     // Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 69d1889..f0e42c0 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -21,6 +21,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
 import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -229,6 +230,9 @@
     public static final int AUDIO_FORMAT_APTX_HD        = 0x21000000;
     /** @hide */
     public static final int AUDIO_FORMAT_LDAC           = 0x23000000;
+    /** @hide */
+    public static final int AUDIO_FORMAT_LC3            = 0x2B000000;
+
 
     /** @hide */
     @IntDef(flag = false, prefix = "AUDIO_FORMAT_", value = {
@@ -238,11 +242,26 @@
             AUDIO_FORMAT_SBC,
             AUDIO_FORMAT_APTX,
             AUDIO_FORMAT_APTX_HD,
-            AUDIO_FORMAT_LDAC }
+            AUDIO_FORMAT_LDAC}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioFormatNativeEnumForBtCodec {}
 
+    /** @hide */
+    @IntDef(flag = false, prefix = "AUDIO_FORMAT_", value = {
+        AUDIO_FORMAT_LC3}
+    )
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AudioFormatNativeEnumForBtLeAudioCodec {}
+
+    /** @hide */
+    @IntDef(flag = false, prefix = "DEVICE_", value = {
+            DEVICE_OUT_BLUETOOTH_A2DP,
+            DEVICE_OUT_BLE_HEADSET}
+    )
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeviceType {}
+
     /**
      * @hide
      * Convert audio format enum values to Bluetooth codec values
@@ -264,6 +283,21 @@
 
     /**
      * @hide
+     * Convert audio format enum values to Bluetooth LE audio codec values
+     */
+    public static int audioFormatToBluetoothLeAudioSourceCodec(
+            @AudioFormatNativeEnumForBtLeAudioCodec int audioFormat) {
+        switch (audioFormat) {
+            case AUDIO_FORMAT_LC3: return BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3;
+            default:
+                Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat)
+                        + " for conversion to BT LE audio codec");
+                return BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+        }
+    }
+
+    /**
+     * @hide
      * Convert a Bluetooth codec to an audio format enum
      * @param btCodec the codec to convert.
      * @return the audio format, or {@link #AUDIO_FORMAT_DEFAULT} if unknown
@@ -1754,10 +1788,10 @@
 
     /**
      * @hide
-     * Returns a list of audio formats (codec) supported on the A2DP offload path.
+     * Returns a list of audio formats (codec) supported on the A2DP and LE audio offload path.
      */
-    public static native int getHwOffloadEncodingFormatsSupportedForA2DP(
-            ArrayList<Integer> formatList);
+    public static native int getHwOffloadFormatsSupportedForBluetoothMedia(
+            @DeviceType int deviceType, ArrayList<Integer> formatList);
 
     /** @hide */
     public static native int setSurroundFormatEnabled(int audioFormat, boolean enabled);
diff --git a/packages/Nsd/OWNERS b/packages/ConnectivityT/OWNERS
similarity index 100%
rename from packages/Nsd/OWNERS
rename to packages/ConnectivityT/OWNERS
diff --git a/packages/Nsd/framework/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
similarity index 100%
rename from packages/Nsd/framework/Android.bp
rename to packages/ConnectivityT/framework-t/Android.bp
diff --git a/packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl
similarity index 100%
rename from packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl
rename to packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl
diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl
similarity index 100%
rename from packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl
diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
similarity index 100%
rename from packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManagerCallback.aidl
diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
similarity index 100%
rename from packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/nsd/INsdServiceConnector.aidl
diff --git a/packages/Nsd/framework/src/android/net/nsd/NsdManager.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
similarity index 100%
rename from packages/Nsd/framework/src/android/net/nsd/NsdManager.java
rename to packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
diff --git a/packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
similarity index 100%
rename from packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java
rename to packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
diff --git a/packages/Nsd/service/Android.bp b/packages/ConnectivityT/service/Android.bp
similarity index 100%
rename from packages/Nsd/service/Android.bp
rename to packages/ConnectivityT/service/Android.bp
diff --git a/packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java b/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
similarity index 100%
rename from packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
rename to packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java
diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
similarity index 93%
rename from packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java
rename to packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
index eac767f..ec8d779 100644
--- a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java
+++ b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java
@@ -20,18 +20,15 @@
 import android.net.LocalSocketAddress;
 import android.os.Build;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.util.LocalLog;
-import android.util.Slog;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-import com.android.server.power.ShutdownThread;
-import com.google.android.collect.Lists;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -40,19 +37,19 @@
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.LinkedList;
+import java.util.Objects;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.LinkedList;
-import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Generic connector class for interfacing with a native daemon which uses the
  * {@code libsysutils} FrameworkListener protocol.
  */
-final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
+final class NativeDaemonConnector implements Runnable, Handler.Callback {
     private final static boolean VDBG = false;
 
     private final String TAG;
@@ -85,13 +82,6 @@
 
     NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
             int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
-        this(callbacks, socket, responseQueueSize, logTag, maxLogSize, wl,
-                FgThread.get().getLooper());
-    }
-
-    NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
-            int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
-            Looper looper) {
         mCallbacks = callbacks;
         mSocket = socket;
         mResponseQueue = new ResponseQueue(responseQueueSize);
@@ -99,15 +89,17 @@
         if (mWakeLock != null) {
             mWakeLock.setReferenceCounted(true);
         }
-        mLooper = looper;
         mSequenceNumber = new AtomicInteger(0);
         TAG = logTag != null ? logTag : "NativeDaemonConnector";
         mLocalLog = new LocalLog(maxLogSize);
+        final HandlerThread thread = new HandlerThread(TAG);
+        thread.start();
+        mLooper = thread.getLooper();
     }
 
     /**
      * Enable Set debugging mode, which causes messages to also be written to both
-     * {@link Slog} in addition to internal log.
+     * {@link Log} in addition to internal log.
      */
     public void setDebug(boolean debug) {
         mDebug = debug;
@@ -126,7 +118,9 @@
      * calls while holding a lock on the given object.
      */
     public void setWarnIfHeld(Object warnIfHeld) {
-        Preconditions.checkState(mWarnIfHeld == null);
+        if (mWarnIfHeld != null) {
+            throw new IllegalStateException("warnIfHeld is already set.");
+        }
         mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
     }
 
@@ -135,23 +129,15 @@
         mCallbackHandler = new Handler(mLooper, this);
 
         while (true) {
-            if (isShuttingDown()) break;
             try {
                 listenToSocket();
             } catch (Exception e) {
                 loge("Error in NativeDaemonConnector: " + e);
-                if (isShuttingDown()) break;
                 SystemClock.sleep(5000);
             }
         }
     }
 
-    private static boolean isShuttingDown() {
-        String shutdownAct = SystemProperties.get(
-            ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
-        return shutdownAct != null && shutdownAct.length() > 0;
-    }
-
     @Override
     public boolean handleMessage(Message msg) {
         final String event = (String) msg.obj;
@@ -183,7 +169,7 @@
         // In order to ensure that unprivileged apps aren't able to impersonate native daemons on
         // production devices, even if said native daemons ill-advisedly pick a socket name that
         // starts with __test__, only allow this on debug builds.
-        if (mSocket.startsWith("__test__") && Build.IS_DEBUGGABLE) {
+        if (mSocket.startsWith("__test__") && Build.isDebuggable()) {
             return new LocalSocketAddress(mSocket);
         } else {
             return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED);
@@ -375,7 +361,7 @@
         try {
             latch.await();
         } catch (InterruptedException e) {
-            Slog.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
+            Log.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e);
         }
     }
 
@@ -462,13 +448,13 @@
     public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
             throws NativeDaemonConnectorException {
         if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
-            Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+            Log.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
                     + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
         }
 
         final long startTime = SystemClock.elapsedRealtime();
 
-        final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
+        final ArrayList<NativeDaemonEvent> events = new ArrayList<>();
 
         final StringBuilder rawBuilder = new StringBuilder();
         final StringBuilder logBuilder = new StringBuilder();
@@ -571,7 +557,7 @@
      */
     public static class Command {
         private String mCmd;
-        private ArrayList<Object> mArguments = Lists.newArrayList();
+        private ArrayList<Object> mArguments = new ArrayList<>();
 
         public Command(String cmd, Object... args) {
             mCmd = cmd;
@@ -586,11 +572,6 @@
         }
     }
 
-    /** {@inheritDoc} */
-    public void monitor() {
-        synchronized (mDaemonLock) { }
-    }
-
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mLocalLog.dump(fd, pw, args);
         pw.println();
@@ -598,12 +579,12 @@
     }
 
     private void log(String logstring) {
-        if (mDebug) Slog.d(TAG, logstring);
+        if (mDebug) Log.d(TAG, logstring);
         mLocalLog.log(logstring);
     }
 
     private void loge(String logstring) {
-        Slog.e(TAG, logstring);
+        Log.e(TAG, logstring);
         mLocalLog.log(logstring);
     }
 
@@ -659,12 +640,12 @@
                 if (found == null) {
                     // didn't find it - make sure our queue isn't too big before adding
                     while (mPendingCmds.size() >= mMaxCount) {
-                        Slog.e("NativeDaemonConnector.ResponseQueue",
+                        Log.e("NativeDaemonConnector.ResponseQueue",
                                 "more buffered than allowed: " + mPendingCmds.size() +
                                 " >= " + mMaxCount);
                         // let any waiter timeout waiting for this
                         PendingCmd pendingCmd = mPendingCmds.remove();
-                        Slog.e("NativeDaemonConnector.ResponseQueue",
+                        Log.e("NativeDaemonConnector.ResponseQueue",
                                 "Removing request: " + pendingCmd.logCmd + " (" +
                                 pendingCmd.cmdNum + ")");
                     }
@@ -706,7 +687,7 @@
                 result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS);
             } catch (InterruptedException e) {}
             if (result == null) {
-                Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
+                Log.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response");
             }
             return result;
         }
diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java
similarity index 100%
rename from packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java
rename to packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnectorException.java
diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
similarity index 93%
rename from packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java
rename to packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
index e6feda3..5683694 100644
--- a/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java
+++ b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonEvent.java
@@ -16,8 +16,7 @@
 
 package com.android.server;
 
-import android.util.Slog;
-import com.google.android.collect.Lists;
+import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.util.ArrayList;
@@ -179,7 +178,7 @@
      * {@link #getMessage()} for any events matching the requested code.
      */
     public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) {
-        final ArrayList<String> result = Lists.newArrayList();
+        final ArrayList<String> result = new ArrayList<>();
         for (NativeDaemonEvent event : events) {
             if (event.getCode() == matchCode) {
                 result.add(event.getMessage());
@@ -212,7 +211,7 @@
         int wordEnd = -1;
         boolean quoted = false;
 
-        if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'");
+        if (DEBUG_ROUTINE) Log.e(LOGTAG, "parsing '" + rawEvent + "'");
         if (rawEvent.charAt(current) == '\"') {
             quoted = true;
             current++;
@@ -240,14 +239,14 @@
             word = word.replace("\\\\", "\\");
             word = word.replace("\\\"", "\"");
 
-            if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'");
+            if (DEBUG_ROUTINE) Log.e(LOGTAG, "found '" + word + "'");
             parsed.add(word);
 
             // find the beginning of the next word - either of these options
             int nextSpace = rawEvent.indexOf(' ', current);
             int nextQuote = rawEvent.indexOf(" \"", current);
             if (DEBUG_ROUTINE) {
-                Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
+                Log.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote);
             }
             if (nextQuote > -1 && nextQuote <= nextSpace) {
                 quoted = true;
@@ -259,8 +258,8 @@
                 }
             } // else we just start the next word after the current and read til the end
             if (DEBUG_ROUTINE) {
-                Slog.e(LOGTAG, "next loop - current=" + current +
-                        ", length=" + length + ", quoted=" + quoted);
+                Log.e(LOGTAG, "next loop - current=" + current
+                        + ", length=" + length + ", quoted=" + quoted);
             }
         }
         return parsed.toArray(new String[parsed.size()]);
diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java
similarity index 100%
rename from packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java
rename to packages/ConnectivityT/service/src/com/android/server/NativeDaemonTimeoutException.java
diff --git a/packages/Nsd/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
similarity index 89%
rename from packages/Nsd/service/src/com/android/server/NsdService.java
rename to packages/ConnectivityT/service/src/com/android/server/NsdService.java
index 3e02084..497107d 100644
--- a/packages/Nsd/service/src/com/android/server/NsdService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
@@ -16,11 +16,9 @@
 
 package com.android.server;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.database.ContentObserver;
-import android.net.Uri;
+import android.content.pm.PackageManager;
 import android.net.nsd.INsdManager;
 import android.net.nsd.INsdManagerCallback;
 import android.net.nsd.INsdServiceConnector;
@@ -32,16 +30,13 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.Base64;
 import android.util.Log;
 import android.util.Pair;
-import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.DumpUtils;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 import com.android.net.module.util.DnsSdTxtRecord;
@@ -67,7 +62,6 @@
     private static final long CLEANUP_DELAY_MS = 10000;
 
     private final Context mContext;
-    private final NsdSettings mNsdSettings;
     private final NsdStateMachine mNsdStateMachine;
     private final DaemonConnection mDaemon;
     private final NativeCallbackReceiver mDaemonCallback;
@@ -122,30 +116,14 @@
             this.removeMessages(NsdManager.DAEMON_CLEANUP);
         }
 
-        /**
-         * Observes the NSD on/off setting, and takes action when changed.
-         */
-        private void registerForNsdSetting() {
-            final ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    notifyEnabled(isNsdEnabled());
-                }
-            };
-
-            final Uri uri = Settings.Global.getUriFor(Settings.Global.NSD_ON);
-            mNsdSettings.registerContentObserver(uri, contentObserver);
-        }
-
         NsdStateMachine(String name, Handler handler) {
             super(name, handler);
             addState(mDefaultState);
                 addState(mDisabledState, mDefaultState);
                 addState(mEnabledState, mDefaultState);
-            State initialState = isNsdEnabled() ? mEnabledState : mDisabledState;
+            State initialState = mEnabledState;
             setInitialState(initialState);
             setLogRecSize(25);
-            registerForNsdSetting();
         }
 
         class DefaultState extends State {
@@ -228,7 +206,7 @@
                         break;
                     case NsdManager.NATIVE_DAEMON_EVENT:
                     default:
-                        Slog.e(TAG, "Unhandled " + msg);
+                        Log.e(TAG, "Unhandled " + msg);
                         return NOT_HANDLED;
                 }
                 return HANDLED;
@@ -274,7 +252,7 @@
 
             private boolean requestLimitReached(ClientInfo clientInfo) {
                 if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
-                    if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo);
+                    if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo);
                     return true;
                 }
                 return false;
@@ -307,7 +285,7 @@
                         transitionTo(mDisabledState);
                         break;
                     case NsdManager.DISCOVER_SERVICES:
-                        if (DBG) Slog.d(TAG, "Discover services");
+                        if (DBG) Log.d(TAG, "Discover services");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
 
@@ -321,8 +299,8 @@
                         id = getUniqueId();
                         if (discoverServices(id, args.serviceInfo.getServiceType())) {
                             if (DBG) {
-                                Slog.d(TAG, "Discover " + msg.arg2 + " " + id +
-                                        args.serviceInfo.getServiceType());
+                                Log.d(TAG, "Discover " + msg.arg2 + " " + id
+                                        + args.serviceInfo.getServiceType());
                             }
                             storeRequestMap(clientId, id, clientInfo, msg.what);
                             clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
@@ -333,7 +311,7 @@
                         }
                         break;
                     case NsdManager.STOP_DISCOVERY:
-                        if (DBG) Slog.d(TAG, "Stop service discovery");
+                        if (DBG) Log.d(TAG, "Stop service discovery");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
 
@@ -353,7 +331,7 @@
                         }
                         break;
                     case NsdManager.REGISTER_SERVICE:
-                        if (DBG) Slog.d(TAG, "Register service");
+                        if (DBG) Log.d(TAG, "Register service");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
                         if (requestLimitReached(clientInfo)) {
@@ -365,7 +343,7 @@
                         maybeStartDaemon();
                         id = getUniqueId();
                         if (registerService(id, args.serviceInfo)) {
-                            if (DBG) Slog.d(TAG, "Register " + clientId + " " + id);
+                            if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
                             storeRequestMap(clientId, id, clientInfo, msg.what);
                             // Return success after mDns reports success
                         } else {
@@ -375,11 +353,11 @@
                         }
                         break;
                     case NsdManager.UNREGISTER_SERVICE:
-                        if (DBG) Slog.d(TAG, "unregister service");
+                        if (DBG) Log.d(TAG, "unregister service");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
                         if (clientInfo == null) {
-                            Slog.e(TAG, "Unknown connector in unregistration");
+                            Log.e(TAG, "Unknown connector in unregistration");
                             break;
                         }
                         id = clientInfo.mClientIds.get(clientId);
@@ -392,7 +370,7 @@
                         }
                         break;
                     case NsdManager.RESOLVE_SERVICE:
-                        if (DBG) Slog.d(TAG, "Resolve service");
+                        if (DBG) Log.d(TAG, "Resolve service");
                         args = (ListenerArgs) msg.obj;
                         clientInfo = mClients.get(args.connector);
 
@@ -430,7 +408,7 @@
                 ClientInfo clientInfo = mIdToClientInfoMap.get(id);
                 if (clientInfo == null) {
                     String name = NativeResponseCode.nameOf(code);
-                    Slog.e(TAG, String.format("id %d for %s has no client mapping", id, name));
+                    Log.e(TAG, String.format("id %d for %s has no client mapping", id, name));
                     return false;
                 }
 
@@ -441,14 +419,14 @@
                     // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
                     // and we may get in this situation.
                     String name = NativeResponseCode.nameOf(code);
-                    Slog.d(TAG, String.format(
+                    Log.d(TAG, String.format(
                             "Notification %s for listener id %d that is no longer active",
                             name, id));
                     return false;
                 }
                 if (DBG) {
                     String name = NativeResponseCode.nameOf(code);
-                    Slog.d(TAG, String.format("Native daemon message %s: %s", name, raw));
+                    Log.d(TAG, String.format("Native daemon message %s: %s", name, raw));
                 }
                 switch (code) {
                     case NativeResponseCode.SERVICE_FOUND:
@@ -492,7 +470,7 @@
                             ++index;
                         }
                         if (index >= cooked[2].length()) {
-                            Slog.e(TAG, "Invalid service found " + raw);
+                            Log.e(TAG, "Invalid service found " + raw);
                             break;
                         }
                         String name = cooked[2].substring(0, index);
@@ -562,13 +540,13 @@
             char c = s.charAt(i);
             if (c == '\\') {
                 if (++i >= s.length()) {
-                    Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+                    Log.e(TAG, "Unexpected end of escape sequence in: " + s);
                     break;
                 }
                 c = s.charAt(i);
                 if (c != '.' && c != '\\') {
                     if (i + 2 >= s.length()) {
-                        Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+                        Log.e(TAG, "Unexpected end of escape sequence in: " + s);
                         break;
                     }
                     c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
@@ -581,11 +559,9 @@
     }
 
     @VisibleForTesting
-    NsdService(Context ctx, NsdSettings settings, Handler handler,
-            DaemonConnectionSupplier fn, long cleanupDelayMs) {
+    NsdService(Context ctx, Handler handler, DaemonConnectionSupplier fn, long cleanupDelayMs) {
         mCleanupDelayMs = cleanupDelayMs;
         mContext = ctx;
-        mNsdSettings = settings;
         mNsdStateMachine = new NsdStateMachine(TAG, handler);
         mNsdStateMachine.start();
         mDaemonCallback = new NativeCallbackReceiver();
@@ -593,12 +569,11 @@
     }
 
     public static NsdService create(Context context) throws InterruptedException {
-        NsdSettings settings = NsdSettings.makeDefault(context);
         HandlerThread thread = new HandlerThread(TAG);
         thread.start();
         Handler handler = new Handler(thread.getLooper());
-        NsdService service = new NsdService(context, settings, handler,
-                DaemonConnection::new, CLEANUP_DELAY_MS);
+        NsdService service =
+                new NsdService(context, handler, DaemonConnection::new, CLEANUP_DELAY_MS);
         service.mDaemonCallback.awaitConnection();
         return service;
     }
@@ -670,10 +645,6 @@
         }
     }
 
-    private void notifyEnabled(boolean isEnabled) {
-        mNsdStateMachine.sendMessage(isEnabled ? NsdManager.ENABLE : NsdManager.DISABLE);
-    }
-
     private void sendNsdStateChangeBroadcast(boolean isEnabled) {
         final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -682,14 +653,6 @@
         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    private boolean isNsdEnabled() {
-        boolean ret = mNsdSettings.isEnabled();
-        if (DBG) {
-            Slog.d(TAG, "Network service discovery is " + (ret ? "enabled" : "disabled"));
-        }
-        return ret;
-    }
-
     private int getUniqueId() {
         if (++mUniqueId == INVALID_ID) return ++mUniqueId;
         return mUniqueId;
@@ -795,12 +758,12 @@
          */
         public boolean execute(Object... args) {
             if (DBG) {
-                Slog.d(TAG, "mdnssd " + Arrays.toString(args));
+                Log.d(TAG, "mdnssd " + Arrays.toString(args));
             }
             try {
                 mNativeConnector.execute("mdnssd", args);
             } catch (NativeDaemonConnectorException e) {
-                Slog.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
+                Log.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
                 return false;
             }
             return true;
@@ -831,7 +794,7 @@
 
     private boolean registerService(int regId, NsdServiceInfo service) {
         if (DBG) {
-            Slog.d(TAG, "registerService: " + regId + " " + service);
+            Log.d(TAG, "registerService: " + regId + " " + service);
         }
         String name = service.getServiceName();
         String type = service.getServiceType();
@@ -880,7 +843,12 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump " + TAG
+                    + " due to missing android.permission.DUMP permission");
+            return;
+        }
 
         for (ClientInfo client : mClients.values()) {
             pw.println("Client Info");
@@ -909,7 +877,7 @@
 
         private ClientInfo(INsdManagerCallback cb) {
             mCb = cb;
-            if (DBG) Slog.d(TAG, "New client");
+            if (DBG) Log.d(TAG, "New client");
         }
 
         @Override
@@ -943,8 +911,10 @@
                 clientId = mClientIds.keyAt(i);
                 globalId = mClientIds.valueAt(i);
                 mIdToClientInfoMap.remove(globalId);
-                if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId +
-                        " global-ID " + globalId + " type " + mClientRequests.get(clientId));
+                if (DBG) {
+                    Log.d(TAG, "Terminating client-ID " + clientId
+                            + " global-ID " + globalId + " type " + mClientRequests.get(clientId));
+                }
                 switch (mClientRequests.get(clientId)) {
                     case NsdManager.DISCOVER_SERVICES:
                         stopServiceDiscovery(globalId);
@@ -1069,35 +1039,4 @@
             }
         }
     }
-
-    /**
-     * Interface which encapsulates dependencies of NsdService that are hard to mock, hard to
-     * override, or have side effects on global state in unit tests.
-     */
-    @VisibleForTesting
-    public interface NsdSettings {
-        boolean isEnabled();
-        void putEnabledStatus(boolean isEnabled);
-        void registerContentObserver(Uri uri, ContentObserver observer);
-
-        static NsdSettings makeDefault(Context context) {
-            final ContentResolver resolver = context.getContentResolver();
-            return new NsdSettings() {
-                @Override
-                public boolean isEnabled() {
-                    return Settings.Global.getInt(resolver, Settings.Global.NSD_ON, 1) == 1;
-                }
-
-                @Override
-                public void putEnabledStatus(boolean isEnabled) {
-                    Settings.Global.putInt(resolver, Settings.Global.NSD_ON, isEnabled ? 1 : 0);
-                }
-
-                @Override
-                public void registerContentObserver(Uri uri, ContentObserver observer) {
-                    resolver.registerContentObserver(uri, false, observer);
-                }
-            };
-        }
-    }
 }
diff --git a/packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
similarity index 100%
rename from packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
rename to packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 3c78560..99e3160 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -28,13 +28,16 @@
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
 import android.content.Context;
+import android.os.Build;
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import androidx.annotation.RequiresApi;
+
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 public class A2dpProfile implements LocalBluetoothProfile {
@@ -226,6 +229,10 @@
         return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED;
     }
 
+    /**
+     * @return whether high quality audio is enabled or not
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
         BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
         if (bluetoothDevice == null) {
@@ -271,6 +278,13 @@
         }
     }
 
+    /**
+     * Gets the label associated with the codec of a Bluetooth device.
+     *
+     * @param device to get codec label from
+     * @return the label associated with the device codec
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
     public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
         BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
         int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
@@ -280,18 +294,18 @@
         }
         // We want to get the highest priority codec, since that's the one that will be used with
         // this device, and see if it is high-quality (ie non-mandatory).
-        BluetoothCodecConfig[] selectable = null;
+        List<BluetoothCodecConfig> selectable = null;
         if (mService.getCodecStatus(device) != null) {
             selectable = mService.getCodecStatus(device).getCodecsSelectableCapabilities();
             // To get the highest priority, we sort in reverse.
-            Arrays.sort(selectable,
+            Collections.sort(selectable,
                     (a, b) -> {
                         return b.getCodecPriority() - a.getCodecPriority();
                     });
         }
 
-        final BluetoothCodecConfig codecConfig = (selectable == null || selectable.length < 1)
-                ? null : selectable[0];
+        final BluetoothCodecConfig codecConfig = (selectable == null || selectable.size() < 1)
+                ? null : selectable.get(0);
         final int codecType = (codecConfig == null || codecConfig.isMandatoryCodec())
                 ? BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID : codecConfig.getCodecType();
 
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 9afdd43c..f167721 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
@@ -43,6 +43,9 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
 
+import java.util.Arrays;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowBluetoothAdapter.class})
 public class A2dpProfileTest {
@@ -179,7 +182,7 @@
                 BluetoothProfile.STATE_CONNECTED);
         BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
         BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
-        BluetoothCodecConfig[] configs = {config};
+        List<BluetoothCodecConfig> configs = Arrays.asList(config);
         when(mBluetoothA2dp.getCodecStatus(mDevice)).thenReturn(status);
         when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
 
@@ -194,7 +197,7 @@
                 BluetoothProfile.STATE_CONNECTED);
         BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
         BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
-        BluetoothCodecConfig[] configs = {config};
+        List<BluetoothCodecConfig> configs = Arrays.asList(config);
         when(mBluetoothA2dp.getCodecStatus(mDevice)).thenReturn(status);
         when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 9cd7083..c30c742 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -98,6 +98,10 @@
     private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config";
     private static final String KEY_DEVICE_SPECIFIC_CONFIG = "device_specific_config";
     private static final String KEY_SIM_SPECIFIC_SETTINGS = "sim_specific_settings";
+    // Restoring sim-specific data backed up from newer Android version to Android 12 was causing a
+    // fatal crash. Creating a backup with a different key will prevent Android 12 versions from
+    // restoring this data.
+    private static final String KEY_SIM_SPECIFIC_SETTINGS_2 = "sim_specific_settings_2";
 
     // Versioning of the state file.  Increment this version
     // number any time the set of state items is altered.
@@ -253,7 +257,7 @@
                         deviceSpecificInformation, data);
         stateChecksums[STATE_SIM_SPECIFIC_SETTINGS] =
                 writeIfChanged(stateChecksums[STATE_SIM_SPECIFIC_SETTINGS],
-                        KEY_SIM_SPECIFIC_SETTINGS, simSpecificSettingsData, data);
+                        KEY_SIM_SPECIFIC_SETTINGS_2, simSpecificSettingsData, data);
 
         writeNewChecksums(stateChecksums, newState);
     }
@@ -395,6 +399,9 @@
                     break;
 
                 case KEY_SIM_SPECIFIC_SETTINGS:
+                    // Intentional fall through so that sim-specific backups from Android 12 will
+                    // also be restored on newer Android versions.
+                case KEY_SIM_SPECIFIC_SETTINGS_2:
                     byte[] restoredSimSpecificSettings = new byte[size];
                     data.readEntityData(restoredSimSpecificSettings, 0, size);
                     restoreSimSpecificSettings(restoredSimSpecificSettings);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 073b4d0..6c6b0e8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1085,14 +1085,17 @@
                 Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE,
                 GlobalSettingsProto.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE);
 
-        final long nitzUpdateToken = p.start(GlobalSettingsProto.NITZ_UPDATE);
+        final long nitzToken = p.start(GlobalSettingsProto.NITZ);
         dumpSetting(s, p,
                 Settings.Global.NITZ_UPDATE_DIFF,
-                GlobalSettingsProto.NitzUpdate.DIFF);
+                GlobalSettingsProto.Nitz.UPDATE_DIFF);
         dumpSetting(s, p,
                 Settings.Global.NITZ_UPDATE_SPACING,
-                GlobalSettingsProto.NitzUpdate.SPACING);
-        p.end(nitzUpdateToken);
+                GlobalSettingsProto.Nitz.UPDATE_SPACING);
+        dumpSetting(s, p,
+                Settings.Global.NITZ_NETWORK_DISCONNECT_RETENTION,
+                GlobalSettingsProto.Nitz.NETWORK_DISCONNECT_RETENTION);
+        p.end(nitzToken);
 
         final long notificationToken = p.start(GlobalSettingsProto.NOTIFICATION);
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 3297937..773b068 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -388,6 +388,7 @@
                     Settings.Global.NETWORK_WATCHLIST_ENABLED,
                     Settings.Global.NEW_CONTACT_AGGREGATOR,
                     Settings.Global.NIGHT_DISPLAY_FORCED_AUTO_MODE_AVAILABLE,
+                    Settings.Global.NITZ_NETWORK_DISCONNECT_RETENTION,
                     Settings.Global.NITZ_UPDATE_DIFF,
                     Settings.Global.NITZ_UPDATE_SPACING,
                     Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 97cc948..87d50f2 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -578,6 +578,9 @@
     <!-- Permission required for CTS test - SettingsMultiPaneDeepLinkTest -->
     <uses-permission android:name="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK" />
 
+    <!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
+    <uses-permission android:name="android.permission.LOCK_DEVICE" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/tests/AndroidTest.xml b/packages/SystemUI/tests/AndroidTest.xml
index fc353a1..5ffd300 100644
--- a/packages/SystemUI/tests/AndroidTest.xml
+++ b/packages/SystemUI/tests/AndroidTest.xml
@@ -18,12 +18,17 @@
         <option name="test-file-name" value="SystemUITests.apk" />
     </target_preparer>
 
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+        <option name="force-root" value="true" />
+    </target_preparer>
+
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="framework-base-presubmit" />
     <option name="test-tag" value="SystemUITests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.systemui.tests" />
         <option name="runner" value="android.testing.TestableInstrumentation" />
+        <option name="test-filter-dir" value="/data/data/com.android.systemui.tests" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/services/Android.bp b/services/Android.bp
index cc0fd98..e11b044 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -23,6 +23,36 @@
     },
 }
 
+// Opt-in config for optimizing and shrinking the services target using R8.
+// Enabled via `export SYSTEM_OPTIMIZE_JAVA=true`, or explicitly in Make via the
+// `SOONG_CONFIG_ANDROID_SYSTEM_OPTIMIZE_JAVA` variable.
+// TODO(b/196084106): Enable optimizations by default after stabilizing and
+// building out retrace infrastructure.
+soong_config_module_type {
+    name: "system_optimized_java_defaults",
+    module_type: "java_defaults",
+    config_namespace: "ANDROID",
+    bool_variables: ["SYSTEM_OPTIMIZE_JAVA"],
+    properties: ["optimize"],
+}
+
+system_optimized_java_defaults {
+    name: "services_java_defaults",
+    soong_config_variables: {
+        SYSTEM_OPTIMIZE_JAVA: {
+            optimize: {
+                enabled: true,
+                optimize: true,
+                shrink: true,
+                proguard_flags_files: ["proguard.flags"],
+            },
+            // Note: Optimizations are disabled by default if unspecified in
+            // the java_library rule.
+            conditions_default: {},
+        },
+    },
+}
+
 filegroup {
     name: "services-main-sources",
     srcs: [
@@ -81,6 +111,7 @@
 // ============================================================
 java_library {
     name: "services",
+    defaults: ["services_java_defaults"],
     installable: true,
 
     dex_preopt: {
diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
index 263ff18..380b1f3 100644
--- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
+++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
@@ -112,9 +112,9 @@
     void handleAirplaneModeChange() {
         if (shouldSkipAirplaneModeChange()) {
             Log.i(TAG, "Ignore airplane mode change");
-            // We have to store Bluetooth state here, so if user turns off Bluetooth
-            // after airplane mode is turned on, we don't forget to turn on Bluetooth
-            // when airplane mode turns off.
+            // Airplane mode enabled when Bluetooth is being used for audio/headering aid.
+            // Bluetooth is not disabled in such case, only state is changed to
+            // BLUETOOTH_ON_AIRPLANE mode.
             mAirplaneHelper.setSettingsInt(Settings.Global.BLUETOOTH_ON,
                     BluetoothManagerService.BLUETOOTH_ON_AIRPLANE);
             if (shouldPopToast()) {
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index b641377..71b463a 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -25,13 +25,14 @@
 per-file *Binder* = file:/core/java/com/android/internal/os/BINDER_OWNERS
 per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
 per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
+per-file **IpSec* = file:/services/core/java/com/android/server/net/OWNERS
+per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
 per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
 per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
 per-file *Storage* = file:/core/java/android/os/storage/OWNERS
 per-file *TimeUpdate* = file:/core/java/android/app/timezone/OWNERS
 per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS
 per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
-per-file IpSecService.java = file:/services/core/java/com/android/server/net/OWNERS
 per-file MmsServiceBroker.java = file:/telephony/OWNERS
 per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS
 per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index cb6e73a..3cc8e76 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -21,18 +21,16 @@
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.pm.UserInfo;
-import android.os.Build;
 import android.os.Environment;
 import android.os.SystemClock;
 import android.os.Trace;
-import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.os.ClassLoaderFactory;
+import com.android.internal.os.SystemServerClassLoaderFactory;
 import com.android.internal.util.Preconditions;
 import com.android.server.SystemService.TargetUser;
 import com.android.server.am.EventLogTags;
@@ -77,9 +75,6 @@
     // Services that should receive lifecycle events.
     private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
 
-    // Map of paths to PathClassLoader, so we don't load the same path multiple times.
-    private final ArrayMap<String, PathClassLoader> mLoadedPaths = new ArrayMap<>();
-
     private int mCurrentPhase = -1;
 
     private UserManagerInternal mUserManagerInternal;
@@ -119,16 +114,8 @@
      * @return The service instance.
      */
     public SystemService startServiceFromJar(String className, String path) {
-        PathClassLoader pathClassLoader = mLoadedPaths.get(path);
-        if (pathClassLoader == null) {
-            // NB: the parent class loader should always be the system server class loader.
-            // Changing it has implications that require discussion with the mainline team.
-            pathClassLoader = (PathClassLoader) ClassLoaderFactory.createClassLoader(
-                    path, null /* librarySearchPath */, null /* libraryPermittedPath */,
-                    this.getClass().getClassLoader(), Build.VERSION.SDK_INT,
-                    true /* isNamespaceShared */, null /* classLoaderName */);
-            mLoadedPaths.put(path, pathClassLoader);
-        }
+        PathClassLoader pathClassLoader = SystemServerClassLoaderFactory.getOrCreateClassLoader(
+                path, this.getClass().getClassLoader());
         final Class<SystemService> serviceClass = loadClassFromLoader(className, pathClassLoader);
         return startService(serviceClass);
     }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b77270f..6c84ca4 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -374,6 +374,16 @@
     private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
 
     /**
+     * Native heap allocations in AppZygote process and its descendants will now have a
+     * non-zero tag in the most significant byte.
+     * @see <a href="https://source.android.com/devices/tech/debug/tagged-pointers">Tagged
+     * Pointers</a>
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S)
+    private static final long NATIVE_HEAP_POINTER_TAGGING_APP_ZYGOTE = 207557677;
+
+    /**
      * Enable asynchronous (ASYNC) memory tag checking in this process. This
      * flag will only have an effect on hardware supporting the ARM Memory
      * Tagging Extension (MTE).
@@ -1738,6 +1748,16 @@
         return level;
     }
 
+    private int decideTaggingLevelForAppZygote(ProcessRecord app) {
+        int level = decideTaggingLevel(app);
+        // TBI ("fake" pointer tagging) in AppZygote is controlled by a separate compat feature.
+        if (!mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING_APP_ZYGOTE, app.info)
+                && level == Zygote.MEMORY_TAG_LEVEL_TBI) {
+            level = Zygote.MEMORY_TAG_LEVEL_NONE;
+        }
+        return level;
+    }
+
     private int decideGwpAsanLevel(ProcessRecord app) {
         // Look at the process attribute first.
        if (app.processInfo != null
@@ -2238,7 +2258,8 @@
                 // not the calling one.
                 appInfo.packageName = app.getHostingRecord().getDefiningPackageName();
                 appInfo.uid = uid;
-                appZygote = new AppZygote(appInfo, uid, firstUid, lastUid);
+                int runtimeFlags = decideTaggingLevelForAppZygote(app);
+                appZygote = new AppZygote(appInfo, uid, firstUid, lastUid, runtimeFlags);
                 mAppZygotes.put(app.info.processName, uid, appZygote);
                 zygoteProcessList = new ArrayList<ProcessRecord>();
                 mAppZygoteProcesses.put(appZygote, zygoteProcessList);
diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS
index 4eac972..f05f403 100644
--- a/services/core/java/com/android/server/biometrics/OWNERS
+++ b/services/core/java/com/android/server/biometrics/OWNERS
@@ -6,3 +6,4 @@
 ilyamaty@google.com
 joshmccloskey@google.com
 jbolinger@google.com
+graciecheng@google.com
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 6ea84ce..ee5bda3 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -171,25 +171,28 @@
     }
 
     private NetworkMetrics getMetricsForNetwork(long timeMs, int netId) {
-        collectPendingMetricsSnapshot(timeMs);
         NetworkMetrics metrics = mNetworkMetrics.get(netId);
-        if (metrics == null) {
-            // TODO: allow to change transport for a given netid.
-            metrics = new NetworkMetrics(netId, getTransports(netId), mConnectTb);
+        final NetworkCapabilities nc = mCallback.getNetworkCapabilities(netId);
+        final long transports = (nc != null) ? BitUtils.packBits(nc.getTransportTypes()) : 0;
+        final boolean forceCollect =
+                (metrics != null && nc != null && metrics.transports != transports);
+        collectPendingMetricsSnapshot(timeMs, forceCollect);
+        if (metrics == null || forceCollect) {
+            metrics = new NetworkMetrics(netId, transports, mConnectTb);
             mNetworkMetrics.put(netId, metrics);
         }
         return metrics;
     }
 
     private NetworkMetricsSnapshot[] getNetworkMetricsSnapshots() {
-        collectPendingMetricsSnapshot(System.currentTimeMillis());
+        collectPendingMetricsSnapshot(System.currentTimeMillis(), false /* forceCollect */);
         return mNetworkMetricsSnapshots.toArray();
     }
 
-    private void collectPendingMetricsSnapshot(long timeMs) {
+    private void collectPendingMetricsSnapshot(long timeMs, boolean forceCollect) {
         // Detects time differences larger than the snapshot collection period.
         // This is robust against clock jumps and long inactivity periods.
-        if (Math.abs(timeMs - mLastSnapshot) <= METRICS_SNAPSHOT_SPAN_MS) {
+        if (!forceCollect && Math.abs(timeMs - mLastSnapshot) <= METRICS_SNAPSHOT_SPAN_MS) {
             return;
         }
         mLastSnapshot = projectSnapshotTime(timeMs);
@@ -394,14 +397,6 @@
         return list;
     }
 
-    private long getTransports(int netId) {
-        final NetworkCapabilities nc = mCallback.getNetworkCapabilities(netId);
-        if (nc == null) {
-            return 0;
-        }
-        return BitUtils.packBits(nc.getTransportTypes());
-    }
-
     /** Helper class for buffering summaries of NetworkMetrics at regular time intervals */
     static class NetworkMetricsSnapshot {
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index b45d87f..81106b1 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -566,7 +566,13 @@
         }
     }
 
-    private static final class Data {
+    /**
+     * Container class for all networkpolicy events data.
+     *
+     * Note: This class needs to be public for RingBuffer class to be able to create
+     * new instances of this.
+     */
+    public static final class Data {
         public int type;
         public long timeStamp;
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 1aa80a9..5b4084e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2438,6 +2438,15 @@
         }
     }
 
+    private String getApexPackageNameContainingPackage(String pkg) {
+        ApexManager apexManager = ApexManager.getInstance();
+        return apexManager.getActiveApexPackageNameContainingPackage(pkg);
+    }
+
+    private boolean isApexApp(String pkg) {
+        return getApexPackageNameContainingPackage(pkg) != null;
+    }
+
     private int runGetPrivappPermissions() {
         final String pkg = getNextArg();
         if (pkg == null) {
@@ -2453,6 +2462,9 @@
         } else if (isSystemExtApp(pkg)) {
             privAppPermissions = SystemConfig.getInstance()
                     .getSystemExtPrivAppPermissions(pkg);
+        } else if (isApexApp(pkg)) {
+            privAppPermissions = SystemConfig.getInstance()
+                    .getApexPrivAppPermissions(getApexPackageNameContainingPackage(pkg), pkg);
         } else {
             privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
         }
@@ -2477,6 +2489,9 @@
         } else if (isSystemExtApp(pkg)) {
             privAppPermissions = SystemConfig.getInstance()
                     .getSystemExtPrivAppDenyPermissions(pkg);
+        } else if (isApexApp(pkg)) {
+            privAppPermissions = SystemConfig.getInstance()
+                    .getApexPrivAppDenyPermissions(getApexPackageNameContainingPackage(pkg), pkg);
         } else {
             privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
         }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 7b12709..f733a2e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3443,10 +3443,15 @@
             return true;
         }
         final String permissionName = permission.getName();
-        if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) {
+        final ApexManager apexManager = ApexManager.getInstance();
+        final String containingApexPackageName =
+                apexManager.getActiveApexPackageNameContainingPackage(packageName);
+        if (isInSystemConfigPrivAppPermissions(pkg, permissionName,
+                containingApexPackageName)) {
             return true;
         }
-        if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) {
+        if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName,
+                containingApexPackageName)) {
             return false;
         }
         // Updated system apps do not need to be allowlisted
@@ -3463,9 +3468,6 @@
         }
         // Only enforce the allowlist on boot
         if (!mSystemReady) {
-            final ApexManager apexManager = ApexManager.getInstance();
-            final String containingApexPackageName =
-                    apexManager.getActiveApexPackageNameContainingPackage(packageName);
             final boolean isInUpdatedApex = containingApexPackageName != null
                     && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
                     MATCH_ACTIVE_PACKAGE));
@@ -3489,7 +3491,7 @@
     }
 
     private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg,
-            @NonNull String permission) {
+            @NonNull String permission, String containingApexPackageName) {
         final SystemConfig systemConfig = SystemConfig.getInstance();
         final Set<String> permissions;
         if (pkg.isVendor()) {
@@ -3498,6 +3500,26 @@
             permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName());
         } else if (pkg.isSystemExt()) {
             permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName());
+        } else if (containingApexPackageName != null) {
+            final Set<String> privAppPermissions = systemConfig.getPrivAppPermissions(
+                    pkg.getPackageName());
+            final Set<String> apexPermissions = systemConfig.getApexPrivAppPermissions(
+                    containingApexPackageName, pkg.getPackageName());
+            if (privAppPermissions != null) {
+                // TODO(andreionea): Remove check as soon as all apk-in-apex
+                // permission allowlists are migrated.
+                Slog.w(TAG, "Package " + pkg.getPackageName() + " is an APK in APEX,"
+                        + " but has permission allowlist on the system image. Please bundle the"
+                        + " allowlist in the " + containingApexPackageName + " APEX instead.");
+                if (apexPermissions != null) {
+                    permissions = new ArraySet<>(privAppPermissions);
+                    permissions.addAll(apexPermissions);
+                } else {
+                    permissions = privAppPermissions;
+                }
+            } else {
+                permissions = apexPermissions;
+            }
         } else {
             permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName());
         }
@@ -3505,7 +3527,7 @@
     }
 
     private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg,
-            @NonNull String permission) {
+            @NonNull String permission, String containingApexPackageName) {
         final SystemConfig systemConfig = SystemConfig.getInstance();
         final Set<String> permissions;
         if (pkg.isVendor()) {
@@ -3514,6 +3536,9 @@
             permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName());
         } else if (pkg.isSystemExt()) {
             permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
+        } else if (containingApexPackageName != null) {
+            permissions = systemConfig.getApexPrivAppDenyPermissions(containingApexPackageName,
+                    pkg.getPackageName());
         } else {
             permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName());
         }
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index be13168..8b80b4a 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -77,6 +77,7 @@
 import android.os.PowerManager.WakeLock;
 import android.os.Process;
 import android.os.SystemClock;
+import android.provider.Settings;
 import android.util.ArraySet;
 import android.util.Slog;
 
@@ -686,6 +687,7 @@
         mUnderlyingNetworkController =
                 mDeps.newUnderlyingNetworkController(
                         mVcnContext,
+                        mConnectionConfig,
                         subscriptionGroup,
                         mLastSnapshot,
                         mUnderlyingNetworkControllerCallback);
@@ -788,8 +790,19 @@
             // TODO(b/179091925): Move the delayed-message handling to BaseState
 
             // If underlying is null, all underlying networks have been lost. Disconnect VCN after a
-            // timeout.
+            // timeout (or immediately if in airplane mode, since the device user has indicated that
+            // the radios should all be turned off).
             if (underlying == null) {
+                if (mDeps.isAirplaneModeOn(mVcnContext)) {
+                    sendMessageAndAcquireWakeLock(
+                            EVENT_UNDERLYING_NETWORK_CHANGED,
+                            TOKEN_ALL,
+                            new EventUnderlyingNetworkChangedInfo(null));
+                    sendDisconnectRequestedAndAcquireWakelock(
+                            DISCONNECT_REASON_UNDERLYING_NETWORK_LOST, false /* shouldQuit */);
+                    return;
+                }
+
                 setDisconnectRequestAlarm();
             } else {
                 // Received a new Network so any previous alarm is irrelevant - cancel + clear it,
@@ -2364,11 +2377,12 @@
         /** Builds a new UnderlyingNetworkController. */
         public UnderlyingNetworkController newUnderlyingNetworkController(
                 VcnContext vcnContext,
+                VcnGatewayConnectionConfig connectionConfig,
                 ParcelUuid subscriptionGroup,
                 TelephonySubscriptionSnapshot snapshot,
                 UnderlyingNetworkControllerCallback callback) {
             return new UnderlyingNetworkController(
-                    vcnContext, subscriptionGroup, snapshot, callback);
+                    vcnContext, connectionConfig, subscriptionGroup, snapshot, callback);
         }
 
         /** Builds a new IkeSession. */
@@ -2424,6 +2438,12 @@
                     validationStatusCallback);
         }
 
+        /** Checks if airplane mode is enabled. */
+        public boolean isAirplaneModeOn(@NonNull VcnContext vcnContext) {
+            return Settings.Global.getInt(vcnContext.getContext().getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
+        }
+
         /** Gets the elapsed real time since boot, in millis. */
         public long getElapsedRealTime() {
             return SystemClock.elapsedRealtime();
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index bea8ae9..4576957 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -15,25 +15,36 @@
  */
 package com.android.server.vcn.routeselection;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_ANY;
+import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_OK;
 
 import static com.android.server.VcnManagementService.LOCAL_LOG;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnCellUnderlyingNetworkPriority;
 import android.net.vcn.VcnManager;
+import android.net.vcn.VcnUnderlyingNetworkPriority;
+import android.net.vcn.VcnWifiUnderlyingNetworkPriority;
 import android.os.ParcelUuid;
 import android.os.PersistableBundle;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Slog;
-import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import com.android.server.vcn.VcnContext;
 
+import java.util.LinkedHashSet;
 import java.util.Set;
 
 /** @hide */
@@ -56,52 +67,20 @@
      */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
-    /** Priority for any cellular network for which the subscription is listed as opportunistic */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
-    /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_WIFI_IN_USE = 1;
-    /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_WIFI_PROSPECTIVE = 2;
-    /** Priority for any standard macro cellular network */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_MACRO_CELLULAR = 3;
+
     /** Priority for any other networks (including unvalidated, etc) */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     static final int PRIORITY_ANY = Integer.MAX_VALUE;
 
-    private static final SparseArray<String> PRIORITY_TO_STRING_MAP = new SparseArray<>();
-
-    static {
-        PRIORITY_TO_STRING_MAP.put(
-                PRIORITY_OPPORTUNISTIC_CELLULAR, "PRIORITY_OPPORTUNISTIC_CELLULAR");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_IN_USE, "PRIORITY_WIFI_IN_USE");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_PROSPECTIVE, "PRIORITY_WIFI_PROSPECTIVE");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_MACRO_CELLULAR, "PRIORITY_MACRO_CELLULAR");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_ANY, "PRIORITY_ANY");
-    }
-
-    /**
-     * Gives networks a priority class, based on the following priorities:
-     *
-     * <ol>
-     *   <li>Opportunistic cellular
-     *   <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
-     *   <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
-     *   <li>Macro cellular
-     *   <li>Any others
-     * </ol>
-     */
-    static int calculatePriorityClass(
+    /** Gives networks a priority class, based on configured VcnGatewayConnectionConfig */
+    public static int calculatePriorityClass(
+            VcnContext vcnContext,
             UnderlyingNetworkRecord networkRecord,
+            LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities,
             ParcelUuid subscriptionGroup,
             TelephonySubscriptionSnapshot snapshot,
             UnderlyingNetworkRecord currentlySelected,
             PersistableBundle carrierConfig) {
-        final NetworkCapabilities caps = networkRecord.networkCapabilities;
-
         // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
 
         if (networkRecord.isBlocked) {
@@ -109,8 +88,167 @@
             return PRIORITY_ANY;
         }
 
-        if (caps.hasTransport(TRANSPORT_CELLULAR)
-                && isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+        if (snapshot == null) {
+            logWtf("Got null snapshot");
+            return PRIORITY_ANY;
+        }
+
+        int priorityIndex = 0;
+        for (VcnUnderlyingNetworkPriority nwPriority : underlyingNetworkPriorities) {
+            if (checkMatchesPriorityRule(
+                    vcnContext,
+                    nwPriority,
+                    networkRecord,
+                    subscriptionGroup,
+                    snapshot,
+                    currentlySelected,
+                    carrierConfig)) {
+                return priorityIndex;
+            }
+            priorityIndex++;
+        }
+        return PRIORITY_ANY;
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static boolean checkMatchesPriorityRule(
+            VcnContext vcnContext,
+            VcnUnderlyingNetworkPriority networkPriority,
+            UnderlyingNetworkRecord networkRecord,
+            ParcelUuid subscriptionGroup,
+            TelephonySubscriptionSnapshot snapshot,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        // TODO: Check Network Quality reported by metric monitors/probers.
+
+        final NetworkCapabilities caps = networkRecord.networkCapabilities;
+        if (!networkPriority.allowMetered() && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+            return false;
+        }
+
+        if (vcnContext.isInTestMode() && caps.hasTransport(TRANSPORT_TEST)) {
+            return true;
+        }
+
+        if (networkPriority instanceof VcnWifiUnderlyingNetworkPriority) {
+            return checkMatchesWifiPriorityRule(
+                    (VcnWifiUnderlyingNetworkPriority) networkPriority,
+                    networkRecord,
+                    currentlySelected,
+                    carrierConfig);
+        }
+
+        if (networkPriority instanceof VcnCellUnderlyingNetworkPriority) {
+            return checkMatchesCellPriorityRule(
+                    vcnContext,
+                    (VcnCellUnderlyingNetworkPriority) networkPriority,
+                    networkRecord,
+                    subscriptionGroup,
+                    snapshot);
+        }
+
+        logWtf(
+                "Got unknown VcnUnderlyingNetworkPriority class: "
+                        + networkPriority.getClass().getSimpleName());
+        return false;
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static boolean checkMatchesWifiPriorityRule(
+            VcnWifiUnderlyingNetworkPriority networkPriority,
+            UnderlyingNetworkRecord networkRecord,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        final NetworkCapabilities caps = networkRecord.networkCapabilities;
+
+        if (!caps.hasTransport(TRANSPORT_WIFI)) {
+            return false;
+        }
+
+        // TODO: Move the Network Quality check to the network metric monitor framework.
+        if (networkPriority.getNetworkQuality()
+                > getWifiQuality(networkRecord, currentlySelected, carrierConfig)) {
+            return false;
+        }
+
+        if (networkPriority.getSsid() != null && networkPriority.getSsid() != caps.getSsid()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static int getWifiQuality(
+            UnderlyingNetworkRecord networkRecord,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        final NetworkCapabilities caps = networkRecord.networkCapabilities;
+        final boolean isSelectedNetwork =
+                currentlySelected != null
+                        && networkRecord.network.equals(currentlySelected.network);
+
+        if (isSelectedNetwork
+                && caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)) {
+            return NETWORK_QUALITY_OK;
+        }
+
+        if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
+            return NETWORK_QUALITY_OK;
+        }
+
+        return NETWORK_QUALITY_ANY;
+    }
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public static boolean checkMatchesCellPriorityRule(
+            VcnContext vcnContext,
+            VcnCellUnderlyingNetworkPriority networkPriority,
+            UnderlyingNetworkRecord networkRecord,
+            ParcelUuid subscriptionGroup,
+            TelephonySubscriptionSnapshot snapshot) {
+        final NetworkCapabilities caps = networkRecord.networkCapabilities;
+
+        if (!caps.hasTransport(TRANSPORT_CELLULAR)) {
+            return false;
+        }
+
+        final TelephonyNetworkSpecifier telephonyNetworkSpecifier =
+                ((TelephonyNetworkSpecifier) caps.getNetworkSpecifier());
+        if (telephonyNetworkSpecifier == null) {
+            logWtf("Got null NetworkSpecifier");
+            return false;
+        }
+
+        final int subId = telephonyNetworkSpecifier.getSubscriptionId();
+        final TelephonyManager subIdSpecificTelephonyMgr =
+                vcnContext
+                        .getContext()
+                        .getSystemService(TelephonyManager.class)
+                        .createForSubscriptionId(subId);
+
+        if (!networkPriority.getAllowedOperatorPlmnIds().isEmpty()) {
+            final String plmnId = subIdSpecificTelephonyMgr.getNetworkOperator();
+            if (!networkPriority.getAllowedOperatorPlmnIds().contains(plmnId)) {
+                return false;
+            }
+        }
+
+        if (!networkPriority.getAllowedSpecificCarrierIds().isEmpty()) {
+            final int carrierId = subIdSpecificTelephonyMgr.getSimSpecificCarrierId();
+            if (!networkPriority.getAllowedSpecificCarrierIds().contains(carrierId)) {
+                return false;
+            }
+        }
+
+        if (!networkPriority.allowRoaming() && !caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
+            return false;
+        }
+
+        if (networkPriority.requireOpportunistic()) {
+            if (!isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+                return false;
+            }
+
             // If this carrier is the active data provider, ensure that opportunistic is only
             // ever prioritized if it is also the active data subscription. This ensures that
             // if an opportunistic subscription is still in the process of being switched to,
@@ -121,36 +259,15 @@
             // Allow the following two cases:
             // 1. Active subId is NOT in the group that this VCN is supporting
             // 2. This opportunistic subscription is for the active subId
-            if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
+            if (snapshot.getAllSubIdsInGroup(subscriptionGroup)
                             .contains(SubscriptionManager.getActiveDataSubscriptionId())
-                    || caps.getSubscriptionIds()
+                    && !caps.getSubscriptionIds()
                             .contains(SubscriptionManager.getActiveDataSubscriptionId())) {
-                return PRIORITY_OPPORTUNISTIC_CELLULAR;
+                return false;
             }
         }
 
-        if (caps.hasTransport(TRANSPORT_WIFI)) {
-            if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
-                    && currentlySelected != null
-                    && networkRecord.network.equals(currentlySelected.network)) {
-                return PRIORITY_WIFI_IN_USE;
-            }
-
-            if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
-                return PRIORITY_WIFI_PROSPECTIVE;
-            }
-        }
-
-        // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
-        // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
-        // the case if the Default Data SubId does not support certain services (eg voice
-        // calling)
-        if (caps.hasTransport(TRANSPORT_CELLULAR)
-                && !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
-            return PRIORITY_MACRO_CELLULAR;
-        }
-
-        return PRIORITY_ANY;
+        return true;
     }
 
     static boolean isOpportunistic(
@@ -185,10 +302,6 @@
         return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
     }
 
-    static String priorityClassToString(int priorityClass) {
-        return PRIORITY_TO_STRING_MAP.get(priorityClass, "unknown");
-    }
-
     private static void logWtf(String msg) {
         Slog.wtf(TAG, msg);
         LOCAL_LOG.log(TAG + " WTF: " + msg);
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index 071c7a6..cd124ee 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -32,6 +32,8 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnGatewayConnectionConfig;
+import android.net.vcn.VcnUnderlyingNetworkPriority;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.ParcelUuid;
@@ -68,6 +70,7 @@
     @NonNull private static final String TAG = UnderlyingNetworkController.class.getSimpleName();
 
     @NonNull private final VcnContext mVcnContext;
+    @NonNull private final VcnGatewayConnectionConfig mConnectionConfig;
     @NonNull private final ParcelUuid mSubscriptionGroup;
     @NonNull private final UnderlyingNetworkControllerCallback mCb;
     @NonNull private final Dependencies mDeps;
@@ -91,24 +94,22 @@
 
     public UnderlyingNetworkController(
             @NonNull VcnContext vcnContext,
+            @NonNull VcnGatewayConnectionConfig connectionConfig,
             @NonNull ParcelUuid subscriptionGroup,
             @NonNull TelephonySubscriptionSnapshot snapshot,
             @NonNull UnderlyingNetworkControllerCallback cb) {
-        this(
-                vcnContext,
-                subscriptionGroup,
-                snapshot,
-                cb,
-                new Dependencies());
+        this(vcnContext, connectionConfig, subscriptionGroup, snapshot, cb, new Dependencies());
     }
 
     private UnderlyingNetworkController(
             @NonNull VcnContext vcnContext,
+            @NonNull VcnGatewayConnectionConfig connectionConfig,
             @NonNull ParcelUuid subscriptionGroup,
             @NonNull TelephonySubscriptionSnapshot snapshot,
             @NonNull UnderlyingNetworkControllerCallback cb,
             @NonNull Dependencies deps) {
         mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
+        mConnectionConfig = Objects.requireNonNull(connectionConfig, "Missing connectionConfig");
         mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
         mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
         mCb = Objects.requireNonNull(cb, "Missing cb");
@@ -399,6 +400,8 @@
             TreeSet<UnderlyingNetworkRecord> sorted =
                     new TreeSet<>(
                             UnderlyingNetworkRecord.getComparator(
+                                    mVcnContext,
+                                    mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
                                     mSubscriptionGroup,
                                     mLastSnapshot,
                                     mCurrentRecord,
@@ -495,12 +498,31 @@
         pw.println(
                 "Currently selected: " + (mCurrentRecord == null ? null : mCurrentRecord.network));
 
+        pw.println("VcnUnderlyingNetworkPriority list:");
+        pw.increaseIndent();
+        int index = 0;
+        for (VcnUnderlyingNetworkPriority priority :
+                mConnectionConfig.getVcnUnderlyingNetworkPriorities()) {
+            pw.println("Priority index: " + index);
+            priority.dump(pw);
+            index++;
+        }
+        pw.decreaseIndent();
+        pw.println();
+
         pw.println("Underlying networks:");
         pw.increaseIndent();
         if (mRouteSelectionCallback != null) {
             for (UnderlyingNetworkRecord record :
                     mRouteSelectionCallback.getSortedUnderlyingNetworks()) {
-                record.dump(pw, mSubscriptionGroup, mLastSnapshot, mCurrentRecord, mCarrierConfig);
+                record.dump(
+                        mVcnContext,
+                        pw,
+                        mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
+                        mSubscriptionGroup,
+                        mLastSnapshot,
+                        mCurrentRecord,
+                        mCarrierConfig);
             }
         }
         pw.decreaseIndent();
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
index 65c69de..27ba854 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
@@ -21,6 +21,7 @@
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.vcn.VcnUnderlyingNetworkPriority;
 import android.os.ParcelUuid;
 import android.os.PersistableBundle;
 
@@ -28,8 +29,10 @@
 import com.android.internal.annotations.VisibleForTesting.Visibility;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import com.android.server.vcn.VcnContext;
 
 import java.util.Comparator;
+import java.util.LinkedHashSet;
 import java.util.Objects;
 
 /**
@@ -73,22 +76,64 @@
     }
 
     static Comparator<UnderlyingNetworkRecord> getComparator(
+            VcnContext vcnContext,
+            LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities,
             ParcelUuid subscriptionGroup,
             TelephonySubscriptionSnapshot snapshot,
             UnderlyingNetworkRecord currentlySelected,
             PersistableBundle carrierConfig) {
         return (left, right) -> {
-            return Integer.compare(
+            final int leftIndex =
                     NetworkPriorityClassifier.calculatePriorityClass(
-                            left, subscriptionGroup, snapshot, currentlySelected, carrierConfig),
+                            vcnContext,
+                            left,
+                            underlyingNetworkPriorities,
+                            subscriptionGroup,
+                            snapshot,
+                            currentlySelected,
+                            carrierConfig);
+            final int rightIndex =
                     NetworkPriorityClassifier.calculatePriorityClass(
-                            right, subscriptionGroup, snapshot, currentlySelected, carrierConfig));
+                            vcnContext,
+                            right,
+                            underlyingNetworkPriorities,
+                            subscriptionGroup,
+                            snapshot,
+                            currentlySelected,
+                            carrierConfig);
+
+            // In the case of networks in the same priority class, prioritize based on other
+            // criteria (eg. actively selected network, link metrics, etc)
+            if (leftIndex == rightIndex) {
+                // TODO: Improve the strategy of network selection when both UnderlyingNetworkRecord
+                // fall into the same priority class.
+                if (isSelected(left, currentlySelected)) {
+                    return -1;
+                }
+                if (isSelected(left, currentlySelected)) {
+                    return 1;
+                }
+            }
+            return Integer.compare(leftIndex, rightIndex);
         };
     }
 
+    private static boolean isSelected(
+            UnderlyingNetworkRecord recordToCheck, UnderlyingNetworkRecord currentlySelected) {
+        if (currentlySelected == null) {
+            return false;
+        }
+        if (currentlySelected.network == recordToCheck.network) {
+            return true;
+        }
+        return false;
+    }
+
     /** Dumps the state of this record for logging and debugging purposes. */
     void dump(
+            VcnContext vcnContext,
             IndentingPrintWriter pw,
+            LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities,
             ParcelUuid subscriptionGroup,
             TelephonySubscriptionSnapshot snapshot,
             UnderlyingNetworkRecord currentlySelected,
@@ -96,15 +141,17 @@
         pw.println("UnderlyingNetworkRecord:");
         pw.increaseIndent();
 
-        final int priorityClass =
+        final int priorityIndex =
                 NetworkPriorityClassifier.calculatePriorityClass(
-                        this, subscriptionGroup, snapshot, currentlySelected, carrierConfig);
-        pw.println(
-                "Priority class: "
-                        + NetworkPriorityClassifier.priorityClassToString(priorityClass)
-                        + " ("
-                        + priorityClass
-                        + ")");
+                        vcnContext,
+                        this,
+                        underlyingNetworkPriorities,
+                        subscriptionGroup,
+                        snapshot,
+                        currentlySelected,
+                        carrierConfig);
+
+        pw.println("Priority index:" + priorityIndex);
         pw.println("mNetwork: " + network);
         pw.println("mNetworkCapabilities: " + networkCapabilities);
         pw.println("mLinkProperties: " + linkProperties);
diff --git a/services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java b/services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java
index 5c1b5ff..1c675c2 100644
--- a/services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java
+++ b/services/core/java/com/android/server/vcn/util/PersistableBundleUtils.java
@@ -46,6 +46,7 @@
     private static final String PARCEL_UUID_KEY = "PARCEL_UUID";
     private static final String BYTE_ARRAY_KEY = "BYTE_ARRAY_KEY";
     private static final String INTEGER_KEY = "INTEGER_KEY";
+    private static final String STRING_KEY = "STRING_KEY";
 
     /**
      * Functional interface to convert an object of the specified type to a PersistableBundle.
@@ -91,6 +92,21 @@
                 return bundle.getInt(INTEGER_KEY);
             };
 
+    /** Serializer to convert s String to a PersistableBundle. */
+    public static final Serializer<String> STRING_SERIALIZER =
+            (i) -> {
+                final PersistableBundle result = new PersistableBundle();
+                result.putString(STRING_KEY, i);
+                return result;
+            };
+
+    /** Deserializer to convert a PersistableBundle to a String. */
+    public static final Deserializer<String> STRING_DESERIALIZER =
+            (bundle) -> {
+                Objects.requireNonNull(bundle, "PersistableBundle is null");
+                return bundle.getString(STRING_KEY);
+            };
+
     /**
      * Converts a ParcelUuid to a PersistableBundle.
      *
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 710a304..e7005da 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -85,6 +85,7 @@
 
     header_libs: [
         "bionic_libc_platform_headers",
+        "bpf_connectivity_headers",
     ],
 }
 
diff --git a/services/proguard.flags b/services/proguard.flags
new file mode 100644
index 0000000..30dd6cf
--- /dev/null
+++ b/services/proguard.flags
@@ -0,0 +1,11 @@
+# TODO(b/196084106): Refine and optimize this configuration. Note that this
+# configuration is only used when `SOONG_CONFIG_ANDROID_SYSTEM_OPTIMIZE_JAVA=true`.
+-keep,allowoptimization,allowaccessmodification class ** {
+  *;
+}
+
+# Various classes subclassed in ethernet-service (avoid marking final).
+-keep public class android.net.** { *; }
+
+# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing).
+-keep public class com.android.server.utils.Slogf { *; }
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/OWNERS b/services/tests/servicestests/src/com/android/server/biometrics/OWNERS
index 8765c9a..6a2192a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/biometrics/OWNERS
@@ -1,7 +1 @@
-set noparent
-
-kchyn@google.com
-jaggies@google.com
-curtislb@google.com
-ilyamaty@google.com
-joshmccloskey@google.com
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index d06fe45..2b855e9 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -822,6 +822,17 @@
             "android.telecom.extra.AUDIO_CODEC_BANDWIDTH_KHZ";
 
     /**
+     * Last known cell identity key to be used to fill geo location header in case of an emergency
+     * call. This entry will not be filled if call is not identified as an emergency call.
+     * {@link Connection}. Only provided to the {@link ConnectionService} for the purpose
+     * of placing an emergency call; will not be present in the {@link InCallService} layer.
+     * The {@link ConnectionService}'s implementation will be logged for fine location access
+     * when an outgoing call is placed in this case.
+     */
+    public static final String EXTRA_LAST_KNOWN_CELL_IDENTITY =
+            "android.telecom.extra.LAST_KNOWN_CELL_IDENTITY";
+
+    /**
      * Boolean connection extra key used to indicate whether device to device communication is
      * available for the current call.
      * @hide
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 4d81b5e..fcc23a9 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -107,6 +107,26 @@
         }
     }
 
+
+    /**
+     * Check whether the caller (or self, if not processing an IPC) has non dangerous
+     * read phone state permission.
+     * @param context app context
+     * @param message detail message
+     * @return true if permission is granted, else false
+     */
+    public static boolean checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
+            Context context, String message) {
+        try {
+            context.enforcePermission(
+                    Manifest.permission.READ_BASIC_PHONE_STATE,
+                    Binder.getCallingPid(), Binder.getCallingUid(), message);
+            return true;
+        } catch (SecurityException se) {
+            return false;
+        }
+    }
+
     /**
      * Check whether the app with the given pid/uid can read phone state.
      *
@@ -545,6 +565,17 @@
     }
 
     /**
+     * Check if the caller (or self, if not processing an IPC) has ACCESS_LAST_KNOWN_CELL_ID
+     * permission
+     *
+     * @return true if caller has ACCESS_LAST_KNOWN_CELL_ID permission else false.
+     */
+    public static boolean checkLastKnownCellIdAccessPermission(Context context) {
+        return context.checkCallingOrSelfPermission("android.permission.ACCESS_LAST_KNOWN_CELL_ID")
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
      * Ensure the caller (or self, if not processing an IPC) has
      * {@link android.Manifest.permission#READ_PHONE_STATE} or carrier privileges.
      *
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a1d68b2..a2efc96 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1895,9 +1895,10 @@
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
      * <p>
-     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE})
     @Nullable
     public String getDeviceSoftwareVersion() {
         return getDeviceSoftwareVersion(getSlotIndex());
@@ -2959,7 +2960,9 @@
      * when opportunistic network is providing cellular internet connection to the user.
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * or {@link android.Manifest.permission#READ_BASIC_PHONE_STATE
+     * READ_BASIC_PHONE_STATE} or that the calling app has carrier privileges
+     * (see {@link #hasCarrierPrivileges}).
      *
      * @return the network type
      *
@@ -2982,7 +2985,9 @@
      * @see #NETWORK_TYPE_NR
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE})
     public @NetworkType int getDataNetworkType() {
         return getDataNetworkType(getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
     }
@@ -3020,10 +3025,14 @@
      * Returns the NETWORK_TYPE_xxxx for voice
      *
      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
-     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * or {@link android.Manifest.permission#READ_BASIC_PHONE_STATE
+     * READ_BASIC_PHONE_STATE} or that the calling app has carrier privileges
+     * (see {@link #hasCarrierPrivileges}).
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE})
     public @NetworkType int getVoiceNetworkType() {
         return getVoiceNetworkType(getSubId());
     }
@@ -6587,12 +6596,7 @@
      * @param AID Application id. See ETSI 102.221 and 101.220.
      * @param p2 P2 parameter (described in ISO 7816-4).
      * @return an IccOpenLogicalChannelResponse object.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openLogicalChannel(byte[], byte)}.
      */
-    @Deprecated
     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, int p2) {
         return iccOpenLogicalChannel(getSubId(), AID, p2);
     }
@@ -6623,12 +6627,7 @@
      * @param p2 P2 parameter (described in ISO 7816-4).
      * @return an IccOpenLogicalChannelResponse object.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openLogicalChannel(byte[], byte)}.
      */
-    @Deprecated
     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
         try {
             ITelephony telephony = getITelephony();
@@ -6656,10 +6655,7 @@
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.Channel#close()}.
      */
-    @Deprecated
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
     public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
@@ -6686,10 +6682,7 @@
      * @param channel is the channel id to be closed as returned by a successful
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.Channel#close()}.
      */
-    @Deprecated
     public boolean iccCloseLogicalChannel(int channel) {
         return iccCloseLogicalChannel(getSubId(), channel);
     }
@@ -6708,10 +6701,7 @@
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.Channel#close()}.
      */
-    @Deprecated
     public boolean iccCloseLogicalChannel(int subId, int channel) {
         try {
             ITelephony telephony = getITelephony();
@@ -6747,10 +6737,7 @@
      * @return The APDU response from the ICC card with the status appended at the end, or null if
      * there is an issue connecting to the Telephony service.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
     @Nullable
@@ -6788,10 +6775,7 @@
      * @param data Data to be sent with the APDU.
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public String iccTransmitApduLogicalChannel(int channel, int cla,
             int instruction, int p1, int p2, int p3, String data) {
         return iccTransmitApduLogicalChannel(getSubId(), channel, cla,
@@ -6820,10 +6804,7 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
             int instruction, int p1, int p2, int p3, String data) {
         try {
@@ -6859,13 +6840,7 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
     @NonNull
@@ -6901,13 +6876,7 @@
      * @param data Data to be sent with the APDU.
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public String iccTransmitApduBasicChannel(int cla,
             int instruction, int p1, int p2, int p3, String data) {
         return iccTransmitApduBasicChannel(getSubId(), cla,
@@ -6934,13 +6903,7 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public String iccTransmitApduBasicChannel(int subId, int cla,
             int instruction, int p1, int p2, int p3, String data) {
         try {
@@ -6968,13 +6931,7 @@
      * @param p3 P3 value of the APDU command.
      * @param filePath
      * @return The APDU response.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
             String filePath) {
         return iccExchangeSimIO(getSubId(), fileID, command, p1, p2, p3, filePath);
@@ -6996,13 +6953,7 @@
      * @param filePath
      * @return The APDU response.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2,
             int p3, String filePath) {
         try {
@@ -7028,13 +6979,7 @@
      * @return The APDU response from the ICC card in hexadecimal format
      *         with the last 4 bytes being the status word. If the command fails,
      *         returns an empty string.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public String sendEnvelopeWithStatus(String content) {
         return sendEnvelopeWithStatus(getSubId(), content);
     }
@@ -7054,13 +6999,7 @@
      *         with the last 4 bytes being the status word. If the command fails,
      *         returns an empty string.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
-     *             {@link android.se.omapi.SEService#getUiccReader(int)},
-     *             {@link android.se.omapi.Reader#openSession()},
-     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
-     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    @Deprecated
     public String sendEnvelopeWithStatus(int subId, String content) {
         try {
             ITelephony telephony = getITelephony();
@@ -9975,7 +9914,9 @@
      *
      * <p>Requires one of the following permissions:
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE},
-     * {@link android.Manifest.permission#MODIFY_PHONE_STATE}, or that the calling app has carrier
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE}, or
+     * {@link android.Manifest.permission#READ_BASIC_PHONE_STATE
+     * READ_BASIC_PHONE_STATE} or that the calling app has carrier
      * privileges (see {@link #hasCarrierPrivileges}).
      *
      * <p>Note that this does not take into account any data restrictions that may be present on the
@@ -9986,7 +9927,8 @@
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
             android.Manifest.permission.MODIFY_PHONE_STATE,
-            android.Manifest.permission.READ_PHONE_STATE})
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE})
     public boolean isDataEnabled() {
         try {
             return isDataEnabledForReason(DATA_ENABLED_REASON_USER);
@@ -10005,14 +9947,17 @@
      *
      * <p>Requires one of the following permissions:
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE},
-     * {@link android.Manifest.permission#READ_PHONE_STATE} or that the calling app
+     * {@link android.Manifest.permission#READ_PHONE_STATE} or
+     * {@link android.Manifest.permission#READ_BASIC_PHONE_STATE
+     * READ_BASIC_PHONE_STATE} or that the calling app
      * has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @return {@code true} if the data roaming is enabled on the subscription, otherwise return
      * {@code false}.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
-            android.Manifest.permission.READ_PHONE_STATE})
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE})
     public boolean isDataRoamingEnabled() {
         boolean isDataRoamingEnabled = false;
         try {
@@ -12411,16 +12356,21 @@
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies
      *      to the given subId. Otherwise, applies to
      * {@link SubscriptionManager#getDefaultDataSubscriptionId()}
-     *
      * @param reason the reason the data enable change is taking place
      * @return whether data is enabled for a reason.
      * <p>Requires Permission:
+     * The calling app has carrier privileges (see {@link #hasCarrierPrivileges}) or
      * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or
-     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}
+     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} or
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * {@link android.Manifest.permission#READ_BASIC_PHONE_STATE}
      * @throws IllegalStateException if the Telephony process is not currently available.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
-            android.Manifest.permission.READ_PHONE_STATE})
+            android.Manifest.permission.READ_PHONE_STATE,
+            android.Manifest.permission.MODIFY_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE
+    })
     public boolean isDataEnabledForReason(@DataEnabledReason int reason) {
         return isDataEnabledForReason(getSubId(), reason);
     }
@@ -12555,14 +12505,11 @@
      *   <LI>And possibly others.</LI>
      * </UL>
      * @return {@code true} if the overall data connection is allowed; {@code false} if not.
-     * <p>Requires Permission:
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or
-     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} or
-     * android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.ACCESS_NETWORK_STATE,
             android.Manifest.permission.READ_PHONE_STATE,
-            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_BASIC_PHONE_STATE})
     public boolean isDataConnectionAllowed() {
         boolean retVal = false;
         try {
@@ -15858,4 +15805,31 @@
             ex.rethrowAsRuntimeException();
         }
     }
+
+    /**
+     * Get last known cell identity.
+     * Require {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
+     * com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID, otherwise throws SecurityException.
+     * If there is current registered network this value will be same as the registered cell
+     * identity. If the device goes out of service the previous cell identity is cached and
+     * will be returned. If the cache age of the Cell identity is more than 24 hours
+     * it will be cleared and null will be returned.
+     * @return last known cell identity {@CellIdentity}.
+     * @hide
+     */
+    @RequiresPermission(allOf = {Manifest.permission.ACCESS_FINE_LOCATION,
+            "com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"})
+    public @Nullable CellIdentity getLastKnownCellIdentity() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) {
+                throw new IllegalStateException("telephony service is null.");
+            }
+            return telephony.getLastKnownCellIdentity(getSubId(), getOpPackageName(),
+                    getAttributionTag());
+        } catch (RemoteException ex) {
+            ex.rethrowAsRuntimeException();
+        }
+        return null;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index c00c741..c2c9497 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -97,7 +97,24 @@
      */
     public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6;
 
-    /** @hide */
+    /**
+     * This feature tag is deregistering because the PDN that the IMS registration is on
+     * is being torn down.
+     * <p>
+     * All open SIP Dialogs associated with this feature tag must be  closed
+     * using {@link SipDelegateConnection#cleanupSession(String)} before this operation can proceed.
+     */
+    public static final int DEREGISTERING_REASON_LOSING_PDN = 7;
+
+    /**
+     * This feature tag is deregistering because of an unspecified reason.
+     * <p>
+     * All open SIP Dialogs associated with this feature tag must be  closed
+     * using {@link SipDelegateConnection#cleanupSession(String)} before this operation can proceed.
+     */
+    public static final int DEREGISTERING_REASON_UNSPECIFIED = 8;
+
+/** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "DEREGISTERED_REASON_", value = {
             DEREGISTERED_REASON_UNKNOWN,
@@ -113,10 +130,13 @@
             DEREGISTERING_REASON_PDN_CHANGE,
             DEREGISTERING_REASON_PROVISIONING_CHANGE,
             DEREGISTERING_REASON_FEATURE_TAGS_CHANGING,
-            DEREGISTERING_REASON_DESTROY_PENDING
+            DEREGISTERING_REASON_DESTROY_PENDING,
+            DEREGISTERING_REASON_LOSING_PDN,
+            DEREGISTERING_REASON_UNSPECIFIED
     })
     public @interface DeregisteringReason {}
 
+    private ArraySet<String> mRegisteringTags = new ArraySet<>();
     private ArraySet<String> mRegisteredTags = new ArraySet<>();
     private final ArraySet<FeatureTagState> mDeregisteringTags = new ArraySet<>();
     private final ArraySet<FeatureTagState> mDeregisteredTags = new ArraySet<>();
@@ -134,6 +154,20 @@
         }
 
         /**
+         * Add the set of feature tags that are associated with this SipDelegate and
+         * the IMS stack is actively trying to register on the carrier network.
+         *
+         * The feature tags will either move to the registered or deregistered state
+         * depending on the result of the registration.
+         * @param featureTags The IMS media feature tags that are in the progress of registering.
+         * @return The in-progress Builder instance for RegistrationState. ]
+         */
+        public @NonNull Builder addRegisteringFeatureTags(@NonNull Set<String> featureTags) {
+            mState.mRegisteringTags.addAll(featureTags);
+            return this;
+        }
+
+        /**
          * Add a feature tag that is currently included in the current network IMS Registration.
          * @param featureTag The IMS media feature tag included in the current IMS registration.
          * @return The in-progress Builder instance for RegistrationState.
@@ -209,6 +243,17 @@
         mRegisteredTags = (ArraySet<String>) source.readArraySet(null);
         readStateFromParcel(source, mDeregisteringTags);
         readStateFromParcel(source, mDeregisteredTags);
+        mRegisteringTags = (ArraySet<String>) source.readArraySet(null);
+    }
+
+    /**
+     * Get the feature tags that are associated with this SipDelegate that the IMS stack is actively
+     * trying to register on the carrier network.
+     * @return A Set of feature tags associated with this SipDelegate that the IMS service is
+     * currently trying to register on the  carrier network.
+     */
+    public @NonNull Set<String> getRegisteringFeatureTags() {
+        return new ArraySet<>(mRegisteringTags);
     }
 
     /**
@@ -286,6 +331,7 @@
         dest.writeArraySet(mRegisteredTags);
         writeStateToParcel(dest, mDeregisteringTags);
         writeStateToParcel(dest, mDeregisteredTags);
+        dest.writeArraySet(mRegisteringTags);
     }
 
     private void writeStateToParcel(Parcel dest, Set<FeatureTagState> state) {
@@ -311,19 +357,22 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         DelegateRegistrationState that = (DelegateRegistrationState) o;
-        return mRegisteredTags.equals(that.mRegisteredTags)
+        return mRegisteringTags.equals(that.mRegisteringTags)
+                && mRegisteredTags.equals(that.mRegisteredTags)
                 && mDeregisteringTags.equals(that.mDeregisteringTags)
                 && mDeregisteredTags.equals(that.mDeregisteredTags);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags);
+        return Objects.hash(mRegisteringTags, mRegisteredTags,
+                mDeregisteringTags, mDeregisteredTags);
     }
 
     @Override
     public String toString() {
         return "DelegateRegistrationState{ registered={" + mRegisteredTags
+                + "}, registering={" + mRegisteringTags
                 + "}, deregistering={" + mDeregisteringTags + "}, deregistered={"
                 + mDeregisteredTags + "}}";
     }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6b33a68..2df5f53 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2509,4 +2509,13 @@
      * Unregister an IMS connection state callback
      */
     void unregisterImsStateCallback(in IImsStateCallback cb);
+
+    /**
+     * return last known cell identity
+     * @param subId user preferred subId.
+     * @param callingPackage the name of the package making the call.
+     * @param callingFeatureId The feature in the package.
+     */
+    CellIdentity getLastKnownCellIdentity(int subId, String callingPackage,
+            String callingFeatureId);
 }
diff --git a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkPriorityTest.java b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkPriorityTest.java
new file mode 100644
index 0000000..476be44
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkPriorityTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.vcn;
+
+import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_ANY;
+import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_OK;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class VcnCellUnderlyingNetworkPriorityTest {
+    private static final Set<String> ALLOWED_PLMN_IDS = new HashSet<>();
+    private static final Set<Integer> ALLOWED_CARRIER_IDS = new HashSet<>();
+
+    // Package private for use in VcnGatewayConnectionConfigTest
+    static VcnCellUnderlyingNetworkPriority getTestNetworkPriority() {
+        return new VcnCellUnderlyingNetworkPriority.Builder()
+                .setNetworkQuality(NETWORK_QUALITY_OK)
+                .setAllowMetered(true /* allowMetered */)
+                .setAllowedOperatorPlmnIds(ALLOWED_PLMN_IDS)
+                .setAllowedSpecificCarrierIds(ALLOWED_CARRIER_IDS)
+                .setAllowRoaming(true /* allowRoaming */)
+                .setRequireOpportunistic(true /* requireOpportunistic */)
+                .build();
+    }
+
+    @Test
+    public void testBuilderAndGetters() {
+        final VcnCellUnderlyingNetworkPriority networkPriority = getTestNetworkPriority();
+        assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality());
+        assertTrue(networkPriority.allowMetered());
+        assertEquals(ALLOWED_PLMN_IDS, networkPriority.getAllowedOperatorPlmnIds());
+        assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getAllowedSpecificCarrierIds());
+        assertTrue(networkPriority.allowRoaming());
+        assertTrue(networkPriority.requireOpportunistic());
+    }
+
+    @Test
+    public void testBuilderAndGettersForDefaultValues() {
+        final VcnCellUnderlyingNetworkPriority networkPriority =
+                new VcnCellUnderlyingNetworkPriority.Builder().build();
+        assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality());
+        assertFalse(networkPriority.allowMetered());
+        assertEquals(new HashSet<String>(), networkPriority.getAllowedOperatorPlmnIds());
+        assertEquals(new HashSet<Integer>(), networkPriority.getAllowedSpecificCarrierIds());
+        assertFalse(networkPriority.allowRoaming());
+        assertFalse(networkPriority.requireOpportunistic());
+    }
+
+    @Test
+    public void testPersistableBundle() {
+        final VcnCellUnderlyingNetworkPriority networkPriority = getTestNetworkPriority();
+        assertEquals(
+                networkPriority,
+                VcnUnderlyingNetworkPriority.fromPersistableBundle(
+                        networkPriority.toPersistableBundle()));
+    }
+}
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index dc338ae..377f526 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -17,6 +17,8 @@
 package android.net.vcn;
 
 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
+import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_PRIORITIES;
+import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_PRIORITIES_KEY;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -30,6 +32,7 @@
 import android.net.ipsec.ike.IkeTunnelConnectionParams;
 import android.net.vcn.persistablebundleutils.IkeSessionParamsUtilsTest;
 import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest;
+import android.os.PersistableBundle;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -38,6 +41,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.Arrays;
+import java.util.LinkedHashSet;
 import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
@@ -50,9 +54,17 @@
             };
     public static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
 
+    private static final LinkedHashSet<VcnUnderlyingNetworkPriority> UNDERLYING_NETWORK_PRIORITIES =
+            new LinkedHashSet();
+
     static {
         Arrays.sort(EXPOSED_CAPS);
         Arrays.sort(UNDERLYING_CAPS);
+
+        UNDERLYING_NETWORK_PRIORITIES.add(
+                VcnCellUnderlyingNetworkPriorityTest.getTestNetworkPriority());
+        UNDERLYING_NETWORK_PRIORITIES.add(
+                VcnWifiUnderlyingNetworkPriorityTest.getTestNetworkPriority());
     }
 
     public static final long[] RETRY_INTERVALS_MS =
@@ -82,7 +94,10 @@
 
     // Public for use in VcnGatewayConnectionTest
     public static VcnGatewayConnectionConfig buildTestConfig() {
-        return buildTestConfigWithExposedCaps(EXPOSED_CAPS);
+        final VcnGatewayConnectionConfig.Builder builder =
+                newBuilder().setVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_PRIORITIES);
+
+        return buildTestConfigWithExposedCaps(builder, EXPOSED_CAPS);
     }
 
     private static VcnGatewayConnectionConfig.Builder newBuilder() {
@@ -159,6 +174,15 @@
     }
 
     @Test
+    public void testBuilderRequiresNonNullNetworkPriorities() {
+        try {
+            newBuilder().setVcnUnderlyingNetworkPriorities(null);
+            fail("Expected exception due to invalid underlyingNetworkPriorities");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    @Test
     public void testBuilderRequiresNonNullRetryInterval() {
         try {
             newBuilder().setRetryIntervalsMillis(null);
@@ -195,6 +219,7 @@
         Arrays.sort(exposedCaps);
         assertArrayEquals(EXPOSED_CAPS, exposedCaps);
 
+        assertEquals(UNDERLYING_NETWORK_PRIORITIES, config.getVcnUnderlyingNetworkPriorities());
         assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams());
 
         assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
@@ -208,6 +233,16 @@
         assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
     }
 
+    @Test
+    public void testParsePersistableBundleWithoutVcnUnderlyingNetworkPriorities() {
+        PersistableBundle configBundle = buildTestConfig().toPersistableBundle();
+        configBundle.putPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY, null);
+
+        final VcnGatewayConnectionConfig config = new VcnGatewayConnectionConfig(configBundle);
+        assertEquals(
+                DEFAULT_UNDERLYING_NETWORK_PRIORITIES, config.getVcnUnderlyingNetworkPriorities());
+    }
+
     private static IkeTunnelConnectionParams buildTunnelConnectionParams(String ikePsk) {
         final IkeSessionParams ikeParams =
                 IkeSessionParamsUtilsTest.createBuilderMinimum()
@@ -249,4 +284,40 @@
         assertNotEquals(tunnelParams, anotherTunnelParams);
         assertNotEquals(config, anotherConfig);
     }
+
+    private static VcnGatewayConnectionConfig buildTestConfigWithVcnUnderlyingNetworkPriorities(
+            LinkedHashSet<VcnUnderlyingNetworkPriority> networkPriorities) {
+        return buildTestConfigWithExposedCaps(
+                new VcnGatewayConnectionConfig.Builder(
+                                "buildTestConfigWithVcnUnderlyingNetworkPriorities",
+                                TUNNEL_CONNECTION_PARAMS)
+                        .setVcnUnderlyingNetworkPriorities(networkPriorities),
+                EXPOSED_CAPS);
+    }
+
+    @Test
+    public void testVcnUnderlyingNetworkPrioritiesEquality() throws Exception {
+        final VcnGatewayConnectionConfig config =
+                buildTestConfigWithVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_PRIORITIES);
+
+        final LinkedHashSet<VcnUnderlyingNetworkPriority> networkPrioritiesEqual =
+                new LinkedHashSet();
+        networkPrioritiesEqual.add(VcnCellUnderlyingNetworkPriorityTest.getTestNetworkPriority());
+        networkPrioritiesEqual.add(VcnWifiUnderlyingNetworkPriorityTest.getTestNetworkPriority());
+        final VcnGatewayConnectionConfig configEqual =
+                buildTestConfigWithVcnUnderlyingNetworkPriorities(networkPrioritiesEqual);
+
+        final LinkedHashSet<VcnUnderlyingNetworkPriority> networkPrioritiesNotEqual =
+                new LinkedHashSet();
+        networkPrioritiesNotEqual.add(
+                VcnWifiUnderlyingNetworkPriorityTest.getTestNetworkPriority());
+        final VcnGatewayConnectionConfig configNotEqual =
+                buildTestConfigWithVcnUnderlyingNetworkPriorities(networkPrioritiesNotEqual);
+
+        assertEquals(UNDERLYING_NETWORK_PRIORITIES, networkPrioritiesEqual);
+        assertEquals(config, configEqual);
+
+        assertNotEquals(UNDERLYING_NETWORK_PRIORITIES, networkPrioritiesNotEqual);
+        assertNotEquals(config, configNotEqual);
+    }
 }
diff --git a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkPriorityTest.java b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkPriorityTest.java
index 69ffead..dd272cb 100644
--- a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkPriorityTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkPriorityTest.java
@@ -30,7 +30,8 @@
     private static final String SSID = "TestWifi";
     private static final int INVALID_NETWORK_QUALITY = -1;
 
-    private static VcnWifiUnderlyingNetworkPriority getTestNetworkPriority() {
+    // Package private for use in VcnGatewayConnectionConfigTest
+    static VcnWifiUnderlyingNetworkPriority getTestNetworkPriority() {
         return new VcnWifiUnderlyingNetworkPriority.Builder()
                 .setNetworkQuality(NETWORK_QUALITY_OK)
                 .setAllowMetered(true /* allowMetered */)
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 15de226..e547400 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -118,6 +118,8 @@
 
     @Test
     public void testNullNetworkDoesNotTriggerDisconnect() throws Exception {
+        doReturn(false).when(mDeps).isAirplaneModeOn(any());
+
         mGatewayConnection
                 .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(null);
@@ -129,6 +131,19 @@
     }
 
     @Test
+    public void testNullNetworkAirplaneModeDisconnects() throws Exception {
+        doReturn(true).when(mDeps).isAirplaneModeOn(any());
+
+        mGatewayConnection
+                .getUnderlyingNetworkControllerCallback()
+                .onSelectedUnderlyingNetworkChanged(null);
+        mTestLooper.dispatchAll();
+
+        assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
+        verify(mIkeSession).kill();
+    }
+
+    @Test
     public void testNewNetworkTriggersMigration() throws Exception {
         mGatewayConnection
                 .getUnderlyingNetworkControllerCallback()
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 8a0af2d..5628321 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -179,7 +179,7 @@
 
         doReturn(mUnderlyingNetworkController)
                 .when(mDeps)
-                .newUnderlyingNetworkController(any(), any(), any(), any());
+                .newUnderlyingNetworkController(any(), any(), any(), any(), any());
         doReturn(mWakeLock)
                 .when(mDeps)
                 .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
new file mode 100644
index 0000000..46a614f
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn.routeselection;
+
+import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_OK;
+
+import static com.android.server.vcn.VcnTestUtils.setupSystemService;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_ANY;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.calculatePriorityClass;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesCellPriorityRule;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesPriorityRule;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.checkMatchesWifiPriorityRule;
+import static com.android.server.vcn.routeselection.UnderlyingNetworkControllerTest.getLinkPropertiesWithName;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnCellUnderlyingNetworkPriority;
+import android.net.vcn.VcnGatewayConnectionConfig;
+import android.net.vcn.VcnManager;
+import android.net.vcn.VcnWifiUnderlyingNetworkPriority;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.os.test.TestLooper;
+import android.telephony.TelephonyManager;
+import android.util.ArraySet;
+
+import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import com.android.server.vcn.VcnContext;
+import com.android.server.vcn.VcnNetworkProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Set;
+import java.util.UUID;
+
+public class NetworkPriorityClassifierTest {
+    private static final String SSID = "TestWifi";
+    private static final String SSID_OTHER = "TestWifiOther";
+    private static final String PLMN_ID = "123456";
+    private static final String PLMN_ID_OTHER = "234567";
+
+    private static final int SUB_ID = 1;
+    private static final int WIFI_RSSI = -60;
+    private static final int WIFI_RSSI_HIGH = -50;
+    private static final int WIFI_RSSI_LOW = -80;
+    private static final int CARRIER_ID = 1;
+    private static final int CARRIER_ID_OTHER = 2;
+
+    private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
+
+    private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES =
+            new NetworkCapabilities.Builder()
+                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                    .setSignalStrength(WIFI_RSSI)
+                    .setSsid(SSID)
+                    .build();
+
+    private static final TelephonyNetworkSpecifier TEL_NETWORK_SPECIFIER =
+            new TelephonyNetworkSpecifier.Builder().setSubscriptionId(SUB_ID).build();
+    private static final NetworkCapabilities CELL_NETWORK_CAPABILITIES =
+            new NetworkCapabilities.Builder()
+                    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                    .setSubscriptionIds(Set.of(SUB_ID))
+                    .setNetworkSpecifier(TEL_NETWORK_SPECIFIER)
+                    .build();
+
+    private static final LinkProperties LINK_PROPERTIES = getLinkPropertiesWithName("test_iface");
+
+    @Mock private Network mNetwork;
+    @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
+    @Mock private TelephonyManager mTelephonyManager;
+
+    private TestLooper mTestLooper;
+    private VcnContext mVcnContext;
+    private UnderlyingNetworkRecord mWifiNetworkRecord;
+    private UnderlyingNetworkRecord mCellNetworkRecord;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        final Context mockContext = mock(Context.class);
+        mTestLooper = new TestLooper();
+        mVcnContext =
+                spy(
+                        new VcnContext(
+                                mockContext,
+                                mTestLooper.getLooper(),
+                                mock(VcnNetworkProvider.class),
+                                false /* isInTestMode */));
+        doNothing().when(mVcnContext).ensureRunningOnLooperThread();
+
+        mWifiNetworkRecord =
+                new UnderlyingNetworkRecord(
+                        mNetwork,
+                        WIFI_NETWORK_CAPABILITIES,
+                        LINK_PROPERTIES,
+                        false /* isBlocked */);
+
+        mCellNetworkRecord =
+                new UnderlyingNetworkRecord(
+                        mNetwork,
+                        CELL_NETWORK_CAPABILITIES,
+                        LINK_PROPERTIES,
+                        false /* isBlocked */);
+
+        setupSystemService(
+                mockContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+        when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
+        when(mTelephonyManager.getNetworkOperator()).thenReturn(PLMN_ID);
+        when(mTelephonyManager.getSimSpecificCarrierId()).thenReturn(CARRIER_ID);
+    }
+
+    @Test
+    public void testMatchWithoutNotMeteredBit() {
+        final VcnWifiUnderlyingNetworkPriority wifiNetworkPriority =
+                new VcnWifiUnderlyingNetworkPriority.Builder()
+                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setAllowMetered(false /* allowMetered */)
+                        .build();
+
+        assertFalse(
+                checkMatchesPriorityRule(
+                        mVcnContext,
+                        wifiNetworkPriority,
+                        mWifiNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot,
+                        null /* currentlySelecetd */,
+                        null /* carrierConfig */));
+    }
+
+    private void verifyMatchWifi(
+            boolean isSelectedNetwork, PersistableBundle carrierConfig, boolean expectMatch) {
+        final VcnWifiUnderlyingNetworkPriority wifiNetworkPriority =
+                new VcnWifiUnderlyingNetworkPriority.Builder()
+                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setAllowMetered(true /* allowMetered */)
+                        .build();
+        final UnderlyingNetworkRecord selectedNetworkRecord =
+                isSelectedNetwork ? mWifiNetworkRecord : null;
+        assertEquals(
+                expectMatch,
+                checkMatchesWifiPriorityRule(
+                        wifiNetworkPriority,
+                        mWifiNetworkRecord,
+                        selectedNetworkRecord,
+                        carrierConfig));
+    }
+
+    @Test
+    public void testMatchSelectedWifi() {
+        verifyMatchWifi(
+                true /* isSelectedNetwork */, null /* carrierConfig */, true /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchSelectedWifiBelowRssiThreshold() {
+        final PersistableBundle carrierConfig = new PersistableBundle();
+        carrierConfig.putInt(
+                VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY, WIFI_RSSI_HIGH);
+        carrierConfig.putInt(
+                VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, WIFI_RSSI_HIGH);
+
+        verifyMatchWifi(true /* isSelectedNetwork */, carrierConfig, false /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchUnselectedWifi() {
+        verifyMatchWifi(
+                false /* isSelectedNetwork */, null /* carrierConfig */, true /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchUnselectedWifiBelowRssiThreshold() {
+        final PersistableBundle carrierConfig = new PersistableBundle();
+        carrierConfig.putInt(
+                VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY, WIFI_RSSI_HIGH);
+
+        verifyMatchWifi(false /* isSelectedNetwork */, carrierConfig, false /* expectMatch */);
+    }
+
+    private void verifyMatchWifiWithSsid(boolean useMatchedSsid, boolean expectMatch) {
+        final String nwPrioritySsid = useMatchedSsid ? SSID : SSID_OTHER;
+        final VcnWifiUnderlyingNetworkPriority wifiNetworkPriority =
+                new VcnWifiUnderlyingNetworkPriority.Builder()
+                        .setNetworkQuality(NETWORK_QUALITY_OK)
+                        .setAllowMetered(true /* allowMetered */)
+                        .setSsid(nwPrioritySsid)
+                        .build();
+
+        assertEquals(
+                expectMatch,
+                checkMatchesWifiPriorityRule(
+                        wifiNetworkPriority,
+                        mWifiNetworkRecord,
+                        null /* currentlySelecetd */,
+                        null /* carrierConfig */));
+    }
+
+    @Test
+    public void testMatchWifiWithSsid() {
+        verifyMatchWifiWithSsid(true /* useMatchedSsid */, true /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchWifiFailWithWrongSsid() {
+        verifyMatchWifiWithSsid(false /* useMatchedSsid */, false /* expectMatch */);
+    }
+
+    private static VcnCellUnderlyingNetworkPriority.Builder getCellNetworkPriorityBuilder() {
+        return new VcnCellUnderlyingNetworkPriority.Builder()
+                .setNetworkQuality(NETWORK_QUALITY_OK)
+                .setAllowMetered(true /* allowMetered */)
+                .setAllowRoaming(true /* allowRoaming */);
+    }
+
+    @Test
+    public void testMatchMacroCell() {
+        assertTrue(
+                checkMatchesCellPriorityRule(
+                        mVcnContext,
+                        getCellNetworkPriorityBuilder().build(),
+                        mCellNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot));
+    }
+
+    @Test
+    public void testMatchOpportunisticCell() {
+        final VcnCellUnderlyingNetworkPriority opportunisticCellNetworkPriority =
+                getCellNetworkPriorityBuilder()
+                        .setRequireOpportunistic(true /* requireOpportunistic */)
+                        .build();
+
+        when(mSubscriptionSnapshot.isOpportunistic(SUB_ID)).thenReturn(true);
+        when(mSubscriptionSnapshot.getAllSubIdsInGroup(SUB_GROUP)).thenReturn(new ArraySet<>());
+
+        assertTrue(
+                checkMatchesCellPriorityRule(
+                        mVcnContext,
+                        opportunisticCellNetworkPriority,
+                        mCellNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot));
+    }
+
+    private void verifyMatchMacroCellWithAllowedPlmnIds(
+            boolean useMatchedPlmnId, boolean expectMatch) {
+        final String networkPriorityPlmnId = useMatchedPlmnId ? PLMN_ID : PLMN_ID_OTHER;
+        final VcnCellUnderlyingNetworkPriority networkPriority =
+                getCellNetworkPriorityBuilder()
+                        .setAllowedOperatorPlmnIds(Set.of(networkPriorityPlmnId))
+                        .build();
+
+        assertEquals(
+                expectMatch,
+                checkMatchesCellPriorityRule(
+                        mVcnContext,
+                        networkPriority,
+                        mCellNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot));
+    }
+
+    @Test
+    public void testMatchMacroCellWithAllowedPlmnIds() {
+        verifyMatchMacroCellWithAllowedPlmnIds(true /* useMatchedPlmnId */, true /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchMacroCellFailWithDisallowedPlmnIds() {
+        verifyMatchMacroCellWithAllowedPlmnIds(
+                false /* useMatchedPlmnId */, false /* expectMatch */);
+    }
+
+    private void verifyMatchMacroCellWithAllowedSpecificCarrierIds(
+            boolean useMatchedCarrierId, boolean expectMatch) {
+        final int networkPriorityCarrierId = useMatchedCarrierId ? CARRIER_ID : CARRIER_ID_OTHER;
+        final VcnCellUnderlyingNetworkPriority networkPriority =
+                getCellNetworkPriorityBuilder()
+                        .setAllowedSpecificCarrierIds(Set.of(networkPriorityCarrierId))
+                        .build();
+
+        assertEquals(
+                expectMatch,
+                checkMatchesCellPriorityRule(
+                        mVcnContext,
+                        networkPriority,
+                        mCellNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot));
+    }
+
+    @Test
+    public void testMatchMacroCellWithAllowedSpecificCarrierIds() {
+        verifyMatchMacroCellWithAllowedSpecificCarrierIds(
+                true /* useMatchedCarrierId */, true /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchMacroCellFailWithDisallowedSpecificCarrierIds() {
+        verifyMatchMacroCellWithAllowedSpecificCarrierIds(
+                false /* useMatchedCarrierId */, false /* expectMatch */);
+    }
+
+    @Test
+    public void testMatchWifiFailWithoutNotRoamingBit() {
+        final VcnCellUnderlyingNetworkPriority networkPriority =
+                getCellNetworkPriorityBuilder().setAllowRoaming(false /* allowRoaming */).build();
+
+        assertFalse(
+                checkMatchesCellPriorityRule(
+                        mVcnContext,
+                        networkPriority,
+                        mCellNetworkRecord,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot));
+    }
+
+    private void verifyCalculatePriorityClass(
+            UnderlyingNetworkRecord networkRecord, int expectedIndex) {
+        final int priorityIndex =
+                calculatePriorityClass(
+                        mVcnContext,
+                        networkRecord,
+                        VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_PRIORITIES,
+                        SUB_GROUP,
+                        mSubscriptionSnapshot,
+                        null /* currentlySelected */,
+                        null /* carrierConfig */);
+
+        assertEquals(expectedIndex, priorityIndex);
+    }
+
+    @Test
+    public void testCalculatePriorityClass() throws Exception {
+        verifyCalculatePriorityClass(mCellNetworkRecord, 2);
+    }
+
+    @Test
+    public void testCalculatePriorityClassFailToMatchAny() throws Exception {
+        final NetworkCapabilities nc =
+                new NetworkCapabilities.Builder()
+                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+                        .setSignalStrength(WIFI_RSSI_LOW)
+                        .setSsid(SSID)
+                        .build();
+        final UnderlyingNetworkRecord wifiNetworkRecord =
+                new UnderlyingNetworkRecord(mNetwork, nc, LINK_PROPERTIES, false /* isBlocked */);
+
+        verifyCalculatePriorityClass(wifiNetworkRecord, PRIORITY_ANY);
+    }
+}
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
index c954cb8..fad9669 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
@@ -42,6 +42,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnGatewayConnectionConfigTest;
 import android.os.ParcelUuid;
 import android.os.test.TestLooper;
 import android.telephony.CarrierConfigManager;
@@ -145,7 +146,11 @@
 
         mUnderlyingNetworkController =
                 new UnderlyingNetworkController(
-                        mVcnContext, SUB_GROUP, mSubscriptionSnapshot, mNetworkControllerCb);
+                        mVcnContext,
+                        VcnGatewayConnectionConfigTest.buildTestConfig(),
+                        SUB_GROUP,
+                        mSubscriptionSnapshot,
+                        mNetworkControllerCb);
     }
 
     private void resetVcnContext() {
@@ -153,7 +158,8 @@
         doNothing().when(mVcnContext).ensureRunningOnLooperThread();
     }
 
-    private static LinkProperties getLinkPropertiesWithName(String iface) {
+    // Package private for use in NetworkPriorityClassifierTest
+    static LinkProperties getLinkPropertiesWithName(String iface) {
         LinkProperties linkProperties = new LinkProperties();
         linkProperties.setInterfaceName(iface);
         return linkProperties;
@@ -182,7 +188,11 @@
                         true /* isInTestMode */);
 
         new UnderlyingNetworkController(
-                vcnContext, SUB_GROUP, mSubscriptionSnapshot, mNetworkControllerCb);
+                vcnContext,
+                VcnGatewayConnectionConfigTest.buildTestConfig(),
+                SUB_GROUP,
+                mSubscriptionSnapshot,
+                mNetworkControllerCb);
 
         verify(cm)
                 .registerNetworkCallback(
@@ -345,6 +355,17 @@
         return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES);
     }
 
+    private static NetworkCapabilities buildResponseNwCaps(
+            NetworkCapabilities requestNetworkCaps, Set<Integer> netCapsSubIds) {
+        final TelephonyNetworkSpecifier telephonyNetworkSpecifier =
+                new TelephonyNetworkSpecifier.Builder()
+                        .setSubscriptionId(netCapsSubIds.iterator().next())
+                        .build();
+        return new NetworkCapabilities.Builder(requestNetworkCaps)
+                .setNetworkSpecifier(telephonyNetworkSpecifier)
+                .build();
+    }
+
     private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback(
             NetworkCapabilities networkCapabilities) {
         verify(mConnectivityManager)
@@ -355,14 +376,17 @@
 
         UnderlyingNetworkListener cb = mUnderlyingNetworkListenerCaptor.getValue();
         cb.onAvailable(mNetwork);
-        cb.onCapabilitiesChanged(mNetwork, networkCapabilities);
+
+        final NetworkCapabilities responseNetworkCaps =
+                buildResponseNwCaps(networkCapabilities, INITIAL_SUB_IDS);
+        cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
         cb.onLinkPropertiesChanged(mNetwork, INITIAL_LINK_PROPERTIES);
         cb.onBlockedStatusChanged(mNetwork, false /* isFalse */);
 
         UnderlyingNetworkRecord expectedRecord =
                 new UnderlyingNetworkRecord(
                         mNetwork,
-                        networkCapabilities,
+                        responseNetworkCaps,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
         verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
@@ -373,12 +397,14 @@
     public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() {
         UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
 
-        cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
+        final NetworkCapabilities responseNetworkCaps =
+                buildResponseNwCaps(UPDATED_NETWORK_CAPABILITIES, UPDATED_SUB_IDS);
+        cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
 
         UnderlyingNetworkRecord expectedRecord =
                 new UnderlyingNetworkRecord(
                         mNetwork,
-                        UPDATED_NETWORK_CAPABILITIES,
+                        responseNetworkCaps,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
         verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
@@ -393,7 +419,7 @@
         UnderlyingNetworkRecord expectedRecord =
                 new UnderlyingNetworkRecord(
                         mNetwork,
-                        INITIAL_NETWORK_CAPABILITIES,
+                        buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS),
                         UPDATED_LINK_PROPERTIES,
                         false /* isBlocked */);
         verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
@@ -403,19 +429,21 @@
     public void testRecordTrackerCallbackNotifiedForNetworkSuspended() {
         UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
 
-        cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
+        final NetworkCapabilities responseNetworkCaps =
+                buildResponseNwCaps(SUSPENDED_NETWORK_CAPABILITIES, UPDATED_SUB_IDS);
+        cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
 
         UnderlyingNetworkRecord expectedRecord =
                 new UnderlyingNetworkRecord(
                         mNetwork,
-                        SUSPENDED_NETWORK_CAPABILITIES,
+                        responseNetworkCaps,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
         verify(mNetworkControllerCb, times(1))
                 .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
         // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
         // change.
-        cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
+        cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
         verify(mNetworkControllerCb, times(1))
                 .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
@@ -425,19 +453,21 @@
         UnderlyingNetworkListener cb =
                 verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES);
 
-        cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
+        final NetworkCapabilities responseNetworkCaps =
+                buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS);
+        cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
 
         UnderlyingNetworkRecord expectedRecord =
                 new UnderlyingNetworkRecord(
                         mNetwork,
-                        INITIAL_NETWORK_CAPABILITIES,
+                        responseNetworkCaps,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
         verify(mNetworkControllerCb, times(1))
                 .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
         // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
         // change.
-        cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
+        cb.onCapabilitiesChanged(mNetwork, responseNetworkCaps);
         verify(mNetworkControllerCb, times(1))
                 .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
@@ -451,7 +481,7 @@
         UnderlyingNetworkRecord expectedRecord =
                 new UnderlyingNetworkRecord(
                         mNetwork,
-                        INITIAL_NETWORK_CAPABILITIES,
+                        buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS),
                         INITIAL_LINK_PROPERTIES,
                         true /* isBlocked */);
         verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
@@ -470,7 +500,8 @@
     public void testRecordTrackerCallbackIgnoresDuplicateRecord() {
         UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
 
-        cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
+        cb.onCapabilitiesChanged(
+                mNetwork, buildResponseNwCaps(INITIAL_NETWORK_CAPABILITIES, INITIAL_SUB_IDS));
 
         // Verify no more calls to the UnderlyingNetworkControllerCallback when the
         // UnderlyingNetworkRecord does not actually change
@@ -482,7 +513,8 @@
         UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
         mUnderlyingNetworkController.teardown();
 
-        cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
+        cb.onCapabilitiesChanged(
+                mNetwork, buildResponseNwCaps(UPDATED_NETWORK_CAPABILITIES, INITIAL_SUB_IDS));
 
         // Verify that the only call was during onAvailable()
         verify(mNetworkControllerCb, times(1)).onSelectedUnderlyingNetworkChanged(any());