Merge "DO not throw exception for ERROR_NO_SUCH_SLOT error" into udc-dev
diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java
index 10daf17..f915e72 100644
--- a/framework/src/android/net/SocketKeepalive.java
+++ b/framework/src/android/net/SocketKeepalive.java
@@ -149,9 +149,7 @@
     public static final int ERROR_INSUFFICIENT_RESOURCES = -32;
 
     /**
-     * There was no such slot. This should only be internally as it indicates
-     * a programming error in the system server. It should not propagate to
-     * applications.
+     * There was no such slot, or no keepalive running on this slot.
      * @hide
      */
     @SystemApi
diff --git a/service/src/com/android/server/connectivity/KeepaliveTracker.java b/service/src/com/android/server/connectivity/KeepaliveTracker.java
index 8c170bc..cc226ce 100644
--- a/service/src/com/android/server/connectivity/KeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveTracker.java
@@ -569,7 +569,20 @@
         } else if (reason == ERROR_STOP_REASON_UNINITIALIZED) {
             throw new IllegalStateException("Unexpected stop reason: " + reason);
         } else if (reason == ERROR_NO_SUCH_SLOT) {
-            throw new IllegalStateException("No such slot: " + reason);
+            // There are multiple independent reasons a keepalive can stop. Some
+            // are software (e.g. the app stops the keepalive) and some are hardware
+            // (e.g. the SIM card gets removed). Therefore, there is a very low
+            // probability that both of these happen at the same time, which would
+            // result in the first stop attempt returning SUCCESS and the second
+            // stop attempt returning NO_SUCH_SLOT. Such a race condition can be
+            // ignored with a log.
+            // This should still be reported because if it happens with any frequency
+            // it probably means there is a bug where the system server is trying
+            // to use a non-existing hardware slot.
+            // TODO : separate the non-existing hardware slot from the case where
+            // there is no keepalive running on this slot.
+            Log.wtf(TAG, "Keepalive on slot " + slot + " can't be stopped : " + reason);
+            notifyErrorCallback(ki.mCallback, reason);
         } else {
             notifyErrorCallback(ki.mCallback, reason);
         }