diff options
author | Justin Klaassen <justinklaassen@google.com> | 2018-04-03 23:21:57 -0400 |
---|---|---|
committer | Justin Klaassen <justinklaassen@google.com> | 2018-04-03 23:21:57 -0400 |
commit | 4d01eeaffaa720e4458a118baa137a11614f00f7 (patch) | |
tree | 66751893566986236788e3c796a7cc5e90d05f52 /android/net/IpSecTransform.java | |
parent | a192cc2a132cb0ee8588e2df755563ec7008c179 (diff) | |
download | android-28-4d01eeaffaa720e4458a118baa137a11614f00f7.tar.gz |
Import Android SDK Platform P [4697573]
/google/data/ro/projects/android/fetch_artifact \
--bid 4697573 \
--target sdk_phone_armv7-win_sdk \
sdk-repo-linux-sources-4697573.zip
AndroidVersion.ApiLevel has been modified to appear as 28
Change-Id: If80578c3c657366cc9cf75f8db13d46e2dd4e077
Diffstat (limited to 'android/net/IpSecTransform.java')
-rw-r--r-- | android/net/IpSecTransform.java | 191 |
1 files changed, 135 insertions, 56 deletions
diff --git a/android/net/IpSecTransform.java b/android/net/IpSecTransform.java index 37e2c4fb..099fe02f 100644 --- a/android/net/IpSecTransform.java +++ b/android/net/IpSecTransform.java @@ -17,11 +17,15 @@ package android.net; import static android.net.IpSecManager.INVALID_RESOURCE_ID; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -80,9 +84,11 @@ public final class IpSecTransform implements AutoCloseable { @Retention(RetentionPolicy.SOURCE) public @interface EncapType {} - private IpSecTransform(Context context, IpSecConfig config) { + /** @hide */ + @VisibleForTesting + public IpSecTransform(Context context, IpSecConfig config) { mContext = context; - mConfig = config; + mConfig = new IpSecConfig(config); mResourceId = INVALID_RESOURCE_ID; } @@ -128,13 +134,6 @@ public final class IpSecTransform implements AutoCloseable { int status = result.status; checkResultStatus(status); mResourceId = result.resourceId; - - /* Keepalive will silently fail if not needed by the config; but, if needed and - * it fails to start, we need to bail because a transform will not be reliable - * to use if keepalive is expected to offload and fails. - */ - // FIXME: if keepalive fails, we need to fail spectacularly - startKeepalive(mContext); Log.d(TAG, "Added Transform with Id " + mResourceId); mCloseGuard.open("build"); } catch (RemoteException e) { @@ -146,6 +145,18 @@ public final class IpSecTransform implements AutoCloseable { } /** + * Equals method used for testing + * + * @hide + */ + @VisibleForTesting + public static boolean equals(IpSecTransform lhs, IpSecTransform rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return IpSecConfig.equals(lhs.getConfig(), rhs.getConfig()) + && lhs.mResourceId == rhs.mResourceId; + } + + /** * Deactivate this {@code IpSecTransform} and free allocated resources. * * <p>Deactivating a transform while it is still applied to a socket will result in errors on @@ -164,13 +175,9 @@ public final class IpSecTransform implements AutoCloseable { return; } try { - /* Order matters here because the keepalive is best-effort but could fail in some - * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we - * still want to clear out the transform. - */ IIpSecService svc = getIpSecService(); svc.deleteTransform(mResourceId); - stopKeepalive(); + stopNattKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { @@ -198,42 +205,35 @@ public final class IpSecTransform implements AutoCloseable { private final Context mContext; private final CloseGuard mCloseGuard = CloseGuard.get(); private ConnectivityManager.PacketKeepalive mKeepalive; - private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; - private Object mKeepaliveSyncLock = new Object(); - private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback = + private Handler mCallbackHandler; + private final ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback = new ConnectivityManager.PacketKeepaliveCallback() { @Override public void onStarted() { - synchronized (mKeepaliveSyncLock) { - mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS; - mKeepaliveSyncLock.notifyAll(); + synchronized (this) { + mCallbackHandler.post(() -> mUserKeepaliveCallback.onStarted()); } } @Override public void onStopped() { - synchronized (mKeepaliveSyncLock) { - mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; - mKeepaliveSyncLock.notifyAll(); + synchronized (this) { + mKeepalive = null; + mCallbackHandler.post(() -> mUserKeepaliveCallback.onStopped()); } } @Override public void onError(int error) { - synchronized (mKeepaliveSyncLock) { - mKeepaliveStatus = error; - mKeepaliveSyncLock.notifyAll(); + synchronized (this) { + mKeepalive = null; + mCallbackHandler.post(() -> mUserKeepaliveCallback.onError(error)); } } }; - /* Package */ - void startKeepalive(Context c) { - if (mConfig.getNattKeepaliveInterval() != 0) { - Log.wtf(TAG, "Keepalive not yet supported."); - } - } + private NattKeepaliveCallback mUserKeepaliveCallback; /** @hide */ @VisibleForTesting @@ -241,9 +241,101 @@ public final class IpSecTransform implements AutoCloseable { return mResourceId; } - /* Package */ - void stopKeepalive() { - return; + /** + * A callback class to provide status information regarding a NAT-T keepalive session + * + * <p>Use this callback to receive status information regarding a NAT-T keepalive session + * by registering it when calling {@link #startNattKeepalive}. + * + * @hide + */ + @SystemApi + public static class NattKeepaliveCallback { + /** The specified {@code Network} is not connected. */ + public static final int ERROR_INVALID_NETWORK = 1; + /** The hardware does not support this request. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = 2; + /** The hardware returned an error. */ + public static final int ERROR_HARDWARE_ERROR = 3; + + /** The requested keepalive was successfully started. */ + public void onStarted() {} + /** The keepalive was successfully stopped. */ + public void onStopped() {} + /** An error occurred. */ + public void onError(int error) {} + } + + /** + * Start a NAT-T keepalive session for the current transform. + * + * For a transform that is using UDP encapsulated IPv4, NAT-T offloading provides + * a power efficient mechanism of sending NAT-T packets at a specified interval. + * + * @param userCallback a {@link #NattKeepaliveCallback} to receive asynchronous status + * information about the requested NAT-T keepalive session. + * @param intervalSeconds the interval between NAT-T keepalives being sent. The + * the allowed range is between 20 and 3600 seconds. + * @param handler a handler on which to post callbacks when received. + * + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, + android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD + }) + public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, + int intervalSeconds, @NonNull Handler handler) throws IOException { + checkNotNull(userCallback); + if (intervalSeconds < 20 || intervalSeconds > 3600) { + throw new IllegalArgumentException("Invalid NAT-T keepalive interval"); + } + checkNotNull(handler); + if (mResourceId == INVALID_RESOURCE_ID) { + throw new IllegalStateException( + "Packet keepalive cannot be started for an inactive transform"); + } + + synchronized (mKeepaliveCallback) { + if (mKeepaliveCallback != null) { + throw new IllegalStateException("Keepalive already active"); + } + + mUserKeepaliveCallback = userCallback; + ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + mKeepalive = cm.startNattKeepalive( + mConfig.getNetwork(), intervalSeconds, mKeepaliveCallback, + NetworkUtils.numericToInetAddress(mConfig.getSourceAddress()), + 4500, // FIXME urgently, we need to get the port number from the Encap socket + NetworkUtils.numericToInetAddress(mConfig.getDestinationAddress())); + mCallbackHandler = handler; + } + } + + /** + * Stop an ongoing NAT-T keepalive session. + * + * Calling this API will request that an ongoing NAT-T keepalive session be terminated. + * If this API is not called when a Transform is closed, the underlying NAT-T session will + * be terminated automatically. + * + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, + android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD + }) + public void stopNattKeepalive() { + synchronized (mKeepaliveCallback) { + if (mKeepalive == null) { + Log.e(TAG, "No active keepalive to stop"); + return; + } + mKeepalive.stop(); + } } /** This class is used to build {@link IpSecTransform} objects. */ @@ -258,6 +350,7 @@ public final class IpSecTransform implements AutoCloseable { * * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ + @NonNull public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. Preconditions.checkNotNull(algo); @@ -272,6 +365,7 @@ public final class IpSecTransform implements AutoCloseable { * * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ + @NonNull public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. Preconditions.checkNotNull(algo); @@ -292,6 +386,7 @@ public final class IpSecTransform implements AutoCloseable { * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to * be applied. */ + @NonNull public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) { Preconditions.checkNotNull(algo); mConfig.setAuthenticatedEncryption(algo); @@ -311,6 +406,7 @@ public final class IpSecTransform implements AutoCloseable { * @param remotePort the UDP port number of the remote host that will send and receive * encapsulated traffic. In the case of IKEv2, this should be port 4500. */ + @NonNull public IpSecTransform.Builder setIpv4Encapsulation( @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { Preconditions.checkNotNull(localSocket); @@ -323,26 +419,6 @@ public final class IpSecTransform implements AutoCloseable { return this; } - // TODO: Decrease the minimum keepalive to maybe 10? - // TODO: Probably a better exception to throw for NATTKeepalive failure - // TODO: Specify the needed NATT keepalive permission. - /** - * Set NAT-T keepalives to be sent with a given interval. - * - * <p>This will set power-efficient keepalive packets to be sent by the system. If NAT-T - * keepalive is requested but cannot be activated, then creation of an {@link - * IpSecTransform} will fail when calling the build method. - * - * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be - * between 20s and 3600s. - * @hide - */ - @SystemApi - public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) { - mConfig.setNattKeepaliveInterval(intervalSeconds); - return this; - } - /** * Build a transport mode {@link IpSecTransform}. * @@ -364,6 +440,7 @@ public final class IpSecTransform implements AutoCloseable { * collides with an existing transform * @throws IOException indicating other errors */ + @NonNull public IpSecTransform buildTransportModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) @@ -400,6 +477,8 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi + @NonNull + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) @@ -413,7 +492,7 @@ public final class IpSecTransform implements AutoCloseable { mConfig.setMode(MODE_TUNNEL); mConfig.setSourceAddress(sourceAddress.getHostAddress()); mConfig.setSpiResourceId(spi.getResourceId()); - return new IpSecTransform(mContext, mConfig); + return new IpSecTransform(mContext, mConfig).activate(); } /** |