Loading Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -201,6 +201,7 @@ java_defaults { "core/java/android/net/INetworkScoreService.aidl", "core/java/android/net/INetworkStatsService.aidl", "core/java/android/net/INetworkStatsSession.aidl", "core/java/android/net/ISocketKeepaliveCallback.aidl", "core/java/android/net/ITestNetworkManager.aidl", "core/java/android/net/ITetheringEventCallback.aidl", "core/java/android/net/ITetheringStatsProvider.aidl", Loading core/java/android/net/ConnectivityManager.java +54 −47 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkActivityListener; import android.os.INetworkManagementService; Loading Loading @@ -75,6 +74,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; /** * Class that answers queries about the state of network connectivity. It also Loading Loading @@ -1813,23 +1815,26 @@ public class ConnectivityManager { public static final int MIN_INTERVAL = 10; private final Network mNetwork; private final PacketKeepaliveCallback mCallback; private final Looper mLooper; private final Messenger mMessenger; private final ISocketKeepaliveCallback mCallback; private final ExecutorService mExecutor; private volatile Integer mSlot; void stopLooper() { mLooper.quit(); } @UnsupportedAppUsage public void stop() { try { mExecutor.execute(() -> { try { if (mSlot != null) { mService.stopKeepalive(mNetwork, mSlot); } } catch (RemoteException e) { Log.e(TAG, "Error stopping packet keepalive: ", e); stopLooper(); throw e.rethrowFromSystemServer(); } }); } catch (RejectedExecutionException e) { // The internal executor has already stopped due to previous event. } } Loading @@ -1837,40 +1842,43 @@ public class ConnectivityManager { Preconditions.checkNotNull(network, "network cannot be null"); Preconditions.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) { mExecutor = Executors.newSingleThreadExecutor(); mCallback = new ISocketKeepaliveCallback.Stub() { @Override public void handleMessage(Message message) { switch (message.what) { case NetworkAgent.EVENT_SOCKET_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); public void onStarted(int slot) { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { mSlot = slot; callback.onStarted(); })); } } catch (Exception e) { Log.e(TAG, "Exception in keepalive callback(" + error + ")", e); @Override public void onStopped() { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { mSlot = null; callback.onStopped(); })); mExecutor.shutdown(); } break; default: Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what)); break; @Override public void onError(int error) { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { mSlot = null; callback.onError(error); })); mExecutor.shutdown(); } @Override public void onDataReceived() { // PacketKeepalive is only used for Nat-T keepalive and as such does not invoke // this callback when data is received. } }); }; } } Loading @@ -1887,12 +1895,11 @@ public class ConnectivityManager { InetAddress srcAddr, int srcPort, InetAddress dstAddr) { final PacketKeepalive k = new PacketKeepalive(network, callback); try { mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(), mService.startNattKeepalive(network, intervalSeconds, k.mCallback, srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress()); } catch (RemoteException e) { Log.e(TAG, "Error starting packet keepalive: ", e); k.stopLooper(); return null; throw e.rethrowFromSystemServer(); } return k; } Loading core/java/android/net/IConnectivityManager.aidl +5 −4 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.net.NetworkMisc; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkState; import android.net.ISocketKeepaliveCallback; import android.net.ProxyInfo; import android.os.Bundle; import android.os.IBinder; Loading Loading @@ -194,15 +195,15 @@ interface IConnectivityManager void factoryReset(); void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr, int srcPort, String dstAddr); void startNattKeepalive(in Network network, int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr); void startNattKeepaliveWithFd(in Network network, in FileDescriptor fd, int resourceId, int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr, int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr, String dstAddr); void startTcpKeepalive(in Network network, in FileDescriptor fd, int intervalSeconds, in Messenger messenger, in IBinder binder); in ISocketKeepaliveCallback cb); void stopKeepalive(in Network network, int slot); Loading core/java/android/net/ISocketKeepaliveCallback.aidl 0 → 100644 +34 −0 Original line number Diff line number Diff line /** * Copyright (c) 2019, 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; /** * Callback to provide status changes of keepalive offload. * * @hide */ oneway interface ISocketKeepaliveCallback { /** The keepalive was successfully started. */ void onStarted(int slot); /** The keepalive was successfully stopped. */ void onStopped(); /** The keepalive was stopped because of an error. */ void onError(int error); /** The keepalive on a TCP socket was stopped because the socket received data. */ void onDataReceived(); } core/java/android/net/NattSocketKeepalive.java +20 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package android.net; import android.annotation.NonNull; import android.os.Binder; import android.os.RemoteException; import android.util.Log; Loading Loading @@ -52,24 +51,30 @@ public final class NattSocketKeepalive extends SocketKeepalive { @Override void startImpl(int intervalSec) { mExecutor.execute(() -> { try { mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mMessenger, new Binder(), mSource.getHostAddress(), mDestination.getHostAddress()); mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mCallback, mSource.getHostAddress(), mDestination.getHostAddress()); } catch (RemoteException e) { Log.e(TAG, "Error starting packet keepalive: ", e); stopLooper(); Log.e(TAG, "Error starting socket keepalive: ", e); throw e.rethrowFromSystemServer(); } }); } @Override void stopImpl() { mExecutor.execute(() -> { try { if (mSlot != null) { mService.stopKeepalive(mNetwork, mSlot); } } catch (RemoteException e) { Log.e(TAG, "Error stopping packet keepalive: ", e); stopLooper(); Log.e(TAG, "Error stopping socket keepalive: ", e); throw e.rethrowFromSystemServer(); } }); } } Loading
Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -201,6 +201,7 @@ java_defaults { "core/java/android/net/INetworkScoreService.aidl", "core/java/android/net/INetworkStatsService.aidl", "core/java/android/net/INetworkStatsSession.aidl", "core/java/android/net/ISocketKeepaliveCallback.aidl", "core/java/android/net/ITestNetworkManager.aidl", "core/java/android/net/ITetheringEventCallback.aidl", "core/java/android/net/ITetheringStatsProvider.aidl", Loading
core/java/android/net/ConnectivityManager.java +54 −47 Original line number Diff line number Diff line Loading @@ -38,7 +38,6 @@ import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkActivityListener; import android.os.INetworkManagementService; Loading Loading @@ -75,6 +74,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; /** * Class that answers queries about the state of network connectivity. It also Loading Loading @@ -1813,23 +1815,26 @@ public class ConnectivityManager { public static final int MIN_INTERVAL = 10; private final Network mNetwork; private final PacketKeepaliveCallback mCallback; private final Looper mLooper; private final Messenger mMessenger; private final ISocketKeepaliveCallback mCallback; private final ExecutorService mExecutor; private volatile Integer mSlot; void stopLooper() { mLooper.quit(); } @UnsupportedAppUsage public void stop() { try { mExecutor.execute(() -> { try { if (mSlot != null) { mService.stopKeepalive(mNetwork, mSlot); } } catch (RemoteException e) { Log.e(TAG, "Error stopping packet keepalive: ", e); stopLooper(); throw e.rethrowFromSystemServer(); } }); } catch (RejectedExecutionException e) { // The internal executor has already stopped due to previous event. } } Loading @@ -1837,40 +1842,43 @@ public class ConnectivityManager { Preconditions.checkNotNull(network, "network cannot be null"); Preconditions.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) { mExecutor = Executors.newSingleThreadExecutor(); mCallback = new ISocketKeepaliveCallback.Stub() { @Override public void handleMessage(Message message) { switch (message.what) { case NetworkAgent.EVENT_SOCKET_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); public void onStarted(int slot) { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { mSlot = slot; callback.onStarted(); })); } } catch (Exception e) { Log.e(TAG, "Exception in keepalive callback(" + error + ")", e); @Override public void onStopped() { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { mSlot = null; callback.onStopped(); })); mExecutor.shutdown(); } break; default: Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what)); break; @Override public void onError(int error) { Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> { mSlot = null; callback.onError(error); })); mExecutor.shutdown(); } @Override public void onDataReceived() { // PacketKeepalive is only used for Nat-T keepalive and as such does not invoke // this callback when data is received. } }); }; } } Loading @@ -1887,12 +1895,11 @@ public class ConnectivityManager { InetAddress srcAddr, int srcPort, InetAddress dstAddr) { final PacketKeepalive k = new PacketKeepalive(network, callback); try { mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(), mService.startNattKeepalive(network, intervalSeconds, k.mCallback, srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress()); } catch (RemoteException e) { Log.e(TAG, "Error starting packet keepalive: ", e); k.stopLooper(); return null; throw e.rethrowFromSystemServer(); } return k; } Loading
core/java/android/net/IConnectivityManager.aidl +5 −4 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.net.NetworkMisc; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkState; import android.net.ISocketKeepaliveCallback; import android.net.ProxyInfo; import android.os.Bundle; import android.os.IBinder; Loading Loading @@ -194,15 +195,15 @@ interface IConnectivityManager void factoryReset(); void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr, int srcPort, String dstAddr); void startNattKeepalive(in Network network, int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr); void startNattKeepaliveWithFd(in Network network, in FileDescriptor fd, int resourceId, int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr, int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr, String dstAddr); void startTcpKeepalive(in Network network, in FileDescriptor fd, int intervalSeconds, in Messenger messenger, in IBinder binder); in ISocketKeepaliveCallback cb); void stopKeepalive(in Network network, int slot); Loading
core/java/android/net/ISocketKeepaliveCallback.aidl 0 → 100644 +34 −0 Original line number Diff line number Diff line /** * Copyright (c) 2019, 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; /** * Callback to provide status changes of keepalive offload. * * @hide */ oneway interface ISocketKeepaliveCallback { /** The keepalive was successfully started. */ void onStarted(int slot); /** The keepalive was successfully stopped. */ void onStopped(); /** The keepalive was stopped because of an error. */ void onError(int error); /** The keepalive on a TCP socket was stopped because the socket received data. */ void onDataReceived(); }
core/java/android/net/NattSocketKeepalive.java +20 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package android.net; import android.annotation.NonNull; import android.os.Binder; import android.os.RemoteException; import android.util.Log; Loading Loading @@ -52,24 +51,30 @@ public final class NattSocketKeepalive extends SocketKeepalive { @Override void startImpl(int intervalSec) { mExecutor.execute(() -> { try { mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mMessenger, new Binder(), mSource.getHostAddress(), mDestination.getHostAddress()); mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mCallback, mSource.getHostAddress(), mDestination.getHostAddress()); } catch (RemoteException e) { Log.e(TAG, "Error starting packet keepalive: ", e); stopLooper(); Log.e(TAG, "Error starting socket keepalive: ", e); throw e.rethrowFromSystemServer(); } }); } @Override void stopImpl() { mExecutor.execute(() -> { try { if (mSlot != null) { mService.stopKeepalive(mNetwork, mSlot); } } catch (RemoteException e) { Log.e(TAG, "Error stopping packet keepalive: ", e); stopLooper(); Log.e(TAG, "Error stopping socket keepalive: ", e); throw e.rethrowFromSystemServer(); } }); } }