diff options
52 files changed, 1515 insertions, 405 deletions
diff --git a/Android.bp b/Android.bp index d298af2ce0b9..26971be0d23e 100644 --- a/Android.bp +++ b/Android.bp @@ -515,6 +515,10 @@ java_library { defaults: ["framework-defaults"], srcs: [":framework-all-sources"], installable: false, + static_libs: [ + // Additional dependencies needed to build the ike API classes. + "ike-internals", + ], apex_available: ["//apex_available:platform"], visibility: [ // DO NOT ADD ANY MORE ENTRIES TO THIS LIST @@ -524,39 +528,9 @@ java_library { ], } -java_library { - name: "framework-annotation-proc", - defaults: ["framework-defaults"], - srcs: [":framework-all-sources"], - libs: [ - "app-compat-annotations", - "unsupportedappusage", - ], - installable: false, - plugins: [ - "compat-changeid-annotation-processor", - ], -} - platform_compat_config { - name: "framework-platform-compat-config", - src: ":framework-annotation-proc", -} - -// A library including just UnsupportedAppUsage.java classes. -// -// Provided for target so that libraries can use it without depending on -// the whole of framework or the core platform API. -// -// Built for host so that the annotation processor can also use this annotation. -java_library { - name: "unsupportedappusage-annotation", - host_supported: true, - srcs: [ - "core/java/android/annotation/IntDef.java", - ], - - sdk_version: "core_current", + name: "framework-platform-compat-config", + src: ":framework-minus-apex", } // A temporary build target that is conditionally included on the bootclasspath if diff --git a/ApiDocs.bp b/ApiDocs.bp index b7e364690d03..7fd116886e7a 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -65,8 +65,9 @@ stubs_defaults { "test-base/src/**/*.java", ":opt-telephony-srcs", ":opt-net-voip-srcs", - ":core-current-stubs-source", - ":core_public_api_files", + ":art-module-public-api-stubs-source", + ":conscrypt-module-public-api-stubs-source", + ":android_icu4j_public_api_files", "test-mock/src/**/*.java", "test-runner/src/**/*.java", ], diff --git a/StubLibraries.bp b/StubLibraries.bp index fccb25898fa4..f0810713f39f 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -47,8 +47,9 @@ stubs_defaults { "core/java/**/*.logtags", ":opt-telephony-srcs", ":opt-net-voip-srcs", - ":core-current-stubs-source", - ":core_public_api_files", + ":art-module-public-api-stubs-source", + ":conscrypt-module-public-api-stubs-source", + ":android_icu4j_public_api_files", ], libs: ["framework-internal-utils"], installable: false, diff --git a/api/current.txt b/api/current.txt index 770be339a4e7..a5b88b381e79 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29146,9 +29146,6 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { ctor public NetworkCapabilities(); ctor public NetworkCapabilities(android.net.NetworkCapabilities); - method @NonNull public android.net.NetworkCapabilities addCapability(int); - method @NonNull public android.net.NetworkCapabilities addTransportType(int); - method public void clearAll(); method public int describeContents(); method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); @@ -29158,13 +29155,6 @@ package android.net { method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); method public boolean hasTransport(int); - method @NonNull public android.net.NetworkCapabilities removeCapability(int); - method @NonNull public android.net.NetworkCapabilities setCapability(int, boolean); - method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int); - method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int); - method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier); - method @NonNull public android.net.NetworkCapabilities setOwnerUid(int); - method @NonNull public android.net.NetworkCapabilities setSignalStrength(int); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR; field public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17; // 0x11 diff --git a/api/system-current.txt b/api/system-current.txt index 4e97dc5d8240..6ab5b1ed25e2 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4399,10 +4399,10 @@ package android.net { public class InvalidPacketException extends java.lang.Exception { ctor public InvalidPacketException(int); + method public int getError(); field public static final int ERROR_INVALID_IP_ADDRESS = -21; // 0xffffffeb field public static final int ERROR_INVALID_LENGTH = -23; // 0xffffffe9 field public static final int ERROR_INVALID_PORT = -22; // 0xffffffea - field public final int error; } public final class IpConfiguration implements android.os.Parcelable { @@ -4456,12 +4456,12 @@ package android.net { } public class KeepalivePacketData { - ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException; + ctor protected KeepalivePacketData(@NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull java.net.InetAddress, @IntRange(from=0, to=65535) int, @NonNull byte[]) throws android.net.InvalidPacketException; + method @NonNull public java.net.InetAddress getDstAddress(); + method public int getDstPort(); method @NonNull public byte[] getPacket(); - field @NonNull public final java.net.InetAddress dstAddress; - field public final int dstPort; - field @NonNull public final java.net.InetAddress srcAddress; - field public final int srcPort; + method @NonNull public java.net.InetAddress getSrcAddress(); + method public int getSrcPort(); } public class LinkAddress implements android.os.Parcelable { @@ -4584,18 +4584,33 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { method @NonNull public int[] getAdministratorUids(); - method @Nullable public String getSSID(); + method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); - method @NonNull public android.net.NetworkCapabilities setAdministratorUids(@NonNull int[]); - method @NonNull public android.net.NetworkCapabilities setRequestorPackageName(@NonNull String); - method @NonNull public android.net.NetworkCapabilities setRequestorUid(int); - method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String); - method @NonNull public android.net.NetworkCapabilities setTransportInfo(@NonNull android.net.TransportInfo); field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16 field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18 } + public static class NetworkCapabilities.Builder { + ctor public NetworkCapabilities.Builder(); + ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); + method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); + method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setOwnerUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setRequestorUid(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkCapabilities.Builder setSignalStrength(int); + method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + } + public class NetworkKey implements android.os.Parcelable { ctor public NetworkKey(android.net.WifiKey); method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult); diff --git a/api/test-current.txt b/api/test-current.txt index 73abb27ec779..9ed451c2f47e 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1511,12 +1511,34 @@ package android.net { } public final class NetworkCapabilities implements android.os.Parcelable { + method @NonNull public int[] getAdministratorUids(); method public int[] getCapabilities(); + method @Nullable public String getSsid(); method @NonNull public int[] getTransportTypes(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); field public static final int TRANSPORT_TEST = 7; // 0x7 } + public static class NetworkCapabilities.Builder { + ctor public NetworkCapabilities.Builder(); + ctor public NetworkCapabilities.Builder(@NonNull android.net.NetworkCapabilities); + method @NonNull public android.net.NetworkCapabilities.Builder addCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder addTransportType(int); + method @NonNull public android.net.NetworkCapabilities build(); + method @NonNull public android.net.NetworkCapabilities.Builder removeCapability(int); + method @NonNull public android.net.NetworkCapabilities.Builder removeTransportType(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setAdministratorUids(@NonNull int[]); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkDownstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setLinkUpstreamBandwidthKbps(int); + method @NonNull public android.net.NetworkCapabilities.Builder setNetworkSpecifier(@Nullable android.net.NetworkSpecifier); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setOwnerUid(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setRequestorPackageName(@Nullable String); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setRequestorUid(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP") public android.net.NetworkCapabilities.Builder setSignalStrength(int); + method @NonNull @RequiresPermission("android.permission.NETWORK_FACTORY") public android.net.NetworkCapabilities.Builder setSsid(@Nullable String); + method @NonNull public android.net.NetworkCapabilities.Builder setTransportInfo(@Nullable android.net.TransportInfo); + } + public class NetworkStack { method @Nullable public static android.os.IBinder getService(); method public static void setServiceForTest(@Nullable android.os.IBinder); diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index e6b90d87a59f..1508a657cf4a 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -916,23 +916,11 @@ public final class BluetoothAdapter { if (!isBleScanAlwaysAvailable()) { return false; } - - int state = getLeState(); - if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) { - String packageName = ActivityThread.currentPackageName(); - if (DBG) { - Log.d(TAG, "disableBLE(): de-registering " + packageName); - } - try { - mManagerService.updateBleAppCount(mToken, false, packageName); - } catch (RemoteException e) { - Log.e(TAG, "", e); - } - return true; - } - - if (DBG) { - Log.d(TAG, "disableBLE(): Already disabled"); + String packageName = ActivityThread.currentPackageName(); + try { + return mManagerService.disableBle(packageName, mToken); + } catch (RemoteException e) { + Log.e(TAG, "", e); } return false; } @@ -973,20 +961,9 @@ public final class BluetoothAdapter { if (!isBleScanAlwaysAvailable()) { return false; } - + String packageName = ActivityThread.currentPackageName(); try { - String packageName = ActivityThread.currentPackageName(); - mManagerService.updateBleAppCount(mToken, true, packageName); - if (isLeEnabled()) { - if (DBG) { - Log.d(TAG, "enableBLE(): Bluetooth already enabled"); - } - return true; - } - if (DBG) { - Log.d(TAG, "enableBLE(): Calling enable"); - } - return mManagerService.enable(packageName); + return mManagerService.enableBle(packageName, mToken); } catch (RemoteException e) { Log.e(TAG, "", e); } diff --git a/core/java/android/net/InvalidPacketException.java b/core/java/android/net/InvalidPacketException.java index 909998d4562c..b3b0f11a776b 100644 --- a/core/java/android/net/InvalidPacketException.java +++ b/core/java/android/net/InvalidPacketException.java @@ -28,7 +28,7 @@ import java.lang.annotation.RetentionPolicy; */ @SystemApi public class InvalidPacketException extends Exception { - public final int error; + private final int mError; // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. /** Invalid IP address. */ @@ -56,6 +56,11 @@ public class InvalidPacketException extends Exception { * See the error code for details. */ public InvalidPacketException(@ErrorCode final int error) { - this.error = error; + this.mError = error; + } + + /** Get error code. */ + public int getError() { + return mError; } } diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 6c0ba2f63a80..e21cb44f72d8 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -19,6 +19,7 @@ package android.net; import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; import static android.net.InvalidPacketException.ERROR_INVALID_PORT; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.net.util.IpUtils; @@ -37,17 +38,17 @@ public class KeepalivePacketData { /** Source IP address */ @NonNull - public final InetAddress srcAddress; + private final InetAddress mSrcAddress; /** Destination IP address */ @NonNull - public final InetAddress dstAddress; + private final InetAddress mDstAddress; /** Source port */ - public final int srcPort; + private final int mSrcPort; /** Destination port */ - public final int dstPort; + private final int mDstPort; /** Packet data. A raw byte string of packet data, not including the link-layer header. */ private final byte[] mPacket; @@ -60,13 +61,14 @@ public class KeepalivePacketData { /** * A holding class for data necessary to build a keepalive packet. */ - protected KeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort, - @NonNull InetAddress dstAddress, int dstPort, - @NonNull byte[] data) throws InvalidPacketException { - this.srcAddress = srcAddress; - this.dstAddress = dstAddress; - this.srcPort = srcPort; - this.dstPort = dstPort; + protected KeepalivePacketData(@NonNull InetAddress srcAddress, + @IntRange(from = 0, to = 65535) int srcPort, @NonNull InetAddress dstAddress, + @IntRange(from = 0, to = 65535) int dstPort, + @NonNull byte[] data) throws InvalidPacketException { + this.mSrcAddress = srcAddress; + this.mDstAddress = dstAddress; + this.mSrcPort = srcPort; + this.mDstPort = dstPort; this.mPacket = data; // Check we have two IP addresses of the same family. @@ -83,6 +85,31 @@ public class KeepalivePacketData { } } + /** Get source IP address. */ + @NonNull + public InetAddress getSrcAddress() { + return mSrcAddress; + } + + /** Get destination IP address. */ + @NonNull + public InetAddress getDstAddress() { + return mDstAddress; + } + + /** Get source port number. */ + public int getSrcPort() { + return mSrcPort; + } + + /** Get destination port number. */ + public int getDstPort() { + return mDstPort; + } + + /** + * Returns a byte array of the given packet data. + */ @NonNull public byte[] getPacket() { return mPacket.clone(); diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java index 29da4952daa5..22288b6205d7 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/core/java/android/net/NattKeepalivePacketData.java @@ -94,10 +94,10 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement /** Write to parcel */ public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeString(srcAddress.getHostAddress()); - out.writeString(dstAddress.getHostAddress()); - out.writeInt(srcPort); - out.writeInt(dstPort); + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); } /** Parcelable Creator */ @@ -115,7 +115,7 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement dstAddress, dstPort); } catch (InvalidPacketException e) { throw new IllegalArgumentException( - "Invalid NAT-T keepalive data: " + e.error); + "Invalid NAT-T keepalive data: " + e.getError()); } } @@ -128,14 +128,16 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement public boolean equals(@Nullable final Object o) { if (!(o instanceof NattKeepalivePacketData)) return false; final NattKeepalivePacketData other = (NattKeepalivePacketData) o; - return this.srcAddress.equals(other.srcAddress) - && this.dstAddress.equals(other.dstAddress) - && this.srcPort == other.srcPort - && this.dstPort == other.dstPort; + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort(); } @Override public int hashCode() { - return Objects.hash(srcAddress, dstAddress, srcPort, dstPort); + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort()); } } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 64e93502a3b1..ad1e50122748 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -19,6 +19,7 @@ package android.net; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -32,6 +33,7 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; @@ -86,6 +88,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Completely clears the contents of this object, removing even the capabilities that are set * by default when the object is constructed. + * @hide */ public void clearAll() { mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; @@ -427,11 +430,12 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given capability to this {@code NetworkCapability} instance. - * Multiple capabilities may be applied sequentially. Note that when searching - * for a network to satisfy a request, all capabilities requested must be satisfied. + * Note that when searching for a network to satisfy a request, all capabilities + * requested must be satisfied. * * @param capability the capability to be added. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { // If the given capability was previously added to the list of unwanted capabilities @@ -446,9 +450,9 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given capability to the list of unwanted capabilities of this - * {@code NetworkCapability} instance. Multiple unwanted capabilities may be applied - * sequentially. Note that when searching for a network to satisfy a request, the network - * must not contain any capability from unwanted capability list. + * {@code NetworkCapability} instance. Note that when searching for a network to + * satisfy a request, the network must not contain any capability from unwanted capability + * list. * <p> * If the capability was previously added to the list of required capabilities (for * example, it was there by default or added using {@link #addCapability(int)} method), then @@ -468,6 +472,7 @@ public final class NetworkCapabilities implements Parcelable { * * @param capability the capability to be removed. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { // Note that this method removes capabilities that were added via addCapability(int), @@ -482,7 +487,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Sets (or clears) the given capability on this {@link NetworkCapabilities} * instance. - * + * @hide */ public @NonNull NetworkCapabilities setCapability(@NetCapability int capability, boolean value) { @@ -757,7 +762,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given transport type to this {@code NetworkCapability} instance. - * Multiple transports may be applied sequentially. Note that when searching + * Multiple transports may be applied. Note that when searching * for a network to satisfy a request, any listed in the request will satisfy the request. * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network @@ -766,6 +771,7 @@ public final class NetworkCapabilities implements Parcelable { * * @param transportType the transport type to be added. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) { checkValidTransportType(transportType); @@ -878,6 +884,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the UID of the owner app. + * @hide */ public @NonNull NetworkCapabilities setOwnerUid(final int uid) { mOwnerUid = uid; @@ -895,6 +902,8 @@ public final class NetworkCapabilities implements Parcelable { * <li>The user's location toggle is on * </ol> * + * Instances of NetworkCapabilities sent to apps without the appropriate permissions will + * have this field cleared out. */ public int getOwnerUid() { return mOwnerUid; @@ -933,7 +942,6 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @NonNull - @SystemApi public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); return this; @@ -947,6 +955,7 @@ public final class NetworkCapabilities implements Parcelable { */ @NonNull @SystemApi + @TestApi public int[] getAdministratorUids() { return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); } @@ -969,15 +978,10 @@ public final class NetworkCapabilities implements Parcelable { * Sets the upstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. * <p> - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. + * {@see Builder#setLinkUpstreamBandwidthKbps} * * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @hide */ public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { mLinkUpBandwidthKbps = upKbps; @@ -998,15 +1002,10 @@ public final class NetworkCapabilities implements Parcelable { * Sets the downstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. * <p> - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. + * {@see Builder#setLinkUpstreamBandwidthKbps} * * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @hide */ public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { mLinkDownBandwidthKbps = downKbps; @@ -1065,6 +1064,7 @@ public final class NetworkCapabilities implements Parcelable { * @param networkSpecifier A concrete, parcelable framework class that extends * NetworkSpecifier. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities setNetworkSpecifier( @NonNull NetworkSpecifier networkSpecifier) { @@ -1086,7 +1086,6 @@ public final class NetworkCapabilities implements Parcelable { * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) { mTransportInfo = transportInfo; return this; @@ -1096,7 +1095,7 @@ public final class NetworkCapabilities implements Parcelable { * Gets the optional bearer specific network specifier. May be {@code null} if not set. * * @return The optional {@link NetworkSpecifier} specifying the bearer specific network - * specifier or {@code null}. See {@link #setNetworkSpecifier}. + * specifier or {@code null}. */ public @Nullable NetworkSpecifier getNetworkSpecifier() { return mNetworkSpecifier; @@ -1166,6 +1165,7 @@ public final class NetworkCapabilities implements Parcelable { * effect when requesting a callback. * * @param signalStrength the bearer-specific signal strength. + * @hide */ public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) { mSignalStrength = signalStrength; @@ -1392,7 +1392,6 @@ public final class NetworkCapabilities implements Parcelable { * Sets the SSID of this network. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) { mSSID = ssid; return this; @@ -1403,7 +1402,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @SystemApi - public @Nullable String getSSID() { + @TestApi + public @Nullable String getSsid() { return mSSID; } @@ -1883,25 +1883,32 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Set the uid of the app making the request. + * Set the UID of the app making the request. * - * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in - * via the public {@link ConnectivityManager} API's will have this field overwritten. + * For instances of NetworkCapabilities representing a request, sets the + * UID of the app making the request. For a network created by the system, + * sets the UID of the only app whose requests can match this network. + * This can be set to {@link Process#INVALID_UID} if there is no such app, + * or if this instance of NetworkCapabilities is about to be sent to a + * party that should not learn about this. * * @param uid UID of the app. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setRequestorUid(int uid) { mRequestorUid = uid; return this; } /** - * @return the uid of the app making the request. + * Returns the UID of the app making the request. * - * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} - * object was not obtained from {@link ConnectivityManager}. + * For a NetworkRequest being made by an app, contains the app's UID. For a network + * created by the system, contains the UID of the only app whose requests can match + * this network, or {@link Process#INVALID_UID} if none or if the + * caller does not have permission to learn about this. + * + * @return the uid of the app making the request. * @hide */ public int getRequestorUid() { @@ -1911,23 +1918,29 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the package name of the app making the request. * - * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in - * via the public {@link ConnectivityManager} API's will have this field overwritten. + * For instances of NetworkCapabilities representing a request, sets the + * package name of the app making the request. For a network created by the system, + * sets the package name of the only app whose requests can match this network. + * This can be set to null if there is no such app, or if this instance of + * NetworkCapabilities is about to be sent to a party that should not learn about this. * * @param packageName package name of the app. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) { mRequestorPackageName = packageName; return this; } /** - * @return the package name of the app making the request. + * Returns the package name of the app making the request. + * + * For a NetworkRequest being made by an app, contains the app's package name. For a + * network created by the system, contains the package name of the only app whose + * requests can match this network, or null if none or if the caller does not have + * permission to learn about this. * - * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained - * from {@link ConnectivityManager}. + * @return the package name of the app making the request. * @hide */ @Nullable @@ -1936,9 +1949,9 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Set the uid and package name of the app making the request. + * Set the uid and package name of the app causing this network to exist. * - * Note: This is intended to be only invoked from within connectivitiy service. + * {@see #setRequestorUid} and {@link #setRequestorPackageName} * * @param uid UID of the app. * @param packageName package name of the app. @@ -1997,4 +2010,316 @@ public final class NetworkCapabilities implements Parcelable { return mRequestorUid == nc.mRequestorUid && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); } + + /** + * Builder class for NetworkCapabilities. + * + * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in + * the built class require holding a signature permission to use - mostly + * {@link android.Manifest.permission.NETWORK_FACTORY}, but refer to the specific + * description of each setter. As this class lives entirely in app space it does not + * enforce these restrictions itself but the system server clears out the relevant + * fields when receiving a NetworkCapabilities object from a caller without the + * appropriate permission. + * + * Apps don't use this builder directly. Instead, they use {@link NetworkRequest} via + * its builder object. + * + * @hide + */ + @SystemApi + @TestApi + public static class Builder { + private final NetworkCapabilities mCaps; + + /** + * Creates a new Builder to construct NetworkCapabilities objects. + */ + public Builder() { + mCaps = new NetworkCapabilities(); + } + + /** + * Creates a new Builder of NetworkCapabilities from an existing instance. + */ + public Builder(@NonNull final NetworkCapabilities nc) { + Objects.requireNonNull(nc); + mCaps = new NetworkCapabilities(nc); + } + + /** + * Adds the given transport type. + * + * Multiple transports may be added. Note that when searching for a network to satisfy a + * request, satisfying any of the transports listed in the request will satisfy the request. + * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a + * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network + * to be selected. This is logically different than + * {@code NetworkCapabilities.NET_CAPABILITY_*}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder addTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.addTransportType(transportType); + return this; + } + + /** + * Removes the given transport type. + * + * {@see #addTransportType}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder removeTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.removeTransportType(transportType); + return this; + } + + /** + * Adds the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder addCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, true); + return this; + } + + /** + * Removes the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder removeCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, false); + return this; + } + + /** + * Sets the owner UID. + * + * The default value is {@link Process#INVALID_UID}. Pass this value to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param ownerUid the owner UID + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setOwnerUid(final int ownerUid) { + mCaps.setOwnerUid(ownerUid); + return this; + } + + /** + * Sets the list of UIDs that are administrators of this network. + * + * <p>UIDs included in administratorUids gain administrator privileges over this + * Network. Examples of UIDs that should be included in administratorUids are: + * <ul> + * <li>Carrier apps with privileges for the relevant subscription + * <li>Active VPN apps + * <li>Other application groups with a particular Network-related role + * </ul> + * + * <p>In general, user-supplied networks (such as WiFi networks) do not have + * administrators. + * + * <p>An app is granted owner privileges over Networks that it supplies. The owner + * UID MUST always be included in administratorUids. + * + * The default value is the empty array. Pass an empty array to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, such as an app using reflection to call this or + * mutate the member in the built object. + * + * @param administratorUids the UIDs to be set as administrators of this Network. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setAdministratorUids(@NonNull final int[] administratorUids) { + Objects.requireNonNull(administratorUids); + mCaps.setAdministratorUids(administratorUids); + return this; + } + + /** + * Sets the upstream bandwidth of the link. + * + * Sets the upstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + * <p> + * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkUpstreamBandwidthKbps(final int upKbps) { + mCaps.setLinkUpstreamBandwidthKbps(upKbps); + return this; + } + + /** + * Sets the downstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + * <p> + * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkDownstreamBandwidthKbps(final int downKbps) { + mCaps.setLinkDownstreamBandwidthKbps(downKbps); + return this; + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + * </p> + * + * @param specifier a concrete, parcelable framework class that extends NetworkSpecifier, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setNetworkSpecifier(@Nullable final NetworkSpecifier specifier) { + mCaps.setNetworkSpecifier(specifier); + return this; + } + + /** + * Sets the optional transport specific information. + * + * @param info A concrete, parcelable framework class that extends {@link TransportInfo}, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setTransportInfo(@Nullable final TransportInfo info) { + mCaps.setTransportInfo(info); + return this; + } + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a + * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the + * same RSSI units reported by wifi code. + * <p> + * Note that when used to register a network callback, this specifies the minimum + * acceptable signal strength. When received as the state of an existing network it + * specifies the current value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means + * no value when received and has no effect when requesting a callback. + * + * Note: for security the system will throw if it receives a NetworkRequest where + * the underlying NetworkCapabilities has this member set from a source that does + * not hold the {@link android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP} + * permission. Apps with this permission can use this indirectly through + * {@link android.net.NetworkRequest}. + * + * @param signalStrength the bearer-specific signal strength. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) + public Builder setSignalStrength(final int signalStrength) { + mCaps.setSignalStrength(signalStrength); + return this; + } + + /** + * Sets the SSID of this network. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, like an app using reflection to set this. + * + * @param ssid the SSID, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setSsid(@Nullable final String ssid) { + mCaps.setSSID(ssid); + return this; + } + + /** + * Set the uid of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param uid UID of the app. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorUid(final int uid) { + mCaps.setRequestorUid(uid); + return this; + } + + /** + * Set the package name of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param packageName package name of the app, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorPackageName(@Nullable final String packageName) { + mCaps.setRequestorPackageName(packageName); + return this; + } + + /** + * Builds the instance of the capabilities. + * + * @return the built instance of NetworkCapabilities. + */ + @NonNull + public NetworkCapabilities build() { + if (mCaps.getOwnerUid() != Process.INVALID_UID) { + if (!ArrayUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { + throw new IllegalStateException("The owner UID must be included in " + + " administrator UIDs."); + } + } + return new NetworkCapabilities(mCaps); + } + } } diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index 767b69351065..5e2a71876103 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -8,4 +8,4 @@ lorenzo@google.com reminv@google.com satk@google.com -per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, tobiast@google.com +per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, ngeoffray@google.com diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS index 309261277024..3271d243e2cd 100644 --- a/core/java/android/net/http/OWNERS +++ b/core/java/android/net/http/OWNERS @@ -1,4 +1,4 @@ narayan@google.com -tobiast@google.com +ngeoffray@google.com include platform/libcore:/OWNERS include platform/external/conscrypt:/OWNERS diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS index 8cffd6a3e548..bc056df23a36 100644 --- a/libs/androidfw/OWNERS +++ b/libs/androidfw/OWNERS @@ -3,4 +3,4 @@ toddke@google.com rtmitchell@google.com per-file CursorWindow.cpp=omakoto@google.com -per-file LocaleDataTables.cpp=vichang@google.com,tobiast@google.com,nikitai@google.com +per-file LocaleDataTables.cpp=vichang@google.com,ngeoffray@google.com,nikitai@google.com diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 656827a80117..c8cf7f503468 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -4,7 +4,6 @@ dsandler@android.com adamcohen@google.com asc@google.com -ashaikh@google.com beverlyt@google.com brockman@google.com cinek@google.com @@ -12,8 +11,8 @@ cwren@google.com dupin@google.com ethibodeau@google.com evanlaird@google.com +hwwang@google.com hyunyoungs@google.com -jmonk@google.com jaggies@google.com jjaggi@google.com joshmcgrath@google.com @@ -29,16 +28,16 @@ mrcasey@google.com mrenouf@google.com nbenbernou@google.com nesciosquid@google.com -ngmatthew@google.com ogunwale@google.com +peanutbutter@google.com pixel@google.com roosa@google.com -shahrk@google.com snoeberger@google.com steell@google.com stwu@google.com sunnygoyal@google.com susikp@google.com +tracyzhou@google.com tsuji@google.com twickham@google.com winsonc@google.com diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp index 0c372351292c..0cfd8843c0f8 100644 --- a/packages/Tethering/Android.bp +++ b/packages/Tethering/Android.bp @@ -16,9 +16,7 @@ java_defaults { name: "TetheringAndroidLibraryDefaults", - // TODO (b/146757305): change to module API once available - // TODO (b/148190005): change to module-libs-api-stubs-current once it is ready. - sdk_version: "core_platform", + sdk_version: "module_current", srcs: [ "src/**/*.java", ":framework-tethering-shared-srcs", @@ -35,15 +33,8 @@ java_defaults { "net-utils-framework-common", ], libs: [ - // Order matters: framework-tethering needs to be before the system stubs, otherwise - // hidden fields in the framework-tethering classes (which are also used to generate stubs) - // will not be found. "framework-tethering", - "android_system_stubs_current", - "framework-res", "unsupportedappusage", - "android_system_stubs_current", - "framework-res", ], plugins: ["java_api_finder"], manifest: "AndroidManifestBase.xml", @@ -91,9 +82,7 @@ cc_library { // Common defaults for compiling the actual APK. java_defaults { name: "TetheringAppDefaults", - // TODO (b/146757305): change to module API once available - // TODO (b/148190005): change to module-libs-api-stubs-current once it is ready. - sdk_version: "core_platform", + sdk_version: "module_current", privileged: true, jni_libs: [ "libtetherutilsjni", @@ -102,12 +91,7 @@ java_defaults { "res", ], libs: [ - // Order matters: framework-tethering needs to be before the system stubs, otherwise - // hidden fields in the framework-tethering classes (which are also used to generate stubs) - // will not be found. "framework-tethering", - "android_system_stubs_current", - "framework-res", ], jarjar_rules: "jarjar-rules.txt", optimize: { diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index 00d0d9c428ff..6af5fe54f281 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -126,17 +126,17 @@ droidstubs { java_library { name: "framework-tethering-stubs-publicapi", srcs: [":framework-tethering-stubs-srcs-publicapi"], - sdk_version: "current", + defaults: ["framework-module-stubs-lib-defaults-publicapi"], } java_library { name: "framework-tethering-stubs-systemapi", srcs: [":framework-tethering-stubs-srcs-systemapi"], - sdk_version: "system_current", + defaults: ["framework-module-stubs-lib-defaults-systemapi"], } java_library { name: "framework-tethering-stubs-module_libs_api", srcs: [":framework-tethering-stubs-srcs-module_libs_api"], - sdk_version: "module_current", + defaults: ["framework-module-stubs-lib-defaults-systemapi"], } diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index 096f4fefa82f..0107a7ef5b59 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -571,9 +571,8 @@ public class TetheringManager { /** * Configure tethering with static IPv4 assignment. * - * The clientAddress must be in the localIPv4Address prefix. A DHCP server will be - * started, but will only be able to offer the client address. The two addresses must - * be in the same prefix. + * A DHCP server will be started, but will only be able to offer the client address. + * The two addresses must be in the same prefix. * * @param localIPv4Address The preferred local IPv4 link address to use. * @param clientAddress The static client address. @@ -584,10 +583,7 @@ public class TetheringManager { @NonNull final LinkAddress clientAddress) { Objects.requireNonNull(localIPv4Address); Objects.requireNonNull(clientAddress); - if (localIPv4Address.getPrefixLength() != clientAddress.getPrefixLength() - || !localIPv4Address.isIpv4() || !clientAddress.isIpv4() - || !new IpPrefix(localIPv4Address.toString()).equals( - new IpPrefix(clientAddress.toString()))) { + if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) { throw new IllegalArgumentException("Invalid server or client addresses"); } @@ -657,6 +653,19 @@ public class TetheringManager { } /** + * Check whether the two addresses are ipv4 and in the same prefix. + * @hide + */ + public static boolean checkStaticAddressConfiguration( + @NonNull final LinkAddress localIPv4Address, + @NonNull final LinkAddress clientAddress) { + return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength() + && localIPv4Address.isIpv4() && clientAddress.isIpv4() + && new IpPrefix(localIPv4Address.toString()).equals( + new IpPrefix(clientAddress.toString())); + } + + /** * Get a TetheringRequestParcel from the configuration * @hide */ diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java index d6bc063210b3..82a26beadacf 100644 --- a/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java +++ b/packages/Tethering/src/android/net/dhcp/DhcpServingParamsParcelExt.java @@ -18,10 +18,12 @@ package android.net.dhcp; import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH; -import android.annotation.NonNull; import android.net.LinkAddress; import android.util.ArraySet; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.net.Inet4Address; import java.util.Collection; import java.util.Collections; @@ -160,6 +162,17 @@ public class DhcpServingParamsParcelExt extends DhcpServingParamsParcel { return this; } + /** + * Set the client address to tell DHCP server only offer this address. + * The client's prefix length is the same as server's. + * + * <p>If not set, the default value is null. + */ + public DhcpServingParamsParcelExt setSingleClientAddr(@Nullable Inet4Address clientAddr) { + this.clientAddr = clientAddr == null ? 0 : inet4AddressToIntHTH(clientAddr); + return this; + } + private static int[] toIntArray(@NonNull Collection<Inet4Address> addrs) { int[] res = new int[addrs.size()]; int i = 0; diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java index c5478d2e1a14..82b17acae592 100644 --- a/packages/Tethering/src/android/net/ip/IpServer.java +++ b/packages/Tethering/src/android/net/ip/IpServer.java @@ -18,6 +18,7 @@ package android.net.ip; import static android.net.InetAddresses.parseNumericAddress; import static android.net.RouteInfo.RTN_UNICAST; +import static android.net.TetheringManager.TetheringRequest.checkStaticAddressConfiguration; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; import static android.net.util.NetworkConstants.FF; @@ -492,17 +493,24 @@ public class IpServer extends StateMachine { } } - private boolean startDhcp(Inet4Address addr, int prefixLen) { + private boolean startDhcp(final LinkAddress serverLinkAddr, final LinkAddress clientLinkAddr) { if (mUsingLegacyDhcp) { return true; } + + final Inet4Address addr = (Inet4Address) serverLinkAddr.getAddress(); + final int prefixLen = serverLinkAddr.getPrefixLength(); + final Inet4Address clientAddr = clientLinkAddr == null ? null : + (Inet4Address) clientLinkAddr.getAddress(); + final DhcpServingParamsParcel params; params = new DhcpServingParamsParcelExt() .setDefaultRouters(addr) .setDhcpLeaseTimeSecs(DHCP_LEASE_TIME_SECS) .setDnsServers(addr) - .setServerAddr(new LinkAddress(addr, prefixLen)) - .setMetered(true); + .setServerAddr(serverLinkAddr) + .setMetered(true) + .setSingleClientAddr(clientAddr); // TODO: also advertise link MTU mDhcpServerStartIndex++; @@ -537,9 +545,10 @@ public class IpServer extends StateMachine { } } - private boolean configureDhcp(boolean enable, Inet4Address addr, int prefixLen) { + private boolean configureDhcp(boolean enable, final LinkAddress serverAddr, + final LinkAddress clientAddr) { if (enable) { - return startDhcp(addr, prefixLen); + return startDhcp(serverAddr, clientAddr); } else { stopDhcp(); return true; @@ -587,7 +596,7 @@ public class IpServer extends StateMachine { // code that calls into NetworkManagementService directly. srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR); mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); - return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH); + return configureDhcp(enabled, mIpv4Address, null /* clientAddress */); } mIpv4Address = new LinkAddress(srvAddr, prefixLen); } catch (IllegalArgumentException e) { @@ -624,7 +633,7 @@ public class IpServer extends StateMachine { mLinkProperties.removeRoute(route); } - return configureDhcp(enabled, srvAddr, prefixLen); + return configureDhcp(enabled, mIpv4Address, mStaticIpv4ClientAddr); } private String getRandomWifiIPv4Address() { @@ -945,7 +954,14 @@ public class IpServer extends StateMachine { } private void maybeConfigureStaticIp(final TetheringRequestParcel request) { - if (request == null) return; + // Ignore static address configuration if they are invalid or null. In theory, static + // addresses should not be invalid here because TetheringManager do not allow caller to + // specify invalid static address configuration. + if (request == null || request.localIPv4Address == null + || request.staticClientAddress == null || !checkStaticAddressConfiguration( + request.localIPv4Address, request.staticClientAddress)) { + return; + } mStaticIpv4ServerAddr = request.localIPv4Address; mStaticIpv4ClientAddr = request.staticClientAddress; diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index 020db5403e31..343ed4b16cd6 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -307,28 +307,22 @@ public class Tethering { userManager, this, mNotificationUpdater); mExecutor = new TetheringThreadExecutor(mHandler); mActiveDataSubIdListener = new ActiveDataSubIdListener(mExecutor); + mNetdCallback = new NetdCallback(); // Load tethering configuration. updateConfiguration(); - // NetdCallback should be registered after updateConfiguration() to ensure - // TetheringConfiguration is created. - mNetdCallback = new NetdCallback(); + } + + /** + * Start to register callbacks. + * Call this function when tethering is ready to handle callback events. + */ + public void startStateMachineUpdaters() { try { mNetd.registerUnsolicitedEventListener(mNetdCallback); } catch (RemoteException e) { mLog.e("Unable to register netd UnsolicitedEventListener"); } - - startStateMachineUpdaters(mHandler); - startTrackDefaultNetwork(); - - final WifiManager wifiManager = getWifiManager(); - if (wifiManager != null) { - wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); - } - } - - private void startStateMachineUpdaters(Handler handler) { mCarrierConfigChange.startListening(); mContext.getSystemService(TelephonyManager.class).listen(mActiveDataSubIdListener, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE); @@ -341,7 +335,14 @@ public class Tethering { filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED); filter.addAction(ACTION_RESTRICT_BACKGROUND_CHANGED); - mContext.registerReceiver(mStateReceiver, filter, null, handler); + mContext.registerReceiver(mStateReceiver, filter, null, mHandler); + + final WifiManager wifiManager = getWifiManager(); + if (wifiManager != null) { + wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback()); + } + + startTrackDefaultNetwork(); } private class TetheringThreadExecutor implements Executor { diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java index c5329d8d3316..c30be25dbd22 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java @@ -80,6 +80,7 @@ public class TetheringService extends Service { mContext = mDeps.getContext(); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mTethering = makeTethering(mDeps); + mTethering.startStateMachineUpdaters(); } /** diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java index 7ac7f5f06e50..45bb4ab6e5f7 100644 --- a/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java +++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java @@ -586,21 +586,21 @@ public class UpstreamNetworkMonitor { */ @VisibleForTesting public static NetworkCapabilities networkCapabilitiesForType(int type) { - final NetworkCapabilities nc = new NetworkCapabilities(); + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); // Map from type to transports. final int notFound = -1; final int transport = sLegacyTypeToTransport.get(type, notFound); Preconditions.checkArgument(transport != notFound, "unknown legacy type: " + type); - nc.addTransportType(transport); + builder.addTransportType(transport); if (type == TYPE_MOBILE_DUN) { - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); // DUN is restricted network, see NetworkCapabilities#FORCE_RESTRICTED_CAPABILITIES. - nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } else { - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } - return nc; + return builder.build(); } } diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp new file mode 100644 index 000000000000..1a1c30d1d5f9 --- /dev/null +++ b/packages/Tethering/tests/integration/Android.bp @@ -0,0 +1,42 @@ +// +// Copyright (C) 2020 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. +// + +android_test { + name: "TetheringIntegrationTests", + certificate: "platform", + platform_apis: true, + srcs: [ + "src/**/*.java", + "src/**/*.kt", + ], + test_suites: [ + "device-tests", + "mts", + ], + static_libs: [ + "NetworkStackApiStableLib", + "androidx.test.rules", + "frameworks-base-testutils", + "mockito-target-extended-minus-junit4", + "net-tests-utils", + "testables", + ], + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + ], +} diff --git a/packages/Tethering/tests/integration/AndroidManifest.xml b/packages/Tethering/tests/integration/AndroidManifest.xml new file mode 100644 index 000000000000..233ba40b5d35 --- /dev/null +++ b/packages/Tethering/tests/integration/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.networkstack.tethering.tests.integration"> + + <uses-permission android:name="android.permission.INTERNET"/> + <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/> + + <application android:debuggable="true"> + <uses-library android:name="android.test.runner" /> + </application> + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.networkstack.tethering.tests.integration" + android:label="Tethering integration tests"> + </instrumentation> +</manifest> diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java new file mode 100644 index 000000000000..492ce3db3424 --- /dev/null +++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import static android.Manifest.permission.MANAGE_TEST_NETWORKS; +import static android.Manifest.permission.NETWORK_SETTINGS; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; + +import android.app.UiAutomation; +import android.content.Context; +import android.net.EthernetManager.TetheredInterfaceCallback; +import android.net.EthernetManager.TetheredInterfaceRequest; +import android.net.TetheringManager.StartTetheringCallback; +import android.net.TetheringManager.TetheringEventCallback; +import android.net.TetheringManager.TetheringRequest; +import android.net.dhcp.DhcpAckPacket; +import android.net.dhcp.DhcpOfferPacket; +import android.net.dhcp.DhcpPacket; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.SystemClock; +import android.system.Os; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.MediumTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.testutils.HandlerUtilsKt; +import com.android.testutils.TapPacketReader; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.FileDescriptor; +import java.net.Inet4Address; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +@MediumTest +public class EthernetTetheringTest { + + private static final String TAG = EthernetTetheringTest.class.getSimpleName(); + private static final int TIMEOUT_MS = 1000; + private static final int PACKET_READ_TIMEOUT_MS = 100; + private static final int DHCP_DISCOVER_ATTEMPTS = 10; + private static final byte[] DHCP_REQUESTED_PARAMS = new byte[] { + DhcpPacket.DHCP_SUBNET_MASK, + DhcpPacket.DHCP_ROUTER, + DhcpPacket.DHCP_DNS_SERVER, + DhcpPacket.DHCP_LEASE_TIME, + }; + private static final String DHCP_HOSTNAME = "testhostname"; + + private final Context mContext = InstrumentationRegistry.getContext(); + private final EthernetManager mEm = mContext.getSystemService(EthernetManager.class); + private final TetheringManager mTm = mContext.getSystemService(TetheringManager.class); + + private TestNetworkInterface mTestIface; + private HandlerThread mHandlerThread; + private Handler mHandler; + private TapPacketReader mTapPacketReader; + + private TetheredInterfaceRequester mTetheredInterfaceRequester; + private MyTetheringEventCallback mTetheringEventCallback; + + private UiAutomation mUiAutomation = + InstrumentationRegistry.getInstrumentation().getUiAutomation(); + + @Before + public void setUp() throws Exception { + mHandlerThread = new HandlerThread(getClass().getSimpleName()); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + mTetheredInterfaceRequester = new TetheredInterfaceRequester(mHandler, mEm); + // Needed to create a TestNetworkInterface, to call requestTetheredInterface, and to receive + // tethered client callbacks. + mUiAutomation.adoptShellPermissionIdentity(MANAGE_TEST_NETWORKS, NETWORK_SETTINGS); + } + + private void cleanUp() throws Exception { + mTm.stopTethering(TetheringManager.TETHERING_ETHERNET); + if (mTetheringEventCallback != null) { + mTetheringEventCallback.awaitInterfaceUntethered(); + mTetheringEventCallback.unregister(); + mTetheringEventCallback = null; + } + if (mTapPacketReader != null) { + TapPacketReader reader = mTapPacketReader; + mHandler.post(() -> reader.stop()); + mTapPacketReader = null; + } + mHandlerThread.quitSafely(); + mTetheredInterfaceRequester.release(); + mEm.setIncludeTestInterfaces(false); + maybeDeleteTestInterface(); + } + + @After + public void tearDown() throws Exception { + try { + cleanUp(); + } finally { + mUiAutomation.dropShellPermissionIdentity(); + } + } + + @Test + public void testVirtualEthernetAlreadyExists() throws Exception { + // This test requires manipulating packets. Skip if there is a physical Ethernet connected. + assumeFalse(mEm.isAvailable()); + + mTestIface = createTestInterface(); + // This must be done now because as soon as setIncludeTestInterfaces(true) is called, the + // interface will be placed in client mode, which will delete the link-local address. + // At that point NetworkInterface.getByName() will cease to work on the interface, because + // starting in R NetworkInterface can no longer see interfaces without IP addresses. + int mtu = getMTU(mTestIface); + + Log.d(TAG, "Including test interfaces"); + mEm.setIncludeTestInterfaces(true); + + final String iface = mTetheredInterfaceRequester.getInterface(); + assertEquals("TetheredInterfaceCallback for unexpected interface", + mTestIface.getInterfaceName(), iface); + + checkVirtualEthernet(mTestIface, mtu); + } + + @Test + public void testVirtualEthernet() throws Exception { + // This test requires manipulating packets. Skip if there is a physical Ethernet connected. + assumeFalse(mEm.isAvailable()); + + CompletableFuture<String> futureIface = mTetheredInterfaceRequester.requestInterface(); + + mEm.setIncludeTestInterfaces(true); + + mTestIface = createTestInterface(); + + final String iface = futureIface.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + assertEquals("TetheredInterfaceCallback for unexpected interface", + mTestIface.getInterfaceName(), iface); + + checkVirtualEthernet(mTestIface, getMTU(mTestIface)); + } + + @Test + public void testPhysicalEthernet() throws Exception { + assumeTrue(mEm.isAvailable()); + + // Get an interface to use. + final String iface = mTetheredInterfaceRequester.getInterface(); + + // Enable Ethernet tethering and check that it starts. + mTetheringEventCallback = enableEthernetTethering(iface); + + // There is nothing more we can do on a physical interface without connecting an actual + // client, which is not possible in this test. + } + + private static final class MyTetheringEventCallback implements TetheringEventCallback { + private final TetheringManager mTm; + private final CountDownLatch mTetheringStartedLatch = new CountDownLatch(1); + private final CountDownLatch mTetheringStoppedLatch = new CountDownLatch(1); + private final CountDownLatch mClientConnectedLatch = new CountDownLatch(1); + private final String mIface; + + private volatile boolean mInterfaceWasTethered = false; + private volatile boolean mUnregistered = false; + private volatile Collection<TetheredClient> mClients = null; + + MyTetheringEventCallback(TetheringManager tm, String iface) { + mTm = tm; + mIface = iface; + } + + public void unregister() { + mTm.unregisterTetheringEventCallback(this); + mUnregistered = true; + } + + @Override + public void onTetheredInterfacesChanged(List<String> interfaces) { + // Ignore stale callbacks registered by previous test cases. + if (mUnregistered) return; + + final boolean wasTethered = mTetheringStartedLatch.getCount() == 0; + if (!mInterfaceWasTethered && (mIface == null || interfaces.contains(mIface))) { + // This interface is being tethered for the first time. + Log.d(TAG, "Tethering started: " + interfaces); + mInterfaceWasTethered = true; + mTetheringStartedLatch.countDown(); + } else if (mInterfaceWasTethered && !interfaces.contains(mIface)) { + Log.d(TAG, "Tethering stopped: " + interfaces); + mTetheringStoppedLatch.countDown(); + } + } + + public void awaitInterfaceTethered() throws Exception { + assertTrue("Ethernet not tethered after " + TIMEOUT_MS + "ms", + mTetheringStartedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + + public void awaitInterfaceUntethered() throws Exception { + // Don't block teardown if the interface was never tethered. + // This is racy because the interface might become tethered right after this check, but + // that can only happen in tearDown if startTethering timed out, which likely means + // the test has already failed. + if (!mInterfaceWasTethered) return; + + assertTrue(mIface + " not untethered after " + TIMEOUT_MS + "ms", + mTetheringStoppedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + + @Override + public void onError(String ifName, int error) { + // Ignore stale callbacks registered by previous test cases. + if (mUnregistered) return; + + fail("TetheringEventCallback got error:" + error + " on iface " + ifName); + } + + @Override + public void onClientsChanged(Collection<TetheredClient> clients) { + // Ignore stale callbacks registered by previous test cases. + if (mUnregistered) return; + + Log.d(TAG, "Got clients changed: " + clients); + mClients = clients; + if (clients.size() > 0) { + mClientConnectedLatch.countDown(); + } + } + + public Collection<TetheredClient> awaitClientConnected() throws Exception { + assertTrue("Did not receive client connected callback after " + TIMEOUT_MS + "ms", + mClientConnectedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + return mClients; + } + } + + private MyTetheringEventCallback enableEthernetTethering(String iface) throws Exception { + MyTetheringEventCallback callback = new MyTetheringEventCallback(mTm, iface); + mTm.registerTetheringEventCallback(mHandler::post, callback); + + StartTetheringCallback startTetheringCallback = new StartTetheringCallback() { + @Override + public void onTetheringFailed(int resultCode) { + fail("Unexpectedly got onTetheringFailed"); + } + }; + Log.d(TAG, "Starting Ethernet tethering"); + mTm.startTethering( + new TetheringRequest.Builder(TetheringManager.TETHERING_ETHERNET).build(), + mHandler::post /* executor */, startTetheringCallback); + callback.awaitInterfaceTethered(); + return callback; + } + + private int getMTU(TestNetworkInterface iface) throws SocketException { + NetworkInterface nif = NetworkInterface.getByName(iface.getInterfaceName()); + assertNotNull("Can't get NetworkInterface object for " + iface.getInterfaceName(), nif); + return nif.getMTU(); + } + + private void checkVirtualEthernet(TestNetworkInterface iface, int mtu) throws Exception { + FileDescriptor fd = iface.getFileDescriptor().getFileDescriptor(); + mTapPacketReader = new TapPacketReader(mHandler, fd, mtu); + mHandler.post(() -> mTapPacketReader.start()); + HandlerUtilsKt.waitForIdle(mHandler, TIMEOUT_MS); + + mTetheringEventCallback = enableEthernetTethering(iface.getInterfaceName()); + checkTetheredClientCallbacks(fd); + } + + private void checkTetheredClientCallbacks(FileDescriptor fd) throws Exception { + // Create a fake client. + byte[] clientMacAddr = new byte[6]; + new Random().nextBytes(clientMacAddr); + + // We have to retransmit DHCP requests because IpServer declares itself to be ready before + // its DhcpServer is actually started. TODO: fix this race and remove this loop. + DhcpPacket offerPacket = null; + for (int i = 0; i < DHCP_DISCOVER_ATTEMPTS; i++) { + Log.d(TAG, "Sending DHCP discover"); + sendDhcpDiscover(fd, clientMacAddr); + offerPacket = getNextDhcpPacket(); + if (offerPacket instanceof DhcpOfferPacket) break; + } + assertTrue("No DHCPOFFER received on interface within timeout", + offerPacket instanceof DhcpOfferPacket); + + sendDhcpRequest(fd, offerPacket, clientMacAddr); + DhcpPacket ackPacket = getNextDhcpPacket(); + assertTrue("No DHCPACK received on interface within timeout", + ackPacket instanceof DhcpAckPacket); + + final Collection<TetheredClient> clients = mTetheringEventCallback.awaitClientConnected(); + assertEquals(1, clients.size()); + final TetheredClient client = clients.iterator().next(); + + // Check the MAC address. + assertEquals(MacAddress.fromBytes(clientMacAddr), client.getMacAddress()); + assertEquals(TetheringManager.TETHERING_ETHERNET, client.getTetheringType()); + + // Check the hostname. + assertEquals(1, client.getAddresses().size()); + TetheredClient.AddressInfo info = client.getAddresses().get(0); + assertEquals(DHCP_HOSTNAME, info.getHostname()); + + // Check the address is the one that was handed out in the DHCP ACK. + DhcpResults dhcpResults = offerPacket.toDhcpResults(); + assertLinkAddressMatches(dhcpResults.ipAddress, info.getAddress()); + + // Check that the lifetime is correct +/- 10s. + final long now = SystemClock.elapsedRealtime(); + final long actualLeaseDuration = (info.getAddress().getExpirationTime() - now) / 1000; + final String msg = String.format("IP address should have lifetime of %d, got %d", + dhcpResults.leaseDuration, actualLeaseDuration); + assertTrue(msg, Math.abs(dhcpResults.leaseDuration - actualLeaseDuration) < 10); + } + + private DhcpPacket getNextDhcpPacket() throws ParseException { + byte[] packet; + while ((packet = mTapPacketReader.popPacket(PACKET_READ_TIMEOUT_MS)) != null) { + try { + return DhcpPacket.decodeFullPacket(packet, packet.length, DhcpPacket.ENCAP_L2); + } catch (DhcpPacket.ParseException e) { + // Not a DHCP packet. Continue. + } + } + return null; + } + + private static final class TetheredInterfaceRequester implements TetheredInterfaceCallback { + private final CountDownLatch mInterfaceAvailableLatch = new CountDownLatch(1); + private final Handler mHandler; + private final EthernetManager mEm; + + private TetheredInterfaceRequest mRequest; + private final CompletableFuture<String> mFuture = new CompletableFuture<>(); + + TetheredInterfaceRequester(Handler handler, EthernetManager em) { + mHandler = handler; + mEm = em; + } + + @Override + public void onAvailable(String iface) { + Log.d(TAG, "Ethernet interface available: " + iface); + mFuture.complete(iface); + } + + @Override + public void onUnavailable() { + mFuture.completeExceptionally(new IllegalStateException("onUnavailable received")); + } + + public CompletableFuture<String> requestInterface() { + assertNull("BUG: more than one tethered interface request", mRequest); + Log.d(TAG, "Requesting tethered interface"); + mRequest = mEm.requestTetheredInterface(mHandler::post, this); + return mFuture; + } + + public String getInterface() throws Exception { + return requestInterface().get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + public void release() { + if (mRequest != null) { + mFuture.obtrudeException(new IllegalStateException("Request already released")); + mRequest.release(); + mRequest = null; + } + } + } + + private void sendDhcpDiscover(FileDescriptor fd, byte[] macAddress) throws Exception { + ByteBuffer packet = DhcpPacket.buildDiscoverPacket(DhcpPacket.ENCAP_L2, + new Random().nextInt() /* transactionId */, (short) 0 /* secs */, + macAddress, false /* unicast */, DHCP_REQUESTED_PARAMS, + false /* rapid commit */, DHCP_HOSTNAME); + sendPacket(fd, packet); + } + + private void sendDhcpRequest(FileDescriptor fd, DhcpPacket offerPacket, byte[] macAddress) + throws Exception { + DhcpResults results = offerPacket.toDhcpResults(); + Inet4Address clientIp = (Inet4Address) results.ipAddress.getAddress(); + Inet4Address serverIdentifier = results.serverAddress; + ByteBuffer packet = DhcpPacket.buildRequestPacket(DhcpPacket.ENCAP_L2, + 0 /* transactionId */, (short) 0 /* secs */, DhcpPacket.INADDR_ANY /* clientIp */, + false /* broadcast */, macAddress, clientIp /* requestedIpAddress */, + serverIdentifier, DHCP_REQUESTED_PARAMS, DHCP_HOSTNAME); + sendPacket(fd, packet); + } + + private void sendPacket(FileDescriptor fd, ByteBuffer packet) throws Exception { + assertNotNull("Only tests on virtual interfaces can send packets", fd); + Os.write(fd, packet); + } + + public void assertLinkAddressMatches(LinkAddress l1, LinkAddress l2) { + // Check all fields except the deprecation and expiry times. + String msg = String.format("LinkAddresses do not match. expected: %s actual: %s", l1, l2); + assertTrue(msg, l1.isSameAddressAs(l2)); + assertEquals("LinkAddress flags do not match", l1.getFlags(), l2.getFlags()); + assertEquals("LinkAddress scope does not match", l1.getScope(), l2.getScope()); + } + + private TestNetworkInterface createTestInterface() throws Exception { + TestNetworkManager tnm = mContext.getSystemService(TestNetworkManager.class); + TestNetworkInterface iface = tnm.createTapInterface(); + Log.d(TAG, "Created test interface " + iface.getInterfaceName()); + assertNotNull(NetworkInterface.getByName(iface.getInterfaceName())); + return iface; + } + + private void maybeDeleteTestInterface() throws Exception { + if (mTestIface != null) { + mTestIface.getFileDescriptor().close(); + Log.d(TAG, "Deleted test interface " + mTestIface.getInterfaceName()); + mTestIface = null; + } + } +} diff --git a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java index e8add9830b5f..f8eb1476bad0 100644 --- a/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java +++ b/packages/Tethering/tests/unit/src/android/net/dhcp/DhcpServingParamsParcelExtTest.java @@ -42,7 +42,9 @@ import java.util.stream.IntStream; @SmallTest public class DhcpServingParamsParcelExtTest { private static final Inet4Address TEST_ADDRESS = inet4Addr("192.168.0.123"); + private static final Inet4Address TEST_CLIENT_ADDRESS = inet4Addr("192.168.0.42"); private static final int TEST_ADDRESS_PARCELED = 0xc0a8007b; + private static final int TEST_CLIENT_ADDRESS_PARCELED = 0xc0a8002a; private static final int TEST_PREFIX_LENGTH = 17; private static final int TEST_LEASE_TIME_SECS = 120; private static final int TEST_MTU = 1000; @@ -105,6 +107,12 @@ public class DhcpServingParamsParcelExtTest { assertFalse(mParcel.metered); } + @Test + public void testSetClientAddr() { + mParcel.setSingleClientAddr(TEST_CLIENT_ADDRESS); + assertEquals(TEST_CLIENT_ADDRESS_PARCELED, mParcel.clientAddr); + } + private static Inet4Address inet4Addr(String addr) { return (Inet4Address) parseNumericAddress(addr); } diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java index 0980514ce268..a418c4a880d2 100644 --- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java +++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java @@ -38,6 +38,7 @@ import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS; +import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE; import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; @@ -484,6 +485,7 @@ public class TetheringTest { mServiceContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_TETHER_STATE_CHANGED)); mTethering = makeTethering(); + mTethering.startStateMachineUpdaters(); verify(mStatsManager, times(1)).registerNetworkStatsProvider(anyString(), any()); verify(mNetd).registerUnsolicitedEventListener(any()); final ArgumentCaptor<PhoneStateListener> phoneListenerCaptor = @@ -1653,10 +1655,13 @@ public class TetheringTest { } @Test - public void testRequestStaticServerIp() throws Exception { - final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24"); - final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24"); - final String serverAddr = "192.168.20.1"; + public void testRequestStaticIp() throws Exception { + final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24"); + final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24"); + final String serverAddr = "192.168.0.123"; + final int clientAddrParceled = 0xc0a8002a; + final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor = + ArgumentCaptor.forClass(DhcpServingParamsParcel.class); mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB, serverLinkAddr, clientLinkAddr), null); mLooper.dispatchAll(); @@ -1665,8 +1670,12 @@ public class TetheringTest { sendUsbBroadcast(true, true, true, TETHERING_USB); mLooper.dispatchAll(); verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr))); - - // TODO: test static client address. + verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(), + any()); + final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue(); + assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress()); + assertEquals(24, params.serverAddrPrefixLength); + assertEquals(clientAddrParceled, params.clientAddr); } // TODO: Test that a request for hotspot mode doesn't interfere with an diff --git a/services/Android.bp b/services/Android.bp index 1ab23955610b..90f98e2bd7a6 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -75,10 +75,6 @@ java_library { "framework-tethering-stubs-module_libs_api", ], - plugins: [ - "compat-changeid-annotation-processor", - ], - // Uncomment to enable output of certain warnings (deprecated, unchecked) //javacflags: ["-Xlint"], @@ -94,8 +90,8 @@ cc_library_shared { } platform_compat_config { - name: "services-platform-compat-config", - src: ":services", + name: "services-platform-compat-config", + src: ":services", } filegroup { diff --git a/services/core/Android.bp b/services/core/Android.bp index b7fd227ed0bb..7a3a910c0447 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -56,10 +56,6 @@ java_library_static { "dnsresolver_aidl_interface-V2-java", "netd_event_listener_interface-java", ], - - plugins: [ - "compat-changeid-annotation-processor", - ], } java_genrule { diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java index 207e007cc62f..ecbf9a48931e 100644 --- a/services/core/java/com/android/server/AppStateTracker.java +++ b/services/core/java/com/android/server/AppStateTracker.java @@ -54,7 +54,6 @@ import com.android.internal.app.IAppOpsCallback; import com.android.internal.app.IAppOpsService; import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; -import com.android.internal.util.Preconditions; import com.android.internal.util.StatLogger; import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage; import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages; @@ -62,6 +61,7 @@ import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrict import java.io.PrintWriter; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** * Class to keep track of the information related to "force app standby", which includes: @@ -416,12 +416,12 @@ public class AppStateTracker { } mStarted = true; - mIActivityManager = Preconditions.checkNotNull(injectIActivityManager()); - mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal()); - mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager()); - mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService()); - mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal()); - mUsageStatsManagerInternal = Preconditions.checkNotNull( + mIActivityManager = Objects.requireNonNull(injectIActivityManager()); + mActivityManagerInternal = Objects.requireNonNull(injectActivityManagerInternal()); + mAppOpsManager = Objects.requireNonNull(injectAppOpsManager()); + mAppOpsService = Objects.requireNonNull(injectIAppOpsService()); + mPowerManagerInternal = Objects.requireNonNull(injectPowerManagerInternal()); + mUsageStatsManagerInternal = Objects.requireNonNull( injectUsageStatsManagerInternal()); mFlagsObserver = new FeatureFlagsObserver(); diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 11c1405d5905..168c8cd713b6 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -747,13 +747,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } - public int updateBleAppCount(IBinder token, boolean enable, String packageName) { - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } + private int updateBleAppCount(IBinder token, boolean enable, String packageName) { ClientDeathRecipient r = mBleApps.get(token); if (r == null && enable) { ClientDeathRecipient deathRec = new ClientDeathRecipient(packageName); @@ -778,13 +772,94 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (DBG) { Slog.d(TAG, appCount + " registered Ble Apps"); } - if (appCount == 0 && mEnable) { - disableBleScanMode(); + return appCount; + } + + private boolean checkBluetoothPermissions(String packageName, boolean requireForeground) { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "checkBluetoothPermissions: bluetooth disallowed"); + } + return false; } - if (appCount == 0 && !mEnableExternal) { - sendBrEdrDownCallback(); + // Check if packageName belongs to callingUid + final int callingUid = Binder.getCallingUid(); + final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!isCallerSystem) { + checkPackage(callingUid, packageName); + + if (requireForeground && !checkIfCallerIsForegroundUser()) { + Slog.w(TAG, "Not allowed for non-active and non system user"); + return false; + } + + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH ADMIN permission"); } - return appCount; + return true; + } + + public boolean enableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "enableBle(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "enableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + updateBleAppCount(token, true, packageName); + + if (mState == BluetoothAdapter.STATE_ON + || mState == BluetoothAdapter.STATE_BLE_ON + || mState == BluetoothAdapter.STATE_TURNING_ON + || mState == BluetoothAdapter.STATE_TURNING_OFF) { + Log.d(TAG, "enableBLE(): Bluetooth already enabled"); + return true; + } + synchronized (mReceiver) { + // waive WRITE_SECURE_SETTINGS permission check + sendEnableMsg(false, + BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName); + } + return true; + } + + public boolean disableBle(String packageName, IBinder token) throws RemoteException { + if (!checkBluetoothPermissions(packageName, false)) { + if (DBG) { + Slog.d(TAG, "disableBLE(): bluetooth disallowed"); + } + return false; + } + + if (DBG) { + Slog.d(TAG, "disableBle(" + packageName + "): mBluetooth =" + mBluetooth + + " mBinding = " + mBinding + " mState = " + + BluetoothAdapter.nameForState(mState)); + } + + if (mState == BluetoothAdapter.STATE_OFF) { + Slog.d(TAG, "disableBLE(): Already disabled"); + return false; + } + updateBleAppCount(token, false, packageName); + + if (mState == BluetoothAdapter.STATE_BLE_ON && !isBleAppPresent()) { + if (mEnable) { + disableBleScanMode(); + } + if (!mEnableExternal) { + addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, + packageName, false); + sendBrEdrDownCallback(); + } + } + return true; } // Clear all apps using BLE scan only mode. @@ -813,6 +888,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG, "onBluetoothServiceUp: mBluetooth is null!"); return; } + if (!mEnableExternal && !isBleAppPresent() && isAirplaneModeOn()) { + // Airplane mode is turned on while enabling BLE only mode, disable + // BLE now. + disableBleScanMode(); + sendBrEdrDownCallback(); + return; + } if (isBluetoothPersistedStateOnBluetooth() || !isBleAppPresent()) { // This triggers transition to STATE_ON mBluetooth.onLeServiceUp(); @@ -862,29 +944,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enableNoAutoConnect(String packageName) { - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, false)) { if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); } return false; } - // Check if packageName belongs to callingUid - final int callingUid = Binder.getCallingUid(); - final boolean isCallerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!isCallerSystem) { - checkPackage(callingUid, packageName); - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - if (DBG) { Slog.d(TAG, "enableNoAutoConnect(): mBluetooth =" + mBluetooth + " mBinding = " + mBinding); } - int callingAppId = UserHandle.getAppId(callingUid); + int callingAppId = UserHandle.getAppId(Binder.getCallingUid()); if (callingAppId != Process.NFC_UID) { throw new SecurityException("no permission to enable Bluetooth quietly"); } @@ -899,32 +971,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enable(String packageName) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (isBluetoothDisallowed()) { + if (!checkBluetoothPermissions(packageName, true)) { if (DBG) { Slog.d(TAG, "enable(): not enabling - bluetooth disallowed"); } return false; } - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "enable(): not allowed for non-active and non system user"); - return false; - } - - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (!isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && !isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + return false; } if (DBG) { @@ -946,25 +1005,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean disable(String packageName, boolean persist) throws RemoteException { - final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - - if (!callerSystem) { - // Check if packageName belongs to callingUid - checkPackage(callingUid, packageName); - - if (!checkIfCallerIsForegroundUser()) { - Slog.w(TAG, "disable(): not allowed for non-active and non system user"); - return false; + if (!checkBluetoothPermissions(packageName, true)) { + if (DBG) { + Slog.d(TAG, "disable(): not disabling - bluetooth disallowed"); } + return false; + } - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, - "Need BLUETOOTH ADMIN permission"); - - if (isEnabled() && mWirelessConsentRequired && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { - return false; - } + final int callingUid = Binder.getCallingUid(); + final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; + if (!callerSystem && isEnabled() && mWirelessConsentRequired + && startConsentUiIfNeeded(packageName, + callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + return false; } if (DBG) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 13097406e595..1484fe7c7c6c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -49,8 +49,6 @@ import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; -import static com.android.internal.util.Preconditions.checkNotNull; - import static java.util.Map.Entry; import android.Manifest; @@ -65,6 +63,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.CaptivePortal; @@ -929,7 +928,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * @see IpConnectivityMetrics.Logger */ public IpConnectivityMetrics.Logger getMetricsLogger() { - return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), + return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), "no IpConnectivityMetrics service"); } @@ -958,10 +957,10 @@ public class ConnectivityService extends IConnectivityManager.Stub IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) { if (DBG) log("ConnectivityService starting up"); - mDeps = checkNotNull(deps, "missing Dependencies"); + mDeps = Objects.requireNonNull(deps, "missing Dependencies"); mSystemProperties = mDeps.getSystemProperties(); mNetIdManager = mDeps.makeNetIdManager(); - mContext = checkNotNull(context, "missing Context"); + mContext = Objects.requireNonNull(context, "missing Context"); mMetricsLog = logger; mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); @@ -991,13 +990,13 @@ public class ConnectivityService extends IConnectivityManager.Stub mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); - mNMS = checkNotNull(netManager, "missing INetworkManagementService"); - mStatsService = checkNotNull(statsService, "missing INetworkStatsService"); - mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); - mPolicyManagerInternal = checkNotNull( + mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService"); + mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService"); + mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager"); + mPolicyManagerInternal = Objects.requireNonNull( LocalServices.getService(NetworkPolicyManagerInternal.class), "missing NetworkPolicyManagerInternal"); - mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver"); + mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver"); mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler); mNetd = netd; @@ -5333,7 +5332,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // specific SSID/SignalStrength, or the calling app has permission to do so. private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc, int callerPid, int callerUid, String callerPackageName) { - if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) { + if (null != nc.getSsid() && !checkSettingsPermission(callerPid, callerUid)) { throw new SecurityException("Insufficient permissions to request a specific SSID"); } @@ -5398,12 +5397,25 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { + final PackageManager pm = mContext.getPackageManager(); + final int userId = UserHandle.getCallingUserId(); + try { + final int callingVersion = pm.getApplicationInfoAsUser( + callingPackageName, 0 /* flags */, userId).targetSdkVersion; + if (callingVersion < version) return false; + } catch (PackageManager.NameNotFoundException e) { } + return true; + } + @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType, @NonNull String callingPackageName) { if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { - throw new SecurityException("Insufficient permissions to specify legacy type"); + if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) { + throw new SecurityException("Insufficient permissions to specify legacy type"); + } } final int callingUid = Binder.getCallingUid(); final NetworkRequest.Type type = (networkCapabilities == null) @@ -5508,7 +5520,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); final int callingUid = Binder.getCallingUid(); networkCapabilities = new NetworkCapabilities(networkCapabilities); enforceNetworkRequestPermissions(networkCapabilities); @@ -5537,7 +5549,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void releasePendingNetworkRequest(PendingIntent operation) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, getCallingUid(), 0, operation)); } @@ -5596,7 +5608,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation, @NonNull String callingPackageName) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); final int callingUid = Binder.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); @@ -5805,7 +5817,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); final String name = TextUtils.isEmpty(extraInfo) - ? nai.networkCapabilities.getSSID() : extraInfo; + ? nai.networkCapabilities.getSsid() : extraInfo; if (DBG) log("registerNetworkAgent " + nai); final long token = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/ExplicitHealthCheckController.java b/services/core/java/com/android/server/ExplicitHealthCheckController.java index f7c4aac2e04f..77059d918052 100644 --- a/services/core/java/com/android/server/ExplicitHealthCheckController.java +++ b/services/core/java/com/android/server/ExplicitHealthCheckController.java @@ -47,6 +47,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.function.Consumer; @@ -113,9 +114,9 @@ class ExplicitHealthCheckController { Slog.wtf(TAG, "Resetting health check controller callbacks"); } - mPassedConsumer = Preconditions.checkNotNull(passedConsumer); - mSupportedConsumer = Preconditions.checkNotNull(supportedConsumer); - mNotifySyncRunnable = Preconditions.checkNotNull(notifySyncRunnable); + mPassedConsumer = Objects.requireNonNull(passedConsumer); + mSupportedConsumer = Objects.requireNonNull(supportedConsumer); + mNotifySyncRunnable = Objects.requireNonNull(notifySyncRunnable); } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 424407a957eb..905c489e1dcb 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -25,8 +25,6 @@ import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; @@ -575,7 +573,7 @@ public class IpSecService extends IIpSecService.Stub { } void put(int key, RefcountedResource<T> obj) { - checkNotNull(obj, "Null resources cannot be added"); + Objects.requireNonNull(obj, "Null resources cannot be added"); mArray.put(key, obj); } @@ -1114,7 +1112,7 @@ public class IpSecService extends IIpSecService.Stub { if (requestedSpi > 0 && requestedSpi < 256) { throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255."); } - checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); + Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); @@ -1231,7 +1229,7 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Specified port number must be a valid non-reserved UDP port"); } - checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); + Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); @@ -1291,8 +1289,8 @@ public class IpSecService extends IIpSecService.Stub { String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, String callingPackage) { enforceTunnelFeatureAndPermissions(callingPackage); - checkNotNull(binder, "Null Binder passed to createTunnelInterface"); - checkNotNull(underlyingNetwork, "No underlying network was specified"); + Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface"); + Objects.requireNonNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); checkInetAddress(remoteAddr); @@ -1573,7 +1571,7 @@ public class IpSecService extends IIpSecService.Stub { "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS"); } - checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); + Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels"); // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS @@ -1642,12 +1640,12 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized IpSecTransformResponse createTransform( IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { - checkNotNull(c); + Objects.requireNonNull(c); if (c.getMode() == IpSecTransform.MODE_TUNNEL) { enforceTunnelFeatureAndPermissions(callingPackage); } checkIpSecConfig(c); - checkNotNull(binder, "Null Binder passed to createTransform"); + Objects.requireNonNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 90e467034e6a..f4b769f5b11b 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -25,7 +25,6 @@ import static android.location.LocationProvider.AVAILABLE; import static android.os.PowerManager.locationPowerSaveModeToString; import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS; -import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.Preconditions.checkState; import android.Manifest; @@ -133,6 +132,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.NoSuchElementException; import java.util.function.Consumer; import java.util.function.Function; @@ -986,7 +986,7 @@ public class LocationManagerService extends ILocationManager.Stub { @GuardedBy("mLock") public void attachLocked(AbstractLocationProvider provider) { - checkNotNull(provider); + Objects.requireNonNull(provider); checkState(mProvider == null); if (D) { diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java index ad02aad6e4cd..eac767f7355c 100644 --- a/services/core/java/com/android/server/NativeDaemonConnector.java +++ b/services/core/java/com/android/server/NativeDaemonConnector.java @@ -46,6 +46,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.LinkedList; +import java.util.Objects; /** * Generic connector class for interfacing with a native daemon which uses the @@ -126,7 +127,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ public void setWarnIfHeld(Object warnIfHeld) { Preconditions.checkState(mWarnIfHeld == null); - mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld); + mWarnIfHeld = Objects.requireNonNull(warnIfHeld); } @Override diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 7d6ae21a830b..1bb3c3ac0cda 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -111,6 +111,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * @hide @@ -458,7 +459,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { @Override public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) { NetworkStack.checkNetworkStackPermission(mContext); - Preconditions.checkNotNull(provider); + Objects.requireNonNull(provider); synchronized(mTetheringStatsProviders) { mTetheringStatsProviders.put(provider, name); } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 39ad3546e452..ba1d8ac31bc4 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -1934,7 +1934,7 @@ class StorageManagerService extends IStorageManager.Stub public void setVolumeNickname(String fsUuid, String nickname) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - Preconditions.checkNotNull(fsUuid); + Objects.requireNonNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); rec.nickname = nickname; @@ -1947,7 +1947,7 @@ class StorageManagerService extends IStorageManager.Stub public void setVolumeUserFlags(String fsUuid, int flags, int mask) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - Preconditions.checkNotNull(fsUuid); + Objects.requireNonNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); @@ -1960,7 +1960,7 @@ class StorageManagerService extends IStorageManager.Stub public void forgetVolume(String fsUuid) { enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); - Preconditions.checkNotNull(fsUuid); + Objects.requireNonNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.remove(fsUuid); @@ -2361,7 +2361,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public String getMountedObbPath(String rawPath) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); warnOnNotMounted(); @@ -2379,7 +2379,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public boolean isObbMounted(String rawPath) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); synchronized (mObbMounts) { return mObbPathToStateMap.containsKey(rawPath); } @@ -2388,10 +2388,10 @@ class StorageManagerService extends IStorageManager.Stub @Override public void mountObb(String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce, ObbInfo obbInfo) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); - Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null"); - Preconditions.checkNotNull(token, "token cannot be null"); - Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(canonicalPath, "canonicalPath cannot be null"); + Objects.requireNonNull(token, "token cannot be null"); + Objects.requireNonNull(obbInfo, "obbIfno cannot be null"); final int callingUid = Binder.getCallingUid(); final ObbState obbState = new ObbState(rawPath, canonicalPath, @@ -2405,7 +2405,7 @@ class StorageManagerService extends IStorageManager.Stub @Override public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) { - Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Objects.requireNonNull(rawPath, "rawPath cannot be null"); final ObbState existingState; synchronized (mObbMounts) { diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java index ff6a5375565a..ba829381b9d4 100644 --- a/services/core/java/com/android/server/SystemServerInitThreadPool.java +++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java @@ -26,6 +26,7 @@ import com.android.server.am.ActivityManagerService; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index d54bacc6cf27..ac897e464659 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -168,14 +168,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { @Override public String toString() { - return "{callingPackage=" + callingPackage + " binder=" + binder - + " callback=" + callback + return "{callingPackage=" + pii(callingPackage) + " callerUid=" + callerUid + " binder=" + + binder + " callback=" + callback + " onSubscriptionsChangedListenererCallback=" + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" - + onOpportunisticSubscriptionsChangedListenerCallback - + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId - + " events=" + Integer.toHexString(events) + "}"; + + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId + + " phoneId=" + phoneId + " events=" + Integer.toHexString(events) + "}"; } } @@ -598,9 +597,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); if (VDBG) { - log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId() - + " callerUserId=" + callerUserId + " callback=" + callback - + " callback.asBinder=" + callback.asBinder()); + log("listen oscl: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() + + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId + + " callback=" + callback + " callback.asBinder=" + callback.asBinder()); } synchronized (mRecords) { @@ -652,9 +651,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); if (VDBG) { - log("listen ooscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId() - + " callerUserId=" + callerUserId + " callback=" + callback - + " callback.asBinder=" + callback.asBinder()); + log("listen ooscl: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() + + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId + + " callback=" + callback + " callback.asBinder=" + callback.asBinder()); } synchronized (mRecords) { @@ -769,9 +768,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { IPhoneStateListener callback, int events, boolean notifyNow, int subId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - String str = "listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events) - + " notifyNow=" + notifyNow + " subId=" + subId + " myUserId=" - + UserHandle.myUserId() + " callerUserId=" + callerUserId; + String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() + + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId=" + + subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId; mListenLog.log(str); if (VDBG) { log(str); @@ -2935,4 +2934,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (info == null) return INVALID_SIM_SLOT_INDEX; return info.getSimSlotIndex(); } + + /** + * On certain build types, we should redact information by default. UID information will be + * preserved in the same log line, so no debugging capability is lost in full bug reports. + * However, privacy-constrained bug report types (e.g. connectivity) cannot display raw + * package names on user builds as it's considered an information leak. + */ + private static String pii(String packageName) { + return Build.IS_DEBUGGABLE ? packageName : "***"; + } } diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 5059a4861a7b..7c8fb5aefd1e 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -220,9 +220,9 @@ public class KeepaliveTracker { + " network=" + mNai.network + " startedState=" + startedStateString(mStartedState) + " " - + IpUtils.addressAndPortToString(mPacket.srcAddress, mPacket.srcPort) + + IpUtils.addressAndPortToString(mPacket.getSrcAddress(), mPacket.getSrcPort()) + "->" - + IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort) + + IpUtils.addressAndPortToString(mPacket.getDstAddress(), mPacket.getDstPort()) + " interval=" + mInterval + " uid=" + mUid + " pid=" + mPid + " privileged=" + mPrivileged + " packetData=" + HexDump.toHexString(mPacket.getPacket()) @@ -250,7 +250,7 @@ public class KeepaliveTracker { private int checkSourceAddress() { // Check that we have the source address. for (InetAddress address : mNai.linkProperties.getAddresses()) { - if (address.equals(mPacket.srcAddress)) { + if (address.equals(mPacket.getSrcAddress())) { return SUCCESS; } } @@ -619,7 +619,7 @@ public class KeepaliveTracker { packet = NattKeepalivePacketData.nattKeepalivePacket( srcAddress, srcPort, dstAddress, NATT_PORT); } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.error); + notifyErrorCallback(cb, e.getError()); return; } KeepaliveInfo ki = null; @@ -662,7 +662,7 @@ public class KeepaliveTracker { notifyErrorCallback(cb, e.error); return; } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.error); + notifyErrorCallback(cb, e.getError()); return; } KeepaliveInfo ki = null; diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 0925de8f9577..34b0aa246433 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -150,7 +150,7 @@ public class NetworkNotificationManager { if (nai != null) { transportType = approximateTransportType(nai); final String extraInfo = nai.networkInfo.getExtraInfo(); - name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSSID() : extraInfo; + name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSsid() : extraInfo; // Only notify for Internet-capable networks. if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) return; } else { @@ -183,14 +183,14 @@ public class NetworkNotificationManager { int icon = getIcon(transportType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { if (transportType == TRANSPORT_CELLULAR) { title = r.getString(R.string.mobile_no_internet); } else if (transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); } else { title = r.getString(R.string.other_networks_no_internet); } @@ -198,19 +198,19 @@ public class NetworkNotificationManager { } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.network_partial_connectivity, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.network_partial_connectivity_detailed); } else if (notifyType == NotificationType.LOST_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); break; case TRANSPORT_CELLULAR: title = r.getString(R.string.network_available_sign_in, 0); diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index 0ab1a3e916e3..4be4c896cbff 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -10,3 +10,4 @@ roosa@google.com erosky@google.com riddlehsu@google.com louischang@google.com +winsonc@google.com diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java index fcf3a56de448..c0c386b3046e 100644 --- a/services/net/java/android/net/TcpKeepalivePacketData.java +++ b/services/net/java/android/net/TcpKeepalivePacketData.java @@ -152,10 +152,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce public boolean equals(@Nullable final Object o) { if (!(o instanceof TcpKeepalivePacketData)) return false; final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o; - return this.srcAddress.equals(other.srcAddress) - && this.dstAddress.equals(other.dstAddress) - && this.srcPort == other.srcPort - && this.dstPort == other.dstPort + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort() && this.tcpAck == other.tcpAck && this.tcpSeq == other.tcpSeq && this.tcpWnd == other.tcpWnd @@ -166,8 +168,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce @Override public int hashCode() { - return Objects.hash(srcAddress, dstAddress, srcPort, dstPort, tcpAck, tcpSeq, tcpWnd, - tcpWndScale, ipTos, ipTtl); + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(), + tcpAck, tcpSeq, tcpWnd, tcpWndScale, ipTos, ipTtl); } /** @@ -182,10 +184,10 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce /** Write to parcel. */ public void writeToParcel(Parcel out, int flags) { - out.writeString(srcAddress.getHostAddress()); - out.writeString(dstAddress.getHostAddress()); - out.writeInt(srcPort); - out.writeInt(dstPort); + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); out.writeByteArray(getPacket()); out.writeInt(tcpSeq); out.writeInt(tcpAck); @@ -219,7 +221,7 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce return readFromParcel(in); } catch (InvalidPacketException e) { throw new IllegalArgumentException( - "Invalid NAT-T keepalive data: " + e.error); + "Invalid NAT-T keepalive data: " + e.getError()); } } @@ -234,10 +236,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce @NonNull public TcpKeepalivePacketDataParcelable toStableParcelable() { final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable(); + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); parcel.srcAddress = srcAddress.getAddress(); - parcel.srcPort = srcPort; + parcel.srcPort = getSrcPort(); parcel.dstAddress = dstAddress.getAddress(); - parcel.dstPort = dstPort; + parcel.dstPort = getDstPort(); parcel.seq = tcpSeq; parcel.ack = tcpAck; parcel.rcvWnd = tcpWnd; @@ -249,10 +253,10 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce @Override public String toString() { - return "saddr: " + srcAddress - + " daddr: " + dstAddress - + " sport: " + srcPort - + " dport: " + dstPort + return "saddr: " + getSrcAddress() + + " daddr: " + getDstAddress() + + " sport: " + getSrcPort() + + " dport: " + getDstPort() + " seq: " + tcpSeq + " ack: " + tcpAck + " wnd: " + tcpWnd diff --git a/services/net/java/android/net/util/KeepalivePacketDataUtil.java b/services/net/java/android/net/util/KeepalivePacketDataUtil.java index 9a51729212f7..4466ea0abe0e 100644 --- a/services/net/java/android/net/util/KeepalivePacketDataUtil.java +++ b/services/net/java/android/net/util/KeepalivePacketDataUtil.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.net.NattKeepalivePacketData; import android.net.NattKeepalivePacketDataParcelable; +import java.net.InetAddress; + /** @hide */ public final class KeepalivePacketDataUtil { /** @@ -29,11 +31,12 @@ public final class KeepalivePacketDataUtil { public static NattKeepalivePacketDataParcelable toStableParcelable( NattKeepalivePacketData pkt) { final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable(); - - parcel.srcAddress = pkt.srcAddress.getAddress(); - parcel.srcPort = pkt.srcPort; - parcel.dstAddress = pkt.dstAddress.getAddress(); - parcel.dstPort = pkt.dstPort; + final InetAddress srcAddress = pkt.getSrcAddress(); + final InetAddress dstAddress = pkt.getDstAddress(); + parcel.srcAddress = srcAddress.getAddress(); + parcel.srcPort = pkt.getSrcPort(); + parcel.dstAddress = dstAddress.getAddress(); + parcel.dstPort = pkt.getDstPort(); return parcel; } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 8d6120c3a771..c37262c6d2cc 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -12157,6 +12157,17 @@ public class TelephonyManager { "android.telephony.extra.NETWORK_COUNTRY"; /** + * The extra used with an {@link #ACTION_NETWORK_COUNTRY_CHANGED} to specify the + * last known the country code in ISO-3166-1 alpha-2 format. + * <p class="note"> + * Retrieve with {@link android.content.Intent#getStringExtra(String)}. + * + * @hide + */ + public static final String EXTRA_LAST_KNOWN_NETWORK_COUNTRY = + "android.telephony.extra.LAST_KNOWN_NETWORK_COUNTRY"; + + /** * Indicate if the user is allowed to use multiple SIM cards at the same time to register * on the network (e.g. Dual Standby or Dual Active) when the device supports it, or if the * usage is restricted. This API is used to prevent usage of multiple SIM card, based on diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 2b5720a47eb6..8de27e8eb281 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -445,14 +445,20 @@ public class LinkPropertiesTest { // Check comparisons work. LinkProperties lp2 = new LinkProperties(lp); assertAllRoutesHaveInterface("wlan0", lp2); - assertEquals(0, lp.compareAllRoutes(lp2).added.size()); - assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); + // LinkProperties#compareAllRoutes exists both in R and before R, but the return type + // changed in R, so a test compiled with the R version of LinkProperties cannot run on Q. + if (isAtLeastR()) { + assertEquals(0, lp.compareAllRoutes(lp2).added.size()); + assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); + } lp2.setInterfaceName("p2p0"); assertAllRoutesHaveInterface("p2p0", lp2); assertAllRoutesNotHaveInterface("wlan0", lp2); - assertEquals(3, lp.compareAllRoutes(lp2).added.size()); - assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); + if (isAtLeastR()) { + assertEquals(3, lp.compareAllRoutes(lp2).added.size()); + assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); + } // Remove route with incorrect interface, no route removed. lp.removeRoute(new RouteInfo(prefix2, null, null)); @@ -480,6 +486,8 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); + assertEquals(1, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); rmnet0.addStackedLink(clat4); assertEquals(1, rmnet0.getStackedLinks().size()); @@ -487,6 +495,9 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(2, rmnet0.getAllAddresses().size()); assertEquals(2, rmnet0.getAllLinkAddresses().size()); + assertEquals(2, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); + assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); rmnet0.addStackedLink(clat4); assertEquals(1, rmnet0.getStackedLinks().size()); @@ -494,6 +505,9 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(2, rmnet0.getAllAddresses().size()); assertEquals(2, rmnet0.getAllLinkAddresses().size()); + assertEquals(2, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); + assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); assertEquals(0, clat4.getStackedLinks().size()); @@ -513,6 +527,8 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); + assertEquals(1, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); assertFalse(rmnet0.removeStackedLink("clat4")); } @@ -936,7 +952,7 @@ public class LinkPropertiesTest { } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testCompareResult() { // Either adding or removing items compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1), @@ -1197,4 +1213,48 @@ public class LinkPropertiesTest { lp.clear(); assertNull(lp.getCaptivePortalData()); } + + private LinkProperties makeIpv4LinkProperties() { + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(NAME); + linkProperties.addLinkAddress(LINKADDRV4); + linkProperties.addDnsServer(DNS1); + linkProperties.addRoute(new RouteInfo(GATEWAY1)); + linkProperties.addRoute(new RouteInfo(GATEWAY2)); + return linkProperties; + } + + private LinkProperties makeIpv6LinkProperties() { + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(NAME); + linkProperties.addLinkAddress(LINKADDRV6); + linkProperties.addDnsServer(DNS6); + linkProperties.addRoute(new RouteInfo(GATEWAY61)); + linkProperties.addRoute(new RouteInfo(GATEWAY62)); + return linkProperties; + } + + @Test + public void testHasIpv4DefaultRoute() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertTrue(Ipv4.hasIpv4DefaultRoute()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertFalse(Ipv6.hasIpv4DefaultRoute()); + } + + @Test + public void testHasIpv4DnsServer() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertTrue(Ipv4.hasIpv4DnsServer()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertFalse(Ipv6.hasIpv4DnsServer()); + } + + @Test + public void testHasIpv6DnsServer() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertFalse(Ipv4.hasIpv6DnsServer()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertTrue(Ipv6.hasIpv6DnsServer()); + } } diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt new file mode 100644 index 000000000000..ef15b668e24c --- /dev/null +++ b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net + +import android.net.wifi.aware.DiscoverySession +import android.net.wifi.aware.PeerHandle +import android.net.wifi.aware.WifiAwareNetworkSpecifier +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 + +import com.android.testutils.assertParcelSane + +import java.lang.IllegalStateException + +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito + +@RunWith(AndroidJUnit4::class) +@SmallTest +class MatchAllNetworkSpecifierTest { + @Test + fun testParcel() { + assertParcelSane(MatchAllNetworkSpecifier(), 0) + } + + @Test(expected = IllegalStateException::class) + fun testSatisfiedBy() { + val specifier = MatchAllNetworkSpecifier() + val discoverySession = Mockito.mock(DiscoverySession::class.java) + val peerHandle = Mockito.mock(PeerHandle::class.java) + val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, + peerHandle).build() + specifier.satisfiedBy(wifiAwareNetworkSpecifier) + } +} diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 9fe1883010b7..916c33981171 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -463,7 +463,9 @@ public class NetworkCapabilitiesTest { nc1.setSSID(TEST_SSID); nc2.combineCapabilities(nc1); - assertTrue(TEST_SSID.equals(nc2.getSSID())); + if (isAtLeastR()) { + assertTrue(TEST_SSID.equals(nc2.getSsid())); + } // Because they now have the same SSID, the following call should not throw nc2.combineCapabilities(nc1); @@ -601,12 +603,16 @@ public class NetworkCapabilitiesTest { // from nc2. assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING)); - assertTrue(TEST_SSID.equals(nc2.getSSID())); + if (isAtLeastR()) { + assertTrue(TEST_SSID.equals(nc2.getSsid())); + } nc1.setSSID(DIFFERENT_TEST_SSID); nc2.set(nc1); assertEquals(nc1, nc2); - assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSSID())); + if (isAtLeastR()) { + assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); + } nc1.setUids(uidRange(10, 13)); nc2.set(nc1); // Overwrites, as opposed to combineCapabilities diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index 23caf4952991..eec3cdbe8d7f 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt @@ -24,7 +24,6 @@ import android.net.Network import android.net.metrics.IpConnectivityLog import android.net.util.SharedLog import android.os.IBinder -import com.android.networkstack.metrics.DataStallStatsUtils import com.android.networkstack.netlink.TcpSocketTracker import com.android.server.NetworkStackService import com.android.server.NetworkStackService.NetworkMonitorConnector @@ -91,7 +90,6 @@ class TestNetworkStackService : Service() { mock(IpConnectivityLog::class.java), mock(SharedLog::class.java), mock(NetworkStackService.NetworkStackServiceManager::class.java), NetworkMonitorDeps(privateDnsBypassNetwork), - mock(DataStallStatsUtils::class.java), mock(TcpSocketTracker::class.java)) cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker())) } diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index e632aafde70e..cea8c5713a6b 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -66,10 +66,10 @@ public final class TcpKeepalivePacketDataTest { fail("InvalidPacketException: " + e); } - assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress); - assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress); - assertEquals(testInfo.srcPort, resultData.srcPort); - assertEquals(testInfo.dstPort, resultData.dstPort); + assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.getSrcAddress()); + assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.getDstAddress()); + assertEquals(testInfo.srcPort, resultData.getSrcPort()); + assertEquals(testInfo.dstPort, resultData.getDstPort()); assertEquals(testInfo.seq, resultData.tcpSeq); assertEquals(testInfo.ack, resultData.tcpAck); assertEquals(testInfo.rcvWnd, resultData.tcpWnd); |