Merge changes from topic "presubmit-am-3f45212ff8404a77b5d8cb58c3b578e8" into tm-dev
* changes:
[automerged blank] Import translations. DO NOT MERGE ANYWHERE 2p: bad763f5f3
Import translations. DO NOT MERGE ANYWHERE
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index 4fefa0a..84cdbf7 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -3,7 +3,7 @@
public final class NetworkStats implements java.lang.AutoCloseable {
method public void close();
- method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
+ method public boolean getNextBucket(@Nullable android.app.usage.NetworkStats.Bucket);
method public boolean hasNextBucket();
}
@@ -40,21 +40,21 @@
}
public class NetworkStatsManager {
- method @WorkerThread public android.app.usage.NetworkStats queryDetails(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUid(int, String, long, long, int) throws java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTag(int, String, long, long, int, int) throws java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(int, String, long, long, int, int, int) throws java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats querySummary(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback);
- method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback, @Nullable android.os.Handler);
- method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback);
+ method @WorkerThread public android.app.usage.NetworkStats queryDetails(int, @Nullable String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForUid(int, @Nullable String, long, long, int) throws java.lang.SecurityException;
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTag(int, @Nullable String, long, long, int, int) throws java.lang.SecurityException;
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(int, @Nullable String, long, long, int, int, int) throws java.lang.SecurityException;
+ method @WorkerThread public android.app.usage.NetworkStats querySummary(int, @Nullable String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, @Nullable String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, @Nullable String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
+ method public void registerUsageCallback(int, @Nullable String, long, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
+ method public void registerUsageCallback(int, @Nullable String, long, @NonNull android.app.usage.NetworkStatsManager.UsageCallback, @Nullable android.os.Handler);
+ method public void unregisterUsageCallback(@NonNull android.app.usage.NetworkStatsManager.UsageCallback);
}
public abstract static class NetworkStatsManager.UsageCallback {
ctor public NetworkStatsManager.UsageCallback();
- method public abstract void onThresholdReached(int, String);
+ method public abstract void onThresholdReached(int, @Nullable String);
}
}
@@ -173,12 +173,12 @@
method public static void incrementOperationCount(int, int);
method public static void setThreadStatsTag(int);
method public static void setThreadStatsUid(int);
- method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
- method public static void tagFileDescriptor(java.io.FileDescriptor) throws java.io.IOException;
- method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
- method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
- method public static void untagFileDescriptor(java.io.FileDescriptor) throws java.io.IOException;
- method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
+ method public static void tagDatagramSocket(@NonNull java.net.DatagramSocket) throws java.net.SocketException;
+ method public static void tagFileDescriptor(@NonNull java.io.FileDescriptor) throws java.io.IOException;
+ method public static void tagSocket(@NonNull java.net.Socket) throws java.net.SocketException;
+ method public static void untagDatagramSocket(@NonNull java.net.DatagramSocket) throws java.net.SocketException;
+ method public static void untagFileDescriptor(@NonNull java.io.FileDescriptor) throws java.io.IOException;
+ method public static void untagSocket(@NonNull java.net.Socket) throws java.net.SocketException;
field public static final int UNSUPPORTED = -1; // 0xffffffff
}
diff --git a/framework-t/api/lint-baseline.txt b/framework-t/api/lint-baseline.txt
index 53e1beb..2996a3e 100644
--- a/framework-t/api/lint-baseline.txt
+++ b/framework-t/api/lint-baseline.txt
@@ -41,86 +41,18 @@
android.net.IpSecTransform.Builder does not declare a `build()` method, but builder classes are expected to
-MissingNullability: android.app.usage.NetworkStats#getNextBucket(android.app.usage.NetworkStats.Bucket) parameter #0:
- Missing nullability on parameter `bucketOut` in method `getNextBucket`
MissingNullability: android.app.usage.NetworkStatsManager#queryDetails(int, String, long, long):
Missing nullability on method `queryDetails` return
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetails(int, String, long, long) parameter #1:
- Missing nullability on parameter `subscriberId` in method `queryDetails`
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetailsForUid(int, String, long, long, int):
- Missing nullability on method `queryDetailsForUid` return
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetailsForUid(int, String, long, long, int) parameter #1:
- Missing nullability on parameter `subscriberId` in method `queryDetailsForUid`
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetailsForUidTag(int, String, long, long, int, int):
- Missing nullability on method `queryDetailsForUidTag` return
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetailsForUidTag(int, String, long, long, int, int) parameter #1:
- Missing nullability on parameter `subscriberId` in method `queryDetailsForUidTag`
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetailsForUidTagState(int, String, long, long, int, int, int):
- Missing nullability on method `queryDetailsForUidTagState` return
-MissingNullability: android.app.usage.NetworkStatsManager#queryDetailsForUidTagState(int, String, long, long, int, int, int) parameter #1:
- Missing nullability on parameter `subscriberId` in method `queryDetailsForUidTagState`
MissingNullability: android.app.usage.NetworkStatsManager#querySummary(int, String, long, long):
Missing nullability on method `querySummary` return
-MissingNullability: android.app.usage.NetworkStatsManager#querySummary(int, String, long, long) parameter #1:
- Missing nullability on parameter `subscriberId` in method `querySummary`
MissingNullability: android.app.usage.NetworkStatsManager#querySummaryForDevice(int, String, long, long):
Missing nullability on method `querySummaryForDevice` return
-MissingNullability: android.app.usage.NetworkStatsManager#querySummaryForDevice(int, String, long, long) parameter #1:
- Missing nullability on parameter `subscriberId` in method `querySummaryForDevice`
MissingNullability: android.app.usage.NetworkStatsManager#querySummaryForUser(int, String, long, long):
Missing nullability on method `querySummaryForUser` return
-MissingNullability: android.app.usage.NetworkStatsManager#querySummaryForUser(int, String, long, long) parameter #1:
- Missing nullability on parameter `subscriberId` in method `querySummaryForUser`
-MissingNullability: android.app.usage.NetworkStatsManager#registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback) parameter #1:
- Missing nullability on parameter `subscriberId` in method `registerUsageCallback`
-MissingNullability: android.app.usage.NetworkStatsManager#registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback) parameter #3:
- Missing nullability on parameter `callback` in method `registerUsageCallback`
-MissingNullability: android.app.usage.NetworkStatsManager#registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler) parameter #1:
- Missing nullability on parameter `subscriberId` in method `registerUsageCallback`
-MissingNullability: android.app.usage.NetworkStatsManager#registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback, android.os.Handler) parameter #3:
- Missing nullability on parameter `callback` in method `registerUsageCallback`
-MissingNullability: android.app.usage.NetworkStatsManager#unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback) parameter #0:
- Missing nullability on parameter `callback` in method `unregisterUsageCallback`
-MissingNullability: android.app.usage.NetworkStatsManager.UsageCallback#onThresholdReached(int, String) parameter #1:
- Missing nullability on parameter `subscriberId` in method `onThresholdReached`
MissingNullability: android.net.IpSecAlgorithm#writeToParcel(android.os.Parcel, int) parameter #0:
Missing nullability on parameter `out` in method `writeToParcel`
MissingNullability: android.net.IpSecManager.UdpEncapsulationSocket#getFileDescriptor():
Missing nullability on method `getFileDescriptor` return
-MissingNullability: android.net.TrafficStats#tagDatagramSocket(java.net.DatagramSocket) parameter #0:
- Missing nullability on parameter `socket` in method `tagDatagramSocket`
-MissingNullability: android.net.TrafficStats#tagFileDescriptor(java.io.FileDescriptor) parameter #0:
- Missing nullability on parameter `fd` in method `tagFileDescriptor`
-MissingNullability: android.net.TrafficStats#tagSocket(java.net.Socket) parameter #0:
- Missing nullability on parameter `socket` in method `tagSocket`
-MissingNullability: android.net.TrafficStats#untagDatagramSocket(java.net.DatagramSocket) parameter #0:
- Missing nullability on parameter `socket` in method `untagDatagramSocket`
-MissingNullability: android.net.TrafficStats#untagFileDescriptor(java.io.FileDescriptor) parameter #0:
- Missing nullability on parameter `fd` in method `untagFileDescriptor`
-MissingNullability: android.net.TrafficStats#untagSocket(java.net.Socket) parameter #0:
- Missing nullability on parameter `socket` in method `untagSocket`
-MissingNullability: com.android.internal.util.FileRotator#FileRotator(java.io.File, String, long, long) parameter #0:
- Missing nullability on parameter `basePath` in method `FileRotator`
-MissingNullability: com.android.internal.util.FileRotator#FileRotator(java.io.File, String, long, long) parameter #1:
- Missing nullability on parameter `prefix` in method `FileRotator`
-MissingNullability: com.android.internal.util.FileRotator#dumpAll(java.io.OutputStream) parameter #0:
- Missing nullability on parameter `os` in method `dumpAll`
-MissingNullability: com.android.internal.util.FileRotator#readMatching(com.android.internal.util.FileRotator.Reader, long, long) parameter #0:
- Missing nullability on parameter `reader` in method `readMatching`
-MissingNullability: com.android.internal.util.FileRotator#rewriteActive(com.android.internal.util.FileRotator.Rewriter, long) parameter #0:
- Missing nullability on parameter `rewriter` in method `rewriteActive`
-MissingNullability: com.android.internal.util.FileRotator#rewriteAll(com.android.internal.util.FileRotator.Rewriter) parameter #0:
- Missing nullability on parameter `rewriter` in method `rewriteAll`
-MissingNullability: com.android.internal.util.FileRotator.Reader#read(java.io.InputStream) parameter #0:
- Missing nullability on parameter `in` in method `read`
-MissingNullability: com.android.internal.util.FileRotator.Writer#write(java.io.OutputStream) parameter #0:
- Missing nullability on parameter `out` in method `write`
-MissingNullability: com.android.server.NetworkManagementSocketTagger#kernelToTag(String) parameter #0:
- Missing nullability on parameter `string` in method `kernelToTag`
-MissingNullability: com.android.server.NetworkManagementSocketTagger#tag(java.io.FileDescriptor) parameter #0:
- Missing nullability on parameter `fd` in method `tag`
-MissingNullability: com.android.server.NetworkManagementSocketTagger#untag(java.io.FileDescriptor) parameter #0:
- Missing nullability on parameter `fd` in method `untag`
RethrowRemoteException: android.app.usage.NetworkStatsManager#queryDetails(int, String, long, long):
diff --git a/framework-t/api/module-lib-current.txt b/framework-t/api/module-lib-current.txt
index 0176b6f..216081a 100644
--- a/framework-t/api/module-lib-current.txt
+++ b/framework-t/api/module-lib-current.txt
@@ -4,6 +4,8 @@
public class NetworkStatsManager {
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void forceUpdate();
method public static int getCollapsedRatType(int);
+ method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getMobileUidStats();
+ method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getWifiUidStats();
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void noteUidForeground(int, boolean);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyNetworkStatus(@NonNull java.util.List<android.net.Network>, @NonNull java.util.List<android.net.NetworkStateSnapshot>, @Nullable String, @NonNull java.util.List<android.net.UnderlyingNetworkInfo>);
method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForDevice(@NonNull android.net.NetworkTemplate, long, long);
@@ -40,9 +42,15 @@
}
public class EthernetManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void addEthernetStateListener(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer);
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void addInterfaceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.InterfaceStateListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public java.util.List<java.lang.String> getInterfaceList();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void removeEthernetStateListener(@NonNull java.util.function.IntConsumer);
method public void removeInterfaceStateListener(@NonNull android.net.EthernetManager.InterfaceStateListener);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void setEthernetEnabled(boolean);
method public void setIncludeTestInterfaces(boolean);
+ field public static final int ETHERNET_STATE_DISABLED = 0; // 0x0
+ field public static final int ETHERNET_STATE_ENABLED = 1; // 0x1
field public static final int ROLE_CLIENT = 1; // 0x1
field public static final int ROLE_NONE = 0; // 0x0
field public static final int ROLE_SERVER = 2; // 0x2
@@ -104,6 +112,24 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStateSnapshot> CREATOR;
}
+ public final class NetworkStats implements java.lang.Iterable<android.net.NetworkStats.Entry> android.os.Parcelable {
+ method @NonNull public java.util.Iterator<android.net.NetworkStats.Entry> iterator();
+ }
+
+ public static class NetworkStats.Entry {
+ method public int getDefaultNetwork();
+ method public int getMetered();
+ method public long getOperations();
+ method public int getRoaming();
+ method public long getRxBytes();
+ method public long getRxPackets();
+ method public int getSet();
+ method public int getTag();
+ method public long getTxBytes();
+ method public long getTxPackets();
+ method public int getUid();
+ }
+
public class NetworkStatsCollection {
method @NonNull public java.util.Map<android.net.NetworkStatsCollection.Key,android.net.NetworkStatsHistory> getEntries();
}
@@ -184,6 +210,7 @@
public class TrafficStats {
method public static void attachSocketTagger();
method public static void init(@NonNull android.content.Context);
+ method public static void setThreadStatsTagDownload();
}
public final class UnderlyingNetworkInfo implements android.os.Parcelable {
diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt
index 46eb9ee..fb932d4 100644
--- a/framework-t/api/system-current.txt
+++ b/framework-t/api/system-current.txt
@@ -2,10 +2,8 @@
package android.app.usage {
public class NetworkStatsManager {
- method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getMobileUidStats();
- method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.net.NetworkStats getWifiUidStats();
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
}
}
@@ -21,16 +19,13 @@
field public static final int STATUS_OK = 0; // 0x0
}
- public abstract class BroadcastRequest implements android.os.Parcelable {
- method public int describeContents();
+ public abstract class BroadcastRequest {
method @NonNull public java.util.List<java.lang.Integer> getMediums();
method @IntRange(from=0xffffff81, to=126) public int getTxPower();
method public int getType();
method public int getVersion();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int BROADCAST_TYPE_NEARBY_PRESENCE = 3; // 0x3
field public static final int BROADCAST_TYPE_UNKNOWN = -1; // 0xffffffff
- field @NonNull public static final android.os.Parcelable.Creator<android.nearby.BroadcastRequest> CREATOR;
field public static final int PRESENCE_VERSION_UNKNOWN = -1; // 0xffffffff
field public static final int PRESENCE_VERSION_V0 = 0; // 0x0
field public static final int PRESENCE_VERSION_V1 = 1; // 0x1
@@ -56,39 +51,41 @@
}
public class FastPairAccountKeyDeviceMetadata {
- method @Nullable public byte[] getAccountKey();
+ method @Nullable public byte[] getDeviceAccountKey();
method @Nullable public android.nearby.FastPairDeviceMetadata getFastPairDeviceMetadata();
method @Nullable public android.nearby.FastPairDiscoveryItem getFastPairDiscoveryItem();
- method @Nullable public byte[] getSha256AccountKeyPublicAddress();
+ method @Nullable public byte[] getSha256DeviceAccountKeyPublicAddress();
}
public static final class FastPairAccountKeyDeviceMetadata.Builder {
ctor public FastPairAccountKeyDeviceMetadata.Builder();
method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata build();
- method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata.Builder setAccountKey(@Nullable byte[]);
+ method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata.Builder setDeviceAccountKey(@Nullable byte[]);
method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata.Builder setFastPairDeviceMetadata(@Nullable android.nearby.FastPairDeviceMetadata);
method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata.Builder setFastPairDiscoveryItem(@Nullable android.nearby.FastPairDiscoveryItem);
- method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata.Builder setSha256AccountKeyPublicAddress(@Nullable byte[]);
+ method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata.Builder setSha256DeviceAccountKeyPublicAddress(@Nullable byte[]);
}
public class FastPairAntispoofKeyDeviceMetadata {
+ method @Nullable public byte[] getAntispoofPublicKey();
+ method @Nullable public android.nearby.FastPairDeviceMetadata getFastPairDeviceMetadata();
}
public static final class FastPairAntispoofKeyDeviceMetadata.Builder {
ctor public FastPairAntispoofKeyDeviceMetadata.Builder();
method @NonNull public android.nearby.FastPairAntispoofKeyDeviceMetadata build();
- method @NonNull public android.nearby.FastPairAntispoofKeyDeviceMetadata.Builder setAntiSpoofPublicKey(@Nullable byte[]);
+ method @NonNull public android.nearby.FastPairAntispoofKeyDeviceMetadata.Builder setAntispoofPublicKey(@Nullable byte[]);
method @NonNull public android.nearby.FastPairAntispoofKeyDeviceMetadata.Builder setFastPairDeviceMetadata(@Nullable android.nearby.FastPairDeviceMetadata);
}
- public abstract class FastPairDataProviderBase {
- ctor public FastPairDataProviderBase(@NonNull String);
- method @Nullable public final android.os.IBinder getBinder();
- method public abstract void onLoadFastPairAccountDevicesMetadata(@NonNull android.nearby.FastPairDataProviderBase.FastPairAccountDevicesMetadataRequest, @NonNull android.nearby.FastPairDataProviderBase.FastPairAccountDevicesMetadataCallback);
- method public abstract void onLoadFastPairAntispoofKeyDeviceMetadata(@NonNull android.nearby.FastPairDataProviderBase.FastPairAntispoofKeyDeviceMetadataRequest, @NonNull android.nearby.FastPairDataProviderBase.FastPairAntispoofKeyDeviceMetadataCallback);
- method public abstract void onLoadFastPairEligibleAccounts(@NonNull android.nearby.FastPairDataProviderBase.FastPairEligibleAccountsRequest, @NonNull android.nearby.FastPairDataProviderBase.FastPairEligibleAccountsCallback);
- method public abstract void onManageFastPairAccount(@NonNull android.nearby.FastPairDataProviderBase.FastPairManageAccountRequest, @NonNull android.nearby.FastPairDataProviderBase.FastPairManageActionCallback);
- method public abstract void onManageFastPairAccountDevice(@NonNull android.nearby.FastPairDataProviderBase.FastPairManageAccountDeviceRequest, @NonNull android.nearby.FastPairDataProviderBase.FastPairManageActionCallback);
+ public abstract class FastPairDataProviderService extends android.app.Service {
+ ctor public FastPairDataProviderService(@NonNull String);
+ method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public abstract void onLoadFastPairAccountDevicesMetadata(@NonNull android.nearby.FastPairDataProviderService.FastPairAccountDevicesMetadataRequest, @NonNull android.nearby.FastPairDataProviderService.FastPairAccountDevicesMetadataCallback);
+ method public abstract void onLoadFastPairAntispoofKeyDeviceMetadata(@NonNull android.nearby.FastPairDataProviderService.FastPairAntispoofKeyDeviceMetadataRequest, @NonNull android.nearby.FastPairDataProviderService.FastPairAntispoofKeyDeviceMetadataCallback);
+ method public abstract void onLoadFastPairEligibleAccounts(@NonNull android.nearby.FastPairDataProviderService.FastPairEligibleAccountsRequest, @NonNull android.nearby.FastPairDataProviderService.FastPairEligibleAccountsCallback);
+ method public abstract void onManageFastPairAccount(@NonNull android.nearby.FastPairDataProviderService.FastPairManageAccountRequest, @NonNull android.nearby.FastPairDataProviderService.FastPairManageActionCallback);
+ method public abstract void onManageFastPairAccountDevice(@NonNull android.nearby.FastPairDataProviderService.FastPairManageAccountDeviceRequest, @NonNull android.nearby.FastPairDataProviderService.FastPairManageActionCallback);
field public static final String ACTION_FAST_PAIR_DATA_PROVIDER = "android.nearby.action.FAST_PAIR_DATA_PROVIDER";
field public static final int ERROR_CODE_BAD_REQUEST = 0; // 0x0
field public static final int ERROR_CODE_INTERNAL_ERROR = 1; // 0x1
@@ -96,46 +93,46 @@
field public static final int MANAGE_REQUEST_REMOVE = 1; // 0x1
}
- public static interface FastPairDataProviderBase.FastPairAccountDevicesMetadataCallback {
+ public static interface FastPairDataProviderService.FastPairAccountDevicesMetadataCallback {
method public void onError(int, @Nullable String);
method public void onFastPairAccountDevicesMetadataReceived(@NonNull java.util.Collection<android.nearby.FastPairAccountKeyDeviceMetadata>);
}
- public static class FastPairDataProviderBase.FastPairAccountDevicesMetadataRequest {
+ public static class FastPairDataProviderService.FastPairAccountDevicesMetadataRequest {
method @NonNull public android.accounts.Account getAccount();
- method @NonNull public java.util.Collection<byte[]> getAccountKeys();
+ method @NonNull public java.util.Collection<byte[]> getDeviceAccountKeys();
}
- public static interface FastPairDataProviderBase.FastPairAntispoofKeyDeviceMetadataCallback {
+ public static interface FastPairDataProviderService.FastPairAntispoofKeyDeviceMetadataCallback {
method public void onError(int, @Nullable String);
method public void onFastPairAntispoofKeyDeviceMetadataReceived(@NonNull android.nearby.FastPairAntispoofKeyDeviceMetadata);
}
- public static class FastPairDataProviderBase.FastPairAntispoofKeyDeviceMetadataRequest {
+ public static class FastPairDataProviderService.FastPairAntispoofKeyDeviceMetadataRequest {
method @NonNull public byte[] getModelId();
}
- public static interface FastPairDataProviderBase.FastPairEligibleAccountsCallback {
+ public static interface FastPairDataProviderService.FastPairEligibleAccountsCallback {
method public void onError(int, @Nullable String);
method public void onFastPairEligibleAccountsReceived(@NonNull java.util.Collection<android.nearby.FastPairEligibleAccount>);
}
- public static class FastPairDataProviderBase.FastPairEligibleAccountsRequest {
+ public static class FastPairDataProviderService.FastPairEligibleAccountsRequest {
}
- public static class FastPairDataProviderBase.FastPairManageAccountDeviceRequest {
+ public static class FastPairDataProviderService.FastPairManageAccountDeviceRequest {
method @NonNull public android.accounts.Account getAccount();
method @NonNull public android.nearby.FastPairAccountKeyDeviceMetadata getAccountKeyDeviceMetadata();
method @Nullable public String getBleAddress();
method public int getRequestType();
}
- public static class FastPairDataProviderBase.FastPairManageAccountRequest {
+ public static class FastPairDataProviderService.FastPairManageAccountRequest {
method @NonNull public android.accounts.Account getAccount();
method public int getRequestType();
}
- public static interface FastPairDataProviderBase.FastPairManageActionCallback {
+ public static interface FastPairDataProviderService.FastPairManageActionCallback {
method public void onError(int, @Nullable String);
method public void onSuccess();
}
@@ -285,6 +282,8 @@
}
public class FastPairEligibleAccount {
+ method @Nullable public android.accounts.Account getAccount();
+ method public boolean isOptIn();
}
public static final class FastPairEligibleAccount.Builder {
@@ -301,43 +300,22 @@
method public static boolean isValidMedium(int);
}
- public final class NearbyDeviceParcelable implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public String getBluetoothAddress();
- method @Nullable public byte[] getData();
- method @Nullable public String getFastPairModelId();
- method public int getMedium();
- method @Nullable public String getName();
- method @IntRange(from=0xffffff81, to=126) public int getRssi();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nearby.NearbyDeviceParcelable> CREATOR;
- }
-
- public static final class NearbyDeviceParcelable.Builder {
- ctor public NearbyDeviceParcelable.Builder();
- method @NonNull public android.nearby.NearbyDeviceParcelable build();
- method @NonNull public android.nearby.NearbyDeviceParcelable.Builder setBluetoothAddress(@Nullable String);
- method @NonNull public android.nearby.NearbyDeviceParcelable.Builder setData(@Nullable byte[]);
- method @NonNull public android.nearby.NearbyDeviceParcelable.Builder setFastPairModelId(@Nullable String);
- method @NonNull public android.nearby.NearbyDeviceParcelable.Builder setMedium(int);
- method @NonNull public android.nearby.NearbyDeviceParcelable.Builder setName(@Nullable String);
- method @NonNull public android.nearby.NearbyDeviceParcelable.Builder setRssi(int);
- }
-
public class NearbyManager {
method public static boolean getFastPairScanEnabled(@NonNull android.content.Context, boolean);
method public static void setFastPairScanEnabled(@NonNull android.content.Context, boolean);
- method public void startBroadcast(@NonNull android.nearby.BroadcastRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.BroadcastCallback);
- method public void startScan(@NonNull android.nearby.ScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.ScanCallback);
- method public void stopBroadcast(@NonNull android.nearby.BroadcastCallback);
- method public void stopScan(@NonNull android.nearby.ScanCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void startBroadcast(@NonNull android.nearby.BroadcastRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.BroadcastCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int startScan(@NonNull android.nearby.ScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.nearby.ScanCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void stopBroadcast(@NonNull android.nearby.BroadcastCallback);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void stopScan(@NonNull android.nearby.ScanCallback);
}
public final class PresenceBroadcastRequest extends android.nearby.BroadcastRequest implements android.os.Parcelable {
+ method public int describeContents();
method @NonNull public java.util.List<java.lang.Integer> getActions();
method @NonNull public android.nearby.PrivateCredential getCredential();
method @NonNull public java.util.List<android.nearby.DataElement> getExtendedProperties();
method @NonNull public byte[] getSalt();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceBroadcastRequest> CREATOR;
}
@@ -350,15 +328,12 @@
method @NonNull public android.nearby.PresenceBroadcastRequest.Builder setVersion(int);
}
- public abstract class PresenceCredential implements android.os.Parcelable {
- method public int describeContents();
+ public abstract class PresenceCredential {
method @NonNull public byte[] getAuthenticityKey();
method @NonNull public java.util.List<android.nearby.CredentialElement> getCredentialElements();
method public int getIdentityType();
method @NonNull public byte[] getSecretId();
method public int getType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceCredential> CREATOR;
field public static final int CREDENTIAL_TYPE_PRIVATE = 0; // 0x0
field public static final int CREDENTIAL_TYPE_PUBLIC = 1; // 0x1
field public static final int IDENTITY_TYPE_PRIVATE = 1; // 0x1
@@ -395,9 +370,11 @@
}
public final class PresenceScanFilter extends android.nearby.ScanFilter implements android.os.Parcelable {
+ method public int describeContents();
method @NonNull public java.util.List<android.nearby.PublicCredential> getCredentials();
method @NonNull public java.util.List<android.nearby.DataElement> getExtendedProperties();
method @NonNull public java.util.List<java.lang.Integer> getPresenceActions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PresenceScanFilter> CREATOR;
}
@@ -411,35 +388,34 @@
}
public final class PrivateCredential extends android.nearby.PresenceCredential implements android.os.Parcelable {
+ method public int describeContents();
method @NonNull public String getDeviceName();
method @NonNull public byte[] getMetadataEncryptionKey();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PrivateCredential> CREATOR;
}
public static final class PrivateCredential.Builder {
- ctor public PrivateCredential.Builder(@NonNull byte[], @NonNull byte[]);
+ ctor public PrivateCredential.Builder(@NonNull byte[], @NonNull byte[], @NonNull byte[], @NonNull String);
method @NonNull public android.nearby.PrivateCredential.Builder addCredentialElement(@NonNull android.nearby.CredentialElement);
method @NonNull public android.nearby.PrivateCredential build();
- method @NonNull public android.nearby.PrivateCredential.Builder setDeviceName(@NonNull String);
method @NonNull public android.nearby.PrivateCredential.Builder setIdentityType(int);
- method @NonNull public android.nearby.PrivateCredential.Builder setMetadataEncryptionKey(@NonNull byte[]);
}
public final class PublicCredential extends android.nearby.PresenceCredential implements android.os.Parcelable {
+ method public int describeContents();
method @NonNull public byte[] getEncryptedMetadata();
method @NonNull public byte[] getEncryptedMetadataKeyTag();
method @NonNull public byte[] getPublicKey();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.nearby.PublicCredential> CREATOR;
}
public static final class PublicCredential.Builder {
- ctor public PublicCredential.Builder(@NonNull byte[], @NonNull byte[]);
+ ctor public PublicCredential.Builder(@NonNull byte[], @NonNull byte[], @NonNull byte[], @NonNull byte[], @NonNull byte[]);
method @NonNull public android.nearby.PublicCredential.Builder addCredentialElement(@NonNull android.nearby.CredentialElement);
method @NonNull public android.nearby.PublicCredential build();
- method @NonNull public android.nearby.PublicCredential.Builder setEncryptedMetadata(@NonNull byte[]);
- method @NonNull public android.nearby.PublicCredential.Builder setEncryptedMetadataKeyTag(@NonNull byte[]);
method @NonNull public android.nearby.PublicCredential.Builder setIdentityType(int);
- method @NonNull public android.nearby.PublicCredential.Builder setPublicKey(@NonNull byte[]);
}
public interface ScanCallback {
@@ -448,12 +424,9 @@
method public void onUpdated(@NonNull android.nearby.NearbyDevice);
}
- public abstract class ScanFilter implements android.os.Parcelable {
- method public int describeContents();
+ public abstract class ScanFilter {
method @IntRange(from=0, to=127) public int getMaxPathLoss();
method public int getType();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.nearby.ScanFilter> CREATOR;
}
public final class ScanRequest implements android.os.Parcelable {
@@ -493,10 +466,10 @@
package android.net {
public class EthernetManager {
- method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
- method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disableInterface(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable android.os.OutcomeReceiver<java.lang.String,android.net.EthernetNetworkManagementException>);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void enableInterface(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable android.os.OutcomeReceiver<java.lang.String,android.net.EthernetNetworkManagementException>);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
- method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.os.OutcomeReceiver<java.lang.String,android.net.EthernetNetworkManagementException>);
}
public static interface EthernetManager.TetheredInterfaceCallback {
@@ -517,7 +490,7 @@
public final class EthernetNetworkUpdateRequest implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public android.net.IpConfiguration getIpConfiguration();
+ method @Nullable public android.net.IpConfiguration getIpConfiguration();
method @Nullable public android.net.NetworkCapabilities getNetworkCapabilities();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR;
@@ -527,7 +500,7 @@
ctor public EthernetNetworkUpdateRequest.Builder();
ctor public EthernetNetworkUpdateRequest.Builder(@NonNull android.net.EthernetNetworkUpdateRequest);
method @NonNull public android.net.EthernetNetworkUpdateRequest build();
- method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setIpConfiguration(@NonNull android.net.IpConfiguration);
+ method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setIpConfiguration(@Nullable android.net.IpConfiguration);
method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
}
@@ -553,7 +526,6 @@
method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
method public int describeContents();
- method @NonNull public java.util.Iterator<android.net.NetworkStats.Entry> iterator();
method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStats> CREATOR;
@@ -577,23 +549,11 @@
public static class NetworkStats.Entry {
ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
- method public int getDefaultNetwork();
- method public int getMetered();
- method public long getOperations();
- method public int getRoaming();
- method public long getRxBytes();
- method public long getRxPackets();
- method public int getSet();
- method public int getTag();
- method public long getTxBytes();
- method public long getTxPackets();
- method public int getUid();
}
public class TrafficStats {
method public static void setThreadStatsTagApp();
method public static void setThreadStatsTagBackup();
- method public static void setThreadStatsTagDownload();
method public static void setThreadStatsTagRestore();
field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = -113; // 0xffffff8f
field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = -128; // 0xffffff80
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 1530eff..e4e2151 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -172,8 +172,8 @@
public final class ProfileNetworkPreference implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public java.util.List<java.lang.Integer> getExcludedUids();
- method @NonNull public java.util.List<java.lang.Integer> getIncludedUids();
+ method @NonNull public int[] getExcludedUids();
+ method @NonNull public int[] getIncludedUids();
method public int getPreference();
method public int getPreferenceEnterpriseId();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -183,8 +183,8 @@
public static final class ProfileNetworkPreference.Builder {
ctor public ProfileNetworkPreference.Builder();
method @NonNull public android.net.ProfileNetworkPreference build();
- method @NonNull public android.net.ProfileNetworkPreference.Builder setExcludedUids(@Nullable java.util.List<java.lang.Integer>);
- method @NonNull public android.net.ProfileNetworkPreference.Builder setIncludedUids(@Nullable java.util.List<java.lang.Integer>);
+ method @NonNull public android.net.ProfileNetworkPreference.Builder setExcludedUids(@NonNull int[]);
+ method @NonNull public android.net.ProfileNetworkPreference.Builder setIncludedUids(@NonNull int[]);
method @NonNull public android.net.ProfileNetworkPreference.Builder setPreference(int);
method @NonNull public android.net.ProfileNetworkPreference.Builder setPreferenceEnterpriseId(int);
}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index bdefed1..53d485d 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -361,6 +361,7 @@
}
public class NetworkReleasedException extends java.lang.Exception {
+ ctor public NetworkReleasedException();
}
public class NetworkRequest implements android.os.Parcelable {
@@ -425,6 +426,8 @@
}
public final class QosCallbackException extends java.lang.Exception {
+ ctor public QosCallbackException(@NonNull String);
+ ctor public QosCallbackException(@NonNull Throwable);
}
public abstract class QosFilter {
@@ -470,9 +473,11 @@
}
public class SocketLocalAddressChangedException extends java.lang.Exception {
+ ctor public SocketLocalAddressChangedException();
}
public class SocketNotBoundException extends java.lang.Exception {
+ ctor public SocketNotBoundException();
}
public final class StaticIpConfiguration implements android.os.Parcelable {
diff --git a/framework/src/android/net/ITestNetworkManager.aidl b/framework/src/android/net/ITestNetworkManager.aidl
index 2a863ad..847f14e 100644
--- a/framework/src/android/net/ITestNetworkManager.aidl
+++ b/framework/src/android/net/ITestNetworkManager.aidl
@@ -29,8 +29,7 @@
*/
interface ITestNetworkManager
{
- TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs);
- TestNetworkInterface createTapInterface();
+ TestNetworkInterface createInterface(boolean isTun, boolean bringUp, in LinkAddress[] addrs);
void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered,
in int[] administratorUids, in IBinder binder);
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index a284670..f7f2f57 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -147,27 +147,32 @@
private String mRequestorPackageName;
/**
- * Enterprise capability identifier 1.
+ * Enterprise capability identifier 1. It will be used to uniquely identify specific
+ * enterprise network.
*/
public static final int NET_ENTERPRISE_ID_1 = 1;
/**
- * Enterprise capability identifier 2.
+ * Enterprise capability identifier 2. It will be used to uniquely identify specific
+ * enterprise network.
*/
public static final int NET_ENTERPRISE_ID_2 = 2;
/**
- * Enterprise capability identifier 3.
+ * Enterprise capability identifier 3. It will be used to uniquely identify specific
+ * enterprise network.
*/
public static final int NET_ENTERPRISE_ID_3 = 3;
/**
- * Enterprise capability identifier 4.
+ * Enterprise capability identifier 4. It will be used to uniquely identify specific
+ * enterprise network.
*/
public static final int NET_ENTERPRISE_ID_4 = 4;
/**
- * Enterprise capability identifier 5.
+ * Enterprise capability identifier 5. It will be used to uniquely identify specific
+ * enterprise network.
*/
public static final int NET_ENTERPRISE_ID_5 = 5;
diff --git a/framework/src/android/net/NetworkReleasedException.java b/framework/src/android/net/NetworkReleasedException.java
index 0629b75..cdfb6a1 100644
--- a/framework/src/android/net/NetworkReleasedException.java
+++ b/framework/src/android/net/NetworkReleasedException.java
@@ -18,6 +18,8 @@
import android.annotation.SystemApi;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Indicates that the {@link Network} was released and is no longer available.
*
@@ -25,7 +27,7 @@
*/
@SystemApi
public class NetworkReleasedException extends Exception {
- /** @hide */
+ @VisibleForTesting
public NetworkReleasedException() {
super("The network was released and is no longer available");
}
diff --git a/framework/src/android/net/ProfileNetworkPreference.java b/framework/src/android/net/ProfileNetworkPreference.java
index f43acce..fb271e3 100644
--- a/framework/src/android/net/ProfileNetworkPreference.java
+++ b/framework/src/android/net/ProfileNetworkPreference.java
@@ -22,14 +22,12 @@
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_5;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.ConnectivityManager.ProfileNetworkPreferencePolicy;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
import java.util.Objects;
/**
@@ -41,31 +39,31 @@
public final class ProfileNetworkPreference implements Parcelable {
private final @ProfileNetworkPreferencePolicy int mPreference;
private final @NetworkCapabilities.EnterpriseId int mPreferenceEnterpriseId;
- private final List<Integer> mIncludedUids;
- private final List<Integer> mExcludedUids;
+ private int[] mIncludedUids = new int[0];
+ private int[] mExcludedUids = new int[0];
- private ProfileNetworkPreference(int preference, List<Integer> includedUids,
- List<Integer> excludedUids,
+ private ProfileNetworkPreference(int preference, int[] includedUids,
+ int[] excludedUids,
@NetworkCapabilities.EnterpriseId int preferenceEnterpriseId) {
mPreference = preference;
mPreferenceEnterpriseId = preferenceEnterpriseId;
if (includedUids != null) {
- mIncludedUids = new ArrayList<>(includedUids);
+ mIncludedUids = includedUids.clone();
} else {
- mIncludedUids = new ArrayList<>();
+ mIncludedUids = new int[0];
}
if (excludedUids != null) {
- mExcludedUids = new ArrayList<>(excludedUids);
+ mExcludedUids = excludedUids.clone();
} else {
- mExcludedUids = new ArrayList<>();
+ mExcludedUids = new int[0];
}
}
private ProfileNetworkPreference(Parcel in) {
mPreference = in.readInt();
- mIncludedUids = in.readArrayList(Integer.class.getClassLoader());
- mExcludedUids = in.readArrayList(Integer.class.getClassLoader());
+ in.readIntArray(mIncludedUids);
+ in.readIntArray(mExcludedUids);
mPreferenceEnterpriseId = in.readInt();
}
@@ -74,31 +72,31 @@
}
/**
- * Get the list of UIDs subject to this preference.
+ * Get the array of UIDs subject to this preference.
*
* Included UIDs and Excluded UIDs can't both be non-empty.
* if both are empty, it means this request applies to all uids in the user profile.
* if included is not empty, then only included UIDs are applied.
* if excluded is not empty, then it is all uids in the user profile except these UIDs.
- * @return List of uids included for the profile preference.
+ * @return Array of uids included for the profile preference.
* {@see #getExcludedUids()}
*/
- public @NonNull List<Integer> getIncludedUids() {
- return new ArrayList<>(mIncludedUids);
+ public @NonNull int[] getIncludedUids() {
+ return mIncludedUids.clone();
}
/**
- * Get the list of UIDS excluded from this preference.
+ * Get the array of UIDS excluded from this preference.
*
* <ul>Included UIDs and Excluded UIDs can't both be non-empty.</ul>
* <ul>If both are empty, it means this request applies to all uids in the user profile.</ul>
* <ul>If included is not empty, then only included UIDs are applied.</ul>
* <ul>If excluded is not empty, then it is all uids in the user profile except these UIDs.</ul>
- * @return List of uids not included for the profile preference.
+ * @return Array of uids not included for the profile preference.
* {@see #getIncludedUids()}
*/
- public @NonNull List<Integer> getExcludedUids() {
- return new ArrayList<>(mExcludedUids);
+ public @NonNull int[] getExcludedUids() {
+ return mExcludedUids.clone();
}
/**
@@ -134,8 +132,8 @@
if (o == null || getClass() != o.getClass()) return false;
final ProfileNetworkPreference that = (ProfileNetworkPreference) o;
return mPreference == that.mPreference
- && (Objects.equals(mIncludedUids, that.mIncludedUids))
- && (Objects.equals(mExcludedUids, that.mExcludedUids))
+ && (Arrays.equals(mIncludedUids, that.mIncludedUids))
+ && (Arrays.equals(mExcludedUids, that.mExcludedUids))
&& mPreferenceEnterpriseId == that.mPreferenceEnterpriseId;
}
@@ -143,8 +141,8 @@
public int hashCode() {
return mPreference
+ mPreferenceEnterpriseId * 2
- + (Objects.hashCode(mIncludedUids) * 11)
- + (Objects.hashCode(mExcludedUids) * 13);
+ + (Arrays.hashCode(mIncludedUids) * 11)
+ + (Arrays.hashCode(mExcludedUids) * 13);
}
/**
@@ -154,8 +152,8 @@
public static final class Builder {
private @ProfileNetworkPreferencePolicy int mPreference =
PROFILE_NETWORK_PREFERENCE_DEFAULT;
- private @NonNull List<Integer> mIncludedUids = new ArrayList<>();
- private @NonNull List<Integer> mExcludedUids = new ArrayList<>();
+ private int[] mIncludedUids = new int[0];
+ private int[] mExcludedUids = new int[0];
private int mPreferenceEnterpriseId;
/**
@@ -177,44 +175,38 @@
}
/**
- * This is a list of uids for which profile perefence is set.
- * Null would mean that this preference applies to all uids in the profile.
- * {@see #setExcludedUids(List<Integer>)}
+ * This is a array of uids for which profile perefence is set.
+ * Empty would mean that this preference applies to all uids in the profile.
+ * {@see #setExcludedUids(int[])}
* Included UIDs and Excluded UIDs can't both be non-empty.
* if both are empty, it means this request applies to all uids in the user profile.
* if included is not empty, then only included UIDs are applied.
* if excluded is not empty, then it is all uids in the user profile except these UIDs.
- * @param uids list of uids that are included
+ * @param uids Array of uids that are included
* @return The builder to facilitate chaining.
*/
@NonNull
- public Builder setIncludedUids(@Nullable List<Integer> uids) {
- if (uids != null) {
- mIncludedUids = new ArrayList<Integer>(uids);
- } else {
- mIncludedUids = new ArrayList<Integer>();
- }
+ public Builder setIncludedUids(@NonNull int[] uids) {
+ Objects.requireNonNull(uids);
+ mIncludedUids = uids.clone();
return this;
}
/**
- * This is a list of uids that are excluded for the profile perefence.
- * {@see #setIncludedUids(List<Integer>)}
+ * This is a array of uids that are excluded for the profile perefence.
+ * {@see #setIncludedUids(int[])}
* Included UIDs and Excluded UIDs can't both be non-empty.
* if both are empty, it means this request applies to all uids in the user profile.
* if included is not empty, then only included UIDs are applied.
* if excluded is not empty, then it is all uids in the user profile except these UIDs.
- * @param uids list of uids that are not included
+ * @param uids Array of uids that are not included
* @return The builder to facilitate chaining.
*/
@NonNull
- public Builder setExcludedUids(@Nullable List<Integer> uids) {
- if (uids != null) {
- mExcludedUids = new ArrayList<Integer>(uids);
- } else {
- mExcludedUids = new ArrayList<Integer>();
- }
+ public Builder setExcludedUids(@NonNull int[] uids) {
+ Objects.requireNonNull(uids);
+ mExcludedUids = uids.clone();
return this;
}
@@ -241,7 +233,7 @@
*/
@NonNull
public ProfileNetworkPreference build() {
- if (mIncludedUids.size() > 0 && mExcludedUids.size() > 0) {
+ if (mIncludedUids.length > 0 && mExcludedUids.length > 0) {
throw new IllegalArgumentException("Both includedUids and excludedUids "
+ "cannot be nonempty");
}
@@ -280,8 +272,8 @@
@Override
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
dest.writeInt(mPreference);
- dest.writeList(mIncludedUids);
- dest.writeList(mExcludedUids);
+ dest.writeIntArray(mIncludedUids);
+ dest.writeIntArray(mExcludedUids);
dest.writeInt(mPreferenceEnterpriseId);
}
diff --git a/framework/src/android/net/QosCallbackException.java b/framework/src/android/net/QosCallbackException.java
index 7fd9a52..ed6eb15 100644
--- a/framework/src/android/net/QosCallbackException.java
+++ b/framework/src/android/net/QosCallbackException.java
@@ -21,6 +21,8 @@
import android.annotation.SystemApi;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -94,16 +96,12 @@
}
}
- /**
- * @hide
- */
+ @VisibleForTesting
public QosCallbackException(@NonNull final String message) {
super(message);
}
- /**
- * @hide
- */
+ @VisibleForTesting
public QosCallbackException(@NonNull final Throwable cause) {
super(cause);
}
diff --git a/framework/src/android/net/SocketLocalAddressChangedException.java b/framework/src/android/net/SocketLocalAddressChangedException.java
index 9daad83..7be3793 100644
--- a/framework/src/android/net/SocketLocalAddressChangedException.java
+++ b/framework/src/android/net/SocketLocalAddressChangedException.java
@@ -18,6 +18,8 @@
import android.annotation.SystemApi;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Thrown when the local address of the socket has changed.
*
@@ -25,7 +27,7 @@
*/
@SystemApi
public class SocketLocalAddressChangedException extends Exception {
- /** @hide */
+ @VisibleForTesting
public SocketLocalAddressChangedException() {
super("The local address of the socket changed");
}
diff --git a/framework/src/android/net/SocketNotBoundException.java b/framework/src/android/net/SocketNotBoundException.java
index b1d7026..59f34a3 100644
--- a/framework/src/android/net/SocketNotBoundException.java
+++ b/framework/src/android/net/SocketNotBoundException.java
@@ -18,6 +18,8 @@
import android.annotation.SystemApi;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Thrown when a previously bound socket becomes unbound.
*
@@ -25,7 +27,7 @@
*/
@SystemApi
public class SocketNotBoundException extends Exception {
- /** @hide */
+ @VisibleForTesting
public SocketNotBoundException() {
super("The socket is unbound");
}
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index 9ddd2f5..280e497 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -49,6 +49,11 @@
@NonNull private final ITestNetworkManager mService;
+ private static final boolean TAP = false;
+ private static final boolean TUN = true;
+ private static final boolean BRING_UP = true;
+ private static final LinkAddress[] NO_ADDRS = new LinkAddress[0];
+
/** @hide */
public TestNetworkManager(@NonNull ITestNetworkManager service) {
mService = Objects.requireNonNull(service, "missing ITestNetworkManager");
@@ -155,7 +160,7 @@
public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) {
try {
final LinkAddress[] arr = new LinkAddress[linkAddrs.size()];
- return mService.createTunInterface(linkAddrs.toArray(arr));
+ return mService.createInterface(TUN, BRING_UP, linkAddrs.toArray(arr));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -173,10 +178,28 @@
@NonNull
public TestNetworkInterface createTapInterface() {
try {
- return mService.createTapInterface();
+ return mService.createInterface(TAP, BRING_UP, NO_ADDRS);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+ /**
+ * Create a tap interface for testing purposes
+ *
+ * @param bringUp whether to bring up the interface before returning it.
+ *
+ * @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the
+ * TAP interface.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
+ @NonNull
+ public TestNetworkInterface createTapInterface(boolean bringUp) {
+ try {
+ return mService.createInterface(TAP, bringUp, NO_ADDRS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index faa9998..1af00c7 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -168,4 +168,15 @@
<!-- Regex of wired ethernet ifaces -->
<string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
+
+ <!-- Ignores Wi-Fi validation failures after roam.
+ If validation fails on a Wi-Fi network after a roam to a new BSSID,
+ assume that the roam temporarily disrupted network connectivity, and
+ ignore all failures until this time has passed.
+ NetworkMonitor will continue to attempt validation, and if it fails after this time has passed,
+ the network will be marked unvalidated.
+
+ Only supported up to S. On T+, the Wi-Fi code should use destroyAndAwaitReplacement in order
+ to ensure that apps see the network disconnect and reconnect. -->
+ <integer translatable="false" name="config_validationFailureAfterRoamIgnoreTimeMillis">-1</integer>
</resources>
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index 9fa6a30..b92dd08 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -40,6 +40,7 @@
<item type="string" name="config_ethernet_tcp_buffers"/>
<item type="array" name="config_ethernet_interfaces"/>
<item type="string" name="config_ethernet_iface_regex"/>
+ <item type="integer" name="config_validationFailureAfterRoamIgnoreTimeMillis" />
</policy>
</overlayable>
</resources>
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 62c5249..e58160a 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -199,6 +199,7 @@
import android.net.resolv.aidl.PrivateDnsValidationEventParcel;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
+import android.net.wifi.WifiInfo;
import android.os.BatteryStatsManager;
import android.os.Binder;
import android.os.Build;
@@ -348,6 +349,9 @@
private static final int DEFAULT_LINGER_DELAY_MS = 30_000;
private static final int DEFAULT_NASCENT_DELAY_MS = 5_000;
+ // The maximum value for the blocking validation result, in milliseconds.
+ public static final int MAX_VALIDATION_FAILURE_BLOCKING_TIME_MS = 10000;
+
// The maximum number of network request allowed per uid before an exception is thrown.
@VisibleForTesting
static final int MAX_NETWORK_REQUESTS_PER_UID = 100;
@@ -2249,7 +2253,10 @@
if (newNc.getNetworkSpecifier() != null) {
newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
}
- newNc.setAdministratorUids(new int[0]);
+ if (!checkAnyPermissionOf(callerPid, callerUid, android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)) {
+ newNc.setAdministratorUids(new int[0]);
+ }
if (!checkAnyPermissionOf(
callerPid, callerUid, android.Manifest.permission.NETWORK_FACTORY)) {
newNc.setAllowedUids(new ArraySet<>());
@@ -3543,6 +3550,7 @@
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
final NetworkCapabilities networkCapabilities = new NetworkCapabilities(
(NetworkCapabilities) arg.second);
+ maybeUpdateWifiRoamTimestamp(nai, networkCapabilities);
processCapabilitiesFromAgent(nai, networkCapabilities);
updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
break;
@@ -3790,15 +3798,22 @@
private void handleNetworkTested(
@NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) {
+ final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0);
+ if (!valid && shouldIgnoreValidationFailureAfterRoam(nai)) {
+ // Assume the validation failure is due to a temporary failure after roaming
+ // and ignore it. NetworkMonitor will continue to retry validation. If it
+ // continues to fail after the block timeout expires, the network will be
+ // marked unvalidated. If it succeeds, then validation state will not change.
+ return;
+ }
+
+ final boolean wasValidated = nai.lastValidated;
+ final boolean wasDefault = isDefaultNetwork(nai);
final boolean wasPartial = nai.partialConnectivity;
nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0);
final boolean partialConnectivityChanged =
(wasPartial != nai.partialConnectivity);
- final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0);
- final boolean wasValidated = nai.lastValidated;
- final boolean wasDefault = isDefaultNetwork(nai);
-
if (DBG) {
final String logMsg = !TextUtils.isEmpty(redirectUrl)
? " with redirect to " + redirectUrl
@@ -4197,6 +4212,23 @@
return nai.created && !nai.destroyed;
}
+ private boolean shouldIgnoreValidationFailureAfterRoam(NetworkAgentInfo nai) {
+ // T+ devices should use destroyAndAwaitReplacement.
+ if (SdkLevel.isAtLeastT()) return false;
+ final long blockTimeOut = Long.valueOf(mResources.get().getInteger(
+ R.integer.config_validationFailureAfterRoamIgnoreTimeMillis));
+ if (blockTimeOut <= MAX_VALIDATION_FAILURE_BLOCKING_TIME_MS
+ && blockTimeOut >= 0) {
+ final long currentTimeMs = SystemClock.elapsedRealtime();
+ long timeSinceLastRoam = currentTimeMs - nai.lastRoamTimestamp;
+ if (timeSinceLastRoam <= blockTimeOut) {
+ log ("blocked because only " + timeSinceLastRoam + "ms after roam");
+ return true;
+ }
+ }
+ return false;
+ }
+
private void handleNetworkAgentDisconnected(Message msg) {
NetworkAgentInfo nai = (NetworkAgentInfo) msg.obj;
disconnectAndDestroyNetwork(nai);
@@ -9613,6 +9645,18 @@
return ((VpnTransportInfo) ti).getType();
}
+ private void maybeUpdateWifiRoamTimestamp(NetworkAgentInfo nai, NetworkCapabilities nc) {
+ if (nai == null) return;
+ final TransportInfo prevInfo = nai.networkCapabilities.getTransportInfo();
+ final TransportInfo newInfo = nc.getTransportInfo();
+ if (!(prevInfo instanceof WifiInfo) || !(newInfo instanceof WifiInfo)) {
+ return;
+ }
+ if (!TextUtils.equals(((WifiInfo)prevInfo).getBSSID(), ((WifiInfo)newInfo).getBSSID())) {
+ nai.lastRoamTimestamp = SystemClock.elapsedRealtime();
+ }
+ }
+
/**
* @param connectionInfo the connection to resolve.
* @return {@code uid} if the connection is found and the app has permission to observe it
@@ -10625,15 +10669,16 @@
@NonNull final UserHandle profile,
@NonNull final ProfileNetworkPreference profileNetworkPreference) {
final UidRange profileUids = UidRange.createForUser(profile);
- Set<UidRange> uidRangeSet = UidRangeUtils.convertListToUidRange(
- profileNetworkPreference.getIncludedUids());
+ Set<UidRange> uidRangeSet = UidRangeUtils.convertArrayToUidRange(
+ profileNetworkPreference.getIncludedUids());
+
if (uidRangeSet.size() > 0) {
if (!UidRangeUtils.isRangeSetInUidRange(profileUids, uidRangeSet)) {
throw new IllegalArgumentException(
"Allow uid range is outside the uid range of profile.");
}
} else {
- ArraySet<UidRange> disallowUidRangeSet = UidRangeUtils.convertListToUidRange(
+ ArraySet<UidRange> disallowUidRangeSet = UidRangeUtils.convertArrayToUidRange(
profileNetworkPreference.getExcludedUids());
if (disallowUidRangeSet.size() > 0) {
if (!UidRangeUtils.isRangeSetInUidRange(profileUids, disallowUidRangeSet)) {
diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java
index fffd2be..a0bfb4a 100644
--- a/service/src/com/android/server/TestNetworkService.java
+++ b/service/src/com/android/server/TestNetworkService.java
@@ -99,12 +99,14 @@
}
/**
- * Create a TUN or TAP interface with the given interface name and link addresses
+ * Create a TUN or TAP interface with the specified parameters.
*
* <p>This method will return the FileDescriptor to the interface. Close it to tear down the
* interface.
*/
- private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) {
+ @Override
+ public TestNetworkInterface createInterface(boolean isTun, boolean bringUp,
+ LinkAddress[] linkAddrs) {
enforceTestNetworkPermissions(mContext);
Objects.requireNonNull(linkAddrs, "missing linkAddrs");
@@ -122,7 +124,9 @@
addr.getPrefixLength());
}
- NetdUtils.setInterfaceUp(mNetd, iface);
+ if (bringUp) {
+ NetdUtils.setInterfaceUp(mNetd, iface);
+ }
return new TestNetworkInterface(tunIntf, iface);
} catch (RemoteException e) {
@@ -132,28 +136,6 @@
}
}
- /**
- * Create a TUN interface with the given interface name and link addresses
- *
- * <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
- * TUN interface.
- */
- @Override
- public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
- return createInterface(true, linkAddrs);
- }
-
- /**
- * Create a TAP interface with the given interface name
- *
- * <p>This method will return the FileDescriptor to the TAP interface. Close it to tear down the
- * TAP interface.
- */
- @Override
- public TestNetworkInterface createTapInterface() {
- return createInterface(false, new LinkAddress[0]);
- }
-
// Tracker for TestNetworkAgents
@GuardedBy("mTestNetworkTracker")
@NonNull
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index cbfc4f7..b73e2cc 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -192,6 +192,8 @@
public boolean everConnected;
// Whether this network has been destroyed and is being kept temporarily until it is replaced.
public boolean destroyed;
+ // To check how long it has been since last roam.
+ public long lastRoamTimestamp;
// Set to true if this Network successfully passed validation or if it did not satisfy the
// default NetworkRequest in which case validation will not be attempted.
diff --git a/service/src/com/android/server/connectivity/NetworkDiagnostics.java b/service/src/com/android/server/connectivity/NetworkDiagnostics.java
index 2e51be3..509110d 100644
--- a/service/src/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/service/src/com/android/server/connectivity/NetworkDiagnostics.java
@@ -206,7 +206,7 @@
}
for (RouteInfo route : mLinkProperties.getRoutes()) {
- if (route.hasGateway()) {
+ if (route.getType() == RouteInfo.RTN_UNICAST && route.hasGateway()) {
InetAddress gateway = route.getGateway();
prepareIcmpMeasurement(gateway);
if (route.isIPv6Default()) {
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index ac46054..2885ba7 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -52,6 +52,7 @@
import android.net.Uri;
import android.net.util.SharedLog;
import android.os.Build;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.SystemConfigManager;
@@ -66,7 +67,10 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
+import com.android.networkstack.apishim.ProcessShimImpl;
+import com.android.networkstack.apishim.common.ProcessShim;
import com.android.server.BpfNetMaps;
import java.util.ArrayList;
@@ -95,6 +99,8 @@
private final Context mContext;
private final BpfNetMaps mBpfNetMaps;
+ private static final ProcessShim sProcessShim = ProcessShimImpl.newInstance();
+
@GuardedBy("this")
private final Set<UserHandle> mUsers = new HashSet<>();
@@ -235,6 +241,10 @@
}
}
+ private static boolean hasSdkSandbox(final int uid) {
+ return SdkLevel.isAtLeastT() && Process.isApplicationUid(uid);
+ }
+
// Return the network permission for the passed list of apps. Note that this depends on the
// current settings of the device (See isUidAllowedOnRestrictedNetworks).
private SparseIntArray makeUidsNetworkPerm(final List<PackageInfo> apps) {
@@ -247,6 +257,10 @@
final int permission = getPackageNetdNetworkPermission(app);
if (isHigherNetworkPermission(permission, uidsPerm.get(uid, PERMISSION_NONE))) {
uidsPerm.put(uid, permission);
+ if (hasSdkSandbox(uid)) {
+ int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
+ uidsPerm.put(sdkSandboxUid, permission);
+ }
}
}
return uidsPerm;
@@ -262,7 +276,11 @@
}
final int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions,
app.requestedPermissionsFlags);
- appIdsPerm.put(appId, appIdsPerm.get(appId) | otherNetdPerms);
+ final int permission = appIdsPerm.get(appId) | otherNetdPerms;
+ appIdsPerm.put(appId, permission);
+ if (hasSdkSandbox(appId)) {
+ appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
+ }
}
return appIdsPerm;
}
@@ -288,11 +306,19 @@
final SparseIntArray appIdsPerm = new SparseIntArray();
for (final int uid : mSystemConfigManager.getSystemPermissionUids(INTERNET)) {
final int appId = UserHandle.getAppId(uid);
- appIdsPerm.put(appId, appIdsPerm.get(appId) | PERMISSION_INTERNET);
+ final int permission = appIdsPerm.get(appId) | PERMISSION_INTERNET;
+ appIdsPerm.put(appId, permission);
+ if (hasSdkSandbox(appId)) {
+ appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
+ }
}
for (final int uid : mSystemConfigManager.getSystemPermissionUids(UPDATE_DEVICE_STATS)) {
final int appId = UserHandle.getAppId(uid);
- appIdsPerm.put(appId, appIdsPerm.get(appId) | PERMISSION_UPDATE_DEVICE_STATS);
+ final int permission = appIdsPerm.get(appId) | PERMISSION_UPDATE_DEVICE_STATS;
+ appIdsPerm.put(appId, permission);
+ if (hasSdkSandbox(appId)) {
+ appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
+ }
}
return appIdsPerm;
}
@@ -592,6 +618,12 @@
SparseIntArray apps = new SparseIntArray();
apps.put(uid, permission);
+
+ if (hasSdkSandbox(uid)) {
+ int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
+ mUidToNetworkPerm.put(sdkSandboxUid, permission);
+ apps.put(sdkSandboxUid, permission);
+ }
sendUidsNetworkPermission(apps, true /* add */);
}
@@ -654,13 +686,25 @@
+ ", tPerm=" + permissionToString(trafficPerm));
if (permission != currentPermission) {
final SparseIntArray apps = new SparseIntArray();
+ int sdkSandboxUid = -1;
+ if (hasSdkSandbox(uid)) {
+ sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
+ }
if (permission == PERMISSION_NONE) {
mUidToNetworkPerm.delete(uid);
apps.put(uid, PERMISSION_NETWORK); // doesn't matter which permission we pick here
+ if (sdkSandboxUid != -1) {
+ mUidToNetworkPerm.delete(sdkSandboxUid);
+ apps.put(sdkSandboxUid, PERMISSION_NETWORK);
+ }
sendUidsNetworkPermission(apps, false);
} else {
mUidToNetworkPerm.put(uid, permission);
apps.put(uid, permission);
+ if (sdkSandboxUid != -1) {
+ mUidToNetworkPerm.put(sdkSandboxUid, permission);
+ apps.put(sdkSandboxUid, permission);
+ }
sendUidsNetworkPermission(apps, true);
}
}
@@ -828,6 +872,10 @@
void sendPackagePermissionsForAppId(int appId, int permissions) {
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
netdPermissionsAppIds.put(appId, permissions);
+ if (hasSdkSandbox(appId)) {
+ int sdkSandboxAppId = sProcessShim.toSdkSandboxUid(appId);
+ netdPermissionsAppIds.put(sdkSandboxAppId, permissions);
+ }
sendAppIdsTrafficPermission(netdPermissionsAppIds);
}
@@ -925,9 +973,19 @@
// Doesn't matter which permission is set here.
removedUids.put(uid, PERMISSION_NETWORK);
mUidToNetworkPerm.delete(uid);
+ if (hasSdkSandbox(uid)) {
+ int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
+ removedUids.put(sdkSandboxUid, PERMISSION_NETWORK);
+ mUidToNetworkPerm.delete(sdkSandboxUid);
+ }
} else {
updatedUids.put(uid, permission);
mUidToNetworkPerm.put(uid, permission);
+ if (hasSdkSandbox(uid)) {
+ int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
+ updatedUids.put(sdkSandboxUid, permission);
+ mUidToNetworkPerm.put(sdkSandboxUid, permission);
+ }
}
}
diff --git a/service/src/com/android/server/connectivity/UidRangeUtils.java b/service/src/com/android/server/connectivity/UidRangeUtils.java
index 7318296..541340b 100644
--- a/service/src/com/android/server/connectivity/UidRangeUtils.java
+++ b/service/src/com/android/server/connectivity/UidRangeUtils.java
@@ -21,6 +21,7 @@
import android.util.ArraySet;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -125,7 +126,7 @@
}
/**
- * Convert a list of uid to set of UidRanges.
+ * Convert a list of uids to set of UidRanges.
* @param uids list of uids
* @return set of UidRanges
* @hide
@@ -153,4 +154,34 @@
uidRangeSet.add(new UidRange(start, stop));
return uidRangeSet;
}
+
+ /**
+ * Convert an array of uids to set of UidRanges.
+ * @param uids array of uids
+ * @return set of UidRanges
+ * @hide
+ */
+ public static ArraySet<UidRange> convertArrayToUidRange(@NonNull int[] uids) {
+ Objects.requireNonNull(uids);
+ final ArraySet<UidRange> uidRangeSet = new ArraySet<UidRange>();
+ if (uids.length == 0) {
+ return uidRangeSet;
+ }
+ int[] uidsNew = uids.clone();
+ Arrays.sort(uidsNew);
+ int start = uidsNew[0];
+ int stop = start;
+
+ for (int i : uidsNew) {
+ if (i <= stop + 1) {
+ stop = i;
+ } else {
+ uidRangeSet.add(new UidRange(start, stop));
+ start = i;
+ stop = i;
+ }
+ }
+ uidRangeSet.add(new UidRange(start, stop));
+ return uidRangeSet;
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
new file mode 100644
index 0000000..2737258
--- /dev/null
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2022 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.cts
+
+import android.Manifest.permission.MANAGE_TEST_NETWORKS
+import android.Manifest.permission.NETWORK_SETTINGS
+import android.net.IpConfiguration
+import android.net.TestNetworkInterface
+import android.net.TestNetworkManager
+import android.platform.test.annotations.AppModeFull
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.android.net.module.util.ArrayTrackRecord
+import com.android.net.module.util.TrackRecord
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.SC_V2
+import com.android.testutils.runAsShell
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertNull
+import kotlin.test.fail
+import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
+import android.os.Handler
+import android.os.HandlerExecutor
+import android.os.Looper
+import com.android.networkstack.apishim.common.EthernetManagerShim.InterfaceStateListener
+import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_ABSENT
+import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_DOWN
+import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_UP
+import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_CLIENT
+import com.android.networkstack.apishim.common.EthernetManagerShim.ROLE_NONE
+import com.android.networkstack.apishim.EthernetManagerShimImpl
+import java.util.concurrent.Executor
+import kotlin.test.assertFalse
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+private const val TIMEOUT_MS = 1000L
+private const val NO_CALLBACK_TIMEOUT_MS = 200L
+private val DEFAULT_IP_CONFIGURATION = IpConfiguration(IpConfiguration.IpAssignment.DHCP,
+ IpConfiguration.ProxySettings.NONE, null, null)
+
+@AppModeFull(reason = "Instant apps can't access EthernetManager")
+@RunWith(AndroidJUnit4::class)
+class EthernetManagerTest {
+ // EthernetManager is not updatable before T, so tests do not need to be backwards compatible
+ @get:Rule
+ val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
+
+ private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
+ private val em by lazy { EthernetManagerShimImpl.newInstance(context) }
+
+ private val createdIfaces = ArrayList<TestNetworkInterface>()
+ private val addedListeners = ArrayList<InterfaceStateListener>()
+
+ private open class EthernetStateListener private constructor(
+ private val history: ArrayTrackRecord<CallbackEntry>
+ ) : InterfaceStateListener,
+ TrackRecord<EthernetStateListener.CallbackEntry> by history {
+ constructor() : this(ArrayTrackRecord())
+
+ val events = history.newReadHead()
+
+ sealed class CallbackEntry {
+ data class InterfaceStateChanged(
+ val iface: String,
+ val state: Int,
+ val role: Int,
+ val configuration: IpConfiguration?
+ ) : CallbackEntry()
+ }
+
+ override fun onInterfaceStateChanged(
+ iface: String,
+ state: Int,
+ role: Int,
+ cfg: IpConfiguration?
+ ) {
+ add(InterfaceStateChanged(iface, state, role, cfg))
+ }
+
+ fun <T : CallbackEntry> expectCallback(expected: T): T {
+ val event = pollForNextCallback()
+ assertEquals(expected, event)
+ return event as T
+ }
+
+ fun expectCallback(iface: TestNetworkInterface, state: Int, role: Int) {
+ expectCallback(InterfaceStateChanged(iface.interfaceName, state, role,
+ if (state != STATE_ABSENT) DEFAULT_IP_CONFIGURATION else null))
+ }
+
+ fun pollForNextCallback(): CallbackEntry {
+ return events.poll(TIMEOUT_MS) ?: fail("Did not receive callback after ${TIMEOUT_MS}ms")
+ }
+
+ fun assertNoCallback() {
+ val cb = events.poll(NO_CALLBACK_TIMEOUT_MS)
+ assertNull(cb, "Expected no callback but got $cb")
+ }
+ }
+
+ @Test
+ public fun testCallbacks() {
+ val executor = HandlerExecutor(Handler(Looper.getMainLooper()))
+
+ // If an interface exists when the callback is registered, it is reported on registration.
+ val iface = runAsShell(MANAGE_TEST_NETWORKS) {
+ createInterface()
+ }
+ val listener = EthernetStateListener()
+ addInterfaceStateListener(executor, listener)
+ listener.expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
+
+ // If an interface appears, existing callbacks see it.
+ // TODO: fix the up/up/down/up callbacks and only send down/up.
+ val iface2 = runAsShell(MANAGE_TEST_NETWORKS) {
+ createInterface()
+ }
+ listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
+ listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
+ listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
+ listener.expectCallback(iface2, STATE_LINK_UP, ROLE_CLIENT)
+
+ // Removing interfaces first sends link down, then STATE_ABSENT/ROLE_NONE.
+ removeInterface(iface)
+ listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT)
+ listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE)
+
+ removeInterface(iface2)
+ listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
+ listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE)
+ listener.assertNoCallback()
+ }
+
+ @Before
+ fun setUp() {
+ runAsShell(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS) {
+ em.setIncludeTestInterfaces(true)
+ }
+ }
+
+ @After
+ fun tearDown() {
+ runAsShell(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS) {
+ em.setIncludeTestInterfaces(false)
+ for (iface in createdIfaces) {
+ if (iface.fileDescriptor.fileDescriptor.valid()) iface.fileDescriptor.close()
+ }
+ for (listener in addedListeners) {
+ em.removeInterfaceStateListener(listener)
+ }
+ }
+ }
+
+ private fun addInterfaceStateListener(executor: Executor, listener: InterfaceStateListener) {
+ em.addInterfaceStateListener(executor, listener)
+ addedListeners.add(listener)
+ }
+
+ private fun createInterface(): TestNetworkInterface {
+ val tnm = context.getSystemService(TestNetworkManager::class.java)
+ return tnm.createTapInterface(false /* bringUp */).also { createdIfaces.add(it) }
+ }
+
+ private fun removeInterface(iface: TestNetworkInterface) {
+ iface.fileDescriptor.close()
+ createdIfaces.remove(iface)
+ }
+
+ private fun doTestGetInterfaceList() {
+ em.setIncludeTestInterfaces(true)
+
+ // Create two test interfaces and check the return list contains the interface names.
+ val iface1 = createInterface()
+ val iface2 = createInterface()
+ var ifaces = em.getInterfaceList()
+ assertTrue(ifaces.size > 0)
+ assertTrue(ifaces.contains(iface1.getInterfaceName()))
+ assertTrue(ifaces.contains(iface2.getInterfaceName()))
+
+ // Remove one existing test interface and check the return list doesn't contain the
+ // removed interface name.
+ removeInterface(iface1)
+ ifaces = em.getInterfaceList()
+ assertFalse(ifaces.contains(iface1.getInterfaceName()))
+ assertTrue(ifaces.contains(iface2.getInterfaceName()))
+
+ removeInterface(iface2)
+ }
+
+ @Test
+ public fun testGetInterfaceList() {
+ runAsShell(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS) {
+ doTestGetInterfaceList()
+ }
+ }
+}
diff --git a/tests/cts/net/src/android/net/cts/QosCallbackExceptionTest.java b/tests/cts/net/src/android/net/cts/QosCallbackExceptionTest.java
new file mode 100644
index 0000000..cd43a34
--- /dev/null
+++ b/tests/cts/net/src/android/net/cts/QosCallbackExceptionTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 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.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.net.NetworkReleasedException;
+import android.net.QosCallbackException;
+import android.net.SocketLocalAddressChangedException;
+import android.net.SocketNotBoundException;
+import android.os.Build;
+
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DevSdkIgnoreRunner.class)
+@IgnoreUpTo(Build.VERSION_CODES.R)
+public class QosCallbackExceptionTest {
+ private static final String ERROR_MESSAGE = "Test Error Message";
+ private static final String ERROR_MSG_SOCK_NOT_BOUND = "The socket is unbound";
+ private static final String ERROR_MSG_NET_RELEASED =
+ "The network was released and is no longer available";
+ private static final String ERROR_MSG_SOCK_ADDR_CHANGED =
+ "The local address of the socket changed";
+
+
+ @Test
+ public void testQosCallbackException() throws Exception {
+ final Throwable testcause = new Throwable(ERROR_MESSAGE);
+ final QosCallbackException exception = new QosCallbackException(testcause);
+ assertEquals(testcause, exception.getCause());
+
+ final QosCallbackException exceptionMsg = new QosCallbackException(ERROR_MESSAGE);
+ assertEquals(ERROR_MESSAGE, exceptionMsg.getMessage());
+ }
+
+ @Test
+ public void testNetworkReleasedExceptions() throws Exception {
+ final Throwable netReleasedException = new NetworkReleasedException();
+ final QosCallbackException exception = new QosCallbackException(netReleasedException);
+
+ assertTrue(exception.getCause() instanceof NetworkReleasedException);
+ assertEquals(netReleasedException, exception.getCause());
+ assertTrue(exception.getMessage().contains(ERROR_MSG_NET_RELEASED));
+ assertThrowableMessageContains(exception, ERROR_MSG_NET_RELEASED);
+ }
+
+ @Test
+ public void testSocketNotBoundExceptions() throws Exception {
+ final Throwable sockNotBoundException = new SocketNotBoundException();
+ final QosCallbackException exception = new QosCallbackException(sockNotBoundException);
+
+ assertTrue(exception.getCause() instanceof SocketNotBoundException);
+ assertEquals(sockNotBoundException, exception.getCause());
+ assertTrue(exception.getMessage().contains(ERROR_MSG_SOCK_NOT_BOUND));
+ assertThrowableMessageContains(exception, ERROR_MSG_SOCK_NOT_BOUND);
+ }
+
+ @Test
+ public void testSocketLocalAddressChangedExceptions() throws Exception {
+ final Throwable localAddrChangedException = new SocketLocalAddressChangedException();
+ final QosCallbackException exception = new QosCallbackException(localAddrChangedException);
+
+ assertTrue(exception.getCause() instanceof SocketLocalAddressChangedException);
+ assertEquals(localAddrChangedException, exception.getCause());
+ assertTrue(exception.getMessage().contains(ERROR_MSG_SOCK_ADDR_CHANGED));
+ assertThrowableMessageContains(exception, ERROR_MSG_SOCK_ADDR_CHANGED);
+ }
+
+ private void assertThrowableMessageContains(QosCallbackException exception, String errorMsg)
+ throws Exception {
+ try {
+ triggerException(exception);
+ fail("Expect exception");
+ } catch (QosCallbackException e) {
+ assertTrue(e.getMessage().contains(errorMsg));
+ }
+ }
+
+ private void triggerException(QosCallbackException exception) throws Exception {
+ throw new QosCallbackException(exception.getCause());
+ }
+}
diff --git a/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java b/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java
index 314fbcf..ca9558b 100644
--- a/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java
+++ b/tests/unit/java/android/net/EthernetNetworkUpdateRequestTest.java
@@ -17,7 +17,9 @@
package android.net;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
-import static com.android.testutils.ParcelUtils.assertParcelSane;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
+
+import static org.junit.Assert.assertThrows;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -47,8 +49,19 @@
EthernetNetworkUpdateRequest reqWithNullCaps =
new EthernetNetworkUpdateRequest.Builder().setIpConfiguration(
buildIpConfiguration()).build();
+ EthernetNetworkUpdateRequest reqWithNullConfig =
+ new EthernetNetworkUpdateRequest.Builder().setNetworkCapabilities(
+ buildNetworkCapabilities()).build();
- assertParcelSane(reqWithNonNull, 2);
- assertParcelSane(reqWithNullCaps, 2);
+ assertParcelingIsLossless(reqWithNonNull);
+ assertParcelingIsLossless(reqWithNullCaps);
+ assertParcelingIsLossless(reqWithNullConfig);
+ }
+
+ @Test
+ public void testEmptyUpdateRequestThrows() {
+ EthernetNetworkUpdateRequest.Builder emptyBuilder =
+ new EthernetNetworkUpdateRequest.Builder();
+ assertThrows(IllegalStateException.class, () -> emptyBuilder.build());
}
}
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index ac369bd..025b28c 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -160,6 +160,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
+import static org.junit.Assume.assumeFalse;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -283,6 +284,7 @@
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
+import android.net.wifi.WifiInfo;
import android.os.BadParcelableException;
import android.os.BatteryStatsManager;
import android.os.Binder;
@@ -7080,6 +7082,36 @@
}
@Test
+ public void testAdminUidsRedacted() throws Exception {
+ final int[] adminUids = new int[] {Process.myUid() + 1};
+ final NetworkCapabilities ncTemplate = new NetworkCapabilities();
+ ncTemplate.setAdministratorUids(adminUids);
+ mCellNetworkAgent =
+ new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), ncTemplate);
+ mCellNetworkAgent.connect(false /* validated */);
+
+ // Verify case where caller has permission
+ mServiceContext.setPermission(
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_GRANTED);
+ TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(callback);
+ callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
+ callback.expectCapabilitiesThat(
+ mCellNetworkAgent, nc -> Arrays.equals(adminUids, nc.getAdministratorUids()));
+ mCm.unregisterNetworkCallback(callback);
+
+ // Verify case where caller does NOT have permission
+ mServiceContext.setPermission(
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, PERMISSION_DENIED);
+ mServiceContext.setPermission(NETWORK_STACK, PERMISSION_DENIED);
+ callback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(callback);
+ callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
+ callback.expectCapabilitiesThat(
+ mCellNetworkAgent, nc -> nc.getAdministratorUids().length == 0);
+ }
+
+ @Test
public void testNonVpnUnderlyingNetworks() throws Exception {
// Ensure wifi and cellular are not torn down.
for (int transport : new int[]{TRANSPORT_CELLULAR, TRANSPORT_WIFI}) {
@@ -13870,12 +13902,13 @@
ProfileNetworkPreference profileNetworkPreference) {
final Set<UidRange> uidRangeSet;
UidRange range = UidRange.createForUser(handle);
- if (profileNetworkPreference.getIncludedUids().size() != 0) {
- uidRangeSet = UidRangeUtils.convertListToUidRange(
+ if (profileNetworkPreference.getIncludedUids().length != 0) {
+ uidRangeSet = UidRangeUtils.convertArrayToUidRange(
profileNetworkPreference.getIncludedUids());
- } else if (profileNetworkPreference.getExcludedUids().size() != 0) {
+
+ } else if (profileNetworkPreference.getExcludedUids().length != 0) {
uidRangeSet = UidRangeUtils.removeRangeSetFromUidRange(
- range, UidRangeUtils.convertListToUidRange(
+ range, UidRangeUtils.convertArrayToUidRange(
profileNetworkPreference.getExcludedUids()));
} else {
uidRangeSet = new ArraySet<>();
@@ -14247,7 +14280,7 @@
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
profileNetworkPreferenceBuilder.setIncludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID)});
registerDefaultNetworkCallbacks();
testPreferenceForUserNetworkUpDownForGivenPreference(
profileNetworkPreferenceBuilder.build(), false, testHandle,
@@ -14266,7 +14299,7 @@
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
profileNetworkPreferenceBuilder.setIncludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
registerDefaultNetworkCallbacks();
testPreferenceForUserNetworkUpDownForGivenPreference(
profileNetworkPreferenceBuilder.build(), false,
@@ -14285,7 +14318,7 @@
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
profileNetworkPreferenceBuilder.setExcludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
registerDefaultNetworkCallbacks();
testPreferenceForUserNetworkUpDownForGivenPreference(
profileNetworkPreferenceBuilder.build(), false,
@@ -14305,7 +14338,7 @@
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
profileNetworkPreferenceBuilder.setExcludedUids(
- List.of(testHandle.getUid(0) - 1));
+ new int[]{testHandle.getUid(0) - 1});
final TestOnCompleteListener listener = new TestOnCompleteListener();
Assert.assertThrows(IllegalArgumentException.class, () -> mCm.setProfileNetworkPreferences(
testHandle, List.of(profileNetworkPreferenceBuilder.build()),
@@ -14313,7 +14346,7 @@
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setIncludedUids(
- List.of(testHandle.getUid(0) - 1));
+ new int[]{testHandle.getUid(0) - 1});
Assert.assertThrows(IllegalArgumentException.class,
() -> mCm.setProfileNetworkPreferences(
testHandle, List.of(profileNetworkPreferenceBuilder.build()),
@@ -14322,9 +14355,9 @@
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setIncludedUids(
- List.of(testHandle.getUid(0) - 1));
+ new int[]{testHandle.getUid(0) - 1});
profileNetworkPreferenceBuilder.setExcludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
Assert.assertThrows(IllegalArgumentException.class,
() -> mCm.setProfileNetworkPreferences(
testHandle, List.of(profileNetworkPreferenceBuilder.build()),
@@ -14335,9 +14368,9 @@
profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder2.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
profileNetworkPreferenceBuilder2.setIncludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
profileNetworkPreferenceBuilder.setIncludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
Assert.assertThrows(IllegalArgumentException.class,
() -> mCm.setProfileNetworkPreferences(
testHandle, List.of(profileNetworkPreferenceBuilder.build(),
@@ -14346,9 +14379,9 @@
profileNetworkPreferenceBuilder2.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder2.setExcludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
profileNetworkPreferenceBuilder.setExcludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
Assert.assertThrows(IllegalArgumentException.class,
() -> mCm.setProfileNetworkPreferences(
testHandle, List.of(profileNetworkPreferenceBuilder.build(),
@@ -14358,9 +14391,9 @@
profileNetworkPreferenceBuilder2.setPreference(
PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
profileNetworkPreferenceBuilder2.setExcludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
profileNetworkPreferenceBuilder.setExcludedUids(
- List.of(testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)));
+ new int[]{testHandle.getUid(TEST_WORK_PROFILE_APP_UID_2)});
Assert.assertThrows(IllegalArgumentException.class,
() -> mCm.setProfileNetworkPreferences(
testHandle, List.of(profileNetworkPreferenceBuilder.build(),
@@ -15571,4 +15604,91 @@
assertNull(readHead.poll(TEST_CALLBACK_TIMEOUT_MS, it -> true));
}
+
+ @Test
+ public void testIgnoreValidationAfterRoamDisabled() throws Exception {
+ assumeFalse(SdkLevel.isAtLeastT());
+ // testIgnoreValidationAfterRoam off
+ doReturn(-1).when(mResources)
+ .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ NetworkCapabilities wifiNc1 = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build());
+ NetworkCapabilities wifiNc2 = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(new WifiInfo.Builder().setBssid("BB:BB:BB:BB:BB:BB").build());
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
+ mWiFiNetworkAgent.connect(true);
+
+ // The default network will be switching to Wi-Fi Network.
+ final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+ wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+ registerDefaultNetworkCallbacks();
+ mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+
+ // Wi-Fi roaming from wifiNc1 to wifiNc2.
+ mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true);
+ mWiFiNetworkAgent.setNetworkInvalid(false);
+ mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
+ mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ }
+
+ @Test
+ public void testIgnoreValidationAfterRoamEnabled() throws Exception {
+ assumeFalse(SdkLevel.isAtLeastT());
+ // testIgnoreValidationAfterRoam on
+ doReturn(5000).when(mResources)
+ .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ NetworkCapabilities wifiNc1 = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(new WifiInfo.Builder().setBssid("AA:AA:AA:AA:AA:AA").build());
+ NetworkCapabilities wifiNc2 = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(new WifiInfo.Builder().setBssid("BB:BB:BB:BB:BB:BB").build());
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp, wifiNc1);
+ mWiFiNetworkAgent.connect(true);
+
+ // The default network will be switching to Wi-Fi Network.
+ final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+ wifiNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+ registerDefaultNetworkCallbacks();
+ mDefaultNetworkCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+
+ // Wi-Fi roaming from wifiNc1 to wifiNc2.
+ mWiFiNetworkAgent.setNetworkCapabilities(wifiNc2, true);
+ mWiFiNetworkAgent.setNetworkInvalid(false);
+ mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
+
+ // Network validation failed, but the result will be ignored.
+ assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
+ NET_CAPABILITY_VALIDATED));
+ mWiFiNetworkAgent.setNetworkValid(false);
+
+ // Behavior of after config_validationFailureAfterRoamIgnoreTimeMillis
+ ConditionVariable waitForValidationBlock = new ConditionVariable();
+ doReturn(50).when(mResources)
+ .getInteger(R.integer.config_validationFailureAfterRoamIgnoreTimeMillis);
+ // Wi-Fi roaming from wifiNc2 to wifiNc1.
+ mWiFiNetworkAgent.setNetworkCapabilities(wifiNc1, true);
+ mWiFiNetworkAgent.setNetworkInvalid(false);
+ waitForValidationBlock.block(150);
+ mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
+ mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ }
}
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 6590543..6b379e8 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -77,6 +77,7 @@
import android.net.UidRange;
import android.net.Uri;
import android.os.Build;
+import android.os.Process;
import android.os.SystemConfigManager;
import android.os.UserHandle;
import android.os.UserManager;
@@ -88,7 +89,10 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.CollectionUtils;
+import com.android.networkstack.apishim.ProcessShimImpl;
+import com.android.networkstack.apishim.common.ProcessShim;
import com.android.server.BpfNetMaps;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -153,6 +157,8 @@
private NetdMonitor mNetdMonitor;
private BpfMapMonitor mBpfMapMonitor;
+ private ProcessShim mProcessShim = ProcessShimImpl.newInstance();
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -197,6 +203,10 @@
return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo);
}
+ private boolean hasSdkSandbox(final int uid) {
+ return SdkLevel.isAtLeastT() && Process.isApplicationUid(uid);
+ }
+
private static PackageInfo systemPackageInfoWithPermissions(String... permissions) {
return packageInfoWithPermissions(
REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM);
@@ -493,6 +503,11 @@
String... permissions) throws Exception {
addPackage(name, uid, permissions);
assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid));
+ if (hasSdkSandbox(uid)) {
+ final int sdkSandboxUid = mProcessShim.toSdkSandboxUid(uid);
+ assertEquals(hasPermission,
+ mPermissionMonitor.hasUseBackgroundNetworksPermission(sdkSandboxUid));
+ }
}
@Test
@@ -531,7 +546,7 @@
}).when(mockBpfmap).setNetPermForUids(anyInt(), any(int[].class));
}
- public void expectTrafficPerm(int permission, int... appIds) {
+ public void expectTrafficPerm(int permission, Integer... appIds) {
for (final int appId : appIds) {
if (mAppIdsTrafficPermission.get(appId, DOES_NOT_EXIST) == DOES_NOT_EXIST) {
fail("appId " + appId + " does not exist.");
@@ -540,6 +555,17 @@
fail("appId " + appId + " has wrong permission: "
+ mAppIdsTrafficPermission.get(appId));
}
+ if (hasSdkSandbox(appId)) {
+ int sdkSandboxAppId = mProcessShim.toSdkSandboxUid(appId);
+ if (mAppIdsTrafficPermission.get(sdkSandboxAppId, DOES_NOT_EXIST)
+ == DOES_NOT_EXIST) {
+ fail("SDK sandbox appId " + sdkSandboxAppId + " does not exist.");
+ }
+ if (mAppIdsTrafficPermission.get(sdkSandboxAppId) != permission) {
+ fail("SDK sandbox appId " + sdkSandboxAppId + " has wrong permission: "
+ + mAppIdsTrafficPermission.get(sdkSandboxAppId));
+ }
+ }
}
}
}
@@ -589,6 +615,17 @@
if (mUidsNetworkPermission.get(uid) != permission) {
fail("uid " + uid + " has wrong permission: " + permission);
}
+ if (hasSdkSandbox(uid)) {
+ int sdkSandboxUid = mProcessShim.toSdkSandboxUid(uid);
+ if (mUidsNetworkPermission.get(sdkSandboxUid, DOES_NOT_EXIST)
+ == DOES_NOT_EXIST) {
+ fail("SDK sandbox uid " + uid + " does not exist.");
+ }
+ if (mUidsNetworkPermission.get(sdkSandboxUid) != permission) {
+ fail("SDK sandbox uid " + uid + " has wrong permission: "
+ + permission);
+ }
+ }
}
}
}
@@ -600,6 +637,14 @@
if (mUidsNetworkPermission.get(uid, DOES_NOT_EXIST) != DOES_NOT_EXIST) {
fail("uid " + uid + " has listed permissions, expected none.");
}
+ if (hasSdkSandbox(uid)) {
+ int sdkSandboxUid = mProcessShim.toSdkSandboxUid(uid);
+ if (mUidsNetworkPermission.get(sdkSandboxUid, DOES_NOT_EXIST)
+ != DOES_NOT_EXIST) {
+ fail("SDK sandbox uid " + sdkSandboxUid
+ + " has listed permissions, expected none.");
+ }
+ }
}
}
}
@@ -785,9 +830,18 @@
// MOCK_APPID2: MOCK_PACKAGE2 does not have any permission.
// SYSTEM_APPID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission
// SYSTEM_APPID2: SYSTEM_PACKAGE2 has only update device stats permission.
+ // The SDK sandbox APPIDs must have permissions mirroring the app
SparseIntArray netdPermissionsAppIds = new SparseIntArray();
netdPermissionsAppIds.put(MOCK_APPID1, PERMISSION_INTERNET);
+ if (hasSdkSandbox(MOCK_APPID1)) {
+ netdPermissionsAppIds.put(mProcessShim.toSdkSandboxUid(MOCK_APPID1),
+ PERMISSION_INTERNET);
+ }
netdPermissionsAppIds.put(MOCK_APPID2, PERMISSION_NONE);
+ if (hasSdkSandbox(MOCK_APPID2)) {
+ netdPermissionsAppIds.put(mProcessShim.toSdkSandboxUid(MOCK_APPID2),
+ PERMISSION_NONE);
+ }
netdPermissionsAppIds.put(SYSTEM_APPID1, PERMISSION_TRAFFIC_ALL);
netdPermissionsAppIds.put(SYSTEM_APPID2, PERMISSION_UPDATE_DEVICE_STATS);
diff --git a/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java b/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java
index b8c2673..b8c552e 100644
--- a/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java
+++ b/tests/unit/java/com/android/server/connectivity/UidRangeUtilsTest.java
@@ -351,4 +351,55 @@
expected.add(uids6);
assertEquals(expected, UidRangeUtils.convertListToUidRange(input));
}
+
+ @Test @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testConvertArrayToUidRange() {
+ final UidRange uids1_1 = new UidRange(1, 1);
+ final UidRange uids1_2 = new UidRange(1, 2);
+ final UidRange uids100_100 = new UidRange(100, 100);
+ final UidRange uids10_10 = new UidRange(10, 10);
+
+ final UidRange uids10_14 = new UidRange(10, 14);
+ final UidRange uids20_24 = new UidRange(20, 24);
+
+ final Set<UidRange> expected = new ArraySet<>();
+ int[] input = new int[0];
+
+ assertThrows(NullPointerException.class, () -> UidRangeUtils.convertArrayToUidRange(null));
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+
+ input = new int[] {1};
+ expected.add(uids1_1);
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+
+ input = new int[]{1, 2};
+ expected.clear();
+ expected.add(uids1_2);
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+
+ input = new int[]{1, 100};
+ expected.clear();
+ expected.add(uids1_1);
+ expected.add(uids100_100);
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+
+ input = new int[]{100, 1};
+ expected.clear();
+ expected.add(uids1_1);
+ expected.add(uids100_100);
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+
+ input = new int[]{100, 1, 2, 1, 10};
+ expected.clear();
+ expected.add(uids1_2);
+ expected.add(uids10_10);
+ expected.add(uids100_100);
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+
+ input = new int[]{10, 11, 12, 13, 14, 20, 21, 22, 23, 24};
+ expected.clear();
+ expected.add(uids10_14);
+ expected.add(uids20_24);
+ assertEquals(expected, UidRangeUtils.convertArrayToUidRange(input));
+ }
}