diff options
162 files changed, 5157 insertions, 2322 deletions
diff --git a/Android.bp b/Android.bp index f8a9e0f0f393..ecf6deeeb432 100644 --- a/Android.bp +++ b/Android.bp @@ -69,7 +69,7 @@ filegroup { // Java/AIDL sources under frameworks/base ":framework-annotations", ":framework-blobstore-sources", - ":framework-connectivity-nsd-sources", + ":framework-connectivity-tiramisu-sources", ":framework-core-sources", ":framework-drm-sources", ":framework-graphics-nonupdatable-sources", diff --git a/core/api/current.txt b/core/api/current.txt index 99226159348b..d9753ab5e4a0 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -120,6 +120,7 @@ package android { 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 @@ package android.bluetooth { 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 @@ package android.bluetooth { 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 @@ package android.bluetooth { 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 @@ package android.os { 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 @@ package android.os { 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 @@ package android.telecom { 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 @@ package android.telephony { 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 @@ package android.telephony { 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 @@ package android.telephony { 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/module-lib-current.txt b/core/api/module-lib-current.txt index 3a35f249d177..81b4ee80a1d2 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -190,6 +190,10 @@ package android.media.session { package android.net { + public final class ConnectivityFrameworkInitializerTiramisu { + method public static void registerServiceWrappers(); + } + public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable { ctor public EthernetNetworkSpecifier(@NonNull String); method public int describeContents(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 84a4a44c5cf0..ca3c51152514 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -66,6 +66,7 @@ package android { field public static final String BIND_TRANSLATION_SERVICE = "android.permission.BIND_TRANSLATION_SERVICE"; field public static final String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT"; field public static final String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE"; + field public static final String BLUETOOTH_MAP = "android.permission.BLUETOOTH_MAP"; field public static final String BRICK = "android.permission.BRICK"; field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE"; field public static final String BROADCAST_CLOSE_SYSTEM_DIALOGS = "android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"; @@ -12055,10 +12056,10 @@ package android.telephony { 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 +12885,7 @@ package android.telephony.ims { 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 +12893,10 @@ package android.telephony.ims { 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 +12905,7 @@ package android.telephony.ims { 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.bp b/core/java/Android.bp index ca9a46847dea..343830a468dc 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -399,6 +399,21 @@ filegroup { ], } +aidl_interface { + name: "android.os.statsbootstrap_aidl", + unstable: true, + srcs: [ + "android/os/IStatsBootstrapAtomService.aidl", + "android/os/StatsBootstrapAtom.aidl", + "android/os/StatsBootstrapAtomValue.aidl", + ], + backend: { + cpp: { + enabled: true, + }, + }, +} + // utility classes statically linked into wifi-service filegroup { name: "framework-wifi-service-shared-srcs", diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index e2fd35940b52..0171f0a5a327 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -125,6 +125,7 @@ import android.media.tv.TvInputManager; import android.media.tv.tunerresourcemanager.ITunerResourceManager; import android.media.tv.tunerresourcemanager.TunerResourceManager; import android.net.ConnectivityFrameworkInitializer; +import android.net.ConnectivityFrameworkInitializerTiramisu; import android.net.EthernetManager; import android.net.IEthernetManager; import android.net.IIpSecService; @@ -140,8 +141,6 @@ import android.net.TetheringManager; import android.net.VpnManager; import android.net.lowpan.ILowpanManager; import android.net.lowpan.LowpanManager; -import android.net.nsd.INsdManager; -import android.net.nsd.NsdManager; import android.net.vcn.IVcnManagementService; import android.net.vcn.VcnManager; import android.net.wifi.WifiFrameworkInitializer; @@ -566,15 +565,6 @@ public final class SystemServiceRegistry { ctx.mMainThread.getHandler()); }}); - registerService(Context.NSD_SERVICE, NsdManager.class, - new CachedServiceFetcher<NsdManager>() { - @Override - public NsdManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IBinder b = ServiceManager.getServiceOrThrow(Context.NSD_SERVICE); - INsdManager service = INsdManager.Stub.asInterface(b); - return new NsdManager(ctx.getOuterContext(), service); - }}); - registerService(Context.PEOPLE_SERVICE, PeopleManager.class, new CachedServiceFetcher<PeopleManager>() { @Override @@ -1486,6 +1476,7 @@ public final class SystemServiceRegistry { MediaFrameworkInitializer.registerServiceWrappers(); RoleFrameworkInitializer.registerServiceWrappers(); SchedulingFrameworkInitializer.registerServiceWrappers(); + ConnectivityFrameworkInitializerTiramisu.registerServiceWrappers(); } finally { // If any of the above code throws, we're in a pretty bad shape and the process // will likely crash, but we'll reset it just in case there's an exception handler... diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 2c875fee101b..14be9215c769 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -2283,21 +2283,21 @@ public final class BluetoothAdapter { 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 1d0bf97c34eb..9a4151adffc7 100644 --- a/core/java/android/bluetooth/BluetoothCodecConfig.java +++ b/core/java/android/bluetooth/BluetoothCodecConfig.java @@ -29,16 +29,14 @@ import java.util.Objects; /** * 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 @@ public final class BluetoothCodecConfig implements Parcelable { 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 @@ public final class BluetoothCodecConfig implements Parcelable { @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 @@ public final class BluetoothCodecConfig implements Parcelable { @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 @@ public final class BluetoothCodecConfig implements Parcelable { @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 @@ public final class BluetoothCodecConfig implements Parcelable { @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 @@ public final class BluetoothCodecConfig implements Parcelable { 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 @@ public final class BluetoothCodecConfig implements Parcelable { 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * Always returns 0 - * * @return 0 * @hide */ @@ -344,20 +415,7 @@ public final class BluetoothCodecConfig implements Parcelable { 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 @@ public final class BluetoothCodecConfig implements Parcelable { /** * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecConfig implements Parcelable { * 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 @@ public final class BluetoothCodecConfig implements Parcelable { 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 @@ public final class BluetoothCodecConfig implements Parcelable { /** * 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 7764ebeb2e33..02606feb3b3f 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 @@ import java.util.Objects; * A2DP source device. * * {@see BluetoothA2dp} - * - * {@hide} */ public final class BluetoothCodecStatus implements Parcelable { /** @@ -39,22 +38,27 @@ public final class BluetoothCodecStatus implements Parcelable { * 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 @@ public final class BluetoothCodecStatus implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecStatus implements Parcelable { * 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 @@ public final class BluetoothCodecStatus implements Parcelable { } /** - * 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 @@ public final class BluetoothCodecStatus implements Parcelable { 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 final class BluetoothCodecStatus implements Parcelable { 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 @@ public final class BluetoothCodecStatus implements Parcelable { }; /** - * 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 000000000000..dcaf4b682f44 --- /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 000000000000..fed9f911d5b3 --- /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 c000e56e7b04..8ee38d3e1260 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -23,7 +23,6 @@ import android.annotation.SdkConstant; 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 @@ public class BluetoothPbap implements BluetoothProfile { 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 0cf9f9fd6f43..e047e5d81a9d 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -233,12 +233,19 @@ public interface BluetoothProfile { 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 @@ public interface BluetoothProfile { 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 a254291f57db..ecd5e4077de9 100644 --- a/core/java/android/bluetooth/BluetoothProfileConnector.java +++ b/core/java/android/bluetooth/BluetoothProfileConnector.java @@ -103,7 +103,7 @@ public abstract class BluetoothProfileConnector<T> { 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 ca01784efd88..9dafa073ab3f 100644 --- a/core/java/android/bluetooth/BluetoothStatusCodes.java +++ b/core/java/android/bluetooth/BluetoothStatusCodes.java @@ -226,6 +226,66 @@ public final class BluetoothStatusCodes { 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 b388beda6b3b..18bad9c3c259 100644 --- a/core/java/android/bluetooth/le/TransportBlock.java +++ b/core/java/android/bluetooth/le/TransportBlock.java @@ -24,6 +24,7 @@ import android.util.Log; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; +import java.util.Arrays; /** * Wrapper for Transport Discovery Data Transport Blocks. @@ -59,8 +60,12 @@ public final class TransportBlock implements Parcelable { 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 @@ public final class TransportBlock implements Parcelable { dest.writeInt(mOrgId); dest.writeInt(mTdsFlags); dest.writeInt(mTransportDataLength); - dest.writeByteArray(mTransportData); + if (mTransportData != null) { + dest.writeByteArray(mTransportData); + } } /** @@ -79,6 +86,21 @@ public final class TransportBlock implements Parcelable { 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 c8e97f9a823a..2b52f19798ad 100644 --- a/core/java/android/bluetooth/le/TransportDiscoveryData.java +++ b/core/java/android/bluetooth/le/TransportDiscoveryData.java @@ -26,6 +26,7 @@ import java.nio.BufferOverflowException; 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 @@ public final class TransportDiscoveryData implements Parcelable { 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 10d5c274ae91..7554cb24b41f 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 2c4ff5889263..84c9fa9b375c 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -409,7 +409,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * 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/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java index 8a0211c2ec2f..70fe5d677b4f 100644 --- a/core/java/android/net/NetworkPolicy.java +++ b/core/java/android/net/NetworkPolicy.java @@ -16,11 +16,19 @@ package android.net; +import static android.net.NetworkStats.METERED_ALL; +import static android.net.NetworkStats.METERED_YES; +import static android.net.NetworkTemplate.MATCH_CARRIER; +import static android.net.NetworkTemplate.MATCH_MOBILE; +import static android.net.NetworkTemplate.SUBSCRIBER_ID_MATCH_RULE_EXACT; + +import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.util.BackupUtils; +import android.util.Log; import android.util.Range; import android.util.RecurrenceRule; @@ -42,10 +50,25 @@ import java.util.Objects; * @hide */ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { + private static final String TAG = NetworkPolicy.class.getSimpleName(); private static final int VERSION_INIT = 1; private static final int VERSION_RULE = 2; private static final int VERSION_RAPID = 3; + /** + * Initial Version of the NetworkTemplate backup serializer. + */ + private static final int TEMPLATE_BACKUP_VERSION_1_INIT = 1; + /** + * Version of the NetworkTemplate backup serializer that added carrier template support. + */ + private static final int TEMPLATE_BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE = 2; + /** + * Latest Version of the NetworkTemplate Backup Serializer. + */ + private static final int TEMPLATE_BACKUP_VERSION_LATEST = + TEMPLATE_BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE; + public static final int CYCLE_NONE = -1; public static final long WARNING_DISABLED = -1; public static final long LIMIT_DISABLED = -1; @@ -255,7 +278,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { DataOutputStream out = new DataOutputStream(baos); out.writeInt(VERSION_RAPID); - out.write(template.getBytesForBackup()); + out.write(getNetworkTemplateBytesForBackup()); cycleRule.writeToStream(out); out.writeLong(warningBytes); out.writeLong(limitBytes); @@ -274,7 +297,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { throw new BackupUtils.BadVersionException("Unknown backup version: " + version); } - final NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in); + final NetworkTemplate template = getNetworkTemplateFromBackup(in); final RecurrenceRule cycleRule; if (version >= VERSION_RULE) { cycleRule = new RecurrenceRule(in); @@ -298,4 +321,61 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> { return new NetworkPolicy(template, cycleRule, warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze, lastRapidSnooze, metered, inferred); } + + @NonNull + private byte[] getNetworkTemplateBytesForBackup() throws IOException { + if (!template.isPersistable()) { + Log.wtf(TAG, "Trying to backup non-persistable template: " + this); + } + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final DataOutputStream out = new DataOutputStream(baos); + + out.writeInt(TEMPLATE_BACKUP_VERSION_LATEST); + + out.writeInt(template.getMatchRule()); + BackupUtils.writeString(out, template.getSubscriberId()); + BackupUtils.writeString(out, template.getNetworkId()); + out.writeInt(template.getMeteredness()); + out.writeInt(template.getSubscriberIdMatchRule()); + + return baos.toByteArray(); + } + + @NonNull + private static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in) + throws IOException, BackupUtils.BadVersionException { + int version = in.readInt(); + if (version < TEMPLATE_BACKUP_VERSION_1_INIT || version > TEMPLATE_BACKUP_VERSION_LATEST) { + throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); + } + + int matchRule = in.readInt(); + final String subscriberId = BackupUtils.readString(in); + final String networkId = BackupUtils.readString(in); + + final int metered; + final int subscriberIdMatchRule; + if (version >= TEMPLATE_BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE) { + metered = in.readInt(); + subscriberIdMatchRule = in.readInt(); + } else { + // For backward compatibility, fill the missing filters from match rules. + metered = (matchRule == MATCH_MOBILE + || matchRule == NetworkTemplate.MATCH_MOBILE_WILDCARD + || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL; + subscriberIdMatchRule = SUBSCRIBER_ID_MATCH_RULE_EXACT; + } + + try { + return new NetworkTemplate(matchRule, + subscriberId, new String[]{subscriberId}, + networkId, metered, NetworkStats.ROAMING_ALL, + NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL, + NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule); + } catch (IllegalArgumentException e) { + throw new BackupUtils.BadVersionException( + "Restored network template contains unknown match rule " + matchRule, e); + } + } } diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index f55bcd31feb7..b989488f9015 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -2,5 +2,6 @@ set noparent 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 000000000000..b3f734524078 --- /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 752ef3e39ab6..55d3ecd2c92f 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.lang.annotation.RetentionPolicy; 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 @@ public final class VcnGatewayConnectionConfig { 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 @@ public final class VcnGatewayConnectionConfig { 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 @@ public final class VcnGatewayConnectionConfig { @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 @@ public final class VcnGatewayConnectionConfig { 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 @@ public final class VcnGatewayConnectionConfig { 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 @@ public final class VcnGatewayConnectionConfig { checkValidCapability(cap); } + Objects.requireNonNull(mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null"); Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null"); validateRetryInterval(mRetryIntervalsMs); @@ -303,6 +368,18 @@ public final class VcnGatewayConnectionConfig { } /** + * 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 @@ public final class VcnGatewayConnectionConfig { 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 @@ public final class VcnGatewayConnectionConfig { mGatewayConnectionName, mTunnelConnectionParams, mExposedCapabilities, + mUnderlyingNetworkPriorities, Arrays.hashCode(mRetryIntervalsMs), mMaxMtu); } @@ -368,6 +451,7 @@ public final class VcnGatewayConnectionConfig { 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 @@ public final class VcnGatewayConnectionConfig { @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 @@ public final class VcnGatewayConnectionConfig { } /** + * 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 @@ public final class VcnGatewayConnectionConfig { 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 27750c659fc9..551f75772b9a 100644 --- a/core/java/android/net/vcn/VcnUnderlyingNetworkPriority.java +++ b/core/java/android/net/vcn/VcnUnderlyingNetworkPriority.java @@ -21,8 +21,10 @@ import android.annotation.IntDef; 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 @@ public abstract class VcnUnderlyingNetworkPriority { /** @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 @@ public abstract class VcnUnderlyingNetworkPriority { 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 @@ public abstract class VcnUnderlyingNetworkPriority { && 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 fc7e7e2c4e41..85eb100779a2 100644 --- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkPriority.java +++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkPriority.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.IndentingPrintWriter; import java.util.Objects; @@ -78,7 +79,13 @@ public final class VcnWifiUnderlyingNetworkPriority extends VcnUnderlyingNetwork } 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 74b814ea4159..c8b4226ecae0 100644 --- a/core/java/android/os/AppZygote.java +++ b/core/java/android/os/AppZygote.java @@ -45,6 +45,8 @@ public class AppZygote { // 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 @@ public class AppZygote { 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 @@ public class AppZygote { 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 be21fea1d0df..2ea63297aff2 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -71,6 +71,9 @@ public class GraphicsEnvironment { 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 @@ public class GraphicsEnvironment { 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 afd0ff747b93..09eac79c991e 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -846,6 +846,19 @@ public final class Parcel { } /** + * 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 @@ public final class Parcel { * 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 @@ public final class Parcel { * 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 @@ public final class Parcel { @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 @@ public final class Parcel { * 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 @@ public final class Parcel { * @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 @@ public final class Parcel { } /** - * 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 @@ public final class Parcel { @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 3e01c53f0469..b7e3068a437c 100644 --- a/core/java/android/os/UpdateEngine.java +++ b/core/java/android/os/UpdateEngine.java @@ -238,7 +238,7 @@ public class UpdateEngine { 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 class UpdateEngine { 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 ac520e8b3dec..84be74669f11 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11218,22 +11218,38 @@ public final class Settings { "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 8c4dcb3b28e2..cd077e1f756c 100644 --- a/core/java/android/util/LocalLog.java +++ b/core/java/android/util/LocalLog.java @@ -22,6 +22,7 @@ import android.os.SystemClock; 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 @@ public final class LocalLog { 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 3550a31f9038..2257f6cd2159 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -8448,13 +8448,13 @@ public final class ViewRootImpl implements ViewParent, 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 000000000000..615e4b793752 --- /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 29e5a5a51ec0..6b9d95ff9137 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.OsConstants; 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 @@ public class ZygoteInit { /** * 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 @@ public class ZygoteInit { } /** + * 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 b0cf5dcbbfd5..ae9d71610aaa 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -56,6 +56,7 @@ import java.io.File; 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 @@ public class SystemConfig { // 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 @@ public class SystemConfig { 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 @@ public class SystemConfig { 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 @@ public class SystemConfig { 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 @@ public class SystemConfig { } 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 @@ public class SystemConfig { 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 @@ public class SystemConfig { } else if (systemExt) { readPrivAppPermissions(parser, mSystemExtPrivAppPermissions, mSystemExtPrivAppDenyPermissions); + } else if (apex) { + readApexPrivAppPermissions(parser, permFile); } else { readPrivAppPermissions(parser, mPrivAppPermissions, mPrivAppDenyPermissions); @@ -1616,6 +1641,43 @@ public class SystemConfig { } } + + /** + * 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 f1ae268f4c16..423ef7cd980b 100644 --- a/core/jni/android_media_AudioAttributes.cpp +++ b/core/jni/android_media_AudioAttributes.cpp @@ -58,7 +58,7 @@ static struct { jmethodID setSystemUsage; jmethodID setInternalCapturePreset; jmethodID setContentType; - jmethodID setFlags; + jmethodID replaceFlags; jmethodID addTag; } gAudioAttributesBuilderMethods; @@ -130,7 +130,7 @@ static jint nativeAudioAttributesToJavaAudioAttributes( 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 @@ int register_android_media_AudioAttributes(JNIEnv *env) 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 4b93363b5b90..c847e4d7654f 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2273,10 +2273,8 @@ android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMic 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 @@ android_media_AudioSystem_getHwOffloadEncodingFormatsSupportedForA2DP( 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 @@ static const JNINativeMethod gMethods[] = {"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 1b3f78c8f3d8..aacf700b1168 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -124,6 +124,7 @@ static jmethodID gCallPostForkChildHooks; 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 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, // 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 @@ int register_com_android_internal_os_Zygote(JNIEnv* env) { 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 cc479e61b855..4d76aee9d722 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 c3d159659622..ed3968ae9b78 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -672,18 +672,31 @@ message GlobalSettingsProto { 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 { - 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 ]; - } - optional NitzUpdate nitz_update = 81; + message Nitz { + option (android.msg_privacy).dest = DEST_EXPLICIT; + + // 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 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 261334b56215..fcf830e3dc27 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--> @@ -2010,7 +2018,7 @@ <permission android:name="android.permission.BLUETOOTH_PRIVILEGED" android:protectionLevel="signature|privileged" /> - <!-- Control access to email providers exclusively for Bluetooth + <!-- @SystemApi Control access to email providers exclusively for Bluetooth @hide --> <permission android:name="android.permission.BLUETOOTH_MAP" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index d052d70442c4..f4acfaa1baca 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 be5063f3609a..8eede56035c1 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 59b46656dd52..bd55426601fc 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { @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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 @@ public class BluetoothCodecConfigTest extends TestCase { 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 83bf2ed19380..1cb2dcae865c 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 @@ public class BluetoothCodecStatusTest extends TestCase { // 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { // 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { // 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 BluetoothCodecConfig[] local_capability_B = { - local_capability1_B, - local_capability2_B, - local_capability3_B, - local_capability4_B, - 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 BluetoothCodecConfig[] local_capability_C = { - local_capability1_C, - local_capability2_C, - local_capability3_C, - local_capability4_C, - 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 BluetoothCodecConfig[] selectable_capability_B = { - selectable_capability1_B, - selectable_capability2_B, - selectable_capability3_B, - selectable_capability4_B, - 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 BluetoothCodecConfig[] selectable_capability_C = { - selectable_capability1_C, - selectable_capability2_C, - selectable_capability3_C, - selectable_capability4_C, - selectable_capability5_C, - }; + 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 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 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 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 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 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 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 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 @@ public class BluetoothCodecStatusTest extends TestCase { 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 000000000000..c3d707cd7596 --- /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/Android.bp b/core/tests/coretests/Android.bp index 93e4a294a2cb..05ec00fe84f0 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -46,6 +46,7 @@ android_test { "androidx.test.ext.junit", "androidx.test.runner", "androidx.test.rules", + "kotlin-test", "mockito-target-minus-junit4", "ub-uiautomator", "platform-test-annotations", diff --git a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt new file mode 100644 index 000000000000..d936cad15689 --- /dev/null +++ b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt @@ -0,0 +1,56 @@ +/* + * 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 + +import android.text.format.Time.TIMEZONE_UTC +import androidx.test.runner.AndroidJUnit4 +import org.junit.Test +import org.junit.runner.RunWith +import java.io.ByteArrayInputStream +import java.io.DataInputStream +import java.time.ZoneId +import kotlin.test.assertEquals + +private const val TEST_IMSI1 = "TESTIMSI1" +private const val TEST_SSID1 = "TESTISSID1" + +@RunWith(AndroidJUnit4::class) +class NetworkPolicyTest { + @Test + fun testTemplateBackupRestore() { + assertPolicyBackupRestore(createTestPolicyForTemplate( + NetworkTemplate.buildTemplateWifi(TEST_SSID1))) + assertPolicyBackupRestore(createTestPolicyForTemplate( + NetworkTemplate.buildTemplateMobileAll(TEST_IMSI1))) + assertPolicyBackupRestore(createTestPolicyForTemplate( + NetworkTemplate.buildTemplateCarrierMetered(TEST_IMSI1))) + } + + private fun createTestPolicyForTemplate(template: NetworkTemplate): NetworkPolicy { + return NetworkPolicy(template, NetworkPolicy.buildRule(5, ZoneId.of(TIMEZONE_UTC)), + NetworkPolicy.WARNING_DISABLED, NetworkPolicy.LIMIT_DISABLED, + NetworkPolicy.SNOOZE_NEVER, NetworkPolicy.SNOOZE_NEVER, NetworkPolicy.SNOOZE_NEVER, + /*metered*/ false, /*inferred*/ true) + } + + private fun assertPolicyBackupRestore(policy: NetworkPolicy) { + val bytes = policy.bytesForBackup + val stream = DataInputStream(ByteArrayInputStream(bytes)) + val restored = NetworkPolicy.getNetworkPolicyFromBackup(stream) + assertEquals(policy, restored) + } +}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java b/core/tests/coretests/src/android/text/format/DateIntervalFormatTest.java index 6be9306bbd2d..bd4d80de9b13 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 @@ public class DateIntervalFormatTest { 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 @@ public class DateIntervalFormatTest { 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 @@ public class DateIntervalFormatTest { 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 @@ public class DateIntervalFormatTest { 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 e81adecc3bad..fefcebeaef20 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -393,6 +393,8 @@ applications that come with the platform <!-- Permissions required for Incremental CTS tests --> <permission name="com.android.permission.USE_INSTALLER_V2"/> <permission name="android.permission.LOADER_USAGE_STATS"/> + <!-- Permissions required for Package Verifier tests --> + <permission name="android.permission.PACKAGE_VERIFICATION_AGENT" /> <!-- Permission required to test system only camera devices. --> <permission name="android.permission.SYSTEM_CAMERA" /> <!-- Permission required to test ExplicitHealthCheckServiceImpl. --> @@ -503,6 +505,8 @@ applications that come with the platform <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 d1e4309c365e..2f61a2883037 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 @@ public final class RequiresPermissionChecker extends BugChecker 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 2c3567a63292..2c005fd81de5 100644 --- a/libs/androidfw/LocaleDataTables.cpp +++ b/libs/androidfw/LocaleDataTables.cpp @@ -34,206 +34,209 @@ const char SCRIPT_CODES[][4] = { /* 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 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({ {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 @@ const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({ {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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 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 @@ std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ }); 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 @@ const std::unordered_map<uint32_t, uint32_t> LATN_PARENTS({ {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 @@ const std::unordered_map<uint32_t, uint32_t> LATN_PARENTS({ {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 c7f56961e498..60f4a5a226db 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -32,6 +32,7 @@ import android.app.NotificationManager; 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 @@ public class AudioManager { /** * 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 69d1889d5762..f0e42c0550ff 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; 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 class AudioSystem 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 @@ public class AudioSystem 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 @@ public class AudioSystem /** * @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 @@ public class AudioSystem /** * @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/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp index 253b4e3a8a09..00c4a9782f33 100644 --- a/media/jni/soundpool/SoundPool.cpp +++ b/media/jni/soundpool/SoundPool.cpp @@ -185,7 +185,7 @@ void SoundPool::stop(int32_t streamID) auto apiLock = kUseApiLock ? std::make_unique<std::lock_guard<std::mutex>>(mApiLock) : nullptr; soundpool::Stream* stream = mStreamManager.findStream(streamID); if (stream != nullptr && stream->requestStop(streamID)) { - mStreamManager.moveToRestartQueue(stream); + mStreamManager.moveToRestartQueue(stream, streamID); } } diff --git a/packages/ConnectivityT/OWNERS b/packages/ConnectivityT/OWNERS new file mode 100644 index 000000000000..e267d19ad7e2 --- /dev/null +++ b/packages/ConnectivityT/OWNERS @@ -0,0 +1,2 @@ +file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking +per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp new file mode 100644 index 000000000000..931a55b27ddb --- /dev/null +++ b/packages/ConnectivityT/framework-t/Android.bp @@ -0,0 +1,139 @@ +// +// 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 { + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + +// NetworkStats related libraries. + +filegroup { + name: "framework-connectivity-netstats-internal-sources", + srcs: [ + "src/android/app/usage/*.java", + "src/android/net/DataUsage*.*", + "src/android/net/INetworkStats*.*", + "src/android/net/NetworkIdentity*.java", + "src/android/net/NetworkStateSnapshot.*", + "src/android/net/NetworkStats*.*", + "src/android/net/NetworkTemplate.*", + "src/android/net/TrafficStats.java", + "src/android/net/UnderlyingNetworkInfo.*", + "src/android/net/netstats/**/*.*", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-netstats-aidl-export-sources", + srcs: [ + "aidl-export/android/net/NetworkStats.aidl", + "aidl-export/android/net/NetworkTemplate.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-netstats-sources", + srcs: [ + ":framework-connectivity-netstats-internal-sources", + ":framework-connectivity-netstats-aidl-export-sources", + ], + visibility: [ + "//visibility:private", + ], +} + +// Nsd related libraries. + +filegroup { + name: "framework-connectivity-nsd-internal-sources", + srcs: [ + "src/android/net/nsd/*.aidl", + "src/android/net/nsd/*.java", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-nsd-aidl-export-sources", + srcs: [ + "aidl-export/android/net/nsd/*.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-nsd-sources", + srcs: [ + ":framework-connectivity-nsd-internal-sources", + ":framework-connectivity-nsd-aidl-export-sources", + ], + visibility: [ + "//visibility:private", + ], +} + +// IpSec related libraries. + +filegroup { + name: "framework-connectivity-ipsec-sources", + srcs: [ + "src/android/net/IIpSecService.aidl", + "src/android/net/IpSec*.*", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +// Connectivity-T common libraries. + +filegroup { + name: "framework-connectivity-tiramisu-internal-sources", + srcs: [ + "src/android/net/ConnectivityFrameworkInitializerTiramisu.java", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-tiramisu-sources", + srcs: [ + ":framework-connectivity-ipsec-sources", + ":framework-connectivity-netstats-sources", + ":framework-connectivity-nsd-sources", + ":framework-connectivity-tiramisu-internal-sources", + ], + visibility: ["//frameworks/base"], +} diff --git a/core/java/android/net/NetworkStats.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl index d06ca65a3e0d..d06ca65a3e0d 100644 --- a/core/java/android/net/NetworkStats.aidl +++ b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkStats.aidl diff --git a/core/java/android/net/NetworkTemplate.aidl b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl index 3d37488d9881..3d37488d9881 100644 --- a/core/java/android/net/NetworkTemplate.aidl +++ b/packages/ConnectivityT/framework-t/aidl-export/android/net/NetworkTemplate.aidl 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 index 657bdd1e8706..657bdd1e8706 100644 --- a/packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl +++ b/packages/ConnectivityT/framework-t/aidl-export/android/net/nsd/NsdServiceInfo.aidl diff --git a/core/java/android/app/usage/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java index 216a4a0987f5..216a4a0987f5 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java index 8a6c85d54896..8a6c85d54896 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java new file mode 100644 index 000000000000..630f902ecfd7 --- /dev/null +++ b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java @@ -0,0 +1,52 @@ +/* + * 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; + +import android.annotation.SystemApi; +import android.app.SystemServiceRegistry; +import android.content.Context; +import android.net.nsd.INsdManager; +import android.net.nsd.NsdManager; + +/** + * Class for performing registration for Connectivity services which are exposed via updatable APIs + * since Android T. + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class ConnectivityFrameworkInitializerTiramisu { + private ConnectivityFrameworkInitializerTiramisu() {} + + /** + * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to + * {@link Context}, so that {@link Context#getSystemService} can return them. + * + * @throws IllegalStateException if this is called anywhere besides + * {@link SystemServiceRegistry}. + */ + public static void registerServiceWrappers() { + SystemServiceRegistry.registerContextAwareService( + Context.NSD_SERVICE, + NsdManager.class, + (context, serviceBinder) -> { + INsdManager service = INsdManager.Stub.asInterface(serviceBinder); + return new NsdManager(context, service); + } + ); + } +} diff --git a/core/java/android/net/DataUsageRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl index d1937c7b8c62..d1937c7b8c62 100644 --- a/core/java/android/net/DataUsageRequest.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.aidl diff --git a/core/java/android/net/DataUsageRequest.java b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java index b06d515b3acf..b06d515b3acf 100644 --- a/core/java/android/net/DataUsageRequest.java +++ b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java diff --git a/core/java/android/net/IIpSecService.aidl b/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl index 933256a3b475..933256a3b475 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IIpSecService.aidl diff --git a/core/java/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl index 12937b5cb2c7..12937b5cb2c7 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl diff --git a/core/java/android/net/INetworkStatsSession.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl index f13f2cb664ba..dfedf6633dcd 100644 --- a/core/java/android/net/INetworkStatsSession.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl @@ -33,7 +33,17 @@ interface INetworkStatsSession { @UnsupportedAppUsage NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields); - /** Return network layer usage summary per UID for traffic that matches template. */ + /** + * Return network layer usage summary per UID for traffic that matches template. + * + * <p>The resulting {@code NetworkStats#getElapsedRealtime()} contains time delta between + * {@code start} and {@code end}. + * + * @param template - a predicate to filter netstats. + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param includeTags - includes data usage tags if true. + */ @UnsupportedAppUsage NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); /** Return historical network layer stats for specific UID traffic that matches template. */ diff --git a/core/java/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java index 86052484eaf6..86052484eaf6 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java diff --git a/core/java/android/net/IpSecConfig.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl index eaefca74d3a0..eaefca74d3a0 100644 --- a/core/java/android/net/IpSecConfig.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.aidl diff --git a/core/java/android/net/IpSecConfig.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java index 575c5ed968f8..575c5ed968f8 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java diff --git a/core/java/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java index c10680761ff1..c10680761ff1 100644 --- a/core/java/android/net/IpSecManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java diff --git a/core/java/android/net/IpSecSpiResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl index 6484a0013c53..6484a0013c53 100644 --- a/core/java/android/net/IpSecSpiResponse.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.aidl diff --git a/core/java/android/net/IpSecSpiResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java index f99e570fb761..f99e570fb761 100644 --- a/core/java/android/net/IpSecSpiResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecSpiResponse.java diff --git a/core/java/android/net/IpSecTransform.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java index b48c1fdaf1b2..b48c1fdaf1b2 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java diff --git a/core/java/android/net/IpSecTransformResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl index 546230d5b888..546230d5b888 100644 --- a/core/java/android/net/IpSecTransformResponse.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.aidl diff --git a/core/java/android/net/IpSecTransformResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java index a38488954fc0..a38488954fc0 100644 --- a/core/java/android/net/IpSecTransformResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransformResponse.java diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl index 7239221415ce..7239221415ce 100644 --- a/core/java/android/net/IpSecTunnelInterfaceResponse.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java index e3411e003d6b..e3411e003d6b 100644 --- a/core/java/android/net/IpSecTunnelInterfaceResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java diff --git a/core/java/android/net/IpSecUdpEncapResponse.aidl b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl index 5e451f3651f1..5e451f3651f1 100644 --- a/core/java/android/net/IpSecUdpEncapResponse.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.aidl diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java index 4e7ba9b515d0..4e7ba9b515d0 100644 --- a/core/java/android/net/IpSecUdpEncapResponse.java +++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java diff --git a/core/java/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java index eb8f43e3d073..eb8f43e3d073 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java index 22ed781da92d..abbebef85c8f 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.android.server.net; +package android.net; + +import static android.net.ConnectivityManager.TYPE_MOBILE; -import android.net.NetworkIdentity; import android.service.NetworkIdentitySetProto; import android.util.proto.ProtoOutputStream; @@ -25,8 +26,6 @@ import java.io.DataOutput; import java.io.IOException; import java.util.HashSet; -import static android.net.ConnectivityManager.TYPE_MOBILE; - /** * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} * active on that interface. @@ -97,6 +96,9 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements } } + /** + * Method to serialize this object into a {@code DataOutput}. + */ public void writeToStream(DataOutput out) throws IOException { out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK); out.writeInt(size()); @@ -179,6 +181,9 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements return ident.compareTo(anotherIdent); } + /** + * Method to dump this object into proto debug file. + */ public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); diff --git a/core/java/android/net/NetworkStateSnapshot.aidl b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl index cb602d7927ce..cb602d7927ce 100644 --- a/core/java/android/net/NetworkStateSnapshot.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl diff --git a/core/java/android/net/NetworkStateSnapshot.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java index 39156343924d..39156343924d 100644 --- a/core/java/android/net/NetworkStateSnapshot.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java diff --git a/core/java/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java index 46c83df96b04..c7ffc1933829 100644 --- a/core/java/android/net/NetworkStats.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java @@ -220,8 +220,10 @@ public final class NetworkStats implements Parcelable { // TODO: move fields to "mVariable" notation /** - * {@link SystemClock#elapsedRealtime()} timestamp when this data was + * {@link SystemClock#elapsedRealtime()} timestamp in milliseconds when this data was * generated. + * It's a timestamps delta when {@link #subtract()}, + * {@code INetworkStatsSession#getSummaryForAllUid()} methods are used. */ private long elapsedRealtime; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java index d25eae409d40..3885a9e6d5cb 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsAccess.java @@ -11,10 +11,10 @@ * 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 + * limitations under the License. */ -package com.android.server.net; +package android.net; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.net.NetworkStats.UID_ALL; @@ -37,7 +37,11 @@ import com.android.server.LocalServices; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -/** Utility methods for controlling access to network stats APIs. */ +/** + * Utility methods for controlling access to network stats APIs. + * + * @hide + */ public final class NetworkStatsAccess { private NetworkStatsAccess() {} diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java index df372b1459af..0d3b9ed4e3d4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.net; +package android.net; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; @@ -31,13 +31,7 @@ import static android.net.TrafficStats.UID_REMOVED; import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; -import static com.android.server.net.NetworkStatsService.TAG; -import android.net.NetworkIdentity; -import android.net.NetworkStats; -import android.net.NetworkStatsHistory; -import android.net.NetworkTemplate; -import android.net.TrafficStats; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; @@ -59,16 +53,15 @@ import com.android.internal.util.FastDataOutput; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Lists; import com.google.android.collect.Maps; +import libcore.io.IoUtils; + import java.io.BufferedInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; -import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -86,8 +79,11 @@ import java.util.Objects; /** * Collection of {@link NetworkStatsHistory}, stored based on combined key of * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. + * + * @hide */ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer { + private static final String TAG = NetworkStatsCollection.class.getSimpleName(); /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; @@ -335,7 +331,13 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Summarize all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. + * the requested parameters across the requested range. + * + * @param template - a predicate for filtering netstats. + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param accessLevel - caller access level. + * @param callerUid - caller UID. */ public NetworkStats getSummary(NetworkTemplate template, long start, long end, @NetworkStatsAccess.Level int accessLevel, int callerUid) { @@ -361,8 +363,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; - entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() ? - DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO; + entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() + ? DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO; entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; @@ -516,6 +518,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** + * Read legacy network summary statistics file format into the collection, + * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. + * + * @deprecated + */ @Deprecated public void readLegacyNetwork(File file) throws IOException { final AtomicFile inputFile = new AtomicFile(file); @@ -555,6 +563,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** + * Read legacy Uid statistics file format into the collection, + * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. + * + * @deprecated + */ @Deprecated public void readLegacyUid(File file, boolean onlyTags) throws IOException { final AtomicFile inputFile = new AtomicFile(file); @@ -769,19 +783,19 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W public final int set; public final int tag; - private final int hashCode; + private final int mHashCode; - public Key(NetworkIdentitySet ident, int uid, int set, int tag) { + Key(NetworkIdentitySet ident, int uid, int set, int tag) { this.ident = ident; this.uid = uid; this.set = set; this.tag = tag; - hashCode = Objects.hash(ident, uid, set, tag); + mHashCode = Objects.hash(ident, uid, set, tag); } @Override public int hashCode() { - return hashCode; + return mHashCode; } @Override diff --git a/core/java/android/net/NetworkStatsHistory.aidl b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl index 8b9069f8fa48..8b9069f8fa48 100644 --- a/core/java/android/net/NetworkStatsHistory.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.aidl diff --git a/core/java/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java index f41306301d42..a875e1ad45a3 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java @@ -526,6 +526,13 @@ public class NetworkStatsHistory implements Parcelable { /** * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. + * + * <p>If the active bucket is not completed yet, it returns the proportional value of it + * based on its duration and the {@code end} param. + * + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param recycle - entry instance for performance, could be null. */ @UnsupportedAppUsage public Entry getValues(long start, long end, Entry recycle) { @@ -535,6 +542,11 @@ public class NetworkStatsHistory implements Parcelable { /** * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. + * + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param now - current timestamp in milliseconds since the epoch (wall clock). + * @param recycle - entry instance for performance, could be null. */ @UnsupportedAppUsage public Entry getValues(long start, long end, long now, Entry recycle) { diff --git a/core/java/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java index c906a13bf41b..8b9c14df7dc8 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java @@ -44,16 +44,10 @@ import android.os.Parcelable; import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.BackupUtils; -import android.util.Log; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -69,19 +63,6 @@ import java.util.Objects; public class NetworkTemplate implements Parcelable { private static final String TAG = "NetworkTemplate"; - /** - * Initial Version of the backup serializer. - */ - public static final int BACKUP_VERSION_1_INIT = 1; - /** - * Version of the backup serializer that added carrier template support. - */ - public static final int BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE = 2; - /** - * Current Version of the Backup Serializer. - */ - private static final int BACKUP_VERSION = BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE; - public static final int MATCH_MOBILE = 1; public static final int MATCH_WIFI = 4; public static final int MATCH_ETHERNET = 5; @@ -849,58 +830,4 @@ public class NetworkTemplate implements Parcelable { return new NetworkTemplate[size]; } }; - - public byte[] getBytesForBackup() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(baos); - - if (!isPersistable()) { - Log.wtf(TAG, "Trying to backup non-persistable template: " + this); - } - - out.writeInt(BACKUP_VERSION); - - out.writeInt(mMatchRule); - BackupUtils.writeString(out, mSubscriberId); - BackupUtils.writeString(out, mNetworkId); - out.writeInt(mMetered); - out.writeInt(mSubscriberIdMatchRule); - - return baos.toByteArray(); - } - - public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in) - throws IOException, BackupUtils.BadVersionException { - int version = in.readInt(); - if (version < BACKUP_VERSION_1_INIT || version > BACKUP_VERSION) { - throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); - } - - int matchRule = in.readInt(); - String subscriberId = BackupUtils.readString(in); - String networkId = BackupUtils.readString(in); - - final int metered; - final int subscriberIdMatchRule; - if (version >= BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE) { - metered = in.readInt(); - subscriberIdMatchRule = in.readInt(); - } else { - // For backward compatibility, fill the missing filters from match rules. - metered = (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD - || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL; - subscriberIdMatchRule = SUBSCRIBER_ID_MATCH_RULE_EXACT; - } - - try { - return new NetworkTemplate(matchRule, - subscriberId, new String[] { subscriberId }, - networkId, metered, NetworkStats.ROAMING_ALL, - NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL, - NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule); - } catch (IllegalArgumentException e) { - throw new BackupUtils.BadVersionException( - "Restored network template contains unknown match rule " + matchRule, e); - } - } } diff --git a/core/java/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java index fa650617f380..fa650617f380 100644 --- a/core/java/android/net/TrafficStats.java +++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java diff --git a/core/java/android/net/UnderlyingNetworkInfo.aidl b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl index a56f2f40583b..a56f2f40583b 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.aidl diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java index 33f9375c03bf..33f9375c03bf 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl index 74c3ba44b69e..74c3ba44b69e 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index 7eaa01e262fe..7eaa01e262fe 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java index 23fc06927ef9..23fc06927ef9 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/nsd/INsdManager.aidl index 89e9cdbd4445..89e9cdbd4445 100644 --- a/packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl +++ b/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 index 1a262ec0e9dd..1a262ec0e9dd 100644 --- a/packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl +++ b/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 index b06ae55b150e..b06ae55b150e 100644 --- a/packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl +++ b/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 index 6c597e26e042..0f21e55b9f27 100644 --- a/packages/Nsd/framework/src/android/net/nsd/NsdManager.java +++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java @@ -16,10 +16,6 @@ package android.net.nsd; -import static com.android.internal.util.Preconditions.checkArgument; -import static com.android.internal.util.Preconditions.checkNotNull; -import static com.android.internal.util.Preconditions.checkStringNotEmpty; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; @@ -32,11 +28,13 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; + +import java.util.Objects; /** * The Network Service Discovery Manager class provides the API to discover services @@ -175,65 +173,63 @@ public final class NsdManager { */ public static final int NSD_STATE_ENABLED = 2; - private static final int BASE = Protocol.BASE_NSD_MANAGER; - /** @hide */ - public static final int DISCOVER_SERVICES = BASE + 1; + public static final int DISCOVER_SERVICES = 1; /** @hide */ - public static final int DISCOVER_SERVICES_STARTED = BASE + 2; + public static final int DISCOVER_SERVICES_STARTED = 2; /** @hide */ - public static final int DISCOVER_SERVICES_FAILED = BASE + 3; + public static final int DISCOVER_SERVICES_FAILED = 3; /** @hide */ - public static final int SERVICE_FOUND = BASE + 4; + public static final int SERVICE_FOUND = 4; /** @hide */ - public static final int SERVICE_LOST = BASE + 5; + public static final int SERVICE_LOST = 5; /** @hide */ - public static final int STOP_DISCOVERY = BASE + 6; + public static final int STOP_DISCOVERY = 6; /** @hide */ - public static final int STOP_DISCOVERY_FAILED = BASE + 7; + public static final int STOP_DISCOVERY_FAILED = 7; /** @hide */ - public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 8; + public static final int STOP_DISCOVERY_SUCCEEDED = 8; /** @hide */ - public static final int REGISTER_SERVICE = BASE + 9; + public static final int REGISTER_SERVICE = 9; /** @hide */ - public static final int REGISTER_SERVICE_FAILED = BASE + 10; + public static final int REGISTER_SERVICE_FAILED = 10; /** @hide */ - public static final int REGISTER_SERVICE_SUCCEEDED = BASE + 11; + public static final int REGISTER_SERVICE_SUCCEEDED = 11; /** @hide */ - public static final int UNREGISTER_SERVICE = BASE + 12; + public static final int UNREGISTER_SERVICE = 12; /** @hide */ - public static final int UNREGISTER_SERVICE_FAILED = BASE + 13; + public static final int UNREGISTER_SERVICE_FAILED = 13; /** @hide */ - public static final int UNREGISTER_SERVICE_SUCCEEDED = BASE + 14; + public static final int UNREGISTER_SERVICE_SUCCEEDED = 14; /** @hide */ - public static final int RESOLVE_SERVICE = BASE + 18; + public static final int RESOLVE_SERVICE = 15; /** @hide */ - public static final int RESOLVE_SERVICE_FAILED = BASE + 19; + public static final int RESOLVE_SERVICE_FAILED = 16; /** @hide */ - public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20; + public static final int RESOLVE_SERVICE_SUCCEEDED = 17; /** @hide */ - public static final int DAEMON_CLEANUP = BASE + 21; + public static final int DAEMON_CLEANUP = 18; /** @hide */ - public static final int DAEMON_STARTUP = BASE + 22; + public static final int DAEMON_STARTUP = 19; /** @hide */ - public static final int ENABLE = BASE + 24; + public static final int ENABLE = 20; /** @hide */ - public static final int DISABLE = BASE + 25; + public static final int DISABLE = 21; /** @hide */ - public static final int NATIVE_DAEMON_EVENT = BASE + 26; + public static final int NATIVE_DAEMON_EVENT = 22; /** @hide */ - public static final int REGISTER_CLIENT = BASE + 27; + public static final int REGISTER_CLIENT = 23; /** @hide */ - public static final int UNREGISTER_CLIENT = BASE + 28; + public static final int UNREGISTER_CLIENT = 24; /** Dns based service discovery protocol */ public static final int PROTOCOL_DNS_SD = 0x0001; @@ -550,7 +546,9 @@ public final class NsdManager { final int key; synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - checkArgument(valueIndex == -1, "listener already in use"); + if (valueIndex != -1) { + throw new IllegalArgumentException("listener already in use"); + } key = nextListenerKey(); mListenerMap.put(key, listener); mServiceMap.put(key, s); @@ -569,7 +567,9 @@ public final class NsdManager { checkListener(listener); synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - checkArgument(valueIndex != -1, "listener not registered"); + if (valueIndex == -1) { + throw new IllegalArgumentException("listener not registered"); + } return mListenerMap.keyAt(valueIndex); } } @@ -598,7 +598,9 @@ public final class NsdManager { */ public void registerService(NsdServiceInfo serviceInfo, int protocolType, RegistrationListener listener) { - checkArgument(serviceInfo.getPort() > 0, "Invalid port number"); + if (serviceInfo.getPort() <= 0) { + throw new IllegalArgumentException("Invalid port number"); + } checkServiceInfo(serviceInfo); checkProtocol(protocolType); int key = putListener(listener, serviceInfo); @@ -660,7 +662,9 @@ public final class NsdManager { * Cannot be null. Cannot be in use for an active service discovery. */ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { - checkStringNotEmpty(serviceType, "Service type cannot be empty"); + if (TextUtils.isEmpty(serviceType)) { + throw new IllegalArgumentException("Service type cannot be empty"); + } checkProtocol(protocolType); NsdServiceInfo s = new NsdServiceInfo(); @@ -719,16 +723,22 @@ public final class NsdManager { } private static void checkListener(Object listener) { - checkNotNull(listener, "listener cannot be null"); + Objects.requireNonNull(listener, "listener cannot be null"); } private static void checkProtocol(int protocolType) { - checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol"); + if (protocolType != PROTOCOL_DNS_SD) { + throw new IllegalArgumentException("Unsupported protocol"); + } } private static void checkServiceInfo(NsdServiceInfo serviceInfo) { - checkNotNull(serviceInfo, "NsdServiceInfo cannot be null"); - checkStringNotEmpty(serviceInfo.getServiceName(), "Service name cannot be empty"); - checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty"); + Objects.requireNonNull(serviceInfo, "NsdServiceInfo cannot be null"); + if (TextUtils.isEmpty(serviceInfo.getServiceName())) { + throw new IllegalArgumentException("Service name cannot be empty"); + } + if (TextUtils.isEmpty(serviceInfo.getServiceType())) { + throw new IllegalArgumentException("Service type cannot be empty"); + } } } diff --git a/packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java index 0946499f164f..0946499f164f 100644 --- a/packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java +++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java diff --git a/packages/Nsd/framework/Android.bp b/packages/ConnectivityT/service/Android.bp index 2363a9f8d4a3..7b8817692b74 100644 --- a/packages/Nsd/framework/Android.bp +++ b/packages/ConnectivityT/service/Android.bp @@ -19,11 +19,13 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// NetworkStats related libraries. + filegroup { - name: "framework-connectivity-nsd-internal-sources", + name: "services.connectivity-netstats-sources", srcs: [ - "src/**/*.java", - "src/**/*.aidl", + "src/com/android/server/net/NetworkIdentity*.java", + "src/com/android/server/net/NetworkStats*.java", ], path: "src", visibility: [ @@ -31,24 +33,43 @@ filegroup { ], } +// Nsd related libraries. + filegroup { - name: "framework-connectivity-nsd-aidl-export-sources", + name: "services.connectivity-nsd-sources", srcs: [ - "aidl-export/**/*.aidl", + "src/com/android/server/INativeDaemon*.java", + "src/com/android/server/NativeDaemon*.java", + "src/com/android/server/Nsd*.java", ], - path: "aidl-export", + path: "src", visibility: [ "//visibility:private", ], } +// IpSec related libraries. + filegroup { - name: "framework-connectivity-nsd-sources", + name: "services.connectivity-ipsec-sources", srcs: [ - ":framework-connectivity-nsd-internal-sources", - ":framework-connectivity-nsd-aidl-export-sources", + "src/com/android/server/IpSecService.java", ], + path: "src", visibility: [ - "//frameworks/base", + "//visibility:private", ], } + +// Connectivity-T common libraries. + +filegroup { + name: "services.connectivity-tiramisu-sources", + srcs: [ + ":services.connectivity-ipsec-sources", + ":services.connectivity-netstats-sources", + ":services.connectivity-nsd-sources", + ], + path: "src", + visibility: ["//frameworks/base/services/core"], +} diff --git a/packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java b/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java index 0cf9dcde012d..0cf9dcde012d 100644 --- a/packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java +++ b/packages/ConnectivityT/service/src/com/android/server/INativeDaemonConnectorCallbacks.java diff --git a/services/core/java/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java index aeb814327e66..aeb814327e66 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java b/packages/ConnectivityT/service/src/com/android/server/NativeDaemonConnector.java index eac767f7355c..ec8d7798e17e 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.LocalSocket; 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.OutputStream; 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo * 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo // 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo } } - /** {@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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo } 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo 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 index 4d8881c68324..4d8881c68324 100644 --- a/packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java +++ b/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 index e6feda3dad22..568369434629 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 @@ public class NativeDaemonEvent { * {@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 @@ public class NativeDaemonEvent { 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 @@ public class NativeDaemonEvent { 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 @@ public class NativeDaemonEvent { } } // 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 index 658f7d6264eb..658f7d6264eb 100644 --- a/packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java +++ b/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 index 3e0208411c21..497107dbf989 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.IBinder; 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { // 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 @@ public class NsdService extends INsdManager.Stub { ++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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } @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 class NsdService extends INsdManager.Stub { } 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 @@ public class NsdService extends INsdManager.Stub { } } - 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 @@ public class NsdService extends INsdManager.Stub { 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 class NsdService extends INsdManager.Stub { */ 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { @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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { 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 @@ public class NsdService extends INsdManager.Stub { } } } - - /** - * 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/services/core/java/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java index e6433db11d7b..e6433db11d7b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java diff --git a/services/core/java/com/android/server/net/NetworkStatsManagerInternal.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsManagerInternal.java index 0e9a9da6804b..0e9a9da6804b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsManagerInternal.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsManagerInternal.java diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java index 2564daeaa1c0..1a0866d2f9c5 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java @@ -22,7 +22,10 @@ import static com.android.internal.util.Preconditions.checkArgument; import android.app.usage.NetworkStatsManager; import android.net.DataUsageRequest; +import android.net.NetworkIdentitySet; import android.net.NetworkStats; +import android.net.NetworkStatsAccess; +import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Bundle; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java index 978ae87d39d5..5e27c776ccb0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java @@ -21,8 +21,11 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.text.format.DateUtils.YEAR_IN_MILLIS; +import android.net.NetworkIdentitySet; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; +import android.net.NetworkStatsAccess; +import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java index c876d411fac1..2beca73ecd72 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java @@ -96,11 +96,14 @@ import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; +import android.net.NetworkIdentitySet; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; +import android.net.NetworkStatsAccess; +import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 5646c752fc90..5646c752fc90 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java diff --git a/packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java b/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java index e2253a2151b0..e2253a2151b0 100644 --- a/packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java +++ b/packages/ConnectivityT/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java diff --git a/packages/Nsd/OWNERS b/packages/Nsd/OWNERS deleted file mode 100644 index 4862377852ac..000000000000 --- a/packages/Nsd/OWNERS +++ /dev/null @@ -1 +0,0 @@ -file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
\ No newline at end of file diff --git a/packages/Nsd/service/Android.bp b/packages/Nsd/service/Android.bp deleted file mode 100644 index 529f58d130ed..000000000000 --- a/packages/Nsd/service/Android.bp +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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 { - // See: http://go/android-license-faq - default_applicable_licenses: ["Android-Apache-2.0"], -} - -filegroup { - name: "services.connectivity-nsd-sources", - srcs: [ - "src/**/*.java", - ], - path: "src", - visibility: [ - "//frameworks/base/services/core", - ], -} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java index 3c7856048860..99e3160fcbe3 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.BluetoothDevice; 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 @@ public class A2dpProfile implements LocalBluetoothProfile { 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 @@ public class A2dpProfile implements LocalBluetoothProfile { } } + /** + * 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 @@ public class A2dpProfile implements LocalBluetoothProfile { } // 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 9afdd43ce73c..f167721f94bf 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.RobolectricTestRunner; 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 @@ public class A2dpProfileTest { 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 @@ public class A2dpProfileTest { 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 9cd7083a2a11..c30c742fd9d9 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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 073b4d00653d..6c6b0e8a5076 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 @@ class SettingsProtoDumpUtil { 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 3297937e3e75..773b0682233f 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -388,6 +388,7 @@ public class SettingsBackupTest { 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 97cc948e134b..1f1e24ac8b1e 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -165,6 +165,7 @@ <uses-permission android:name="com.android.permission.USE_INSTALLER_V2" /> <uses-permission android:name="android.permission.INSTALL_TEST_ONLY_PACKAGE" /> <uses-permission android:name="com.android.permission.USE_SYSTEM_DATA_LOADERS" /> + <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" /> <uses-permission android:name="android.permission.MOVE_PACKAGE" /> <uses-permission android:name="android.permission.KEEP_UNINSTALLED_PACKAGES" /> <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> @@ -578,6 +579,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 fc353a1945a6..5ffd3008c6cd 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 cc0fd98c7060..e11b0442377e 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -23,6 +23,36 @@ java_defaults { }, } +// 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 { // ============================================================ java_library { name: "services", + defaults: ["services_java_defaults"], installable: true, dex_preopt: { diff --git a/services/core/Android.bp b/services/core/Android.bp index d65969c11357..1dda14ca0db5 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -111,7 +111,7 @@ java_library_static { "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/wm/EventLogTags.logtags", "java/com/android/server/policy/EventLogTags.logtags", - ":services.connectivity-nsd-sources", + ":services.connectivity-tiramisu-sources", ], libs: [ diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java index 263ff189a288..380b1f37b981 100644 --- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java +++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java @@ -112,9 +112,9 @@ class BluetoothAirplaneModeListener { 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 b6413773046f..71b463a4db8c 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -25,13 +25,14 @@ per-file *Battery* = file:/BATTERY_STATS_OWNERS 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 cb6e73af56ac..3cc8e7672557 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.Nullable; 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 @@ public final class SystemServiceManager implements Dumpable { // 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 @@ public final class SystemServiceManager implements Dumpable { * @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 b77270f5963b..6c84ca4d9251 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { // 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 4eac97286880..f05f40353e30 100644 --- a/services/core/java/com/android/server/biometrics/OWNERS +++ b/services/core/java/com/android/server/biometrics/OWNERS @@ -6,3 +6,4 @@ curtislb@google.com 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 6ea84ce35002..ee5bda3abc91 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 @@ public class NetdEventListenerService extends INetdEventListener.Stub { } 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 @@ public class NetdEventListenerService extends INetdEventListener.Stub { 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 b45d87fbed5f..81106b1a5ca7 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 @@ public class NetworkPolicyLogger { } } - 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 1aa80a953d6c..5b4084e9b229 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 @@ class PackageManagerShellCommand extends ShellCommand { } } + 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 @@ class PackageManagerShellCommand extends ShellCommand { } 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 @@ class PackageManagerShellCommand extends ShellCommand { } 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 7b12709e4efd..f733a2e0bb3f 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { } 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { } 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 @@ public class PermissionManagerService extends IPermissionManager.Stub { 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 be13168815d9..8b80b4a0b21e 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; 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 @@ public class VcnGatewayConnection extends StateMachine { mUnderlyingNetworkController = mDeps.newUnderlyingNetworkController( mVcnContext, + mConnectionConfig, subscriptionGroup, mLastSnapshot, mUnderlyingNetworkControllerCallback); @@ -788,8 +790,19 @@ public class VcnGatewayConnection extends StateMachine { // 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 @@ public class VcnGatewayConnection extends StateMachine { /** 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 @@ public class VcnGatewayConnection extends StateMachine { 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 bea8ae932a9d..45769575111f 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,61 +67,188 @@ class NetworkPriorityClassifier { */ @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<>(); + /** 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) { + // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED + + if (networkRecord.isBlocked) { + logWtf("Network blocked for System Server: " + networkRecord.network); + return PRIORITY_ANY; + } + + if (snapshot == null) { + logWtf("Got null snapshot"); + return PRIORITY_ANY; + } - 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"); + int priorityIndex = 0; + for (VcnUnderlyingNetworkPriority nwPriority : underlyingNetworkPriorities) { + if (checkMatchesPriorityRule( + vcnContext, + nwPriority, + networkRecord, + subscriptionGroup, + snapshot, + currentlySelected, + carrierConfig)) { + return priorityIndex; + } + priorityIndex++; + } + return 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( + @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; + } - // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED + if (vcnContext.isInTestMode() && caps.hasTransport(TRANSPORT_TEST)) { + return true; + } - if (networkRecord.isBlocked) { - logWtf("Network blocked for System Server: " + networkRecord.network); - return PRIORITY_ANY; + 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; } - if (caps.hasTransport(TRANSPORT_CELLULAR) - && isOpportunistic(snapshot, caps.getSubscriptionIds())) { + 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 @@ class NetworkPriorityClassifier { // 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; - } - } - - 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; + return false; } } - // 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 @@ class NetworkPriorityClassifier { 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 071c7a683cbf..cd124ee6a9fa 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.Network; 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 @@ public class UnderlyingNetworkController { @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 class UnderlyingNetworkController { 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 @@ public class UnderlyingNetworkController { TreeSet<UnderlyingNetworkRecord> sorted = new TreeSet<>( UnderlyingNetworkRecord.getComparator( + mVcnContext, + mConnectionConfig.getVcnUnderlyingNetworkPriorities(), mSubscriptionGroup, mLastSnapshot, mCurrentRecord, @@ -495,12 +498,31 @@ public class UnderlyingNetworkController { 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 65c69dedcb28..27ba854ab197 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.annotation.Nullable; 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; 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 @@ public class UnderlyingNetworkRecord { } 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 @@ public class UnderlyingNetworkRecord { 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 5c1b5ffb2209..1c675c228554 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 @@ public class PersistableBundleUtils { 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 @@ public class PersistableBundleUtils { 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 710a304545af..e7005daf5626 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -85,6 +85,7 @@ cc_library_static { header_libs: [ "bionic_libc_platform_headers", + "bpf_connectivity_headers", ], } diff --git a/services/proguard.flags b/services/proguard.flags new file mode 100644 index 000000000000..30dd6cf545b9 --- /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 8765c9a64b77..6a2192a2c7fb 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 d06fe45a104c..2b855e92c549 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -822,6 +822,17 @@ public abstract class Connection extends Conferenceable { "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 4d81b5e54470..fcc23a924d85 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -107,6 +107,26 @@ public final class TelephonyPermissions { } } + + /** + * 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 @@ public final class TelephonyPermissions { } /** + * 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/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 5ffe45f8c489..d3fc033e1b1d 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -5821,6 +5821,7 @@ public class CarrierConfigManager { sDefaults.putInt( KEY_OPPORTUNISTIC_TIME_TO_SCAN_AFTER_CAPABILITY_SWITCH_TO_PRIMARY_LONG, 120000); + sDefaults.putAll(ImsServiceEntitlement.getDefaults()); sDefaults.putAll(Gps.getDefaults()); sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY, new int[] { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a1d68b215ba5..a2efc962ed9c 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1895,9 +1895,10 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * @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 @@ public class TelephonyManager { * 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 @@ public class TelephonyManager { * * <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 @@ public class TelephonyManager { */ @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 @@ public class TelephonyManager { * * <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 @@ public class TelephonyManager { * <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 @@ public class TelephonyManager { * <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 @@ public class TelephonyManager { 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 c00c741a0d60..c2c9497cef3d 100644 --- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java +++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java @@ -97,7 +97,24 @@ public final class DelegateRegistrationState implements Parcelable { */ 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 @@ public final class DelegateRegistrationState implements Parcelable { 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 @@ public final class DelegateRegistrationState implements Parcelable { } /** + * 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 @@ public final class DelegateRegistrationState implements Parcelable { 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 @@ public final class DelegateRegistrationState implements Parcelable { dest.writeArraySet(mRegisteredTags); writeStateToParcel(dest, mDeregisteringTags); writeStateToParcel(dest, mDeregisteredTags); + dest.writeArraySet(mRegisteringTags); } private void writeStateToParcel(Parcel dest, Set<FeatureTagState> state) { @@ -311,19 +357,22 @@ public final class DelegateRegistrationState implements Parcelable { 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 6b33a6894365..2df5f53147bc 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -2509,4 +2509,13 @@ interface ITelephony { * 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 000000000000..476be44ee759 --- /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 dc338ae0fdc7..377f526a9825 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.IkeSessionParams; 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.Test; 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 class VcnGatewayConnectionConfigTest { }; 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 class VcnGatewayConnectionConfigTest { // 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 @@ public class VcnGatewayConnectionConfigTest { } @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 @@ public class VcnGatewayConnectionConfigTest { 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 @@ public class VcnGatewayConnectionConfigTest { 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 @@ public class VcnGatewayConnectionConfigTest { 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 69ffeadbffae..dd272cb38596 100644 --- a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkPriorityTest.java +++ b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkPriorityTest.java @@ -30,7 +30,8 @@ public class VcnWifiUnderlyingNetworkPriorityTest { 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 15de226cdc40..e547400fff73 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 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection @Test public void testNullNetworkDoesNotTriggerDisconnect() throws Exception { + doReturn(false).when(mDeps).isAirplaneModeOn(any()); + mGatewayConnection .getUnderlyingNetworkControllerCallback() .onSelectedUnderlyingNetworkChanged(null); @@ -129,6 +131,19 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection } @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 8a0af2dff8c8..5628321b5975 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 @@ public class VcnGatewayConnectionTestBase { 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 000000000000..46a614f60ae7 --- /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 c954cb84df7f..fad9669911bb 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.Network; 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 @@ public class UnderlyingNetworkControllerTest { mUnderlyingNetworkController = new UnderlyingNetworkController( - mVcnContext, SUB_GROUP, mSubscriptionSnapshot, mNetworkControllerCb); + mVcnContext, + VcnGatewayConnectionConfigTest.buildTestConfig(), + SUB_GROUP, + mSubscriptionSnapshot, + mNetworkControllerCb); } private void resetVcnContext() { @@ -153,7 +158,8 @@ public class UnderlyingNetworkControllerTest { 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 @@ public class UnderlyingNetworkControllerTest { true /* isInTestMode */); new UnderlyingNetworkController( - vcnContext, SUB_GROUP, mSubscriptionSnapshot, mNetworkControllerCb); + vcnContext, + VcnGatewayConnectionConfigTest.buildTestConfig(), + SUB_GROUP, + mSubscriptionSnapshot, + mNetworkControllerCb); verify(cm) .registerNetworkCallback( @@ -345,6 +355,17 @@ public class UnderlyingNetworkControllerTest { 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 @@ public class UnderlyingNetworkControllerTest { 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 class UnderlyingNetworkControllerTest { 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 @@ public class UnderlyingNetworkControllerTest { 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 class UnderlyingNetworkControllerTest { 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 @@ public class UnderlyingNetworkControllerTest { 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 @@ public class UnderlyingNetworkControllerTest { 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 class UnderlyingNetworkControllerTest { 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 @@ public class UnderlyingNetworkControllerTest { 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()); diff --git a/tools/locked_region_code_injection/Android.bp b/tools/locked_region_code_injection/Android.bp index 98c0e69cbf8e..3e1297190622 100644 --- a/tools/locked_region_code_injection/Android.bp +++ b/tools/locked_region_code_injection/Android.bp @@ -12,10 +12,10 @@ java_binary_host { manifest: "manifest.txt", srcs: ["src/**/*.java"], static_libs: [ - "asm-6.0", - "asm-commons-6.0", - "asm-tree-6.0", - "asm-analysis-6.0", + "asm-7.0", + "asm-commons-7.0", + "asm-tree-7.0", + "asm-analysis-7.0", "guava-21.0", ], } diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java index 1002c88e9281..335b3f82c533 100644 --- a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java +++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockTargetStateAnalysis.java @@ -13,8 +13,6 @@ */ package lockedregioncodeinjection; -import java.util.ArrayList; -import java.util.List; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.MethodInsnNode; @@ -22,6 +20,9 @@ import org.objectweb.asm.tree.analysis.AnalyzerException; import org.objectweb.asm.tree.analysis.BasicInterpreter; import org.objectweb.asm.tree.analysis.BasicValue; +import java.util.ArrayList; +import java.util.List; + /** * A simple dataflow analysis to determine if the operands on the stack must be one of target lock * class type. @@ -31,6 +32,7 @@ public class LockTargetStateAnalysis extends BasicInterpreter { private final List<LockTarget> targetLocks; public LockTargetStateAnalysis(List<LockTarget> targetLocks) { + super(Utils.ASM_VERSION); this.targetLocks = targetLocks; } diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java index 219c2b3a2fec..f1e84b1d8a33 100644 --- a/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java +++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/Utils.java @@ -13,13 +13,14 @@ */ package lockedregioncodeinjection; +import org.objectweb.asm.Opcodes; + import java.util.ArrayList; import java.util.List; -import org.objectweb.asm.Opcodes; public class Utils { - public static final int ASM_VERSION = Opcodes.ASM6; + public static final int ASM_VERSION = Opcodes.ASM7; /** * Reads a comma separated configuration similar to the Jack definition. diff --git a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java index c408b9e99c32..31fa0bf63416 100644 --- a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java +++ b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java @@ -30,7 +30,7 @@ import org.junit.Test; * rm -fr out/* * * # Make booster - * javac -cp lib/asm-6.0_BETA.jar:lib/asm-commons-6.0_BETA.jar:lib/asm-tree-6.0_BETA.jar:lib/asm-analysis-6.0_BETA.jar:lib/guava-21.0.jar src/*/*.java -d out/ + * javac -cp lib/asm-7.0_BETA.jar:lib/asm-commons-7.0_BETA.jar:lib/asm-tree-7.0_BETA.jar:lib/asm-analysis-7.0_BETA.jar:lib/guava-21.0.jar src/*/*.java -d out/ * pushd out * jar cfe lockedregioncodeinjection.jar lockedregioncodeinjection.Main */*.class * popd @@ -43,7 +43,7 @@ import org.junit.Test; * popd * * # Run tool on unit tests. - * java -ea -cp lib/asm-6.0_BETA.jar:lib/asm-commons-6.0_BETA.jar:lib/asm-tree-6.0_BETA.jar:lib/asm-analysis-6.0_BETA.jar:lib/guava-21.0.jar:out/lockedregioncodeinjection.jar \ + * java -ea -cp lib/asm-7.0_BETA.jar:lib/asm-commons-7.0_BETA.jar:lib/asm-tree-7.0_BETA.jar:lib/asm-analysis-7.0_BETA.jar:lib/guava-21.0.jar:out/lockedregioncodeinjection.jar \ * lockedregioncodeinjection.Main \ * -i out/test_input.jar -o out/test_output.jar \ * --targets 'Llockedregioncodeinjection/TestTarget;' \ |