diff options
Diffstat (limited to 'core/java/android/net')
-rw-r--r-- | core/java/android/net/ConnectivityManager.java | 136 | ||||
-rw-r--r-- | core/java/android/net/IConnectivityManager.aidl | 5 | ||||
-rw-r--r-- | core/java/android/net/NetworkAgent.java | 90 |
3 files changed, 226 insertions, 5 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index dc8ff8f..86a50c6 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1206,6 +1206,142 @@ public class ConnectivityManager { return true; } + /** @hide */ + public static class PacketKeepaliveCallback { + /** 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) {} + } + + /** + * Allows applications to request that the system periodically send specific packets on their + * behalf, using hardware offload to save battery power. + * + * To request that the system send keepalives, call one of the methods that return a + * {@link ConnectivityManager.PacketKeepalive} object, such as {@link #startNattKeepalive}, + * passing in a non-null callback. If the callback is successfully started, the callback's + * {@code onStarted} method will be called. If an error occurs, {@code onError} will be called, + * specifying one of the {@code ERROR_*} constants in this class. + * + * To stop an existing keepalive, call {@link stop}. The system will call {@code onStopped} if + * the operation was successfull or {@code onError} if an error occurred. + * + * @hide + */ + public class PacketKeepalive { + + private static final String TAG = "PacketKeepalive"; + + /** @hide */ + public static final int SUCCESS = 0; + + /** @hide */ + public static final int NO_KEEPALIVE = -1; + + /** @hide */ + public static final int BINDER_DIED = -10; + + /** The specified {@code Network} is not connected. */ + public static final int ERROR_INVALID_NETWORK = -20; + /** The specified IP addresses are invalid. For example, the specified source IP address is + * not configured on the specified {@code Network}. */ + public static final int ERROR_INVALID_IP_ADDRESS = -21; + /** The requested port is invalid. */ + public static final int ERROR_INVALID_PORT = -22; + /** The packet length is invalid (e.g., too long). */ + public static final int ERROR_INVALID_LENGTH = -23; + /** The packet transmission interval is invalid (e.g., too short). */ + public static final int ERROR_INVALID_INTERVAL = -24; + + /** The hardware does not support this request. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = -30; + + public static final int NATT_PORT = 4500; + + private final Network mNetwork; + private final PacketKeepaliveCallback mCallback; + private final Looper mLooper; + private final Messenger mMessenger; + + private volatile Integer mSlot; + + void stopLooper() { + mLooper.quit(); + } + + public void stop() { + try { + mService.stopKeepalive(mNetwork, mSlot); + } catch (RemoteException e) { + Log.e(TAG, "Error stopping packet keepalive: ", e); + stopLooper(); + } + } + + private PacketKeepalive(Network network, PacketKeepaliveCallback callback) { + checkNotNull(network, "network cannot be null"); + checkNotNull(callback, "callback cannot be null"); + mNetwork = network; + mCallback = callback; + HandlerThread thread = new HandlerThread(TAG); + thread.start(); + mLooper = thread.getLooper(); + mMessenger = new Messenger(new Handler(mLooper) { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case NetworkAgent.EVENT_PACKET_KEEPALIVE: + int error = message.arg2; + try { + if (error == SUCCESS) { + if (mSlot == null) { + mSlot = message.arg1; + mCallback.onStarted(); + } else { + mSlot = null; + stopLooper(); + mCallback.onStopped(); + } + } else { + stopLooper(); + mCallback.onError(error); + } + } catch (Exception e) { + Log.e(TAG, "Exception in keepalive callback(" + error + ")", e); + } + break; + default: + Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what)); + break; + } + } + }); + } + } + + /** + * Starts an IPsec NAT-T keepalive packet with the specified parameters. + * + * @hide + */ + public PacketKeepalive startNattKeepalive( + Network network, int intervalSeconds, PacketKeepaliveCallback callback, + InetAddress srcAddr, int srcPort, InetAddress dstAddr) { + final PacketKeepalive k = new PacketKeepalive(network, callback); + try { + mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(), + srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress()); + } catch (RemoteException e) { + Log.e(TAG, "Error starting packet keepalive: ", e); + k.stopLooper(); + return null; + } + return k; + } + /** * Ensure that a network route exists to deliver traffic to the specified * host via the specified network interface. An attempt to add a route that diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 46c28a6..d4dd669 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -160,4 +160,9 @@ interface IConnectivityManager boolean setUnderlyingNetworksForVpn(in Network[] networks); void factoryReset(); + + void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger, + in IBinder binder, String srcAddr, int srcPort, String dstAddr); + + void stopKeepalive(in Network network, int slot); } diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index e6fc1ea..85a584a 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -25,6 +25,7 @@ import android.util.Log; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import android.net.ConnectivityManager.PacketKeepalive; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; @@ -143,11 +144,46 @@ public abstract class NetworkAgent extends Handler { */ public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9; - /** Sent by ConnectivityService to the NetworkAgent to inform the agent to pull + /** + * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull * the underlying network connection for updated bandwidth information. */ public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10; + /** + * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent + * periodically on the given interval. + * + * arg1 = the slot number of the keepalive to start + * arg2 = interval in seconds + * obj = KeepalivePacketData object describing the data to be sent + * + * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + */ + public static final int CMD_START_PACKET_KEEPALIVE = BASE + 11; + + /** + * Requests that the specified keepalive packet be stopped. + * + * arg1 = slot number of the keepalive to stop. + * + * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + */ + public static final int CMD_STOP_PACKET_KEEPALIVE = BASE + 12; + + /** + * Sent by the NetworkAgent to ConnectivityService to provide status on a packet keepalive + * request. This may either be the reply to a CMD_START_PACKET_KEEPALIVE, or an asynchronous + * error notification. + * + * This is also sent by KeepaliveTracker to the app's ConnectivityManager.PacketKeepalive to + * so that the app's PacketKeepaliveCallback methods can be called. + * + * arg1 = slot number of the keepalive + * arg2 = error code + */ + public static final int EVENT_PACKET_KEEPALIVE = BASE + 13; + public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null); @@ -240,18 +276,41 @@ public abstract class NetworkAgent extends Handler { } case CMD_SAVE_ACCEPT_UNVALIDATED: { saveAcceptUnvalidated(msg.arg1 != 0); + break; + } + case CMD_START_PACKET_KEEPALIVE: { + startPacketKeepalive(msg); + break; + } + case CMD_STOP_PACKET_KEEPALIVE: { + stopPacketKeepalive(msg); + break; } } } private void queueOrSendMessage(int what, Object obj) { + queueOrSendMessage(what, 0, 0, obj); + } + + private void queueOrSendMessage(int what, int arg1, int arg2) { + queueOrSendMessage(what, arg1, arg2, null); + } + + private void queueOrSendMessage(int what, int arg1, int arg2, Object obj) { + Message msg = Message.obtain(); + msg.what = what; + msg.arg1 = arg1; + msg.arg2 = arg2; + msg.obj = obj; + queueOrSendMessage(msg); + } + + private void queueOrSendMessage(Message msg) { synchronized (mPreConnectedQueue) { if (mAsyncChannel != null) { - mAsyncChannel.sendMessage(what, obj); + mAsyncChannel.sendMessage(msg); } else { - Message msg = Message.obtain(); - msg.what = what; - msg.obj = obj; mPreConnectedQueue.add(msg); } } @@ -365,6 +424,27 @@ public abstract class NetworkAgent extends Handler { protected void saveAcceptUnvalidated(boolean accept) { } + /** + * Requests that the network hardware send the specified packet at the specified interval. + */ + protected void startPacketKeepalive(Message msg) { + onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + } + + /** + * Requests that the network hardware send the specified packet at the specified interval. + */ + protected void stopPacketKeepalive(Message msg) { + onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); + } + + /** + * Called by the network when a packet keepalive event occurs. + */ + public void onPacketKeepaliveEvent(int slot, int reason) { + queueOrSendMessage(EVENT_PACKET_KEEPALIVE, slot, reason); + } + protected void log(String s) { Log.d(LOG_TAG, "NetworkAgent: " + s); } |