Merge "Add MM#6 string overlay"
diff --git a/api/current.txt b/api/current.txt
index df4f8b7..bd33681 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -40500,11 +40500,10 @@
}
public static class DownloadRequest.Builder {
- ctor public DownloadRequest.Builder();
+ ctor public DownloadRequest.Builder(android.net.Uri);
method public android.telephony.mbms.DownloadRequest build();
method public android.telephony.mbms.DownloadRequest.Builder setAppIntent(android.content.Intent);
method public android.telephony.mbms.DownloadRequest.Builder setServiceInfo(android.telephony.mbms.FileServiceInfo);
- method public android.telephony.mbms.DownloadRequest.Builder setSource(android.net.Uri);
method public android.telephony.mbms.DownloadRequest.Builder setSubscriptionId(int);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 16fa870..2a002a5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -44017,13 +44017,12 @@
}
public static class DownloadRequest.Builder {
- ctor public DownloadRequest.Builder();
+ ctor public DownloadRequest.Builder(android.net.Uri);
method public android.telephony.mbms.DownloadRequest build();
method public android.telephony.mbms.DownloadRequest.Builder setAppIntent(android.content.Intent);
method public android.telephony.mbms.DownloadRequest.Builder setOpaqueData(byte[]);
method public android.telephony.mbms.DownloadRequest.Builder setServiceId(java.lang.String);
method public android.telephony.mbms.DownloadRequest.Builder setServiceInfo(android.telephony.mbms.FileServiceInfo);
- method public android.telephony.mbms.DownloadRequest.Builder setSource(android.net.Uri);
method public android.telephony.mbms.DownloadRequest.Builder setSubscriptionId(int);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index cf8b8b3..23648b6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -40722,11 +40722,10 @@
}
public static class DownloadRequest.Builder {
- ctor public DownloadRequest.Builder();
+ ctor public DownloadRequest.Builder(android.net.Uri);
method public android.telephony.mbms.DownloadRequest build();
method public android.telephony.mbms.DownloadRequest.Builder setAppIntent(android.content.Intent);
method public android.telephony.mbms.DownloadRequest.Builder setServiceInfo(android.telephony.mbms.FileServiceInfo);
- method public android.telephony.mbms.DownloadRequest.Builder setSource(android.net.Uri);
method public android.telephony.mbms.DownloadRequest.Builder setSubscriptionId(int);
}
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index ead406c..79310e2 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -24,6 +24,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
/**
* IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to
@@ -75,13 +76,7 @@
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
/** @hide */
- @StringDef({
- CRYPT_AES_CBC,
- AUTH_HMAC_MD5,
- AUTH_HMAC_SHA1,
- AUTH_HMAC_SHA256,
- AUTH_HMAC_SHA512
- })
+ @StringDef({CRYPT_AES_CBC, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA512})
@Retention(RetentionPolicy.SOURCE)
public @interface AlgorithmName {}
@@ -197,4 +192,12 @@
.append("}")
.toString();
}
+
+ /** package */
+ static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) {
+ if (lhs == null || rhs == null) return (lhs == rhs);
+ return (lhs.mName.equals(rhs.mName)
+ && Arrays.equals(lhs.mKey, rhs.mKey)
+ && lhs.mTruncLenBits == rhs.mTruncLenBits);
+ }
};
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 5a5c740..632b7fc 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -17,105 +17,170 @@
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+
+import com.android.internal.annotations.VisibleForTesting;
/** @hide */
public final class IpSecConfig implements Parcelable {
private static final String TAG = "IpSecConfig";
- //MODE_TRANSPORT or MODE_TUNNEL
- int mode;
+ // MODE_TRANSPORT or MODE_TUNNEL
+ private int mMode = IpSecTransform.MODE_TRANSPORT;
- // For tunnel mode
- InetAddress localAddress;
+ // Needs to be valid only for tunnel mode
+ // Preventing this from being null simplifies Java->Native binder
+ private String mLocalAddress = "";
- InetAddress remoteAddress;
+ // Preventing this from being null simplifies Java->Native binder
+ private String mRemoteAddress = "";
- // Limit selection by network interface
- Network network;
+ // The underlying Network that represents the "gateway" Network
+ // for outbound packets. It may also be used to select packets.
+ private Network mNetwork;
public static class Flow {
// Minimum requirements for identifying a transform
// SPI identifying the IPsec flow in packet processing
// and a remote IP address
- int spiResourceId;
+ private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID;
// Encryption Algorithm
- IpSecAlgorithm encryption;
+ private IpSecAlgorithm mEncryption;
// Authentication Algorithm
- IpSecAlgorithm authentication;
+ private IpSecAlgorithm mAuthentication;
@Override
public String toString() {
return new StringBuilder()
- .append("{spiResourceId=")
- .append(spiResourceId)
- .append(", encryption=")
- .append(encryption)
- .append(", authentication=")
- .append(authentication)
+ .append("{mSpiResourceId=")
+ .append(mSpiResourceId)
+ .append(", mEncryption=")
+ .append(mEncryption)
+ .append(", mAuthentication=")
+ .append(mAuthentication)
.append("}")
.toString();
}
+
+ static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) {
+ if (lhs == null || rhs == null) return (lhs == rhs);
+ return (lhs.mSpiResourceId == rhs.mSpiResourceId
+ && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption)
+ && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication));
+ }
}
- final Flow[] flow = new Flow[] {new Flow(), new Flow()};
+ private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()};
// For tunnel mode IPv4 UDP Encapsulation
// IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE
- int encapType;
- int encapLocalPortResourceId;
- int encapRemotePort;
+ private int mEncapType = IpSecTransform.ENCAP_NONE;
+ private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID;
+ private int mEncapRemotePort;
// An interval, in seconds between the NattKeepalive packets
- int nattKeepaliveInterval;
+ private int mNattKeepaliveInterval;
+
+ /** Set the mode for this IPsec transform */
+ public void setMode(int mode) {
+ mMode = mode;
+ }
+
+ /** Set the local IP address for Tunnel mode */
+ public void setLocalAddress(String localAddress) {
+ if (localAddress == null) {
+ throw new IllegalArgumentException("localAddress may not be null!");
+ }
+ mLocalAddress = localAddress;
+ }
+
+ /** Set the remote IP address for this IPsec transform */
+ public void setRemoteAddress(String remoteAddress) {
+ if (remoteAddress == null) {
+ throw new IllegalArgumentException("remoteAddress may not be null!");
+ }
+ mRemoteAddress = remoteAddress;
+ }
+
+ /** Set the SPI for a given direction by resource ID */
+ public void setSpiResourceId(int direction, int resourceId) {
+ mFlow[direction].mSpiResourceId = resourceId;
+ }
+
+ /** Set the encryption algorithm for a given direction */
+ public void setEncryption(int direction, IpSecAlgorithm encryption) {
+ mFlow[direction].mEncryption = encryption;
+ }
+
+ /** Set the authentication algorithm for a given direction */
+ public void setAuthentication(int direction, IpSecAlgorithm authentication) {
+ mFlow[direction].mAuthentication = authentication;
+ }
+
+ public void setNetwork(Network network) {
+ mNetwork = network;
+ }
+
+ public void setEncapType(int encapType) {
+ mEncapType = encapType;
+ }
+
+ public void setEncapSocketResourceId(int resourceId) {
+ mEncapSocketResourceId = resourceId;
+ }
+
+ public void setEncapRemotePort(int port) {
+ mEncapRemotePort = port;
+ }
+
+ public void setNattKeepaliveInterval(int interval) {
+ mNattKeepaliveInterval = interval;
+ }
// Transport or Tunnel
public int getMode() {
- return mode;
+ return mMode;
}
- public InetAddress getLocalAddress() {
- return localAddress;
+ public String getLocalAddress() {
+ return mLocalAddress;
}
public int getSpiResourceId(int direction) {
- return flow[direction].spiResourceId;
+ return mFlow[direction].mSpiResourceId;
}
- public InetAddress getRemoteAddress() {
- return remoteAddress;
+ public String getRemoteAddress() {
+ return mRemoteAddress;
}
public IpSecAlgorithm getEncryption(int direction) {
- return flow[direction].encryption;
+ return mFlow[direction].mEncryption;
}
public IpSecAlgorithm getAuthentication(int direction) {
- return flow[direction].authentication;
+ return mFlow[direction].mAuthentication;
}
public Network getNetwork() {
- return network;
+ return mNetwork;
}
public int getEncapType() {
- return encapType;
+ return mEncapType;
}
- public int getEncapLocalResourceId() {
- return encapLocalPortResourceId;
+ public int getEncapSocketResourceId() {
+ return mEncapSocketResourceId;
}
public int getEncapRemotePort() {
- return encapRemotePort;
+ return mEncapRemotePort;
}
public int getNattKeepaliveInterval() {
- return nattKeepaliveInterval;
+ return mNattKeepaliveInterval;
}
// Parcelable Methods
@@ -127,82 +192,70 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- // TODO: Use a byte array or other better method for storing IPs that can also include scope
- out.writeString((localAddress != null) ? localAddress.getHostAddress() : null);
- // TODO: Use a byte array or other better method for storing IPs that can also include scope
- out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null);
- out.writeParcelable(network, flags);
- out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags);
- out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags);
- out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags);
- out.writeInt(encapType);
- out.writeInt(encapLocalPortResourceId);
- out.writeInt(encapRemotePort);
+ out.writeInt(mMode);
+ out.writeString(mLocalAddress);
+ out.writeString(mRemoteAddress);
+ out.writeParcelable(mNetwork, flags);
+ out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags);
+ out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags);
+ out.writeInt(mEncapType);
+ out.writeInt(mEncapSocketResourceId);
+ out.writeInt(mEncapRemotePort);
+ out.writeInt(mNattKeepaliveInterval);
}
- // Package Private: Used by the IpSecTransform.Builder;
- // there should be no public constructor for this object
- IpSecConfig() {}
-
- private static InetAddress readInetAddressFromParcel(Parcel in) {
- String addrString = in.readString();
- if (addrString == null) {
- return null;
- }
- try {
- return InetAddress.getByName(addrString);
- } catch (UnknownHostException e) {
- Log.wtf(TAG, "Invalid IpAddress " + addrString);
- return null;
- }
- }
+ @VisibleForTesting
+ public IpSecConfig() {}
private IpSecConfig(Parcel in) {
- localAddress = readInetAddressFromParcel(in);
- remoteAddress = readInetAddressFromParcel(in);
- network = (Network) in.readParcelable(Network.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt();
- flow[IpSecTransform.DIRECTION_IN].encryption =
+ mMode = in.readInt();
+ mLocalAddress = in.readString();
+ mRemoteAddress = in.readString();
+ mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
+ mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt();
+ mFlow[IpSecTransform.DIRECTION_IN].mEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_IN].authentication =
+ mFlow[IpSecTransform.DIRECTION_IN].mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt();
- flow[IpSecTransform.DIRECTION_OUT].encryption =
+ mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt();
+ mFlow[IpSecTransform.DIRECTION_OUT].mEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- flow[IpSecTransform.DIRECTION_OUT].authentication =
+ mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
- encapType = in.readInt();
- encapLocalPortResourceId = in.readInt();
- encapRemotePort = in.readInt();
+ mEncapType = in.readInt();
+ mEncapSocketResourceId = in.readInt();
+ mEncapRemotePort = in.readInt();
+ mNattKeepaliveInterval = in.readInt();
}
@Override
public String toString() {
StringBuilder strBuilder = new StringBuilder();
strBuilder
- .append("{mode=")
- .append(mode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
- .append(", localAddress=")
- .append(localAddress)
- .append(", remoteAddress=")
- .append(remoteAddress)
- .append(", network=")
- .append(network)
- .append(", encapType=")
- .append(encapType)
- .append(", encapLocalPortResourceId=")
- .append(encapLocalPortResourceId)
- .append(", encapRemotePort=")
- .append(encapRemotePort)
- .append(", nattKeepaliveInterval=")
- .append(nattKeepaliveInterval)
- .append(", flow[OUT]=")
- .append(flow[IpSecTransform.DIRECTION_OUT])
- .append(", flow[IN]=")
- .append(flow[IpSecTransform.DIRECTION_IN])
+ .append("{mMode=")
+ .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT")
+ .append(", mLocalAddress=")
+ .append(mLocalAddress)
+ .append(", mRemoteAddress=")
+ .append(mRemoteAddress)
+ .append(", mNetwork=")
+ .append(mNetwork)
+ .append(", mEncapType=")
+ .append(mEncapType)
+ .append(", mEncapSocketResourceId=")
+ .append(mEncapSocketResourceId)
+ .append(", mEncapRemotePort=")
+ .append(mEncapRemotePort)
+ .append(", mNattKeepaliveInterval=")
+ .append(mNattKeepaliveInterval)
+ .append(", mFlow[OUT]=")
+ .append(mFlow[IpSecTransform.DIRECTION_OUT])
+ .append(", mFlow[IN]=")
+ .append(mFlow[IpSecTransform.DIRECTION_IN])
.append("}");
return strBuilder.toString();
@@ -218,4 +271,23 @@
return new IpSecConfig[size];
}
};
+
+ @VisibleForTesting
+ /** Equals method used for testing */
+ public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) {
+ if (lhs == null || rhs == null) return (lhs == rhs);
+ return (lhs.mMode == rhs.mMode
+ && lhs.mLocalAddress.equals(rhs.mLocalAddress)
+ && lhs.mRemoteAddress.equals(rhs.mRemoteAddress)
+ && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork))
+ || (lhs.mNetwork == rhs.mNetwork))
+ && lhs.mEncapType == rhs.mEncapType
+ && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId
+ && lhs.mEncapRemotePort == rhs.mEncapRemotePort
+ && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval
+ && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT],
+ rhs.mFlow[IpSecTransform.DIRECTION_OUT])
+ && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN],
+ rhs.mFlow[IpSecTransform.DIRECTION_IN]));
+ }
}
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index d7908c8..d7b3256 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -26,6 +26,8 @@
import android.util.AndroidException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
@@ -188,7 +190,8 @@
}
/** @hide */
- int getResourceId() {
+ @VisibleForTesting
+ public int getResourceId() {
return mResourceId;
}
}
@@ -489,7 +492,8 @@
}
/** @hide */
- int getResourceId() {
+ @VisibleForTesting
+ public int getResourceId() {
return mResourceId;
}
};
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 62fd65b..e15a2c6 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -68,10 +68,10 @@
public @interface TransformDirection {}
/** @hide */
- public static final int MODE_TUNNEL = 0;
+ public static final int MODE_TRANSPORT = 0;
/** @hide */
- public static final int MODE_TRANSPORT = 1;
+ public static final int MODE_TUNNEL = 1;
/** @hide */
public static final int ENCAP_NONE = 0;
@@ -113,7 +113,11 @@
return IIpSecService.Stub.asInterface(b);
}
- private void checkResultStatusAndThrow(int status)
+ /**
+ * Checks the result status and throws an appropriate exception if
+ * the status is not Status.OK.
+ */
+ private void checkResultStatus(int status)
throws IOException, IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException {
switch (status) {
@@ -141,7 +145,7 @@
IpSecTransformResponse result =
svc.createTransportModeTransform(mConfig, new Binder());
int status = result.status;
- checkResultStatusAndThrow(status);
+ checkResultStatus(status);
mResourceId = result.resourceId;
/* Keepalive will silently fail if not needed by the config; but, if needed and
@@ -243,61 +247,20 @@
/* Package */
void startKeepalive(Context c) {
- // FIXME: NO_KEEPALIVE needs to be a constant
- if (mConfig.getNattKeepaliveInterval() == 0) {
- return;
- }
-
- ConnectivityManager cm =
- (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
-
- if (mKeepalive != null) {
- Log.wtf(TAG, "Keepalive already started for this IpSecTransform.");
- return;
- }
-
- synchronized (mKeepaliveSyncLock) {
- mKeepalive =
- cm.startNattKeepalive(
- mConfig.getNetwork(),
- mConfig.getNattKeepaliveInterval(),
- mKeepaliveCallback,
- mConfig.getLocalAddress(),
- 0x1234, /* FIXME: get the real port number again,
- which we need to retrieve from the provided
- EncapsulationSocket, and which isn't currently
- stashed in IpSecConfig */
- mConfig.getRemoteAddress());
- try {
- // FIXME: this is still a horrible way to fudge the synchronous callback
- mKeepaliveSyncLock.wait(2000);
- } catch (InterruptedException e) {
- }
- }
- if (mKeepaliveStatus != ConnectivityManager.PacketKeepalive.SUCCESS) {
- throw new UnsupportedOperationException("Packet Keepalive cannot be started");
+ if (mConfig.getNattKeepaliveInterval() != 0) {
+ Log.wtf(TAG, "Keepalive not yet supported.");
}
}
- /* Package */
- int getResourceId() {
+ /** @hide */
+ @VisibleForTesting
+ public int getResourceId() {
return mResourceId;
}
/* Package */
void stopKeepalive() {
- if (mKeepalive == null) {
- return;
- }
- mKeepalive.stop();
- synchronized (mKeepaliveSyncLock) {
- if (mKeepaliveStatus == ConnectivityManager.PacketKeepalive.SUCCESS) {
- try {
- mKeepaliveSyncLock.wait(2000);
- } catch (InterruptedException e) {
- }
- }
- }
+ return;
}
/**
@@ -323,7 +286,7 @@
*/
public IpSecTransform.Builder setEncryption(
@TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.flow[direction].encryption = algo;
+ mConfig.setEncryption(direction, algo);
return this;
}
@@ -338,7 +301,7 @@
*/
public IpSecTransform.Builder setAuthentication(
@TransformDirection int direction, IpSecAlgorithm algo) {
- mConfig.flow[direction].authentication = algo;
+ mConfig.setAuthentication(direction, algo);
return this;
}
@@ -361,9 +324,7 @@
*/
public IpSecTransform.Builder setSpi(
@TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
- // TODO: convert to using the resource Id of the SPI. Then build() can validate
- // the owner in the IpSecService
- mConfig.flow[direction].spiResourceId = spi.getResourceId();
+ mConfig.setSpiResourceId(direction, spi.getResourceId());
return this;
}
@@ -378,7 +339,7 @@
*/
@SystemApi
public IpSecTransform.Builder setUnderlyingNetwork(Network net) {
- mConfig.network = net;
+ mConfig.setNetwork(net);
return this;
}
@@ -395,10 +356,9 @@
*/
public IpSecTransform.Builder setIpv4Encapsulation(
IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
- // TODO: check encap type is valid.
- mConfig.encapType = ENCAP_ESPINUDP;
- mConfig.encapLocalPortResourceId = localSocket.getResourceId();
- mConfig.encapRemotePort = remotePort;
+ mConfig.setEncapType(ENCAP_ESPINUDP);
+ mConfig.setEncapSocketResourceId(localSocket.getResourceId());
+ mConfig.setEncapRemotePort(remotePort);
return this;
}
@@ -416,7 +376,7 @@
*/
@SystemApi
public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
- mConfig.nattKeepaliveInterval = intervalSeconds;
+ mConfig.setNattKeepaliveInterval(intervalSeconds);
return this;
}
@@ -449,10 +409,8 @@
public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
throws IpSecManager.ResourceUnavailableException,
IpSecManager.SpiUnavailableException, IOException {
- //FIXME: argument validation here
- //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
- mConfig.mode = MODE_TRANSPORT;
- mConfig.remoteAddress = remoteAddress;
+ mConfig.setMode(MODE_TRANSPORT);
+ mConfig.setRemoteAddress(remoteAddress.getHostAddress());
return new IpSecTransform(mContext, mConfig).activate();
}
@@ -473,9 +431,9 @@
InetAddress localAddress, InetAddress remoteAddress) {
//FIXME: argument validation here
//throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
- mConfig.localAddress = localAddress;
- mConfig.remoteAddress = remoteAddress;
- mConfig.mode = MODE_TUNNEL;
+ mConfig.setLocalAddress(localAddress.getHostAddress());
+ mConfig.setRemoteAddress(remoteAddress.getHostAddress());
+ mConfig.setMode(MODE_TUNNEL);
return new IpSecTransform(mContext, mConfig);
}
@@ -489,14 +447,5 @@
mContext = context;
mConfig = new IpSecConfig();
}
-
- /**
- * Return an {@link IpSecConfig} object for testing purposes.
- * @hide
- */
- @VisibleForTesting
- public IpSecConfig getIpSecConfig() {
- return mConfig;
- }
}
}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 2c9fb23..4e474c8 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -683,9 +683,9 @@
*/
public boolean hasIPv4Address() {
for (LinkAddress address : mLinkAddresses) {
- if (address.getAddress() instanceof Inet4Address) {
- return true;
- }
+ if (address.getAddress() instanceof Inet4Address) {
+ return true;
+ }
}
return false;
}
@@ -725,9 +725,9 @@
*/
public boolean hasIPv4DefaultRoute() {
for (RouteInfo r : mRoutes) {
- if (r.isIPv4Default()) {
- return true;
- }
+ if (r.isIPv4Default()) {
+ return true;
+ }
}
return false;
}
@@ -740,9 +740,9 @@
*/
public boolean hasIPv6DefaultRoute() {
for (RouteInfo r : mRoutes) {
- if (r.isIPv6Default()) {
- return true;
- }
+ if (r.isIPv6Default()) {
+ return true;
+ }
}
return false;
}
@@ -755,9 +755,9 @@
*/
public boolean hasIPv4DnsServer() {
for (InetAddress ia : mDnses) {
- if (ia instanceof Inet4Address) {
- return true;
- }
+ if (ia instanceof Inet4Address) {
+ return true;
+ }
}
return false;
}
@@ -770,9 +770,9 @@
*/
public boolean hasIPv6DnsServer() {
for (InetAddress ia : mDnses) {
- if (ia instanceof Inet6Address) {
- return true;
- }
+ if (ia instanceof Inet6Address) {
+ return true;
+ }
}
return false;
}
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index c091420..7f588ad 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -737,7 +737,9 @@
private void closeWithStatus(int status, String msg) {
if (mClosed) return;
mClosed = true;
- mGuard.close();
+ if (mGuard != null) {
+ mGuard.close();
+ }
// Status MUST be sent before closing actual descriptor
writeCommStatusAndClose(status, msg);
IoUtils.closeQuietly(mFd);
diff --git a/core/java/com/android/internal/os/LoggingPrintStream.java b/core/java/com/android/internal/os/LoggingPrintStream.java
index f14394a..d27874c 100644
--- a/core/java/com/android/internal/os/LoggingPrintStream.java
+++ b/core/java/com/android/internal/os/LoggingPrintStream.java
@@ -28,12 +28,15 @@
import java.util.Formatter;
import java.util.Locale;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* A print stream which logs output line by line.
*
* {@hide}
*/
-abstract class LoggingPrintStream extends PrintStream {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public abstract class LoggingPrintStream extends PrintStream {
private final StringBuilder builder = new StringBuilder();
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index 1b354d0..eabe3b9 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -91,6 +91,10 @@
return s & 0xffff;
}
+ public static int uint16(byte hi, byte lo) {
+ return ((hi & 0xff) << 8) | (lo & 0xff);
+ }
+
public static long uint32(int i) {
return i & 0xffffffffL;
}
diff --git a/core/java/com/android/internal/widget/LinearLayoutManager.java b/core/java/com/android/internal/widget/LinearLayoutManager.java
index d82c746..0000a74 100644
--- a/core/java/com/android/internal/widget/LinearLayoutManager.java
+++ b/core/java/com/android/internal/widget/LinearLayoutManager.java
@@ -168,10 +168,6 @@
/**
* Constructor used when layout manager is set in XML by RecyclerView attribute
* "layoutManager". Defaults to vertical orientation.
- *
- * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation
- * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout
- * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd
*/
public LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 18f3177..09e37e1 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -40,6 +40,7 @@
#include "android_view_InputChannel.h"
#include "android_view_KeyEvent.h"
+#include "android-base/stringprintf.h"
#include "nativebridge/native_bridge.h"
#include "nativeloader/native_loader.h"
@@ -265,6 +266,8 @@
// ------------------------------------------------------------------------
+static thread_local std::string g_error_msg;
+
static jlong
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
jobject messageQueue, jstring internalDataDir, jstring obbDir,
@@ -277,7 +280,6 @@
ScopedUtfChars pathStr(env, path);
std::unique_ptr<NativeCode> code;
bool needs_native_bridge = false;
- std::string error_msg;
void* handle = OpenNativeLibrary(env,
sdkVersion,
@@ -285,12 +287,12 @@
classLoader,
libraryPath,
&needs_native_bridge,
- &error_msg);
+ &g_error_msg);
if (handle == nullptr) {
ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s",
pathStr.c_str(),
- error_msg.c_str());
+ g_error_msg.c_str());
return 0;
}
@@ -306,19 +308,22 @@
env->ReleaseStringUTFChars(funcName, funcStr);
if (code->createActivityFunc == NULL) {
- ALOGW("ANativeActivity_onCreate not found");
+ g_error_msg = needs_native_bridge ? NativeBridgeGetError() : dlerror();
+ ALOGW("ANativeActivity_onCreate not found: %s", g_error_msg.c_str());
return 0;
}
code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
if (code->messageQueue == NULL) {
- ALOGW("Unable to retrieve native MessageQueue");
+ g_error_msg = "Unable to retrieve native MessageQueue";
+ ALOGW("%s", g_error_msg.c_str());
return 0;
}
int msgpipe[2];
if (pipe(msgpipe)) {
- ALOGW("could not create pipe: %s", strerror(errno));
+ g_error_msg = android::base::StringPrintf("could not create pipe: %s", strerror(errno));
+ ALOGW("%s", g_error_msg.c_str());
return 0;
}
code->mainWorkRead = msgpipe[0];
@@ -334,7 +339,8 @@
code->ANativeActivity::callbacks = &code->callbacks;
if (env->GetJavaVM(&code->vm) < 0) {
- ALOGW("NativeActivity GetJavaVM failed");
+ g_error_msg = "NativeActivity GetJavaVM failed";
+ ALOGW("%s", g_error_msg.c_str());
return 0;
}
code->env = env;
@@ -381,7 +387,9 @@
}
static jstring getDlError_native(JNIEnv* env, jobject clazz) {
- return env->NewStringUTF(dlerror());
+ jstring result = env->NewStringUTF(g_error_msg.c_str());
+ g_error_msg.clear();
+ return result;
}
static void
diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp
index 5c45b4b..b3bcaa0 100644
--- a/core/jni/android_app_admin_SecurityLog.cpp
+++ b/core/jni/android_app_admin_SecurityLog.cpp
@@ -14,183 +14,26 @@
* limitations under the License.
*/
-#include <fcntl.h>
-
-#include <nativehelper/JNIHelp.h>
-#include "core_jni_helpers.h"
-#include "jni.h"
+#include <log/log_id.h>
#include <private/android_logger.h>
-// The size of the tag number comes out of the payload size.
-#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+
+#include "core_jni_helpers.h"
+#include "eventlog_helper.h"
namespace android {
-static jclass gCollectionClass;
-static jmethodID gCollectionAddID;
-
-static jclass gEventClass;
-static jmethodID gEventInitID;
-
-static jclass gIntegerClass;
-static jfieldID gIntegerValueID;
-
-static jclass gLongClass;
-static jfieldID gLongValueID;
-
-static jclass gFloatClass;
-static jfieldID gFloatValueID;
-
-static jclass gStringClass;
-
+constexpr char kSecurityLogEventClass[] = "android/app/admin/SecurityLog$SecurityEvent";
+template class EventLogHelper<log_id_t::LOG_ID_SECURITY, kSecurityLogEventClass>;
+using SLog = EventLogHelper<log_id_t::LOG_ID_SECURITY, kSecurityLogEventClass>;
static jboolean android_app_admin_SecurityLog_isLoggingEnabled(JNIEnv* env,
jobject /* clazz */) {
return (bool)__android_log_security();
}
-static jint android_app_admin_SecurityLog_writeEvent_String(JNIEnv* env,
- jobject /* clazz */,
- jint tag, jstring value) {
- uint8_t buf[MAX_EVENT_PAYLOAD];
-
- // Don't throw NPE -- I feel like it's sort of mean for a logging function
- // to be all crashy if you pass in NULL -- but make the NULL value explicit.
- const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL";
- uint32_t len = strlen(str);
- size_t max = sizeof(buf) - sizeof(len) - 2; // Type byte, final newline
- if (len > max) len = max;
-
- buf[0] = EVENT_TYPE_STRING;
- memcpy(&buf[1], &len, sizeof(len));
- memcpy(&buf[1 + sizeof(len)], str, len);
- buf[1 + sizeof(len) + len] = '\n';
-
- if (value != NULL) env->ReleaseStringUTFChars(value, str);
- return __android_log_security_bwrite(tag, buf, 2 + sizeof(len) + len);
-}
-
-static jint android_app_admin_SecurityLog_writeEvent_Array(JNIEnv* env, jobject clazz,
- jint tag, jobjectArray value) {
- if (value == NULL) {
- return android_app_admin_SecurityLog_writeEvent_String(env, clazz, tag, NULL);
- }
-
- uint8_t buf[MAX_EVENT_PAYLOAD];
- const size_t max = sizeof(buf) - 1; // leave room for final newline
- size_t pos = 2; // Save room for type tag & array count
-
- jsize copied = 0, num = env->GetArrayLength(value);
- for (; copied < num && copied < 255; ++copied) {
- jobject item = env->GetObjectArrayElement(value, copied);
- if (item == NULL || env->IsInstanceOf(item, gStringClass)) {
- if (pos + 1 + sizeof(jint) > max) break;
- const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL";
- jint len = strlen(str);
- if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len);
- buf[pos++] = EVENT_TYPE_STRING;
- memcpy(&buf[pos], &len, sizeof(len));
- memcpy(&buf[pos + sizeof(len)], str, len);
- pos += sizeof(len) + len;
- if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str);
- } else if (env->IsInstanceOf(item, gIntegerClass)) {
- jint intVal = env->GetIntField(item, gIntegerValueID);
- if (pos + 1 + sizeof(intVal) > max) break;
- buf[pos++] = EVENT_TYPE_INT;
- memcpy(&buf[pos], &intVal, sizeof(intVal));
- pos += sizeof(intVal);
- } else if (env->IsInstanceOf(item, gLongClass)) {
- jlong longVal = env->GetLongField(item, gLongValueID);
- if (pos + 1 + sizeof(longVal) > max) break;
- buf[pos++] = EVENT_TYPE_LONG;
- memcpy(&buf[pos], &longVal, sizeof(longVal));
- pos += sizeof(longVal);
- } else if (env->IsInstanceOf(item, gFloatClass)) {
- jfloat floatVal = env->GetFloatField(item, gFloatValueID);
- if (pos + 1 + sizeof(floatVal) > max) break;
- buf[pos++] = EVENT_TYPE_FLOAT;
- memcpy(&buf[pos], &floatVal, sizeof(floatVal));
- pos += sizeof(floatVal);
- } else {
- jniThrowException(env,
- "java/lang/IllegalArgumentException",
- "Invalid payload item type");
- return -1;
- }
- env->DeleteLocalRef(item);
- }
-
- buf[0] = EVENT_TYPE_LIST;
- buf[1] = copied;
- buf[pos++] = '\n';
- return __android_log_security_bwrite(tag, buf, pos);
-}
-
-static void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) {
- struct logger_list *logger_list;
- if (startTime) {
- logger_list = android_logger_list_alloc_time(loggerMode,
- log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
- } else {
- logger_list = android_logger_list_alloc(loggerMode, 0, 0);
- }
- if (!logger_list) {
- jniThrowIOException(env, errno);
- return;
- }
-
- if (!android_logger_open(logger_list, LOG_ID_SECURITY)) {
- jniThrowIOException(env, errno);
- android_logger_list_free(logger_list);
- return;
- }
-
- while (1) {
- log_msg log_msg;
- int ret = android_logger_list_read(logger_list, &log_msg);
-
- if (ret == 0) {
- break;
- }
- if (ret < 0) {
- if (ret == -EINTR) {
- continue;
- }
- if (ret == -EINVAL) {
- jniThrowException(env, "java/io/IOException", "Event too short");
- } else if (ret != -EAGAIN) {
- jniThrowIOException(env, -ret); // Will throw on return
- }
- break;
- }
-
- if (log_msg.id() != LOG_ID_SECURITY) {
- continue;
- }
-
- jsize len = ret;
- jbyteArray array = env->NewByteArray(len);
- if (array == NULL) {
- break;
- }
-
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, log_msg.buf, len);
- env->ReleaseByteArrayElements(array, bytes, 0);
-
- jobject event = env->NewObject(gEventClass, gEventInitID, array);
- if (event == NULL) {
- break;
- }
-
- env->CallBooleanMethod(out, gCollectionAddID, event);
- env->DeleteLocalRef(event);
- env->DeleteLocalRef(array);
- }
-
- android_logger_list_close(logger_list);
-}
-
static void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* clazz */,
jobject out) {
@@ -198,7 +41,7 @@
jniThrowNullPointerException(env, NULL);
return;
}
- readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out);
+ SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out);
}
static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */,
@@ -209,7 +52,7 @@
jniThrowNullPointerException(env, NULL);
return;
}
- readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out);
+ SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out);
}
static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */,
@@ -219,7 +62,7 @@
jniThrowNullPointerException(env, NULL);
return;
}
- readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out);
+ SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out);
}
static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */,
@@ -229,7 +72,8 @@
jniThrowNullPointerException(env, NULL);
return;
}
- readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out);
+ SLog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp,
+ out);
}
/*
@@ -243,11 +87,11 @@
},
{ "writeEvent",
"(ILjava/lang/String;)I",
- (void*) android_app_admin_SecurityLog_writeEvent_String
+ (void*) SLog::writeEventString
},
{ "writeEvent",
"(I[Ljava/lang/Object;)I",
- (void*) android_app_admin_SecurityLog_writeEvent_Array
+ (void*) SLog::writeEventArray
},
{ "readEvents",
"(Ljava/util/Collection;)V",
@@ -267,41 +111,8 @@
},
};
-static struct { const char *name; jclass *clazz; } gClasses[] = {
- { "android/app/admin/SecurityLog$SecurityEvent", &gEventClass },
- { "java/lang/Integer", &gIntegerClass },
- { "java/lang/Long", &gLongClass },
- { "java/lang/Float", &gFloatClass },
- { "java/lang/String", &gStringClass },
- { "java/util/Collection", &gCollectionClass },
-};
-
-static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
- { &gIntegerClass, "value", "I", &gIntegerValueID },
- { &gLongClass, "value", "J", &gLongValueID },
- { &gFloatClass, "value", "F", &gFloatValueID },
-};
-
-static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
- { &gEventClass, "<init>", "([B)V", &gEventInitID },
- { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
-};
-
int register_android_app_admin_SecurityLog(JNIEnv* env) {
- for (int i = 0; i < NELEM(gClasses); ++i) {
- jclass clazz = FindClassOrDie(env, gClasses[i].name);
- *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
- }
-
- for (int i = 0; i < NELEM(gFields); ++i) {
- *gFields[i].id = GetFieldIDOrDie(env,
- *gFields[i].c, gFields[i].name, gFields[i].ft);
- }
-
- for (int i = 0; i < NELEM(gMethods); ++i) {
- *gMethods[i].id = GetMethodIDOrDie(env,
- *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
- }
+ SLog::Init(env);
return RegisterMethodsOrDie(
env,
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 9fd7c40..3b5a144 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -14,214 +14,20 @@
* limitations under the License.
*/
-#include <fcntl.h>
-
-#include <log/log_event_list.h>
-
-#include <log/log.h>
+#include <android-base/macros.h>
+#include <log/log_id.h>
#include <nativehelper/JNIHelp.h>
-#include "core_jni_helpers.h"
#include "jni.h"
-#define UNUSED __attribute__((__unused__))
+#include "core_jni_helpers.h"
+#include "eventlog_helper.h"
namespace android {
-static jclass gCollectionClass;
-static jmethodID gCollectionAddID;
-
-static jclass gEventClass;
-static jmethodID gEventInitID;
-
-static jclass gIntegerClass;
-static jfieldID gIntegerValueID;
-
-static jclass gLongClass;
-static jfieldID gLongValueID;
-
-static jclass gFloatClass;
-static jfieldID gFloatValueID;
-
-static jclass gStringClass;
-
-/*
- * In class android.util.EventLog:
- * static native int writeEvent(int tag, int value)
- */
-static jint android_util_EventLog_writeEvent_Integer(JNIEnv* env UNUSED,
- jobject clazz UNUSED,
- jint tag, jint value)
-{
- android_log_event_list ctx(tag);
- ctx << (int32_t)value;
- return ctx.write();
-}
-
-/*
- * In class android.util.EventLog:
- * static native int writeEvent(long tag, long value)
- */
-static jint android_util_EventLog_writeEvent_Long(JNIEnv* env UNUSED,
- jobject clazz UNUSED,
- jint tag, jlong value)
-{
- android_log_event_list ctx(tag);
- ctx << (int64_t)value;
- return ctx.write();
-}
-
-/*
- * In class android.util.EventLog:
- * static native int writeEvent(long tag, float value)
- */
-static jint android_util_EventLog_writeEvent_Float(JNIEnv* env UNUSED,
- jobject clazz UNUSED,
- jint tag, jfloat value)
-{
- android_log_event_list ctx(tag);
- ctx << (float)value;
- return ctx.write();
-}
-
-/*
- * In class android.util.EventLog:
- * static native int writeEvent(int tag, String value)
- */
-static jint android_util_EventLog_writeEvent_String(JNIEnv* env,
- jobject clazz UNUSED,
- jint tag, jstring value) {
- android_log_event_list ctx(tag);
- // Don't throw NPE -- I feel like it's sort of mean for a logging function
- // to be all crashy if you pass in NULL -- but make the NULL value explicit.
- if (value != NULL) {
- const char *str = env->GetStringUTFChars(value, NULL);
- ctx << str;
- env->ReleaseStringUTFChars(value, str);
- } else {
- ctx << "NULL";
- }
- return ctx.write();
-}
-
-/*
- * In class android.util.EventLog:
- * static native int writeEvent(long tag, Object... value)
- */
-static jint android_util_EventLog_writeEvent_Array(JNIEnv* env, jobject clazz,
- jint tag, jobjectArray value) {
- android_log_event_list ctx(tag);
-
- if (value == NULL) {
- ctx << "[NULL]";
- return ctx.write();
- }
-
- jsize copied = 0, num = env->GetArrayLength(value);
- for (; copied < num && copied < 255; ++copied) {
- if (ctx.status()) break;
- jobject item = env->GetObjectArrayElement(value, copied);
- if (item == NULL) {
- ctx << "NULL";
- } else if (env->IsInstanceOf(item, gStringClass)) {
- const char *str = env->GetStringUTFChars((jstring) item, NULL);
- ctx << str;
- env->ReleaseStringUTFChars((jstring) item, str);
- } else if (env->IsInstanceOf(item, gIntegerClass)) {
- ctx << (int32_t)env->GetIntField(item, gIntegerValueID);
- } else if (env->IsInstanceOf(item, gLongClass)) {
- ctx << (int64_t)env->GetLongField(item, gLongValueID);
- } else if (env->IsInstanceOf(item, gFloatClass)) {
- ctx << (float)env->GetFloatField(item, gFloatValueID);
- } else {
- jniThrowException(env,
- "java/lang/IllegalArgumentException",
- "Invalid payload item type");
- return -1;
- }
- env->DeleteLocalRef(item);
- }
- return ctx.write();
-}
-
-static void readEvents(JNIEnv* env, int loggerMode, jintArray tags, jlong startTime, jobject out) {
- struct logger_list *logger_list;
- if (startTime) {
- logger_list = android_logger_list_alloc_time(loggerMode,
- log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
- } else {
- logger_list = android_logger_list_alloc(loggerMode, 0, 0);
- }
- if (!logger_list) {
- jniThrowIOException(env, errno);
- return;
- }
-
- if (!android_logger_open(logger_list, LOG_ID_EVENTS)) {
- jniThrowIOException(env, errno);
- android_logger_list_free(logger_list);
- return;
- }
-
- jsize tagLength = env->GetArrayLength(tags);
- jint *tagValues = env->GetIntArrayElements(tags, NULL);
-
- while (1) {
- log_msg log_msg;
- int ret = android_logger_list_read(logger_list, &log_msg);
-
- if (ret == 0) {
- break;
- }
- if (ret < 0) {
- if (ret == -EINTR) {
- continue;
- }
- if (ret == -EINVAL) {
- jniThrowException(env, "java/io/IOException", "Event too short");
- } else if (ret != -EAGAIN) {
- jniThrowIOException(env, -ret); // Will throw on return
- }
- break;
- }
-
- if (log_msg.id() != LOG_ID_EVENTS) {
- continue;
- }
-
- int32_t tag = * (int32_t *) log_msg.msg();
-
- int found = 0;
- for (int i = 0; !found && i < tagLength; ++i) {
- found = (tag == tagValues[i]);
- }
-
- if (found) {
- jsize len = ret;
- jbyteArray array = env->NewByteArray(len);
- if (array == NULL) {
- break;
- }
-
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, log_msg.buf, len);
- env->ReleaseByteArrayElements(array, bytes, 0);
-
- jobject event = env->NewObject(gEventClass, gEventInitID, array);
- if (event == NULL) {
- break;
- }
-
- env->CallBooleanMethod(out, gCollectionAddID, event);
- env->DeleteLocalRef(event);
- env->DeleteLocalRef(array);
- }
- }
-
- android_logger_list_close(logger_list);
-
- env->ReleaseIntArrayElements(tags, tagValues, 0);
-}
+constexpr char kEventLogEventClass[] = "android/util/EventLog$Event";
+template class EventLogHelper<log_id_t::LOG_ID_EVENTS, kEventLogEventClass>;
+using ELog = EventLogHelper<log_id_t::LOG_ID_EVENTS, kEventLogEventClass>;
/*
* In class android.util.EventLog:
@@ -229,7 +35,7 @@
*
* Reads events from the event log
*/
-static void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz UNUSED,
+static void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz ATTRIBUTE_UNUSED,
jintArray tags,
jobject out) {
@@ -238,7 +44,7 @@
return;
}
- readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, tags, 0, out);
+ ELog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, tags, 0, out);
}
/*
* In class android.util.EventLog:
@@ -246,7 +52,7 @@
*
* Reads events from the event log, blocking until events after timestamp are to be overwritten.
*/
-static void android_util_EventLog_readEventsOnWrapping(JNIEnv* env, jobject clazz UNUSED,
+static void android_util_EventLog_readEventsOnWrapping(JNIEnv* env, jobject clazz ATTRIBUTE_UNUSED,
jintArray tags,
jlong timestamp,
jobject out) {
@@ -254,8 +60,8 @@
jniThrowNullPointerException(env, NULL);
return;
}
- readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP,
- tags, timestamp, out);
+ ELog::readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, tags,
+ timestamp, out);
}
/*
@@ -263,17 +69,11 @@
*/
static const JNINativeMethod gRegisterMethods[] = {
/* name, signature, funcPtr */
- { "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer },
- { "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long },
- { "writeEvent", "(IF)I", (void*) android_util_EventLog_writeEvent_Float },
- { "writeEvent",
- "(ILjava/lang/String;)I",
- (void*) android_util_EventLog_writeEvent_String
- },
- { "writeEvent",
- "(I[Ljava/lang/Object;)I",
- (void*) android_util_EventLog_writeEvent_Array
- },
+ { "writeEvent", "(II)I", (void*) ELog::writeEventInteger },
+ { "writeEvent", "(IJ)I", (void*) ELog::writeEventLong },
+ { "writeEvent", "(IF)I", (void*) ELog::writeEventFloat },
+ { "writeEvent", "(ILjava/lang/String;)I", (void*) ELog::writeEventString },
+ { "writeEvent", "(I[Ljava/lang/Object;)I", (void*) ELog::writeEventArray },
{ "readEvents",
"([ILjava/util/Collection;)V",
(void*) android_util_EventLog_readEvents
@@ -284,41 +84,8 @@
},
};
-static struct { const char *name; jclass *clazz; } gClasses[] = {
- { "android/util/EventLog$Event", &gEventClass },
- { "java/lang/Integer", &gIntegerClass },
- { "java/lang/Long", &gLongClass },
- { "java/lang/Float", &gFloatClass },
- { "java/lang/String", &gStringClass },
- { "java/util/Collection", &gCollectionClass },
-};
-
-static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
- { &gIntegerClass, "value", "I", &gIntegerValueID },
- { &gLongClass, "value", "J", &gLongValueID },
- { &gFloatClass, "value", "F", &gFloatValueID },
-};
-
-static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
- { &gEventClass, "<init>", "([B)V", &gEventInitID },
- { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
-};
-
int register_android_util_EventLog(JNIEnv* env) {
- for (int i = 0; i < NELEM(gClasses); ++i) {
- jclass clazz = FindClassOrDie(env, gClasses[i].name);
- *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz);
- }
-
- for (int i = 0; i < NELEM(gFields); ++i) {
- *gFields[i].id = GetFieldIDOrDie(env,
- *gFields[i].c, gFields[i].name, gFields[i].ft);
- }
-
- for (int i = 0; i < NELEM(gMethods); ++i) {
- *gMethods[i].id = GetMethodIDOrDie(env,
- *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
- }
+ ELog::Init(env);
return RegisterMethodsOrDie(
env,
diff --git a/core/jni/eventlog_helper.h b/core/jni/eventlog_helper.h
new file mode 100644
index 0000000..3a05195
--- /dev/null
+++ b/core/jni/eventlog_helper.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef FRAMEWORKS_BASE_CORE_JNI_EVENTLOG_HELPER_H_
+#define FRAMEWORKS_BASE_CORE_JNI_EVENTLOG_HELPER_H_
+
+#include <memory>
+
+#include <fcntl.h>
+
+#include <android-base/macros.h>
+#include <log/log_event_list.h>
+
+#include <log/log.h>
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include "core_jni_helpers.h"
+#include "jni.h"
+
+namespace android {
+
+template <log_id_t LogID, const char* EventClassDescriptor>
+class EventLogHelper {
+public:
+ static void Init(JNIEnv* env) {
+ struct { const char *name; jclass *clazz; } gClasses[] = {
+ { EventClassDescriptor, &gEventClass },
+ { "java/lang/Integer", &gIntegerClass },
+ { "java/lang/Long", &gLongClass },
+ { "java/lang/Float", &gFloatClass },
+ { "java/lang/String", &gStringClass },
+ { "java/util/Collection", &gCollectionClass },
+ };
+ struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = {
+ { &gIntegerClass, "value", "I", &gIntegerValueID },
+ { &gLongClass, "value", "J", &gLongValueID },
+ { &gFloatClass, "value", "F", &gFloatValueID },
+ };
+ struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = {
+ { &gEventClass, "<init>", "([B)V", &gEventInitID },
+ { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID },
+ };
+
+ for (size_t i = 0; i < NELEM(gClasses); ++i) {
+ ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, gClasses[i].name));
+ *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz.get());
+ }
+ for (size_t i = 0; i < NELEM(gFields); ++i) {
+ *gFields[i].id = GetFieldIDOrDie(env,
+ *gFields[i].c, gFields[i].name, gFields[i].ft);
+ }
+
+ for (size_t i = 0; i < NELEM(gMethods); ++i) {
+ *gMethods[i].id = GetMethodIDOrDie(env,
+ *gMethods[i].c, gMethods[i].name, gMethods[i].mt);
+ }
+ }
+
+ static jint writeEventInteger(JNIEnv* env ATTRIBUTE_UNUSED, jobject clazz ATTRIBUTE_UNUSED,
+ jint tag, jint value) {
+ android_log_event_list ctx(tag);
+ ctx << (int32_t)value;
+ return ctx.write(LogID);
+ }
+ static jint writeEventLong(JNIEnv* env ATTRIBUTE_UNUSED, jobject clazz ATTRIBUTE_UNUSED,
+ jint tag, jlong value) {
+ android_log_event_list ctx(tag);
+ ctx << (int64_t)value;
+ return ctx.write(LogID);
+ }
+ static jint writeEventFloat(JNIEnv* env ATTRIBUTE_UNUSED, jobject clazz ATTRIBUTE_UNUSED,
+ jint tag, jfloat value) {
+ android_log_event_list ctx(tag);
+ ctx << (float)value;
+ return ctx.write(LogID);
+ }
+ static jint writeEventString(JNIEnv* env, jobject clazz ATTRIBUTE_UNUSED, jint tag,
+ jstring value) {
+ android_log_event_list ctx(tag);
+ // Don't throw NPE -- I feel like it's sort of mean for a logging function
+ // to be all crashy if you pass in NULL -- but make the NULL value explicit.
+ ctx << (value != nullptr ? ScopedUtfChars(env, value).c_str() : "NULL");
+ return ctx.write(LogID);
+ }
+ static jint writeEventArray(JNIEnv* env, jobject clazz ATTRIBUTE_UNUSED, jint tag,
+ jobjectArray value) {
+ android_log_event_list ctx(tag);
+
+ if (value == nullptr) {
+ ctx << "[NULL]";
+ return ctx.write(LogID);
+ }
+
+ jsize copied = 0, num = env->GetArrayLength(value);
+ for (; copied < num && copied < 255; ++copied) {
+ if (ctx.status()) break;
+ ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(value, copied));
+ if (item == nullptr) {
+ ctx << "NULL";
+ } else if (env->IsInstanceOf(item.get(), gStringClass)) {
+ ctx << ScopedUtfChars(env, (jstring) item.get()).c_str();
+ } else if (env->IsInstanceOf(item.get(), gIntegerClass)) {
+ ctx << (int32_t)env->GetIntField(item.get(), gIntegerValueID);
+ } else if (env->IsInstanceOf(item.get(), gLongClass)) {
+ ctx << (int64_t)env->GetLongField(item.get(), gLongValueID);
+ } else if (env->IsInstanceOf(item.get(), gFloatClass)) {
+ ctx << (float)env->GetFloatField(item.get(), gFloatValueID);
+ } else {
+ jniThrowException(env,
+ "java/lang/IllegalArgumentException",
+ "Invalid payload item type");
+ return -1;
+ }
+ }
+ return ctx.write(LogID);
+ }
+
+ static void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) {
+ readEvents(env, loggerMode, nullptr, startTime, out);
+ }
+
+ static void readEvents(JNIEnv* env, int loggerMode, jintArray jTags, jlong startTime,
+ jobject out) {
+ std::unique_ptr<struct logger_list, decltype(&android_logger_list_close)> logger_list(
+ nullptr, android_logger_list_close);
+ if (startTime) {
+ logger_list.reset(android_logger_list_alloc_time(loggerMode,
+ log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0));
+ } else {
+ logger_list.reset(android_logger_list_alloc(loggerMode, 0, 0));
+ }
+ if (!logger_list) {
+ jniThrowIOException(env, errno);
+ return;
+ }
+
+ if (!android_logger_open(logger_list.get(), LogID)) {
+ jniThrowIOException(env, errno);
+ return;
+ }
+
+ ScopedIntArrayRO tags(env);
+ if (jTags != nullptr) {
+ tags.reset(jTags);
+ }
+
+ while (1) {
+ log_msg log_msg;
+ int ret = android_logger_list_read(logger_list.get(), &log_msg);
+
+ if (ret == 0) {
+ return;
+ }
+ if (ret < 0) {
+ if (ret == -EINTR) {
+ continue;
+ }
+ if (ret == -EINVAL) {
+ jniThrowException(env, "java/io/IOException", "Event too short");
+ } else if (ret != -EAGAIN) {
+ jniThrowIOException(env, -ret); // Will throw on return
+ }
+ return;
+ }
+
+ if (log_msg.id() != LogID) {
+ continue;
+ }
+
+ int32_t tag = * (int32_t *) log_msg.msg();
+
+ if (jTags != nullptr) {
+ bool found = false;
+ for (size_t i = 0; !found && i < tags.size(); ++i) {
+ found = (tag == tags[i]);
+ }
+ if (!found) {
+ continue;
+ }
+ }
+
+ jsize len = ret;
+ ScopedLocalRef<jbyteArray> array(env, env->NewByteArray(len));
+ if (array == nullptr) {
+ return;
+ }
+
+ {
+ ScopedByteArrayRW bytes(env, array.get());
+ memcpy(bytes.get(), log_msg.buf, len);
+ }
+
+ ScopedLocalRef<jobject> event(env,
+ env->NewObject(gEventClass, gEventInitID, array.get()));
+ if (event == nullptr) {
+ return;
+ }
+
+ env->CallBooleanMethod(out, gCollectionAddID, event.get());
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ return;
+ }
+ }
+ }
+
+private:
+ static jclass gCollectionClass;
+ static jmethodID gCollectionAddID;
+
+ static jclass gEventClass;
+ static jmethodID gEventInitID;
+
+ static jclass gIntegerClass;
+ static jfieldID gIntegerValueID;
+
+ static jclass gLongClass;
+ static jfieldID gLongValueID;
+
+ static jclass gFloatClass;
+ static jfieldID gFloatValueID;
+
+ static jclass gStringClass;
+};
+
+// Explicit instantiation declarations.
+template <log_id_t LogID, const char* EventClassDescriptor>
+jclass EventLogHelper<LogID, EventClassDescriptor>::gCollectionClass;
+template <log_id_t LogID, const char* EventClassDescriptor>
+jmethodID EventLogHelper<LogID, EventClassDescriptor>::gCollectionAddID;
+
+template <log_id_t LogID, const char* EventClassDescriptor>
+jclass EventLogHelper<LogID, EventClassDescriptor>::gEventClass;
+template <log_id_t LogID, const char* EventClassDescriptor>
+jmethodID EventLogHelper<LogID, EventClassDescriptor>::gEventInitID;
+
+template <log_id_t LogID, const char* EventClassDescriptor>
+jclass EventLogHelper<LogID, EventClassDescriptor>::gIntegerClass;
+template <log_id_t LogID, const char* EventClassDescriptor>
+jfieldID EventLogHelper<LogID, EventClassDescriptor>::gIntegerValueID;
+
+template <log_id_t LogID, const char* EventClassDescriptor>
+jclass EventLogHelper<LogID, EventClassDescriptor>::gLongClass;
+template <log_id_t LogID, const char* EventClassDescriptor>
+jfieldID EventLogHelper<LogID, EventClassDescriptor>::gLongValueID;
+
+template <log_id_t LogID, const char* EventClassDescriptor>
+jclass EventLogHelper<LogID, EventClassDescriptor>::gFloatClass;
+template <log_id_t LogID, const char* EventClassDescriptor>
+jfieldID EventLogHelper<LogID, EventClassDescriptor>::gFloatValueID;
+
+template <log_id_t LogID, const char* EventClassDescriptor>
+jclass EventLogHelper<LogID, EventClassDescriptor>::gStringClass;
+
+} // namespace android
+
+#endif // FRAMEWORKS_BASE_CORE_JNI_EVENTLOG_HELPER_H_
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7e47a2a..7849245 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2971,4 +2971,8 @@
<!-- An array of packages that need to be treated as type service in battery settings -->
<string-array translatable="false" name="config_batteryPackageTypeService"/>
+
+ <!-- Decide whether to display 'No service' on status bar instead of 'Emergency calls only'
+ when SIM is unready. -->
+ <bool name="config_display_no_service_when_sim_unready">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 786080f9..4724399 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3038,4 +3038,5 @@
<java-symbol type="array" name="config_batteryPackageTypeSystem" />
<java-symbol type="array" name="config_batteryPackageTypeService" />
+ <java-symbol type="bool" name="config_display_no_service_when_sim_unready" />
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index fe03fba..16a0e5a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -64,7 +64,11 @@
// again when the PUK locked SIM is re-entered.
case ABSENT: {
KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(mSubId);
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ // onSimStateChanged callback can fire when the SIM PIN lock is not currently
+ // active and mCallback is null.
+ if (mCallback != null) {
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ }
break;
}
default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 826a03d..fddb12d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -70,7 +70,11 @@
// move into the READY state and the PUK lock keyguard should be removed.
case READY: {
KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(mSubId);
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ // mCallback can be null if onSimStateChanged callback is called when keyguard
+ // isn't active.
+ if (mCallback != null) {
+ mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ }
break;
}
default:
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 3056831..2e1f142 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -33,6 +33,7 @@
import android.net.IpSecTransform;
import android.net.IpSecTransformResponse;
import android.net.IpSecUdpEncapResponse;
+import android.net.NetworkUtils;
import android.net.util.NetdService;
import android.os.Binder;
import android.os.IBinder;
@@ -42,11 +43,14 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -54,6 +58,7 @@
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicInteger;
+
import libcore.io.IoUtils;
/** @hide */
@@ -252,7 +257,11 @@
return (mReferenceCount.get() > 0);
}
- public void checkOwnerOrSystemAndThrow() {
+ /**
+ * Ensures that the caller is either the owner of this resource or has the system UID and
+ * throws a SecurityException otherwise.
+ */
+ public void checkOwnerOrSystem() {
if (uid != Binder.getCallingUid()
&& android.os.Process.SYSTEM_UID != Binder.getCallingUid()) {
throw new SecurityException("Only the owner may access managed resources!");
@@ -335,12 +344,12 @@
private class ManagedResourceArray<T extends ManagedResource> {
SparseArray<T> mArray = new SparseArray<>();
- T get(int key) {
+ T getAndCheckOwner(int key) {
T val = mArray.get(key);
// The value should never be null unless the resource doesn't exist
// (since we do not allow null resources to be added).
if (val != null) {
- val.checkOwnerOrSystemAndThrow();
+ val.checkOwnerOrSystem();
}
return val;
}
@@ -405,12 +414,8 @@
.ipSecDeleteSecurityAssociation(
mResourceId,
direction,
- (mConfig.getLocalAddress() != null)
- ? mConfig.getLocalAddress().getHostAddress()
- : "",
- (mConfig.getRemoteAddress() != null)
- ? mConfig.getRemoteAddress().getHostAddress()
- : "",
+ mConfig.getLocalAddress(),
+ mConfig.getRemoteAddress(),
spi);
} catch (ServiceSpecificException e) {
// FIXME: get the error code and throw is at an IOException from Errno Exception
@@ -638,11 +643,45 @@
}
}
+ /**
+ * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
+ * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
+ */
+ private static void checkInetAddress(String inetAddress) {
+ if (TextUtils.isEmpty(inetAddress)) {
+ throw new IllegalArgumentException("Unspecified address");
+ }
+
+ InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress);
+
+ if (checkAddr.isAnyLocalAddress()) {
+ throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress);
+ }
+ }
+
+ /**
+ * Checks the user-provided direction field and throws an IllegalArgumentException if it is not
+ * DIRECTION_IN or DIRECTION_OUT
+ */
+ private static void checkDirection(int direction) {
+ switch (direction) {
+ case IpSecTransform.DIRECTION_OUT:
+ case IpSecTransform.DIRECTION_IN:
+ return;
+ }
+ throw new IllegalArgumentException("Invalid Direction: " + direction);
+ }
+
@Override
/** Get a new SPI and maintain the reservation in the system server */
public synchronized IpSecSpiResponse reserveSecurityParameterIndex(
int direction, String remoteAddress, int requestedSpi, IBinder binder)
throws RemoteException {
+ checkDirection(direction);
+ checkInetAddress(remoteAddress);
+ /* requestedSpi can be anything in the int range, so no check is needed. */
+ checkNotNull(binder, "Null Binder passed to reserveSecurityParameterIndex");
+
int resourceId = mNextResourceId.getAndIncrement();
int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX;
@@ -651,9 +690,7 @@
try {
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) {
return new IpSecSpiResponse(
- IpSecManager.Status.RESOURCE_UNAVAILABLE,
- INVALID_RESOURCE_ID,
- spi);
+ IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi);
}
spi =
mSrvConfig
@@ -686,7 +723,7 @@
throws RemoteException {
// We want to non-destructively get so that we can check credentials before removing
// this from the records.
- T record = resArray.get(resourceId);
+ T record = resArray.getAndCheckOwner(resourceId);
if (record == null) {
throw new IllegalArgumentException(
@@ -751,6 +788,8 @@
throw new IllegalArgumentException(
"Specified port number must be a valid non-reserved UDP port");
}
+ checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
+
int resourceId = mNextResourceId.getAndIncrement();
FileDescriptor sockFd = null;
try {
@@ -792,6 +831,68 @@
}
/**
+ * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
+ * IllegalArgumentException if they are not.
+ */
+ private void checkIpSecConfig(IpSecConfig config) {
+ if (config.getLocalAddress() == null) {
+ throw new IllegalArgumentException("Invalid null Local InetAddress");
+ }
+
+ if (config.getRemoteAddress() == null) {
+ throw new IllegalArgumentException("Invalid null Remote InetAddress");
+ }
+
+ switch (config.getMode()) {
+ case IpSecTransform.MODE_TRANSPORT:
+ if (!config.getLocalAddress().isEmpty()) {
+ throw new IllegalArgumentException("Non-empty Local Address");
+ }
+ // Must be valid, and not a wildcard
+ checkInetAddress(config.getRemoteAddress());
+ break;
+ case IpSecTransform.MODE_TUNNEL:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid IpSecTransform.mode: " + config.getMode());
+ }
+
+ switch (config.getEncapType()) {
+ case IpSecTransform.ENCAP_NONE:
+ break;
+ case IpSecTransform.ENCAP_ESPINUDP:
+ case IpSecTransform.ENCAP_ESPINUDP_NON_IKE:
+ if (mUdpSocketRecords.getAndCheckOwner(
+ config.getEncapSocketResourceId()) == null) {
+ throw new IllegalStateException(
+ "No Encapsulation socket for Resource Id: "
+ + config.getEncapSocketResourceId());
+ }
+
+ int port = config.getEncapRemotePort();
+ if (port <= 0 || port > 0xFFFF) {
+ throw new IllegalArgumentException("Invalid remote UDP port: " + port);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType());
+ }
+
+ for (int direction : DIRECTIONS) {
+ IpSecAlgorithm crypt = config.getEncryption(direction);
+ IpSecAlgorithm auth = config.getAuthentication(direction);
+ if (crypt == null && auth == null) {
+ throw new IllegalArgumentException("Encryption and Authentication are both null");
+ }
+
+ if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) {
+ throw new IllegalStateException("No SPI for specified Resource Id");
+ }
+ }
+ }
+
+ /**
* Create a transport mode transform, which represent two security associations (one in each
* direction) in the kernel. The transform will be cached by the system server and must be freed
* when no longer needed. It is possible to free one, deleting the SA from underneath sockets
@@ -801,17 +902,19 @@
@Override
public synchronized IpSecTransformResponse createTransportModeTransform(
IpSecConfig c, IBinder binder) throws RemoteException {
+ checkIpSecConfig(c);
+ checkNotNull(binder, "Null Binder passed to createTransportModeTransform");
int resourceId = mNextResourceId.getAndIncrement();
if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) {
return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE);
}
SpiRecord[] spis = new SpiRecord[DIRECTIONS.length];
- // TODO: Basic input validation here since it's coming over the Binder
+
int encapType, encapLocalPort = 0, encapRemotePort = 0;
UdpSocketRecord socketRecord = null;
encapType = c.getEncapType();
if (encapType != IpSecTransform.ENCAP_NONE) {
- socketRecord = mUdpSocketRecords.get(c.getEncapLocalResourceId());
+ socketRecord = mUdpSocketRecords.getAndCheckOwner(c.getEncapSocketResourceId());
encapLocalPort = socketRecord.getPort();
encapRemotePort = c.getEncapRemotePort();
}
@@ -820,23 +923,18 @@
IpSecAlgorithm auth = c.getAuthentication(direction);
IpSecAlgorithm crypt = c.getEncryption(direction);
- spis[direction] = mSpiRecords.get(c.getSpiResourceId(direction));
+ spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction));
int spi = spis[direction].getSpi();
try {
- mSrvConfig.getNetdInstance()
+ mSrvConfig
+ .getNetdInstance()
.ipSecAddSecurityAssociation(
resourceId,
c.getMode(),
direction,
- (c.getLocalAddress() != null)
- ? c.getLocalAddress().getHostAddress()
- : "",
- (c.getRemoteAddress() != null)
- ? c.getRemoteAddress().getHostAddress()
- : "",
- (c.getNetwork() != null)
- ? c.getNetwork().getNetworkHandle()
- : 0,
+ c.getLocalAddress(),
+ c.getRemoteAddress(),
+ (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0,
spi,
(auth != null) ? auth.getName() : "",
(auth != null) ? auth.getKey() : null,
@@ -879,7 +977,7 @@
// Synchronize liberally here because we are using ManagedResources in this block
TransformRecord info;
// FIXME: this code should be factored out into a security check + getter
- info = mTransformRecords.get(resourceId);
+ info = mTransformRecords.getAndCheckOwner(resourceId);
if (info == null) {
throw new IllegalArgumentException("Transform " + resourceId + " is not active");
@@ -899,12 +997,8 @@
socket.getFileDescriptor(),
resourceId,
direction,
- (c.getLocalAddress() != null)
- ? c.getLocalAddress().getHostAddress()
- : "",
- (c.getRemoteAddress() != null)
- ? c.getRemoteAddress().getHostAddress()
- : "",
+ c.getLocalAddress(),
+ c.getRemoteAddress(),
info.getSpiRecord(direction).getSpi());
}
} catch (ServiceSpecificException e) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 5583e86..d7cd81f 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1371,6 +1371,7 @@
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
}
+ mUpstreamNetworkMonitor.setCurrentUpstream((ns != null) ? ns.network : null);
setUpstreamNetwork(ns);
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 057704a..cff216c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -596,9 +596,10 @@
}
mNatUpdateCallbacksReceived++;
+ final String natDescription = String.format("%s (%s, %s) -> (%s, %s)",
+ protoName, srcAddr, srcPort, dstAddr, dstPort);
if (DBG) {
- mLog.log(String.format("NAT timeout update: %s (%s, %s) -> (%s, %s)",
- protoName, srcAddr, srcPort, dstAddr, dstPort));
+ mLog.log("NAT timeout update: " + natDescription);
}
final int timeoutSec = connectionTimeoutUpdateSecondsFor(proto);
@@ -609,7 +610,7 @@
NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg);
} catch (ErrnoException e) {
mNatUpdateNetlinkErrors++;
- mLog.e("Error updating NAT conntrack entry: " + e
+ mLog.e("Error updating NAT conntrack entry >" + natDescription + "<: " + e
+ ", msg: " + NetlinkConstants.hexify(msg));
mLog.log("NAT timeout update callbacks received: " + mNatUpdateCallbacksReceived);
mLog.log("NAT timeout update netlink errors: " + mNatUpdateNetlinkErrors);
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index c5f7528..b35ed75 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -95,7 +95,10 @@
private NetworkCallback mDefaultNetworkCallback;
private NetworkCallback mMobileNetworkCallback;
private boolean mDunRequired;
- private Network mCurrentDefault;
+ // The current system default network (not really used yet).
+ private Network mDefaultInternetNetwork;
+ // The current upstream network used for tethering.
+ private Network mTetheringUpstreamNetwork;
public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, SharedLog log, int what) {
mContext = ctx;
@@ -130,10 +133,12 @@
releaseCallback(mDefaultNetworkCallback);
mDefaultNetworkCallback = null;
+ mDefaultInternetNetwork = null;
releaseCallback(mListenAllCallback);
mListenAllCallback = null;
+ mTetheringUpstreamNetwork = null;
mNetworkMap.clear();
}
@@ -207,7 +212,7 @@
break;
default:
/* If we've found an active upstream connection that's not DUN/HIPRI
- * we should stop any outstanding DUN/HIPRI start requests.
+ * we should stop any outstanding DUN/HIPRI requests.
*
* If we found NONE we don't want to do this as we want any previous
* requests to keep trying to bring up something we can use.
@@ -219,6 +224,10 @@
return typeStatePair.ns;
}
+ public void setCurrentUpstream(Network upstream) {
+ mTetheringUpstreamNetwork = upstream;
+ }
+
public Set<IpPrefix> getLocalPrefixes() {
return (Set<IpPrefix>) mLocalPrefixes.clone();
}
@@ -250,7 +259,7 @@
// These request*() calls can be deleted post oag/339444.
return;
}
- mCurrentDefault = network;
+ mDefaultInternetNetwork = network;
break;
case CALLBACK_MOBILE_REQUEST:
@@ -302,6 +311,13 @@
network, newNc));
}
+ // Log changes in upstream network signal strength, if available.
+ if (network.equals(mTetheringUpstreamNetwork) && newNc.hasSignalStrength()) {
+ final int newSignal = newNc.getSignalStrength();
+ final String prevSignal = getSignalStrength(prev.networkCapabilities);
+ mLog.logf("upstream network signal strength: %s -> %s", prevSignal, newSignal);
+ }
+
mNetworkMap.put(network, new NetworkState(
null, prev.linkProperties, newNc, network, null, null));
// TODO: If sufficient information is available to select a more
@@ -330,9 +346,21 @@
notifyTarget(EVENT_ON_LINKPROPERTIES, network);
}
+ private void handleSuspended(int callbackType, Network network) {
+ if (callbackType != CALLBACK_LISTEN_ALL) return;
+ if (!network.equals(mTetheringUpstreamNetwork)) return;
+ mLog.log("SUSPENDED current upstream: " + network);
+ }
+
+ private void handleResumed(int callbackType, Network network) {
+ if (callbackType != CALLBACK_LISTEN_ALL) return;
+ if (!network.equals(mTetheringUpstreamNetwork)) return;
+ mLog.log("RESUMED current upstream: " + network);
+ }
+
private void handleLost(int callbackType, Network network) {
if (callbackType == CALLBACK_TRACK_DEFAULT) {
- mCurrentDefault = null;
+ mDefaultInternetNetwork = null;
// Receiving onLost() for a default network does not necessarily
// mean the network is gone. We wait for a separate notification
// on either the LISTEN_ALL or MOBILE_REQUEST callbacks before
@@ -401,8 +429,15 @@
recomputeLocalPrefixes();
}
- // TODO: Handle onNetworkSuspended();
- // TODO: Handle onNetworkResumed();
+ @Override
+ public void onNetworkSuspended(Network network) {
+ handleSuspended(mCallbackType, network);
+ }
+
+ @Override
+ public void onNetworkResumed(Network network) {
+ handleResumed(mCallbackType, network);
+ }
@Override
public void onLost(Network network) {
@@ -467,4 +502,9 @@
return prefixSet;
}
+
+ private static String getSignalStrength(NetworkCapabilities nc) {
+ if (nc == null || !nc.hasSignalStrength()) return "unknown";
+ return Integer.toString(nc.getSignalStrength());
+ }
}
diff --git a/services/net/java/android/net/ip/ConnectivityPacketTracker.java b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
index 0230f36..1925c39 100644
--- a/services/net/java/android/net/ip/ConnectivityPacketTracker.java
+++ b/services/net/java/android/net/ip/ConnectivityPacketTracker.java
@@ -25,6 +25,7 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.PacketSocketAddress;
+import android.text.TextUtils;
import android.util.Log;
import android.util.LocalLog;
@@ -59,11 +60,14 @@
private static final boolean DBG = false;
private static final String MARK_START = "--- START ---";
private static final String MARK_STOP = "--- STOP ---";
+ private static final String MARK_NAMED_START = "--- START (%s) ---";
+ private static final String MARK_NAMED_STOP = "--- STOP (%s) ---";
private final String mTag;
private final LocalLog mLog;
private final BlockingSocketReader mPacketListener;
private boolean mRunning;
+ private String mDisplayName;
public ConnectivityPacketTracker(Handler h, NetworkInterface netif, LocalLog log) {
final String ifname;
@@ -85,14 +89,16 @@
mPacketListener = new PacketListener(h, ifindex, hwaddr, mtu);
}
- public void start() {
+ public void start(String displayName) {
mRunning = true;
+ mDisplayName = displayName;
mPacketListener.start();
}
public void stop() {
mPacketListener.stop();
mRunning = false;
+ mDisplayName = null;
}
private final class PacketListener extends BlockingSocketReader {
@@ -133,16 +139,19 @@
@Override
protected void onStart() {
- mLog.log(MARK_START);
+ final String msg = TextUtils.isEmpty(mDisplayName)
+ ? MARK_START
+ : String.format(MARK_NAMED_START, mDisplayName);
+ mLog.log(msg);
}
@Override
protected void onStop() {
- if (mRunning) {
- mLog.log(MARK_STOP);
- } else {
- mLog.log(MARK_STOP + " (packet listener stopped unexpectedly)");
- }
+ String msg = TextUtils.isEmpty(mDisplayName)
+ ? MARK_STOP
+ : String.format(MARK_NAMED_STOP, mDisplayName);
+ if (!mRunning) msg += " (packet listener stopped unexpectedly)";
+ mLog.log(msg);
}
@Override
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index bc07b81..e33f6c9 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -26,6 +26,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties.ProvisioningChange;
import android.net.LinkProperties;
+import android.net.Network;
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
@@ -348,6 +349,16 @@
return this;
}
+ public Builder withNetwork(Network network) {
+ mConfig.mNetwork = network;
+ return this;
+ }
+
+ public Builder withDisplayName(String displayName) {
+ mConfig.mDisplayName = displayName;
+ return this;
+ }
+
public ProvisioningConfiguration build() {
return new ProvisioningConfiguration(mConfig);
}
@@ -362,6 +373,8 @@
/* package */ ApfCapabilities mApfCapabilities;
/* package */ int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
/* package */ int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ /* package */ Network mNetwork = null;
+ /* package */ String mDisplayName = null;
public ProvisioningConfiguration() {} // used by Builder
@@ -374,6 +387,9 @@
mStaticIpConfig = other.mStaticIpConfig;
mApfCapabilities = other.mApfCapabilities;
mProvisioningTimeoutMs = other.mProvisioningTimeoutMs;
+ mIPv6AddrGenMode = other.mIPv6AddrGenMode;
+ mNetwork = other.mNetwork;
+ mDisplayName = other.mDisplayName;
}
@Override
@@ -388,6 +404,8 @@
.add("mApfCapabilities: " + mApfCapabilities)
.add("mProvisioningTimeoutMs: " + mProvisioningTimeoutMs)
.add("mIPv6AddrGenMode: " + mIPv6AddrGenMode)
+ .add("mNetwork: " + mNetwork)
+ .add("mDisplayName: " + mDisplayName)
.toString();
}
@@ -1441,10 +1459,10 @@
@Override
public void enter() {
// Get the Configuration for ApfFilter from Context
- boolean filter802_3Frames =
+ final boolean filter802_3Frames =
mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
- int[] ethTypeBlackList = mContext.getResources().getIntArray(
+ final int[] ethTypeBlackList = mContext.getResources().getIntArray(
R.array.config_apfEthTypeBlackList);
mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
@@ -1456,7 +1474,7 @@
}
mPacketTracker = createPacketTracker();
- if (mPacketTracker != null) mPacketTracker.start();
+ if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName);
if (mConfiguration.mEnableIPv6 && !startIPv6()) {
doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
@@ -1470,7 +1488,7 @@
return;
}
- InitialConfiguration config = mConfiguration.mInitialConfig;
+ final InitialConfiguration config = mConfiguration.mInitialConfig;
if ((config != null) && !applyInitialConfig(config)) {
// TODO introduce a new IpManagerEvent constant to distinguish this error case.
doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java
index 6065268..5a3a8be 100644
--- a/services/net/java/android/net/util/NetworkConstants.java
+++ b/services/net/java/android/net/util/NetworkConstants.java
@@ -107,6 +107,20 @@
public static final int RFC6177_MIN_PREFIX_LENGTH = 48;
/**
+ * ICMP common (v4/v6) constants.
+ *
+ * See also:
+ * - https://tools.ietf.org/html/rfc792
+ * - https://tools.ietf.org/html/rfc4443
+ */
+ public static final int ICMP_HEADER_TYPE_OFFSET = 0;
+ public static final int ICMP_HEADER_CODE_OFFSET = 1;
+ public static final int ICMP_HEADER_CHECKSUM_OFFSET = 2;
+ public static final int ICMP_ECHO_IDENTIFIER_OFFSET = 4;
+ public static final int ICMP_ECHO_SEQUENCE_NUMBER_OFFSET = 6;
+ public static final int ICMP_ECHO_DATA_OFFSET = 8;
+
+ /**
* ICMPv6 constants.
*
* See also:
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
index 343d237..bbd3d13 100644
--- a/services/net/java/android/net/util/SharedLog.java
+++ b/services/net/java/android/net/util/SharedLog.java
@@ -106,6 +106,10 @@
record(Category.NONE, msg);
}
+ public void logf(String fmt, Object... args) {
+ log(String.format(fmt, args));
+ }
+
public void mark(String msg) {
record(Category.MARK, msg);
}
diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java
index 5a57f32..f0d60b6 100644
--- a/telephony/java/android/telephony/mbms/DownloadRequest.java
+++ b/telephony/java/android/telephony/mbms/DownloadRequest.java
@@ -16,6 +16,7 @@
package android.telephony.mbms;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.content.Intent;
import android.net.Uri;
@@ -26,7 +27,6 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -71,6 +71,19 @@
private String appIntent;
private int version = CURRENT_VERSION;
+
+ /**
+ * Builds a new DownloadRequest.
+ * @param sourceUri the source URI for the DownloadRequest to be built. This URI should
+ * never be null.
+ */
+ public Builder(@NonNull Uri sourceUri) {
+ if (sourceUri == null) {
+ throw new IllegalArgumentException("Source URI must be non-null.");
+ }
+ source = sourceUri;
+ }
+
/**
* Sets the service from which the download request to be built will download from.
* @param serviceInfo
@@ -92,15 +105,6 @@
}
/**
- * Sets the source URI for the download request to be built.
- * @param source
- */
- public Builder setSource(Uri source) {
- this.source = source;
- return this;
- }
-
- /**
* Set the subscription ID on which the file(s) should be downloaded.
* @param subscriptionId
*/
@@ -316,9 +320,11 @@
throw new RuntimeException("Could not get sha256 hash object");
}
if (version >= 1) {
- // Hash the source URI, destination URI, and the app intent
+ // Hash the source URI and the app intent
digest.update(sourceUri.toString().getBytes(StandardCharsets.UTF_8));
- digest.update(serializedResultIntentForApp.getBytes(StandardCharsets.UTF_8));
+ if (serializedResultIntentForApp != null) {
+ digest.update(serializedResultIntentForApp.getBytes(StandardCharsets.UTF_8));
+ }
}
// Add updates for future versions here
return Base64.encodeToString(digest.digest(), Base64.URL_SAFE | Base64.NO_WRAP);
diff --git a/tests/net/java/android/net/IpSecConfigTest.java b/tests/net/java/android/net/IpSecConfigTest.java
new file mode 100644
index 0000000..1b4bef5
--- /dev/null
+++ b/tests/net/java/android/net/IpSecConfigTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 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 org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link IpSecConfig}. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class IpSecConfigTest {
+
+ @Test
+ public void testDefaults() throws Exception {
+ IpSecConfig c = new IpSecConfig();
+ assertEquals(IpSecTransform.MODE_TRANSPORT, c.getMode());
+ assertEquals("", c.getLocalAddress());
+ assertEquals("", c.getRemoteAddress());
+ assertNull(c.getNetwork());
+ assertEquals(IpSecTransform.ENCAP_NONE, c.getEncapType());
+ assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getEncapSocketResourceId());
+ assertEquals(0, c.getEncapRemotePort());
+ assertEquals(0, c.getNattKeepaliveInterval());
+ for (int direction :
+ new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}) {
+ assertNull(c.getEncryption(direction));
+ assertNull(c.getAuthentication(direction));
+ assertEquals(IpSecManager.INVALID_RESOURCE_ID, c.getSpiResourceId(direction));
+ }
+ }
+
+ @Test
+ public void testParcelUnparcel() throws Exception {
+ assertParcelingIsLossless(new IpSecConfig());
+
+ IpSecConfig c = new IpSecConfig();
+ c.setMode(IpSecTransform.MODE_TUNNEL);
+ c.setLocalAddress("0.0.0.0");
+ c.setRemoteAddress("1.2.3.4");
+ c.setEncapType(android.system.OsConstants.UDP_ENCAP_ESPINUDP);
+ c.setEncapSocketResourceId(7);
+ c.setEncapRemotePort(22);
+ c.setNattKeepaliveInterval(42);
+ c.setEncryption(
+ IpSecTransform.DIRECTION_OUT,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.CRYPT_AES_CBC,
+ new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}));
+ c.setAuthentication(
+ IpSecTransform.DIRECTION_OUT,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.AUTH_HMAC_SHA1,
+ new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0}));
+ c.setSpiResourceId(IpSecTransform.DIRECTION_OUT, 1984);
+ c.setEncryption(
+ IpSecTransform.DIRECTION_IN,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.CRYPT_AES_CBC,
+ new byte[] {2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}));
+ c.setAuthentication(
+ IpSecTransform.DIRECTION_IN,
+ new IpSecAlgorithm(
+ IpSecAlgorithm.AUTH_HMAC_SHA1,
+ new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 1}));
+ c.setSpiResourceId(IpSecTransform.DIRECTION_IN, 99);
+ assertParcelingIsLossless(c);
+ }
+
+ private void assertParcelingIsLossless(IpSecConfig ci) throws Exception {
+ Parcel p = Parcel.obtain();
+ ci.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ IpSecConfig co = IpSecConfig.CREATOR.createFromParcel(p);
+ assertTrue(IpSecConfig.equals(co, ci));
+ }
+}
diff --git a/tests/net/java/com/android/internal/util/BitUtilsTest.java b/tests/net/java/com/android/internal/util/BitUtilsTest.java
index 0ad8a21..f4dc12a 100644
--- a/tests/net/java/com/android/internal/util/BitUtilsTest.java
+++ b/tests/net/java/com/android/internal/util/BitUtilsTest.java
@@ -56,6 +56,25 @@
}
@Test
+ public void testUnsignedShortComposition() {
+ byte b0 = 0;
+ byte b1 = 1;
+ byte b2 = 2;
+ byte b10 = 10;
+ byte b16 = 16;
+ byte b128 = -128;
+ byte b224 = -32;
+ byte b255 = -1;
+ assertEquals(0x0000, uint16(b0, b0));
+ assertEquals(0xffff, uint16(b255, b255));
+ assertEquals(0x0a01, uint16(b10, b1));
+ assertEquals(0x8002, uint16(b128, b2));
+ assertEquals(0x01ff, uint16(b1, b255));
+ assertEquals(0x80ff, uint16(b128, b255));
+ assertEquals(0xe010, uint16(b224, b16));
+ }
+
+ @Test
public void testUnsignedIntWideningConversions() {
assertEquals(0, uint32(0));
assertEquals(1, uint32(1));
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
new file mode 100644
index 0000000..9057a10
--- /dev/null
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.INetd;
+import android.net.IpSecAlgorithm;
+import android.net.IpSecConfig;
+import android.net.IpSecManager;
+import android.net.IpSecSpiResponse;
+import android.net.IpSecTransform;
+import android.net.IpSecTransformResponse;
+import android.net.NetworkUtils;
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.support.test.filters.SmallTest;
+import android.system.OsConstants;
+
+import java.net.Socket;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/** Unit tests for {@link IpSecService}. */
+@SmallTest
+@RunWith(Parameterized.class)
+public class IpSecServiceParameterizedTest {
+
+ private static final int DROID_SPI = 0xD1201D;
+ private static final int DROID_SPI2 = DROID_SPI + 1;
+
+ private final String mRemoteAddr;
+
+ @Parameterized.Parameters
+ public static Collection ipSecConfigs() {
+ return Arrays.asList(new Object[][] {{"8.8.4.4"}, {"2601::10"}});
+ }
+
+ private static final byte[] CRYPT_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ private static final byte[] AUTH_KEY = {
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
+ };
+
+ Context mMockContext;
+ INetd mMockNetd;
+ IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
+ IpSecService mIpSecService;
+
+ public IpSecServiceParameterizedTest(String remoteAddr) {
+ mRemoteAddr = remoteAddr;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mMockContext = mock(Context.class);
+ mMockNetd = mock(INetd.class);
+ mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
+ mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
+
+ // Injecting mock netd
+ when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
+ }
+
+ @Test
+ public void testIpSecServiceReserveSpi() throws Exception {
+ when(mMockNetd.ipSecAllocateSpi(
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ eq(mRemoteAddr),
+ eq(DROID_SPI)))
+ .thenReturn(DROID_SPI);
+
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, mRemoteAddr, DROID_SPI, new Binder());
+ assertEquals(IpSecManager.Status.OK, spiResp.status);
+ assertEquals(DROID_SPI, spiResp.spi);
+ }
+
+ @Test
+ public void testReleaseSecurityParameterIndex() throws Exception {
+ when(mMockNetd.ipSecAllocateSpi(
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ eq(mRemoteAddr),
+ eq(DROID_SPI)))
+ .thenReturn(DROID_SPI);
+
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, mRemoteAddr, DROID_SPI, new Binder());
+
+ mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
+
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(spiResp.resourceId), anyInt(), anyString(), anyString(), eq(DROID_SPI));
+ }
+
+ IpSecConfig buildIpSecConfig() throws Exception {
+ IpSecManager ipSecManager = new IpSecManager(mIpSecService);
+
+ // Mocking the netd to allocate SPI
+ when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
+ .thenReturn(DROID_SPI)
+ .thenReturn(DROID_SPI2);
+
+ IpSecAlgorithm encryptAlgo = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
+ IpSecAlgorithm authAlgo =
+ new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 8);
+
+ /** Allocate and add SPI records in the IpSecService through IpSecManager interface. */
+ IpSecManager.SecurityParameterIndex outSpi =
+ ipSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT,
+ NetworkUtils.numericToInetAddress(mRemoteAddr));
+ IpSecManager.SecurityParameterIndex inSpi =
+ ipSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_IN,
+ NetworkUtils.numericToInetAddress(mRemoteAddr));
+
+ IpSecConfig config = new IpSecConfig();
+ config.setSpiResourceId(IpSecTransform.DIRECTION_IN, inSpi.getResourceId());
+ config.setSpiResourceId(IpSecTransform.DIRECTION_OUT, outSpi.getResourceId());
+ config.setEncryption(IpSecTransform.DIRECTION_OUT, encryptAlgo);
+ config.setAuthentication(IpSecTransform.DIRECTION_OUT, authAlgo);
+ config.setEncryption(IpSecTransform.DIRECTION_IN, encryptAlgo);
+ config.setAuthentication(IpSecTransform.DIRECTION_IN, authAlgo);
+ config.setRemoteAddress(mRemoteAddr);
+ return config;
+ }
+
+ @Test
+ public void testCreateTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+ verify(mMockNetd)
+ .ipSecAddSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ anyLong(),
+ eq(DROID_SPI),
+ eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
+ eq(AUTH_KEY),
+ anyInt(),
+ eq(IpSecAlgorithm.CRYPT_AES_CBC),
+ eq(CRYPT_KEY),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ verify(mMockNetd)
+ .ipSecAddSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ anyLong(),
+ eq(DROID_SPI2),
+ eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
+ eq(AUTH_KEY),
+ anyInt(),
+ eq(IpSecAlgorithm.CRYPT_AES_CBC),
+ eq(CRYPT_KEY),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ }
+
+ @Test
+ public void testDeleteTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
+
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI));
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI2));
+ }
+
+ @Test
+ public void testApplyTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
+
+ int resourceId = createTransformResp.resourceId;
+ mIpSecService.applyTransportModeTransform(pfd, resourceId);
+
+ verify(mMockNetd)
+ .ipSecApplyTransportModeTransform(
+ eq(pfd.getFileDescriptor()),
+ eq(resourceId),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI));
+ verify(mMockNetd)
+ .ipSecApplyTransportModeTransform(
+ eq(pfd.getFileDescriptor()),
+ eq(resourceId),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI2));
+ }
+
+ @Test
+ public void testRemoveTransportModeTransform() throws Exception {
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
+ mIpSecService.removeTransportModeTransform(pfd, 1);
+
+ verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
+ }
+}
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
index 23fee28..efc58cc 100644
--- a/tests/net/java/com/android/server/IpSecServiceTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -23,34 +23,28 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.INetd;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecConfig;
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
import android.net.IpSecTransform;
-import android.net.IpSecTransformResponse;
import android.net.IpSecUdpEncapResponse;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.support.test.filters.SmallTest;
import android.system.ErrnoException;
import android.system.Os;
+
import java.io.FileDescriptor;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,13 +56,8 @@
public class IpSecServiceTest {
private static final int DROID_SPI = 0xD1201D;
- private static final int DROID_SPI2 = DROID_SPI + 1;
private static final int TEST_UDP_ENCAP_INVALID_PORT = 100;
private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 100000;
- private static final int TEST_UDP_ENCAP_PORT = 34567;
-
- private static final String IPV4_LOOPBACK = "127.0.0.1";
- private static final String IPV4_ADDR = "192.168.0.2";
private static final InetAddress INADDR_ANY;
@@ -80,21 +69,6 @@
}
}
- private static final int[] DIRECTIONS =
- new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN};
- private static final byte[] CRYPT_KEY = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
- };
- private static final byte[] AUTH_KEY = {
- 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
- 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
- };
-
Context mMockContext;
INetd mMockNetd;
IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
@@ -118,44 +92,6 @@
}
@Test
- public void testIpSecServiceReserveSpi() throws Exception {
- when(mMockNetd.ipSecAllocateSpi(
- anyInt(),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- eq(IPV4_LOOPBACK),
- eq(DROID_SPI)))
- .thenReturn(DROID_SPI);
-
- IpSecSpiResponse spiResp =
- mIpSecService.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_OUT, IPV4_LOOPBACK, DROID_SPI, new Binder());
- assertEquals(IpSecManager.Status.OK, spiResp.status);
- assertEquals(DROID_SPI, spiResp.spi);
- }
-
- @Test
- public void testReleaseSecurityParameterIndex() throws Exception {
- when(mMockNetd.ipSecAllocateSpi(
- anyInt(),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- eq(IPV4_LOOPBACK),
- eq(DROID_SPI)))
- .thenReturn(DROID_SPI);
-
- IpSecSpiResponse spiResp =
- mIpSecService.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_OUT, IPV4_LOOPBACK, DROID_SPI, new Binder());
-
- mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
-
- verify(mMockNetd)
- .ipSecDeleteSecurityAssociation(
- eq(spiResp.resourceId), anyInt(), anyString(), anyString(), eq(DROID_SPI));
- }
-
- @Test
public void testReleaseInvalidSecurityParameterIndex() throws Exception {
try {
mIpSecService.releaseSecurityParameterIndex(1);
@@ -285,108 +221,6 @@
}
}
- IpSecConfig buildIpSecConfig() throws Exception {
- IpSecManager ipSecManager = new IpSecManager(mIpSecService);
-
- // Mocking the netd to allocate SPI
- when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
- .thenReturn(DROID_SPI)
- .thenReturn(DROID_SPI2);
-
- IpSecAlgorithm encryptAlgo = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
- IpSecAlgorithm authAlgo =
- new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 8);
-
- InetAddress localAddr = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
-
- /** Allocate and add SPI records in the IpSecService through IpSecManager interface. */
- IpSecManager.SecurityParameterIndex outSpi =
- ipSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, localAddr);
- IpSecManager.SecurityParameterIndex inSpi =
- ipSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, localAddr);
-
- IpSecConfig ipSecConfig =
- new IpSecTransform.Builder(mMockContext)
- .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
- .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
- .setEncryption(IpSecTransform.DIRECTION_OUT, encryptAlgo)
- .setAuthentication(IpSecTransform.DIRECTION_OUT, authAlgo)
- .setEncryption(IpSecTransform.DIRECTION_IN, encryptAlgo)
- .setAuthentication(IpSecTransform.DIRECTION_IN, authAlgo)
- .getIpSecConfig();
- return ipSecConfig;
- }
-
- @Test
- public void testCreateTransportModeTransform() throws Exception {
- IpSecConfig ipSecConfig = buildIpSecConfig();
-
- IpSecTransformResponse createTransformResp =
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- assertEquals(IpSecManager.Status.OK, createTransformResp.status);
-
- verify(mMockNetd)
- .ipSecAddSecurityAssociation(
- eq(createTransformResp.resourceId),
- anyInt(),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- anyString(),
- anyLong(),
- eq(DROID_SPI),
- eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
- eq(AUTH_KEY),
- anyInt(),
- eq(IpSecAlgorithm.CRYPT_AES_CBC),
- eq(CRYPT_KEY),
- anyInt(),
- anyInt(),
- anyInt(),
- anyInt());
- verify(mMockNetd)
- .ipSecAddSecurityAssociation(
- eq(createTransformResp.resourceId),
- anyInt(),
- eq(IpSecTransform.DIRECTION_IN),
- anyString(),
- anyString(),
- anyLong(),
- eq(DROID_SPI2),
- eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
- eq(AUTH_KEY),
- anyInt(),
- eq(IpSecAlgorithm.CRYPT_AES_CBC),
- eq(CRYPT_KEY),
- anyInt(),
- anyInt(),
- anyInt(),
- anyInt());
- }
-
- @Test
- public void testDeleteTransportModeTransform() throws Exception {
- IpSecConfig ipSecConfig = buildIpSecConfig();
-
- IpSecTransformResponse createTransformResp =
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
-
- verify(mMockNetd)
- .ipSecDeleteSecurityAssociation(
- eq(createTransformResp.resourceId),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- anyString(),
- eq(DROID_SPI));
- verify(mMockNetd)
- .ipSecDeleteSecurityAssociation(
- eq(createTransformResp.resourceId),
- eq(IpSecTransform.DIRECTION_IN),
- anyString(),
- anyString(),
- eq(DROID_SPI2));
- }
-
@Test
public void testDeleteInvalidTransportModeTransform() throws Exception {
try {
@@ -397,39 +231,31 @@
}
@Test
- public void testApplyTransportModeTransform() throws Exception {
- IpSecConfig ipSecConfig = buildIpSecConfig();
-
- IpSecTransformResponse createTransformResp =
- mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
- ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
-
- int resourceId = createTransformResp.resourceId;
- mIpSecService.applyTransportModeTransform(pfd, resourceId);
-
- verify(mMockNetd)
- .ipSecApplyTransportModeTransform(
- eq(pfd.getFileDescriptor()),
- eq(resourceId),
- eq(IpSecTransform.DIRECTION_OUT),
- anyString(),
- anyString(),
- eq(DROID_SPI));
- verify(mMockNetd)
- .ipSecApplyTransportModeTransform(
- eq(pfd.getFileDescriptor()),
- eq(resourceId),
- eq(IpSecTransform.DIRECTION_IN),
- anyString(),
- anyString(),
- eq(DROID_SPI2));
- }
-
- @Test
public void testRemoveTransportModeTransform() throws Exception {
ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
mIpSecService.removeTransportModeTransform(pfd, 1);
verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
}
+
+ @Test
+ public void testValidateIpAddresses() throws Exception {
+ String[] invalidAddresses =
+ new String[] {"www.google.com", "::", "2001::/64", "0.0.0.0", ""};
+ for (String address : invalidAddresses) {
+ try {
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, address, DROID_SPI, new Binder());
+ fail("Invalid address was passed through IpSecService validation: " + address);
+ } catch (IllegalArgumentException e) {
+ } catch (Exception e) {
+ fail(
+ "Invalid InetAddress was not caught in validation: "
+ + address
+ + ", Exception: "
+ + e);
+ }
+ }
+ }
}